Contacts & audience sync
Add contacts from your backend, import an audience, and keep optional marketing consent with its evidence.
Create or update by email
POST /v1/contacts upserts a contact by normalized email within the key’s workspace. Use contacts:write. Marketing consent is optional: omitting it preserves existing consent; a new contact defaults to no consent.
curl -X POST "$BASE_URL/api/v1/contacts" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"email": "alex@example.com",
"name": "Alex Morgan",
"attributes": {"customer_id": "cust_123"},
"marketing_consent": true,
"consent_source": "signup-form-v2: explicit opt-in on 2026-11-05"
}'| Field / scope | Description | Requirement / access |
|---|---|---|
email | Valid email address; normalized to lowercase | Required |
name | Contact name | Optional |
attributes | Custom JSON attributes; replaced when supplied | Optional |
marketing_consent | Explicit true to grant, false to revoke | Optional |
consent_source | Evidence/source of opt-in; required when true | Conditional |
Consent is a separate choice
Leave marketing_consent and consent_source out when you are only syncing a customer record. Do not interpret purchases, account creation, or a sales inquiry as marketing consent. The service records consent events with the actor, source, and server timestamp. Follow the Collect consent in your app guide at /docs/checkbox-consent for checkbox markup and a server-side integration example.
Update or revoke
PATCH /v1/contacts/:id can change name, attributes, or consent. Explicit false revokes consent and adds a marketing suppression. Recording true later does not silently remove an existing suppression; inspect Suppressions before assuming marketing is enabled.
{ "marketing_consent": false, "consent_source": "customer-preferences" }Bulk imports
POST /v1/contacts/import accepts up to 1,000 contact objects in contacts. The import is transactional: an invalid item rolls back the batch. For large audiences, send separate bounded batches and retain progress in your application.
{ "contacts": [
{ "email": "alex@example.com", "name": "Alex" },
{ "email": "sam@example.com", "marketing_consent": true,
"consent_source": "newsletter-form: explicit opt-in" }
] }Organize lists
Create a list with POST /v1/lists and {name,contact_ids?}. Add members with POST /v1/lists/:id/contacts and {contact_ids:[...]}. API-key tenant scope applies throughout. Lists organize the audience; membership alone does not grant consent.