Reference

ContactZapp API reference

The ContactZapp API reads and writes the contacts in a ContactZapp account, so that Zapier, Make, n8n and your own code can use them.

Create an API key in ContactZapp under Settings, Advanced. Send it with every request as Authorization: Bearer <key>. The first call to try is GET /api/v1/me.

GET /api/v1/openapi.json

This API's OpenAPI document.

No API key needed.

Returns this API's OpenAPI 3.1 document as JSON. It needs no API key, so tools such as Pipedream and Activepieces can import it from the live API.

Responses

StatusWhat it means
200The OpenAPI document.

GET /api/v1/me

Who this API key acts for, on which plan, with which scopes.

Any API key can call this.

Checks an API key. Returns the user the key acts for, the user's plan and the key's scopes. Any live key may call it, so it is the call to make when you want to test a key.

Send the key in every request as Authorization: Bearer <key>. Each operation names the scope it needs; a key without that scope gets 403. There is a limit on requests; past it the answer is 429 with a Retry-After header. Every error body has a stable code.

Responses

StatusWhat it means
200The key's user, plan and scopes.
401No API key (api_key_missing; a session cookie alone counts as none), or one that is not a live key: unknown, revoked or malformed (api_key_invalid).
429The user's keys together made 60 requests in the last minute (rate_limited). Retry-After says, in seconds, when the next request would be served.
500The server could not complete the request (internal_error). The cause is logged, never returned.
503The key or the rate limit could not be checked (unavailable). Retry.

GET /api/v1/contacts

Find the user's contacts by email, phone or text, or list them.

Needs the contacts:read scope.

Finds the user's contacts, or lists them. Give at most one of email, phone and query:

  • email and phone find the contacts that hold that address or number. An email is compared ignoring case, and a phone number ignoring formatting.
  • query is the same free-text search the Contacts screen has.
  • With none of them, every contact is listed, newest first.

Pages work with a cursor: pass nextCursor back as cursor, with the same filter, until a page comes back without one. Deleted and merged contacts are never returned.

Parameters

NameInTypeRequiredWhat it is
emailquerystringNo
phonequerystringNo
queryquerystringNo
cursorquerystringNoThe previous page's nextCursor.
limitqueryintegerNoPage size; 50 when omitted.

Responses

StatusWhat it means
200One page of contacts.
400A query parameter this route cannot use (invalid_parameter): a limit out of range, a cursor this route did not issue, or two filters where one is allowed.
401No API key (api_key_missing; a session cookie alone counts as none), or one that is not a live key: unknown, revoked or malformed (api_key_invalid).
403The key lacks the scope this route needs (insufficient_scope).
429The user's keys together made 60 requests in the last minute (rate_limited). Retry-After says, in seconds, when the next request would be served.
500The server could not complete the request (internal_error). The cause is logged, never returned.
503The key or the rate limit could not be checked (unavailable). Retry.

POST /api/v1/contacts

Create a contact, treated like one arriving from a sync.

Needs the contacts:write scope.

Creates a contact. It is treated like a contact that arrives from a sync.

The contact is written to one of the user's two-way accounts, which ContactZapp chooses: the earliest-linked account that keeps an address book and is not paused. The sync then copies it to every other two-way account, and never to a read-only one. It is matched like any incoming contact:

  • when the user's auto-merge level covers the match, the values are added to the contact the user already has (200, merged);
  • otherwise the contact is created (201, created), and a possible match waits in Review duplicates (201, needs_review).

A create is never refused for the plan's contact limit. Over the limit, the contact is created frozen (201), and contact.frozen in the answer is true. ContactZapp keeps a frozen contact but does not sync it until the user upgrades or frees a place.

Send an Idempotency-Key header to make a retry safe. A repeat with the same key and the same body within 24 hours answers with the first result and writes nothing. The same key with a different body is a 422.

Parameters

NameInTypeRequiredWhat it is
Idempotency-KeyheaderstringNoAny string of 1 to 255 bytes that the caller chooses for this write, such as a UUID. A repeat with the same key and the same body within 24 hours answers with the first result and writes nothing; the same key with another body is a 422.

Responses

StatusWhat it means
200The values were merged into a contact the user has (merged).
201A new contact (created, or needs_review with its possible matches).
400The body is not a contact (invalid_body), carries an impossible date (invalid_date) or no value at all (empty_contact), or the Idempotency-Key header is empty or too long (idempotency_key_invalid), or the body carries a field a contact write does not take (unknown_field).
401No API key (api_key_missing; a session cookie alone counts as none), or one that is not a live key: unknown, revoked or malformed (api_key_invalid).
403The key lacks the scope this route needs (insufficient_scope).
409The contact waits in Review duplicates (contact_pending_review), was merged away or deleted (contact_gone), or changed while it was written (contact_changed, retry); or a request with this Idempotency-Key is still being handled (idempotency_key_in_progress).
413The request body is larger than the API accepts (body_too_large).
422The user has no two-way account that keeps an address book and is not paused (no_account_to_write_to), or this Idempotency-Key was used with another body in the last 24 hours (idempotency_key_reused).
429The user's keys together made 60 requests in the last minute (rate_limited). Retry-After says, in seconds, when the next request would be served.
500The server could not complete the request (internal_error). The cause is logged, never returned.
503The key or the rate limit could not be checked (unavailable). Retry.

