@drin00/sdk. It mirrors the wire contract one-to-one, so anything you can do over REST you can do here with types and autocomplete.
Requirements. Node.js 20+ and, for types, TypeScript 5.6+. The SDK ships ESM with bundled type declarations — no extra
@types package needed.Install
Create a client
Construct one client and reuse it. The only required option isapiKey; pass sender only when you authenticate with an account-wide key (see Authentication).
create / get / list / delete methods as appropriate:
emails·domains·inboxes·threads·inbound·webhookssuppressions·contacts·templates·apiKeys·metrics
Send
emails.send() resolves to { id } — the message id you can use to retrieve status or reply later.
domains.listVerified() convenience — it auto-pages and returns only the domains a from address may use:
Idempotent sends. Pass an idempotency key as the second argument —
drin.emails.send(body, { idempotencyKey: "order-42" }) — to make a retry safe. See Idempotency & retries.Paginate
Every list endpoint returns{ data, nextCursor }. The easiest way to walk all of it is .paginate(), an async iterator that fetches each page lazily and stops when nextCursor is null — re-using whatever filter you passed:
.list() and thread the cursor:
paginate() is available on emails, domains, threads, contacts, suppressions, templates, webhooks, and apiKeys.
Receive & reply
Inbound mail lands on an inbox and is joined into a thread alongside your outbound messages. Reply in one call — Drin handles the addressing and the threading headers:Verify a webhook
webhooks.verify() is a pure, local check — no network call. Pass the raw request body (the exact bytes you received, before any JSON parsing) and the Drin-Signature header. It returns the typed payload on success and throws DrinWebhookVerificationError on any mismatch.
Typed errors
Every failure is a subclass ofDrinError, so you can branch with instanceof or on err.type. The base carries type, status, requestId, and (when present) param.
429 and 5xx with exponential backoff and full jitter (default 2 retries). A POST is retried only when you supplied an idempotency key, so a send is never duplicated. See Errors for the full type table.
React Email helper
If you author emails with React Email, render and send in one step with the optional helper exported from@drin00/sdk/react-email. It generates a plain-text alternative by default for deliverability.
Optional peer dependency. The helper imports
@react-email/render lazily. Install it (npm i @react-email/render) or pass an explicit render function — the core SDK never forces a React toolchain on anyone who doesn’t need it.Next steps
API reference
Every endpoint, parameter, and response shape the SDK wraps.
Other languages
No TypeScript? Call the same REST API from any stack.
Authentication
Project-scoped vs account-wide keys, and the
sender option.Webhooks
Subscribe to delivery, bounce, complaint, open, and click events.
