Skip to main content

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
All endpoints are authenticated with your AutoSend project API key sent as a Bearer token. The Resend API key required to read from your Resend account is passed in the request body for each call. It is never persisted in plaintext - it is encrypted while the background job is queued.

Prerequisites

Before you start, make sure you have:
  1. An AutoSend project API key - create one on the API Keys page. Keys look like AS_xxxxxxxx_xxxxxxxxxxxxxxxxxxxx.
  2. 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.
  3. The base URL for all requests: https://api.autosend.com/v1

Authentication

Every request uses two headers:
HeaderValue
AuthorizationBearer <YOUR_AUTOSEND_API_KEY>
Content-Typeapplication/json

How Resend Maps to AutoSend

Resend and AutoSend model their assets a little differently. The migration applies these mappings:
ResendAutoSendNotes
TemplateTemplateHTML, subject, and name are migrated. Templates using #each are flagged for review.
Contact propertyCustom fieldType is mapped (string/text to string, number, boolean, date).
AudienceContact listList metadata is created; members are associated in the contacts phase.
TopicSuppression groupCreated as an empty group - Resend’s API exposes no per-topic subscription state.
Unsubscribed contactGlobal suppression entryResend has no unsubscribe groups, so unsubscribed contacts are suppressed globally.
1

Preview the migration

Call POST /migrations/resend/plan to confirm the Resend key is valid and see what will be migrated.
2

Run the full migration

Call POST /migrations/resend/migrate with migrateAll: true or with specific IDs you want to import.
3

Or run a targeted migration

Use POST /migrations/resend/template to migrate selected templates only.

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

FieldTypeRequiredDescription
resendApiKeystringyesYour Resend API key
curl --request POST \
  --url https://api.autosend.com/v1/migrations/resend/plan \
  --header 'Authorization: Bearer AS_YOUR_AUTOSEND_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
    "resendApiKey": "re_your_resend_api_key"
  }'

Response 200

{
  "success": true,
  "message": "Migration plan fetched successfully",
  "data": {
    "contactsCount": 12453,
    "unsubscribedCount": 87,
    "templatesCount": 24,
    "templates": [
      {
        "templateId": "tmpl_abc123",
        "templateName": "Welcome email",
        "status": "active",
        "updatedAt": "2025-08-12T10:24:11Z"
      }
    ],
    "customFields": [
      {
        "resendFieldId": "1",
        "resendFieldName": "company",
        "autosendFieldName": "company",
        "fieldType": "string"
      }
    ],
    "audiences": [
      {
        "id": "aud-uuid-1",
        "name": "Newsletter subscribers"
      }
    ],
    "audiencesCount": 5,
    "topics": [
      {
        "id": "topic-uuid-1",
        "name": "Product updates",
        "description": "Monthly product newsletter",
        "defaultSubscription": "opt_in",
        "visibility": "public"
      }
    ],
    "topicsCount": 3
  }
}

Run the full migration

Kicks off a background migration job that imports the selected Resend assets into your AutoSend project. Returns a bulkOperationId immediately; the work continues in the background. POST /v1/migrations/resend/migrate

Request body

FieldTypeRequiredDefaultDescription
resendApiKeystringyes-Your Resend API key
migrateAllbooleannofalseIf true, migrate everything returned by /plan. Per-type ID arrays below are populated from the plan when empty.
templateIdsstring[]no[]Specific Resend template IDs to migrate
audienceIdsstring[]no[]Specific Resend audience IDs to migrate (each becomes an AutoSend contact list)
topicIdsstring[]no[]Specific Resend topic IDs to migrate (each becomes an AutoSend suppression group)
customFieldMappingsobject[]no[]Resend to AutoSend custom field mappings (see schema below)
ignoreTemplatesbooleannofalseSkip templates phase
ignoreCustomFieldsbooleannofalseSkip custom fields phase
ignoreAudiencesbooleannofalseSkip audiences (contact lists) phase
ignoreTopicsbooleannofalseSkip topics (suppression groups) phase
ignoreContactsbooleannofalseSkip contacts phase
ignoreSuppressionsbooleannofalseSkip the global unsubscribe (suppression) phase
customFieldMappings item schema:
{
  "resendFieldId": "1",
  "resendFieldName": "company",
  "autosendFieldName": "company",
  "fieldType": "string"
}
fieldType must be one of: string, number, boolean, date.

Migration phases

The job runs in this order:
  1. Custom fields - creates AutoSend custom field definitions from the mappings.
  2. Templates - fetches each Resend template’s HTML and subject and creates the matching AutoSend template. Templates containing #each are flagged for manual review.
  3. Audiences to contact lists - creates the AutoSend list metadata for each audience.
  4. 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.
  5. Topics to suppression groups - creates a matching (empty) suppression group for each topic.
  6. Suppressions - globally suppresses every Resend contact marked as unsubscribed.