GET /api/v1/contacts/{id}

One of the user's contacts.

Needs the contacts:read scope.

Returns one contact. id is the contact's id or its publicId (CS-0042). A deleted or merged contact is a 404, and so is another user's contact.

Parameters

NameInTypeRequiredWhat it is
idpathstringYes

Responses

StatusWhat it means
200The contact.
401No API key (api_key_missing; a session cookie alone counts as none), or one that is not a live key: unknown, revoked or malformed (api_key_invalid).
403The key lacks the scope this route needs (insufficient_scope).
404No such contact or trigger for this key's user (not_found).
429The user's keys together made 60 requests in the last minute (rate_limited). Retry-After says, in seconds, when the next request would be served.
500The server could not complete the request (internal_error). The cause is logged, never returned.
503The key or the rate limit could not be checked (unavailable). Retry.

PATCH /api/v1/contacts/{id}

Change a contact's fields, as the app's edit does.

Needs the contacts:write scope.

Changes a contact's fields, as the app's edit does. Only the fields in the body change; a field the body leaves out keeps its value.

The change is recorded in History as the user's, naming the API key, and written to every two-way account the contact is in, never to a read-only one. A contact waiting in Review duplicates cannot be changed until the review is decided (409, contact_pending_review). Idempotency-Key works as it does when you create a contact.

Parameters

NameInTypeRequiredWhat it is
idpathstringYesThe contact's id or its publicId (CS-0042).
Idempotency-KeyheaderstringNoAny string of 1 to 255 bytes that the caller chooses for this write, such as a UUID. A repeat with the same key and the same body within 24 hours answers with the first result and writes nothing; the same key with another body is a 422.

Responses

StatusWhat it means
200The contact as it is now (updated).
400The body is not a contact (invalid_body), carries an impossible date (invalid_date) or no value at all (empty_contact), or the Idempotency-Key header is empty or too long (idempotency_key_invalid), or the body carries a field a contact write does not take (unknown_field).
401No API key (api_key_missing; a session cookie alone counts as none), or one that is not a live key: unknown, revoked or malformed (api_key_invalid).
403The key lacks the scope this route needs (insufficient_scope).
404No such contact or trigger for this key's user (not_found).
409The contact waits in Review duplicates (contact_pending_review), was merged away or deleted (contact_gone), or changed while it was written (contact_changed, retry); or a request with this Idempotency-Key is still being handled (idempotency_key_in_progress).
413The request body is larger than the API accepts (body_too_large).
422The user has no two-way account that keeps an address book and is not paused (no_account_to_write_to), or this Idempotency-Key was used with another body in the last 24 hours (idempotency_key_reused).
429The user's keys together made 60 requests in the last minute (rate_limited). Retry-After says, in seconds, when the next request would be served.
500The server could not complete the request (internal_error). The cause is logged, never returned.
503The key or the rate limit could not be checked (unavailable). Retry.

GET /api/v1/accounts

The user's linked accounts.

Needs the contacts:read scope.

Lists the user's linked accounts, as the Settings screen does: provider, name, sync direction, connection state and when each account last synced.

Responses

StatusWhat it means
200The linked accounts.
401No API key (api_key_missing; a session cookie alone counts as none), or one that is not a live key: unknown, revoked or malformed (api_key_invalid).
403The key lacks the scope this route needs (insufficient_scope).
429The user's keys together made 60 requests in the last minute (rate_limited). Retry-After says, in seconds, when the next request would be served.
500The server could not complete the request (internal_error). The cause is logged, never returned.
503The key or the rate limit could not be checked (unavailable). Retry.

GET /api/v1/triggers/{event}

A polling trigger — the newest events of one type first.

Needs the contacts:read scope.

Polling trigger: returns the newest events of one type first. This is what Zapier, Make and n8n poll to start an automation. Each item has an id that never changes. Polling again with nothing new returns the same ids, and a new event appears at the top. Deduplicate by id.

contact.created, contact.updated, contacts.merged and account.needs_attention come from the change history ContactZapp records. One item is one recorded event, and it is kept as long as the History screen keeps it. match.needs_review comes from the duplicate flags the Contacts screen shows: one item for each contact flagged as a possible duplicate and not yet merged. Its id changes when the flag is raised again.

Each item carries what an automation needs without a second call: the contact's fields (null when the contact has since been deleted or merged), for a merge the ids of the contacts it absorbed, and for an account the account and why it needs attention.

Parameters

NameInTypeRequiredWhat it is
eventpathYes
cursorquerystringNoThe previous page's nextCursor, to read further back.
limitqueryintegerNoPage size; 50 when omitted.

Responses

StatusWhat it means
200One page of events, newest first.
400A query parameter this route cannot use (invalid_parameter): a limit out of range, a cursor this route did not issue, or two filters where one is allowed.
401No API key (api_key_missing; a session cookie alone counts as none), or one that is not a live key: unknown, revoked or malformed (api_key_invalid).
403The key lacks the scope this route needs (insufficient_scope).
404No such contact or trigger for this key's user (not_found).
429The user's keys together made 60 requests in the last minute (rate_limited). Retry-After says, in seconds, when the next request would be served.
500The server could not complete the request (internal_error). The cause is logged, never returned.
503The key or the rate limit could not be checked (unavailable). Retry.