Start an async CSV contact import

POST
/v1/contacts/import

Uploads the CSV to R2 and inserts a pending job; a per-minute cron parses and upserts it in bounded batches (IMPORT_BATCH = 500 data rows/tick) so an import of any size never blows one Worker invocation's budget. Poll GET /v1/contacts/imports/{id} for progress. The CSV's header row must contain an email column; every other column becomes a contact attribute. Emits contact.import.completed when done.

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

multipart/form-data
  1. body
file*file

CSV file, max 10 MB.

Formatbinary

Response Body

Import job created.

application/json
  1. response
import_id?string
status?"pending"
Value in"pending"
curl -X POST "https://example.com/v1/contacts/import" \  -F file="string"
{  "import_id": "string",  "status": "pending"}