Documentation Index
Fetch the complete documentation index at: https://mintlify.com/DataTalksClub/datamailer/llms.txt
Use this file to discover all available pages before exploring further.
POST /api/contacts is the primary way to sync contact data into Datamailer. It creates or updates the global contact record, creates or updates the audience- and client-scoped subscription, applies email validation and suppression state, and assigns audience-scoped tags — all in a single atomic request.
Endpoint
Authentication
Requires a Bearer token issued to the client whose slug matches theclient field in the request body.
Request body
The recipient’s email address. Must be a valid RFC 5321 address. Normalized to lowercase before storage; the original casing is preserved for display.
Slug of the audience to subscribe the contact to. Must belong to the same organization as the authenticated client.
Slug of the client making the request. Must exactly match the authenticated client’s slug or the request is rejected with
403 Forbidden.Subscription status to set. One of
pending, subscribed, or unsubscribed. Defaults to pending when omitted.List of tag name strings to assign to this contact within the audience. Tags are audience-scoped and created automatically if they do not exist. Pass an empty array
[] or omit the field to leave existing tags unchanged.Whether the contact’s email address has been verified by the client application. When
true and no prior verified_at timestamp exists, the current time is recorded. Already-set verified_at timestamps are preserved.External email validation result to store on the contact record.
Contact-level suppression flags to apply. Suppression is global — it affects deliverability across all audiences.
Response
A successful call returns HTTP200 with the full contact status payload plus a tags array.
Internal Datamailer ID for the contact record.
Normalized (lowercased) email address for the contact.
Always
true for a successful upsert response.Whether the contact has a
verified_at timestamp set at the contact level.ISO-8601 UTC timestamp of contact-level verification, or
null if not verified.Current email validation state.
Whether the contact has opted out of all marketing email globally.
Whether the contact’s address has hard bounced.
Whether the contact has filed a spam complaint.
Audience-scoped subscription state.
Client-scoped subscription state. Same shape as
audience.Whether a marketing campaign email can currently be sent to this contact for this audience and client.
false if the contact is suppressed, has a non-deliverable email validation status, is not subscribed, or has not been verified on any subscription level.Whether a transactional email can currently be sent to this contact.
false only if the contact has hard bounced or complained.Sorted list of tag slugs currently assigned to this contact within the audience.
Example
Request
Response
Error codes
Validation errors return HTTP400 (or 403 for client mismatch) with the following structure:
| Field | Error code | Meaning |
|---|---|---|
email | required | email was missing or blank. |
email | invalid | email did not pass RFC 5321 format validation. |
audience | required | audience was missing or blank. |
audience | not_found | No audience with that slug exists in the authenticated client’s organization. |
client | required | client was missing or blank. |
client | forbidden | client does not match the authenticated client’s slug. Returns HTTP 403. |
status | invalid | status is not one of pending, subscribed, or unsubscribed. |
tags | must_be_list | tags was provided but is not a JSON array. |
tags | must_be_non_empty_strings | One or more tag entries are not non-empty strings. |
verified | must_be_boolean | verified was provided but is not a boolean. |
email_validation | must_be_object | email_validation was provided but is not a JSON object. |
email_validation.status | invalid | email_validation.status is not a recognized EmailValidationStatus value. |
suppression | must_be_object | suppression was provided but is not a JSON object. |
suppression.global_unsubscribed | must_be_boolean | Suppression flag value is not a boolean. |