The API uses the same contact-upsert, deduplication, plan-cap, and suppression controls as product imports. Automation can add and update approved data; it cannot silently make a suppressed recipient sendable.
Prepare the destination first
- Create a workspace key with
imports:write; addenrollments:writefor enrollment. - Confirm that the target campaign, published sequence, sending pool, schedule, and safety controls are ready.
- Choose a conflict policy:
skip,fill_empty_only, oroverwrite. - Use stable source identifiers in your own system and generate a unique idempotency key for each logical batch.
1. Submit a contact batch
curl -X POST https://app.mailsequence.com/api/v1/contacts/import \
-H "Authorization: Bearer $MAILSEQUENCE_API_KEY" \
-H "Idempotency-Key: crm-export-2026-09-08-001" \
-H "Content-Type: application/json" \
-d '{
"conflict_policy":"fill_empty_only",
"rows":[
{"email":"ada@example.com","first_name":"Ada","company":"Example Co"}
]
}'
Each row requires an email. One request can contain up to 10,000 rows. Split larger loads into named batches. The API returns a validation error for unsupported fields.
What happens during import
| Concern | Behavior |
|---|---|
| Deduplication | Email is matched inside the key's workspace. |
| Existing fields | The selected conflict policy decides whether values are skipped, filled, or overwritten. |
| Suppression | Existing suppression and block-list decisions remain in force; import never un-suppresses. |
| Capacity | Plan contact limits and available headroom are enforced. |
| Execution | The request returns a batch handle; processing continues asynchronously in bounded chunks. |
| Retry | The same request and idempotency key resolve to the same logical operation. |
2. Poll the batch handle
curl https://app.mailsequence.com/api/v1/imports/IMPORT_ID \
-H "Authorization: Bearer $MAILSEQUENCE_API_KEY"
Wait for the terminal batch state and inspect the created, updated, skipped, and suppressed counts. A successful submission is not evidence that every row was usable or eligible for sending.
3. Resolve the destination IDs
Use the contacts collection with an exact email filter to find the destination contact ID, and list campaigns in the same workspace to resolve the target campaign. Do not carry IDs between client workspaces.
4. Enroll an eligible contact
curl -X POST \
https://app.mailsequence.com/api/v1/campaigns/CAMPAIGN_ID/enrollments \
-H "Authorization: Bearer $MAILSEQUENCE_API_KEY" \
-H "Idempotency-Key: enroll-contact-123-campaign-45" \
-H "Content-Type: application/json" \
-d '{"contact_id":123}'
Enrollment creates local lifecycle state. Delivery runs asynchronously. Existing enrollment, suppression, campaign readiness, and plan constraints can prevent the transition. Inspect conflict and validation responses before retrying.
5. Observe and control the lifecycle
Read enrollments and use the documented pause, resume, or stop routes when your workflow requires a state change. Subscribe to reply, bounce, and completion webhooks for event-driven downstream work. A recipient reply or suppression change remains authoritative over scheduled follow-up.
Sources and product basis
- MailSequence public API reference
Current import, batch-status, contact, campaign, enrollment, and lifecycle schemas. - MailSequence email verification
Verification states, risk policy, and suppression-aware preparation. - Reply-based stopping guide
How inbound replies and suppression affect remaining follow-up.