Contact and entity batch imports
Submit contact, deal, and appointment imports and poll their status.
Use the entity-specific batch import endpoints when you need to submit multiple contacts, deals, or appointments for asynchronous processing.
| Entity | Create a batch | Poll one batch | List batches |
|---|---|---|---|
| Contacts | POST /v1/contacts/imports/batch | GET /v1/contacts/imports/{id} | GET /v1/contacts/imports |
| Deals | POST /v1/deals/imports/batch | GET /v1/deals/imports/{id} | GET /v1/deals/imports |
| Appointments | POST /v1/appointments/imports/batch | GET /v1/appointments/imports/{id} | GET /v1/appointments/imports |
Every batch request creates a new import job. The API does not deduplicate
requests by payload or external_id, so retrying a successful request creates
another job.
Submit an inline payload
Batch requests use JSON and include a non-empty payload array. Each item is an
entity import record. The request body limit is 5 MB. Multipart uploads and file
IDs are not supported by these endpoints.
curl https://api.getmateo.com/v1/contacts/imports/batch \
--request POST \
--header "Authorization: Bearer $MATEO_API_TOKEN" \
--header "hellomateo-version: 2026-07-01" \
--header "Content-Type: application/json" \
--data '{
"external_id": "erp-contact-import-2026-07-14",
"contact_list_external_id": "newsletter",
"payload": [
{
"external_id": "customer-1001",
"full_name": "Ada Lovelace",
"email": "ada@example.com"
},
{
"external_id": "customer-1002",
"full_name": "Grace Hopper",
"email": "grace@example.com"
}
]
}'For contact batches, use at most one of contact_list_id and
contact_list_external_id.
Deal and appointment batches use the same envelope and accept their respective record fields:
{
"external_id": "erp-deal-import-2026-07-14",
"allow_deal_reassignment": false,
"payload": [
{
"external_id": "deal-1001",
"name": "Annual renewal",
"contact_external_id": "customer-1001"
}
]
}Send that body to POST /v1/deals/imports/batch. For appointments, send the
appointment records to POST /v1/appointments/imports/batch and use
allow_appointment_reassignment when needed.
Batch routes return 415 Unsupported Media Type when Content-Type is missing
or is not a JSON media type. They return 413 Payload Too Large when the JSON
body exceeds 5 MB. Malformed JSON and payload validation failures return 400 Bad Request.
A successful submission returns 201 Created and the new import job. This
abbreviated example highlights the fields used for polling:
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"type": "contact_details",
"external_id": "erp-contact-import-2026-07-14",
"status": "pending",
"started_at": null,
"completed_at": null,
"total_count": null,
"success_count": null,
"failed_count": null,
"failure": null
}Poll the import
Build the detail URL from the returned id and the same entity collection used
to create the job:
curl https://api.getmateo.com/v1/contacts/imports/3c90c3cc-0d44-4b50-8888-8dd25736052a \
--header "Authorization: Bearer $MATEO_API_TOKEN" \
--header "hellomateo-version: 2026-07-01"Batch 1 exposes coarse status semantics:
pendingmeans at least one result count is not available yet.completedmeanstotal_count,success_count, andfailed_countare all available.
A completed job may still contain failed records. Check success_count and
failed_count rather than treating completed as “every record succeeded.”
The status schema also reserves processing, failed, and unknown for the
persisted lifecycle rollout. The following response is abbreviated:
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"type": "contact_details",
"status": "completed",
"total_count": 2,
"success_count": 1,
"failed_count": 1,
"failure": null
}Poll with backoff until the job reaches a terminal status. Do not repeatedly submit the batch to check whether it finished.
List and filter imports
Entity import history is separate for contacts, deals, and appointments. Lists are ordered by creation time and use cursor pagination.
curl --globoff 'https://api.getmateo.com/v1/contacts/imports?status[in]=pending,completed&limit=20' \
--header "Authorization: Bearer $MATEO_API_TOKEN" \
--header "hellomateo-version: 2026-07-01"Follow next_page_url when it is present. You can also filter by one
external_id or use external_id[in] for multiple values.