API automation guide

Import leads and enroll eligible contacts safely.

Submit an asynchronous import, check the batch result, review accepted records, and enroll eligible contacts into a prepared campaign with idempotent requests.

Reviewed September 8, 202612 minute readProduct behavior checked against current implementation
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; add enrollments:write for enrollment.
  • Confirm that the target campaign, published sequence, sending pool, schedule, and safety controls are ready.
  • Choose a conflict policy: skip, fill_empty_only, or overwrite.
  • 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

ConcernBehavior
DeduplicationEmail is matched inside the key's workspace.
Existing fieldsThe selected conflict policy decides whether values are skipped, filled, or overwritten.
SuppressionExisting suppression and block-list decisions remain in force; import never un-suppresses.
CapacityPlan contact limits and available headroom are enforced.
ExecutionThe request returns a batch handle; processing continues asynchronously in bounded chunks.
RetryThe 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.

Do not build a loop that imports, enrolls, and forgets. Keep batch reconciliation, recipient eligibility, campaign readiness, reply ownership, and incident handling in the automation design.

Sources and product basis

Automate a controlled campaign handoff.

Import in traceable batches, reconcile the result, and enroll contacts only after the campaign is ready.