Migrate from Resend
For teams coming from Resend. Sendoka's email API is deliberately close — most code needs minimal changes, and you pick up SMS + platform mode for free.
Field mapping
| Resend | Sendoka |
|---|---|
POST /emails |
POST /api/v1/emails |
from, to, subject, html, text |
Same |
cc, bcc |
Same |
reply_to |
reply_to |
tags: [{ name, value }] |
tags: [string] + metadata: { ... } |
attachments: [{ filename, content, contentType }] |
attachments: [{ filename, content, content_type }] (snake_case) |
headers: { ... } |
headers: { ... } |
scheduled_at: "in 1 hour" |
scheduled_at: "2026-04-22T11:14:00Z" (ISO UTC, no relative strings) |
Code diff
// Resend
import { Resend } from "resend";
const resend = new Resend(process.env.RESEND_API_KEY);
await resend.emails.send({
from: "you@yourdomain.com",
to: ["user@example.com"],
subject: "Welcome",
html: "<p>Hi</p>",
});
// Sendoka — plain HTTP
await fetch("https://api.sendoka.com/api/v1/emails", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.SENDOKA_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
from: "you@yourdomain.com",
to: ["user@example.com"],
subject: "Welcome",
html: "<p>Hi</p>",
}),
});
What's different
- Snake_case in JSON.
content_type,scheduled_at,reply_to,track_opens,track_clicks. - Tags are strings +
metadataobject, not{ name, value }pairs. Migrate tag names to thetags: string[]array and key-value tags tometadata. - No relative
scheduled_at. Pass absolute ISO UTC. - Idempotency is a header, not a body field:
Idempotency-Key: <uuid>. - Batch endpoint returns per-row
{ index, id, status, error }, not an array of ids. Checkresults[i].status === "sent". - Broadcasts → audiences.
POST /api/v1/audiences+POST /audiences/:id/contacts+POST /audiences/:id/send. - Webhooks are HMAC-signed with
t={unix}, v1={hex}format — verify with your stack's HMAC primitive (Nodecrypto.createHmac, Pythonhmac).
Domain verification
Same mechanism (SES DKIM/SPF). Dashboard → Domains → Add. CNAMEs are in the same format, but you'll need to point them at Sendoka's SES account, not Resend's. Old Resend CNAMEs can be removed after your Sendoka domain verifies.
Keep them both live for a week if you want to do a gradual cutover — send test traffic to Sendoka, compare deliverability, flip the remaining traffic.
What you gain
- SMS.
POST /api/v1/smswith the same key. - Platform mode. Sub-organize your own customers as tenants — isolated suppressions, webhooks, domains.
- Scheduled sends + cancellation.
DELETE /api/v1/emails/:idwhilescheduled. - Per-key rate limits + IP CIDR allowlists.
- Audit log of key/domain/webhook changes.
Gotchas
- React Email templates work unchanged — render to HTML string on your side, pass as
html. - Idempotency window is 24h — Resend's is 6h. Replays from that gap are now safe.
- Webhook retry is exponential backoff, max 5 attempts — matches Resend's envelope.