Migrations

Import from SendGrid, Postmark or Mailgun (Beta)

Reads your account at SendGrid, Postmark or Mailgun with the API key you send and imports what you select: sending domains (with the exact DNS changes, compared with what each domain publishes today), webhooks (created disabled, with events mapped), templates (variables converted; anything that cannot convert, and templates with an unsubscribe link, are imported as drafts and listed), and suppressions (hard bounces, complaints, unsubscribes; partial opt-outs become product email opt-outs; bounces caused by a block on the old provider's servers and temporary failures are skipped). Real imports are stored: see GET /migrations/{id} and /migrations/{id}/report.

The key is used for this request only. It is never stored, logged or returned.

One request works for about 40 seconds. When there is more to do, the response has has_more: true and a next_cursor: send the same body again with cursor set to continue (wait retry_after_seconds first when it is set). Each response reports the items it handled and running totals. Re-running an import is safe: domains, webhooks (same URL), templates (same alias) and suppressions that already exist are skipped. Set dry_run: true to preview without writing anything.

Rate limits: 10 new imports per workspace per hour; 300 continuation requests per hour.

post/migrations

Request

  • Base URL: https://api.groundmail.dev
  • URL: https://api.groundmail.dev/migrations
  • Auth: HTTP bearer

Request body

provider'sendgrid' | 'postmark' | 'mailgun' required
api_keystring required

SendGrid API key, Postmark server API token, or Mailgun private API key. Read access is enough. Used for this request only; never stored.

account_api_keystring

Postmark only. The account API token, needed to import sending domains.

region'us' | 'eu'

SendGrid and Mailgun only. Use eu for EU-region accounts.

resourcesstring[]

What to import. Defaults to all four. Ignored when cursor is set.

dry_runboolean

Preview without writing anything. Suppressions are counted from the first page of each list only (suppressions.estimated: true). Ignored when cursor is set.

cursorstring

The next_cursor from the previous response, to continue the same import.

Response

What this request imported, running totals, and (when finished) the code change

Changes

No recorded changes to this operation across all 2 revisions of this API.