Getting started

Migrate from Resend

Point your existing Resend code at Sooner by changing the base URL and API key, and see what is compatible and what is not yet supported.

Sooner implements Resend's REST API with the same paths, field names, response shapes, error names and webhook signatures. For most code, migrating means changing two values.

Change the base URL and key

Set your environment variables:

Shell
RESEND_API_KEY=sn_your_sooner_key
RESEND_BASE_URL=https://api.sooner.dev

Or pass the base URL when you create the client:

TypeScript
import { Resend } from "resend";

const resend = new Resend(process.env.SOONER_API_KEY, { baseUrl: "https://api.sooner.dev" });

Your calls stay the same:

TypeScript
await resend.emails.send({
  from: "Acme <hi@acme.com>",
  to: ["you@example.com"],
  subject: "Welcome",
  html: "<p>Thanks for signing up</p>",
});

Over plain HTTP, replace https://api.resend.com with https://api.sooner.dev and keep the rest of the request.

What is compatible

  • Paths and methods for emails, batch, domains, API keys, contacts, segments, topics, contact properties, broadcasts, templates, suppressions and webhooks. The older /audiences paths also work and return the same data as /segments, with object set to audience.
  • Field names, including both snake_case and camelCase spellings where Resend accepts them: reply_to or replyTo, scheduled_at or scheduledAt, topic_id or topicId. Broadcasts accept audience_id as an alias of segment_id.
  • Error bodies: { "statusCode", "message", "name" }, with Resend's error names. See Errors.
  • Idempotency: the Idempotency-Key header on send and batch. See Idempotency.
  • Scheduling: ISO 8601 or natural language such as in 1 hour. See Scheduling.
  • Pagination: limit and after, with has_more. See Pagination.
  • Webhook signatures: Svix-compatible headers and whsec_ secrets. See Verify signatures.
  • Template variables: the {{{NAME}}} and {{{NAME|fallback}}} syntax, and broadcast variables such as FIRST_NAME and RESEND_UNSUBSCRIBE_URL.

What is different

AreaSooner behavior
API keysPrefix is sn_, and keys belong to one project.
IDsIDs are opaque strings. Do not parse them or assume a length.
react fieldSooner does not render React on the server. The Resend SDK renders react to HTML in your process before sending, so it works through the SDK. Raw HTTP callers must send html or text.
AttachmentsInline (base64) content is limited to 4 MB per request. Pass larger files by URL with path. Batch emails cannot have attachments. See Attachments.
Rate limitsThe limit is per team and depends on your plan, from 10 to 1,000 requests per second. See Rate limits.
Restricted keysA sending_access key can only call POST /emails and POST /emails/batch. Everything else returns 401 restricted_api_key.
Deleting an API keyDELETE /api-keys/{id} returns 200 with an empty body.
Webhook eventsSooner adds contact.created, contact.updated, contact.deleted, domain.verified and domain.failed. See Event types.
UsageGET /usage is a Sooner endpoint that returns your quota and usage. See Usage.
Deleting from a segmentDELETE /segments/{id}/contacts/{identifier} deletes the contact. To only remove a contact from a segment, use DELETE /contacts/{identifier}/segments/{segmentId}.

Not supported

Do not rely on these. They are not available in Sooner today:

  • Automations and custom events
  • Inbound (receiving) email and inboxes
  • CSV contact imports
  • A logs endpoint
  • An SMTP relay
  • Server-side rendering of the react field
  • Email and password sign-in to the dashboard (sign-in is with GitHub or Google)

Migration checklist

  1. Create a Sooner account and a project for each product you want to separate.
  2. Add and verify each sending domain in Sooner. The DNS records are specific to Sooner, so add them in addition to your existing records, and switch your sending when the domain shows as verified. A domain can only be registered by one team on Sooner.
  3. Create API keys. Use sending_access keys for application servers that only send email, and optionally restrict a key to one domain.
  4. Recreate your webhook endpoints. Each endpoint gets a new signing secret, so update the secret in your handler. See Webhooks.
  5. Recreate templates, topics, segments and contact properties through the API or the dashboard, then add your contacts with POST /contacts. There is no CSV import.
  6. Swap the base URL and key in a staging environment, send a test email, and check it in the dashboard under Emails.
  7. Roll out to production.