Skip to content

Sync your contacts

A contact sync has two parts. When a customer joins, you backfill the people your platform already holds for them, 500 at a time. After that, each change on your side is one upsert by your own id for the person. Both are idempotent, so a sync that runs twice does no harm. Do the backfill before the customer’s first campaign.

  1. Create an attribute definition for each fact your templates and your customers’ campaigns will read: first name, plan, home site. Definitions belong to your platform, so this happens once, not per customer.
  2. Create the customer’s workspace, with your id for the customer as its reference.

Create or update contacts in a batch takes up to 500 contacts, each with its reference and the fields of a single upsert:

Terminal window
curl -X POST https://api.sendtruss.com/v1/workspaces/ref:cust_4821/contacts/batch \
-H "Authorization: Bearer $SENDTRUSS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"contacts": [
{
"reference": "guest_998",
"email": "ana@example.com",
"locale": "pt-BR",
"attributes": {"first_name": "Ana"},
"marketing": {"state": "subscribed", "at": "2025-06-14T18:20:00Z"}
},
{
"reference": "guest_999",
"email": "ben@example.com",
"attributes": {"first_name": "Ben"}
}
]
}'

Each contact is written or refused on its own, so one bad address doesn’t fail the other 499. The answer is always 200, with one result per contact in the order you sent them:

{
"data": [
{"reference": "guest_998", "result": "created", "id": "01JA2Q5D3B8C1E6F9G2H4J7K0M"},
{
"reference": "guest_999",
"result": "refused",
"code": "email_taken",
"message": "Another contact in this workspace has this email.",
"contact": "ref:guest_412",
"doc_url": "https://docs.sendtruss.com/errors/#email_taken"
}
]
}

Check every result. A refused one carries the same code, message and doc_url a single upsert would have answered with, plus errors by field for validation_failed. Fix the data and send that contact again; sending the whole batch again is fine too, since contacts already written are just updated.

A batch counts as one request against your platform’s limit. Send batches one after another, not all at once, and on a 429 wait for the seconds in Retry-After.

Send marketing only for people who actually agreed to marketing (or said no), with the time they did. Everyone else is created pending and gets no marketing, which is what you want for people whose consent you don’t know. Transactional email reaches them either way.

If your records hold an opt-out, send it as unsubscribed with its time. It protects the person from a later sync that still carries an older “yes”.

After the backfill, call Create or update a contact whenever a person changes on your side, sending only the fields that changed:

Terminal window
curl -X PUT https://api.sendtruss.com/v1/workspaces/ref:cust_4821/contacts/ref:guest_998 \
-H "Authorization: Bearer $SENDTRUSS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"email": "ana.souza@example.com"}'

It answers 201 if the contact is new and 200 if it existed. Fields you leave out stay as they are, except tags, which, when you send it, is the contact’s whole set.

When the person agrees to marketing in your platform, send subscribed with the time. If it’s refused with consent_older_than_opt_out, the person left marketing after the time you sent. Don’t retry it: the newer choice wins, and the person rejoins through your own sign-up flow, which sends a fresh subscribed.

Some changes start with the person, not with you: they leave marketing through the link in an email, or their address bounces. Register a webhook endpoint for contact.left_marketing, contact.rejoined_marketing and contact.suppressed, and update your own records when they arrive, so your platform shows the same state we hold. A sync shouldn’t send a consent back for these; we already have the person’s choice.

When a person no longer belongs in the customer’s list, delete the contact:

Terminal window
curl -X DELETE https://api.sendtruss.com/v1/workspaces/ref:cust_4821/contacts/ref:guest_998 \
-H "Authorization: Bearer $SENDTRUSS_API_KEY"

When they ask to be forgotten, erase them instead. See Privacy and erasure for the difference.

List a workspace’s contacts, newest first, 50 to a page, filtered by marketing status, a tag’s key or part of the address:

Terminal window
curl "https://api.sendtruss.com/v1/workspaces/ref:cust_4821/contacts?status=subscribed" \
-H "Authorization: Bearer $SENDTRUSS_API_KEY"

Follow links.next in each answer for the next page.