Overview
AutoSend provides a set of public API endpoints to migrate your Resend assets into your AutoSend project:- Templates
- Contacts and audiences (contact lists)
- Contact properties (custom fields)
- Topics (suppression groups)
- Unsubscribed contacts
Prerequisites
Before you start, make sure you have:- An AutoSend project API key - create one on the API Keys page. Keys look like
AS_xxxxxxxx_xxxxxxxxxxxxxxxxxxxx. - A Resend API key - generate one in Resend under API Keys. The key needs read access to templates, contacts, audiences, contact properties, and topics. Keys look like
re_xxxxxxxxxxxxxxxxxxxxxxxx. - The base URL for all requests:
https://api.autosend.com/v1
Authentication
Every request uses two headers:| Header | Value |
|---|---|
Authorization | Bearer <YOUR_AUTOSEND_API_KEY> |
Content-Type | application/json |
How Resend Maps to AutoSend
Resend and AutoSend model their assets a little differently. The migration applies these mappings:| Resend | AutoSend | Notes |
|---|---|---|
| Template | Template | HTML, subject, and name are migrated. Templates using #each are flagged for review. |
| Contact property | Custom field | Type is mapped (string/text to string, number, boolean, date). |
| Audience | Contact list | List metadata is created; members are associated in the contacts phase. |
| Topic | Suppression group | Created as an empty group - Resend’s API exposes no per-topic subscription state. |
| Unsubscribed contact | Global suppression entry | Resend has no unsubscribe groups, so unsubscribed contacts are suppressed globally. |
Recommended Flow
Preview the migration
Call
POST /migrations/resend/plan to confirm the Resend key is valid and see what will be migrated.Run the full migration
Call
POST /migrations/resend/migrate with migrateAll: true or with specific IDs you want to import.Endpoints
Get migration plan
Fetches a preview of everything that can be migrated from your Resend account: templates, contact properties (custom fields), audiences, topics, the total contact count, and the count of unsubscribed contacts.POST /v1/migrations/resend/plan
Request body
| Field | Type | Required | Description |
|---|---|---|---|
resendApiKey | string | yes | Your Resend API key |
Response 200
Run the full migration
Kicks off a background migration job that imports the selected Resend assets into your AutoSend project. Returns abulkOperationId immediately; the work continues in the background.
POST /v1/migrations/resend/migrate
Request body
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
resendApiKey | string | yes | - | Your Resend API key |
migrateAll | boolean | no | false | If true, migrate everything returned by /plan. Per-type ID arrays below are populated from the plan when empty. |
templateIds | string[] | no | [] | Specific Resend template IDs to migrate |
audienceIds | string[] | no | [] | Specific Resend audience IDs to migrate (each becomes an AutoSend contact list) |
topicIds | string[] | no | [] | Specific Resend topic IDs to migrate (each becomes an AutoSend suppression group) |
customFieldMappings | object[] | no | [] | Resend to AutoSend custom field mappings (see schema below) |
ignoreTemplates | boolean | no | false | Skip templates phase |
ignoreCustomFields | boolean | no | false | Skip custom fields phase |
ignoreAudiences | boolean | no | false | Skip audiences (contact lists) phase |
ignoreTopics | boolean | no | false | Skip topics (suppression groups) phase |
ignoreContacts | boolean | no | false | Skip contacts phase |
ignoreSuppressions | boolean | no | false | Skip the global unsubscribe (suppression) phase |
customFieldMappings item schema:
fieldType must be one of: string, number, boolean, date.
Migration phases
The job runs in this order:- Custom fields - creates AutoSend custom field definitions from the mappings.
- Templates - fetches each Resend template’s HTML and subject and creates the matching AutoSend template. Templates containing
#eachare flagged for manual review. - Audiences to contact lists - creates the AutoSend list metadata for each audience.
- Contacts - imports all global Resend contacts, then associates each audience’s members with the contact list created in step 3. Contact properties are mapped onto custom fields via
customFieldMappings. - Topics to suppression groups - creates a matching (empty) suppression group for each topic.
- Suppressions - globally suppresses every Resend contact marked as
unsubscribed.
Example A - migrate everything
Example B - migrate selected assets only
Example C - contacts only, skip everything else
Response 202 Accepted
Hold on to the
bulkOperationId. Your AutoSend dashboard shows progress against it, and progress is also published in real time over the project’s Pusher channel as the job moves through each phase.Common errors
| HTTP | Code | Meaning |
|---|---|---|
| 400 | RESEND_MIGRATION_IN_PROGRESS | A migration is already running for this project - wait for it to finish |
| 400 | RESEND_NO_ITEMS_TO_MIGRATE | Nothing selected and migrateAll was not set |
| 500 | RESEND_FAILED_TO_FETCH_PLAN | Resend API key is invalid or rejected |
| 500 | RESEND_MIGRATION_CREATION_FAILED | Could not schedule the migration job - retry shortly |
Migrate one or more templates
Migrate specific Resend templates without touching anything else. Useful for one-off moves or for syncing a template after edits in Resend.POST /v1/migrations/resend/template
Request body
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
resendApiKey | string | yes | - | Your Resend API key |
resendTemplateIds | string[] | yes | - | Resend template IDs to migrate (min 1) |
onExistUpdateHTML | boolean | no | false | If a template with the same ID already exists in AutoSend, overwrite its HTML and subject |
Response 200
FAQ
Is my Resend API key stored anywhere?
Is my Resend API key stored anywhere?
The key is held in memory for the lifetime of the migration request and encrypted at rest while the background job is queued. It is never logged or stored in plaintext.
Why are my topics imported as empty suppression groups?
Why are my topics imported as empty suppression groups?
Resend’s contact object exposes no per-topic subscription state, so the migration can create the group but cannot derive its members from the API. Globally unsubscribed contacts are still captured in the separate suppressions phase.
Can I re-run a migration?
Can I re-run a migration?
Yes. Templates are upserted by their Resend
templateId when onExistUpdateHTML: true. Contacts and suppressed emails are upserted by email address, so duplicates are safe. Re-creating an already-existing custom field will fail that one creation and be reported in the metrics, but the run continues. Only one migration can run per project at a time.How long does it take?
How long does it take?
Templates and topics are usually done in seconds. Contacts depend on how many you have. Resend’s API is rate-limited to roughly 2 requests/second, and the migration spaces requests out and retries on
429 to stay within that limit, so large contact counts take proportionally longer. The request returns immediately - the job keeps running after your HTTP connection closes.How do custom field values get attached to contacts?
How do custom field values get attached to contacts?
During the contacts phase, each Resend contact’s
properties are matched against your customFieldMappings (by resendFieldId, falling back to resendFieldName) and written onto the AutoSend contact’s custom fields. Include the mappings in /migrate (or use migrateAll) to populate them.Support
If a migration fails or produces unexpected results, send us:- The
bulkOperationIdreturned by/migrate - Your AutoSend project ID
- The approximate time of the request
Next Steps
Email Templates
Manage the templates you just migrated from Resend.
Contacts
Browse and segment the contacts imported from Resend.
Unsubscribe Groups
Review the suppression groups created during migration.
Sending Domain
Verify your sending domain so migrated templates can start sending.