Build with Sent

This is the production blueprint for integrating SentSent — the opinionated, end-to-end way to architect and ship a real messaging integration, not a pile of disconnected snippets.

Where the Concepts explain what Sent is and the SDK reference documents every method, this section shows you how the pieces fit together into an application you'd be comfortable running in production: how to structure the code, handle credentials safely, send messages, receive and verify webhooks, track delivery, and harden the whole thing before go-live.

The code samples in these pages are written against the current, official Sent SDKs and the v3 API, shown across seven languages (TypeScript, Python, Go, Java, C#, PHP, Ruby) so you can apply the pattern to your stack.

Who this is for

Engineers integrating Sent into a real backend. You know your language and framework; you want the right way to wire Sent in — the architecture, the security boundaries, and the failure modes — without rediscovering them the hard way. Everything is framework-agnostic and shown in multiple languages via tabs; apply the pattern to your stack.

How to read this

The section follows the path you actually build in. Read it straight through the first time, then use it as a reference.

The mental model

A robust Sent integration has two independent flows, and most of this guide is about building each one well:

  • Outbound — your app calls Sent to send templated messages. The work is structuring a thin, testable service layer over the SDK and mapping errors into your own API surface.
  • Inbound — Sent calls you over webhooks as messages progress (sent → delivered → read / failed) and when recipients reply. The work is verifying those requests are authentic, acknowledging fast, and updating your own state idempotently.

In plain English: your app calls Sent to send (top path), and Sent calls your webhook receiver back with delivery events (bottom path) — two separate directions, one shared service layer in between.

Three principles this guide is built on

The API key is a request credential, not config

Build the SDK client per request from an Authorization: Bearer header. Never bake a key into a boot-time singleton or a stored env var. This is the single most common thing to get wrong — see Authentication.

A webhook endpoint is a security boundary

It's a public URL that mutates your state. Verify the signature against the raw body before doing anything else, every time.

Ship stateless

Keep per-request and per-event state out of process memory in production so you can scale horizontally. We show the in-memory pattern, then how to productionize it.

Start small, then scale

This guide shows the full production shape up front so you can see where everything ends up — but that shape is a ceiling, not a floor. If you're shipping a single-tenant app on one instance this week, you don't need Redis, a queue, Kubernetes, or distributed tracing to send a correct first message:

  • One Sent account, no reseller model? The per-request client pattern still applies (see Authentication for exactly what it buys you), but you can skip the multi-tenant reasoning — there's no second tenant to isolate.
  • One running instance? In-memory state for message status, webhook secrets, and idempotency/dedupe keys is fine to start and fine to ship with. Scaling & deployment is what you read before you add a second instance, not before your first deploy.
  • No background jobs yet? The queue-worker patterns in Errors & resilience are for when sends become long-running or bulk — skip them until you actually have a queue.

Everything else — structuring the service layer, verifying webhooks, mapping delivery status — applies from message one and isn't optional.

Next steps

On this page