An open-source API to save contacts. Send a POST with an email and any other fields you want, and they get saved as-is.
Create a contact. If the email already exists the contact is updated rather than duplicated.
| required | The contact's email, used as the unique key. | |
| * | optional | Any other JSON fields such as name, plan or source are saved as-is. |
{ "email": "ada@example.com", "name": "Ada", "plan": "pro" }
{
"id": "con_a1b2",
"email": "ada@example.com",
"name": "Ada",
"plan": "pro",
"created_at": "2026-07-04T10:00:00Z",
"updated_at": "2026-07-04T10:00:00Z"
}
List your contacts, sorted by created_at, newest first.
| page | optional | Which page to return, starting at 1. Defaults to 1. |
| page_size | optional | How many contacts per page, 1–100. Defaults to 20. |
GET /v1/contacts?page=1&page_size=20
{
"data": [
{
"id": "con_a1b2",
"email": "ada@example.com",
"name": "Ada",
"plan": "pro",
"created_at": "2026-07-04T10:00:00Z",
"updated_at": "2026-07-04T10:00:00Z"
}
],
"page": 1,
"page_size": 20,
"total": 137,
"total_pages": 7
}
total is the full contact count across all pages; total_pages is ceil(total / page_size). There are more pages while page < total_pages.
Fetch a single contact by id.
{
"id": "con_a1b2",
"email": "ada@example.com",
"name": "Ada",
"plan": "pro",
"created_at": "2026-07-04T10:00:00Z",
"updated_at": "2026-07-04T10:00:00Z"
}
Update a contact by sending only the fields you want to change.
{ "plan": "enterprise" }
{
"id": "con_a1b2",
"email": "ada@example.com",
"name": "Ada",
"plan": "enterprise",
"updated_at": "2026-07-04T11:30:00Z"
}
Delete a contact.
{ "id": "con_a1b2", "deleted": true }
The base URL is https://contactapi.dev and every request carries your key in a header.
Authorization: Bearer YOUR_KEY
ck_secret_… | Use this on your backend. It has full access to every endpoint above. |
ck_pub_… | Use this in a browser. It can only create contacts and is locked to your domains. |