{slug}.in.senderkit.email — and you provision addresses on
it from the dashboard or the API. Mail sent to an address is parsed, delivered
to your backend as a message.received webhook, and optionally forwarded to a
real inbox.
How it works
- Create an inbound address from the dashboard or
POST /v1/inbound/addresses. - Point whatever should reach you — a support alias, a reply-to on an outbound email, a webhook endpoint you hand to a third party — at that address.
- When mail arrives, SenderKit parses it and fires a
message.receivedwebhook to every endpoint subscribed to that event (or to one specific endpoint, if the address is bound to it). - Optionally, the address also forwards a copy of the mail to a real inbox.
The shared receiving domain
The first time you create an inbound address, SenderKit provisions{slug}.in.senderkit.email for your workspace automatically — there’s no DNS
to configure, since it’s a domain SenderKit already owns and receives mail on.
To receive on your own domain instead, see Custom domains
below.
Custom domains
Instead of (or alongside) the shared domain, you can claim your own domain to receive mail on — e.g.inbound.acme.com.
Dashboard: open Inbound, and use the domain picker in New address
to add one, or manage existing ones from the domains section at the top of the
page.
API:
records to publish:
- An MX record on the domain, pointing at SenderKit’s inbound mail host — required for every custom domain.
- A DKIM TXT record, proving ownership — only when this domain doesn’t already have a verified custom sending domain on the same workspace. If it does, that identity is reused and the MX is all that’s outstanding.
status from pending to verified — the same polling and
72-hour expiry window as custom sending domains.
A domain that doesn’t verify in time flips to failed and can be re-claimed.
Conflict protection: claiming a domain that already has live MX records
pointing somewhere else — a domain actively receiving mail via Google
Workspace, for example — is rejected with 409 and code existing_mx,
naming the current mail host(s), instead of silently redirecting that
domain’s mail to SenderKit. Confirm you want to proceed, then retry the same
request with "acknowledgeExistingMx": true.
A domain already claimed by another workspace (or already claimed as a
sending domain by a
different workspace) is rejected as domain_claimed. Deleting a custom
domain stops its addresses from receiving mail immediately; the shared
domain can’t be deleted. GET /v1/inbound/domains lists every domain on the
workspace, including the shared one.
Creating an address
Dashboard: open Inbound in the sidebar and click New address. API:- Omit
localPartto get an unguessable generated one (rcv-xxxxxxxxxx) — useful when you’re embedding the address somewhere you don’t want a guessable alias, like a reply-to header on an outbound email. Otherwise it’s 1-64 characters ofa-z,0-9,.,_,-, must start and end alphanumeric, and is lowercased automatically. - Pass
localPart: "*"for a catch-all address that receives mail for every local part on its domain that no exact address already claims — an exact-match address always takes priority over the catch-all, and the catch-all sentinel bypasses the character rules and the reserved-name list. A catch-all counts as one address against the plan cap like any other. domainIdmints the address on a verified custom domain (itsidfromGET /v1/inbound/domains) instead of the shared domain.livemodedefaults totrue. A test-mode address (false) still receives real mail and fans out to test-mode webhook endpoints, but any configuredforwardTois recorded as a test send rather than actually delivered. Every address — test or live — counts the same toward the plan’s inbound address cap below; only messages received on a test-mode address skip the message quota (see Billing).forwardTois optional and forwards a copy of every received message to a real inbox. It can’t point at another inbound address — that’s rejected as a mail loop.webhookEndpointIdoptionally binds the address to one specific webhook endpoint — that endpoint receivesmessage.receivedeven if it isn’t itself subscribed to the event, but it must be active and in the same mode (livemode) as the address. Left unset,message.receivedevents fan out to every active endpoint subscribed to that event in the address’s mode.- A few local parts (
postmaster,abuse,unsubscribe) are reserved and can’t be claimed.
inbound scope.
Reading received mail
GET /v1/inbound/messages lists received-message summaries newest first, with
limit / before pagination and an optional address filter.
GET /v1/inbound/messages/{id} returns the full message — parsed text and
html bodies, from/to/cc, raw headers, a strippedReply (the
plain-text reply with quoted history and signature stripped for reply-parsing
use cases), and scanning verdicts (spam, virus, SPF, DKIM), as reported.
Each message also has a status:
Only
received messages trigger the message.received webhook and any
forward.
Combined text + html body storage is capped at 256 KB; longer messages are
still delivered in full to your webhook endpoint’s payload size limits with
truncated: true set.
Attachments and the raw message
Attachments aren’t stored separately from the original message — fetch one at a time fromGET /v1/inbound/messages/{id}/attachments/{index} (the index
matches attachments[].index on the message), or fetch the full original
message/rfc822 source from GET /v1/inbound/messages/{id}/raw. Both require
the inbound scope and are only available for 30 days after receipt —
afterward they return 410 with code raw_expired.
Billing
A received live message counts against your plan’s monthly message quota, the same pool outbound sends draw from — one received email is one message, just like one outbound send. Test-mode addresses (livemode: false) don’t
consume quota. See Messages → Retention for
how the quota itself is enforced.
Inbound addresses are a separate, smaller plan-limited resource:
Creating an address past your plan’s cap returns
403 with code
plan_limit.
Deleting an address
Deleting an address doesn’t delete its message history — past received messages stay queryable. Mail sent to a deleted address afterward is simply dropped, the same as mail to any other unmatched recipient.Webhooks
Verify signatures and handle the
message.received payload.Authentication
The
inbound API key scope.