Appearance
Retrieve a contact import
Check the status and result of an import.
http
GET /v1/contacts/imports/{id}Requires a Full access API key.
Path parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | The contact import id. |
Example
bash
curl "https://api.sendgrail.com/v1/contacts/imports/$IMPORT_ID" \
-H "Authorization: Bearer $SENDGRAIL_API_KEY"js
const res = await fetch(
`https://api.sendgrail.com/v1/contacts/imports/${id}`,
{ headers: { Authorization: `Bearer ${process.env.SENDGRAIL_API_KEY}` } },
);
const { status, counts } = await res.json();Response
json
{
"object": "contact_import",
"id": "479e3145-dd38-476b-932c-529ceb705947",
"status": "completed",
"created_at": "2026-05-15T18:32:37+00:00",
"completed_at": "2026-05-15T18:33:42+00:00",
"counts": {
"total": 1200,
"created": 800,
"updated": 300,
"skipped": 75,
"failed": 25
}
}Status
| Value | Meaning |
|---|---|
queued | Accepted, waiting for a worker to pick it up. |
in_progress | Being processed now. |
completed | Finished — counts and completed_at are set. |
failed | The file itself could not be processed (no header row, unreadable upload). Individual bad rows do not fail the import — they're counted under failed in counts. |
Poll until status is completed or failed. counts and completed_at are null until then.
Counts
Present once the import has run:
| Field | Meaning |
|---|---|
total | Rows read from the file (excluding the header). |
created | New contacts added. |
updated | Existing contacts updated — only under on_conflict: upsert. |
skipped | Existing contacts left untouched — only under on_conflict: skip. |
failed | Rows with a missing or invalid email address. |
created + updated + skipped + failed equals total.
An import belonging to another team answers 404.