DocumentationBulk import

Bulk import

POST /contacts/bulk — upsert up to 1000 contacts per request.

Import or update many contacts in a single API call. Each item uses the same shape as upsert contact.

Required scope: contacts:write.

POST https://api.mailingcore.com/contacts/bulk
Authorization: Bearer mc_live_xxxx
X-Tenant-Id: clxxxxxxxx
Content-Type: application/json

Request body

{
  "contacts": [
    {
      "email": "[email protected]",
      "externalId": "crm-1",
      "locale": "en",
      "optIn": true,
      "attributes": { "firstName": "Alice" }
    },
    {
      "email": "[email protected]",
      "externalId": "crm-2",
      "locale": "es",
      "optIn": true
    }
  ]
}

Limits

RuleValue
Max contacts per request1000 (CONTACTS_BULK_MAX)
Min contacts per request1
Upsert keyexternalId if present, else email

Example

curl -X POST "https://api.mailingcore.com/contacts/bulk" \
  -H "Authorization: Bearer mc_live_xxxx" \
  -H "X-Tenant-Id: clxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "contacts": [
      { "email": "[email protected]", "externalId": "crm-1", "locale": "en", "optIn": true },
      { "email": "[email protected]", "externalId": "crm-2", "locale": "es", "optIn": true }
    ]
  }'

Typical response: 200 with a summary of created, updated, and failed rows.

Recommended sync pattern

  1. Export from your CRM

    Export contacts with externalId, email, locale, and optIn. Include updatedSince metadata if your CRM tracks it.

  2. Chunk into batches of 1000

    Split the export into arrays of at most 1000 items per POST /contacts/bulk call.

  3. Incremental updates

    For ongoing sync, use GET /contacts?updatedSince=... to pull changes from MailingCore, or push deltas with bulk upsert keyed on externalId.

  4. Verify audience

    Before a campaign, check locale coverage to confirm each language has enough opted-in contacts.

Common errors

CodeCause
400Empty array, invalid email, or more than 1000 contacts
403Missing contacts:write scope