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
| Rule | Value |
|---|---|
| Max contacts per request | 1000 (CONTACTS_BULK_MAX) |
| Min contacts per request | 1 |
| Upsert key | externalId 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
Export from your CRM
Export contacts with
externalId,email,locale, andoptIn. IncludeupdatedSincemetadata if your CRM tracks it.Chunk into batches of 1000
Split the export into arrays of at most 1000 items per
POST /contacts/bulkcall.Incremental updates
For ongoing sync, use
GET /contacts?updatedSince=...to pull changes from MailingCore, or push deltas with bulk upsert keyed onexternalId.Verify audience
Before a campaign, check locale coverage to confirm each language has enough opted-in contacts.
Common errors
| Code | Cause |
|---|---|
| 400 | Empty array, invalid email, or more than 1000 contacts |
| 403 | Missing contacts:write scope |