Upsert up to 100 contacts

POST
/v1/contacts/batch

Each item is validated/upserted independently — a bad item is a per-item failure, not a whole-batch rejection. The plan cap is checked once up front against the batch size, not per item. Deliberately emits no webhooks and does not trigger automation enrollment (to avoid a fan-out storm from a large batch).

Authorization

bearerAuth
headerAuthorizationBearer <token>

API key sent as Authorization: Bearer <key>. Looked up by SHA-256 hash (email_core::sha256_hex) against api_keys.hash; revoked keys and keys belonging to a suspended tenant are rejected. See the top-level Authentication section for permission levels.

Request Body

application/json
  1. body
contacts*array<>
Items1 <= items <= 100

Response Body

Batch processed.

application/json
  1. response
data?array<>
summary?
curl -X POST "https://example.com/v1/contacts/batch" \  -H "Content-Type: application/json" \  -d '{    "contacts": [      {        "email": "user@example.com"      }    ]  }'
{  "data": [    {      "index": 0,      "email": "string",      "id": "string",      "status": "string",      "created": true,      "error": "string"    }  ],  "summary": {    "created": 0,    "updated": 0,    "failed": 0  }}