Example A - migrate everything

curl --request POST \
  --url https://api.autosend.com/v1/migrations/resend/migrate \
  --header 'Authorization: Bearer AS_YOUR_AUTOSEND_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
    "resendApiKey": "re_your_resend_api_key",
    "migrateAll": true
  }'

Example B - migrate selected assets only

curl --request POST \
  --url https://api.autosend.com/v1/migrations/resend/migrate \
  --header 'Authorization: Bearer AS_YOUR_AUTOSEND_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
    "resendApiKey": "re_your_resend_api_key",
    "templateIds": ["tmpl_abc123", "tmpl_def456"],
    "audienceIds": ["aud-uuid-1"],
    "customFieldMappings": [
      {
        "resendFieldId": "1",
        "resendFieldName": "company",
        "autosendFieldName": "company",
        "fieldType": "string"
      }
    ],
    "ignoreTopics": true
  }'

Example C - contacts only, skip everything else

curl --request POST \
  --url https://api.autosend.com/v1/migrations/resend/migrate \
  --header 'Authorization: Bearer AS_YOUR_AUTOSEND_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
    "resendApiKey": "re_your_resend_api_key",
    "migrateAll": true,
    "ignoreTemplates": true,
    "ignoreCustomFields": true,
    "ignoreAudiences": true,
    "ignoreTopics": true,
    "ignoreSuppressions": true
  }'

Response 202 Accepted

{
  "success": true,
  "message": "Resend migration initiated successfully",
  "data": {
    "bulkOperationId": "65fa1d2b8c9a4f1234567890",
    "status": "PENDING",
    "message": "Resend migration initiated successfully"
  }
}
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

HTTPCodeMeaning
400RESEND_MIGRATION_IN_PROGRESSA migration is already running for this project - wait for it to finish
400RESEND_NO_ITEMS_TO_MIGRATENothing selected and migrateAll was not set
500RESEND_FAILED_TO_FETCH_PLANResend API key is invalid or rejected
500RESEND_MIGRATION_CREATION_FAILEDCould 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.
Always test migrated templates that contain complex Handlebars expressions such as #each before sending production traffic to them.
POST /v1/migrations/resend/template

Request body

FieldTypeRequiredDefaultDescription
resendApiKeystringyes-Your Resend API key
resendTemplateIdsstring[]yes-Resend template IDs to migrate (min 1)
onExistUpdateHTMLbooleannofalseIf a template with the same ID already exists in AutoSend, overwrite its HTML and subject
curl --request POST \
  --url https://api.autosend.com/v1/migrations/resend/template \
  --header 'Authorization: Bearer AS_YOUR_AUTOSEND_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
    "resendApiKey": "re_your_resend_api_key",
    "resendTemplateIds": ["tmpl_abc123", "tmpl_def456"],
    "onExistUpdateHTML": true
  }'

Response 200

{
  "success": true,
  "message": "Template migrated successfully",
  "data": [
    {
      "templateId": "tmpl_abc123",
      "templateName": "Welcome email",
      "subject": "Welcome to Acme",
      "templateType": "TRANSACTIONAL",
      "createdAt": "2026-05-14T08:12:11.234Z"
    }
  ]
}

FAQ

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.
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.
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.
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.
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:
  1. The bulkOperationId returned by /migrate
  2. Your AutoSend project ID
  3. The approximate time of the request
Email [email protected] with these details and we’ll investigate.

Next Steps

https://mintcdn.com/autosend-13920f5c/nx_wYfWx3qeZwg1C/icons/email-templates.svg?fit=max&auto=format&n=nx_wYfWx3qeZwg1C&q=85&s=461e1cf135b49bcb45ed4373269d54b9

Email Templates

Manage the templates you just migrated from Resend.
https://mintcdn.com/autosend-13920f5c/nx_wYfWx3qeZwg1C/icons/contacts.svg?fit=max&auto=format&n=nx_wYfWx3qeZwg1C&q=85&s=93b686fb3cb253812d2ab70168336374

Contacts

Browse and segment the contacts imported from Resend.
https://mintlify.s3.us-west-1.amazonaws.com/autosend-13920f5c/icons/unsubscribe-groups.svg

Unsubscribe Groups

Review the suppression groups created during migration.
https://mintcdn.com/autosend-13920f5c/nx_wYfWx3qeZwg1C/icons/domain.svg?fit=max&auto=format&n=nx_wYfWx3qeZwg1C&q=85&s=9393f9f9b0f7029e6ba8acf2bc09d864

Sending Domain

Verify your sending domain so migrated templates can start sending.