Create several contacts
POST /contacts/batch
The nightly sync, rather than the signup hook. Up to 100 per request, each
entry exactly the body POST /contacts takes.
[
{ "email": "alice@example.com", "properties": { "plan": "pro" } },
{ "email": "bob@example.com", "properties": { "plan": "free" } }
]
The response is one result per input, in the order you sent them:
{
"data": [
{ "email": "alice@example.com", "status": "created" },
{ "email": "bob@example.com", "status": "updated" }
]
}
status is created, updated or skipped, or the error slug for that entry
with a message beside it.
It answers 200 even when entries failed
One bad address is that address’s problem: a 4xx for the whole request would
make you replay the entries that were fine, and hit the same bad one again. So
check status per entry. The request itself is refused only when the batch is
empty or longer than 100 — both wrong before anything was attempted.
The contact ceiling is the exception worth knowing about. It is a fact about
the account, not the row, so once one entry reports quota_exceeded every
remaining one will too. They are still reported in place rather than truncating
the list, because results you match to inputs by position have to be as many as
you sent.
Still one contact per address
A batch containing the same address twice applies both, in order — the second is an update of what the first wrote, not a duplicate.