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.devOr 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
/audiencespaths also work and return the same data as/segments, withobjectset toaudience. - Field names, including both
snake_caseandcamelCasespellings where Resend accepts them:reply_toorreplyTo,scheduled_atorscheduledAt,topic_idortopicId. Broadcasts acceptaudience_idas an alias ofsegment_id. - Error bodies:
{ "statusCode", "message", "name" }, with Resend's error names. See Errors. - Idempotency: the
Idempotency-Keyheader on send and batch. See Idempotency. - Scheduling: ISO 8601 or natural language such as
in 1 hour. See Scheduling. - Pagination:
limitandafter, withhas_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 asFIRST_NAMEandRESEND_UNSUBSCRIBE_URL.
What is different
| Area | Sooner behavior |
|---|---|
| API keys | Prefix is sn_, and keys belong to one project. |
| IDs | IDs are opaque strings. Do not parse them or assume a length. |
react field | Sooner 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. |
| Attachments | Inline (base64) content is limited to 4 MB per request. Pass larger files by URL with path. Batch emails cannot have attachments. See Attachments. |
| Rate limits | The limit is per team and depends on your plan, from 10 to 1,000 requests per second. See Rate limits. |
| Restricted keys | A sending_access key can only call POST /emails and POST /emails/batch. Everything else returns 401 restricted_api_key. |
| Deleting an API key | DELETE /api-keys/{id} returns 200 with an empty body. |
| Webhook events | Sooner adds contact.created, contact.updated, contact.deleted, domain.verified and domain.failed. See Event types. |
| Usage | GET /usage is a Sooner endpoint that returns your quota and usage. See Usage. |
| Deleting from a segment | DELETE /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
reactfield - Email and password sign-in to the dashboard (sign-in is with GitHub or Google)
Migration checklist
- Create a Sooner account and a project for each product you want to separate.
- 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.
- Create API keys. Use
sending_accesskeys for application servers that only send email, and optionally restrict a key to one domain. - Recreate your webhook endpoints. Each endpoint gets a new signing secret, so update the secret in your handler. See Webhooks.
- 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. - Swap the base URL and key in a staging environment, send a test email, and check it in the dashboard under Emails.
- Roll out to production.