ElementsChannel

Receipts

Delivery ledger, seven-state outcomes, consent opt-out, and hard-bounce suppression — process-local by default.

Every Channel send records a receipt — success (sent / fallback), suppression, or a classified failure. Provider bounces and complaints update that ledger through normalized outcomes. There is no oke_receipts SQL table and no fx.channel.getReceipt helper.

For operators watching deliverability — Console projects the ledger; Flows only see send results via fx.send’s { ok: true } gate.

The one rule

Consent and prior hard bounces suppress before any driver runs. Default suppression / consent / receipts stores are process-local memory — inject shared stores for multi-instance, or run a single Channel consumer, until a durable driver ships.

Smallest Example

Send and accept the receipt

const result = await fx.send(noteCreatedMail, {
  to: "alice@example.com",
  data: { id: "n1", title: "Hi" },
});
// result.ok === true on the fx gate when the capability succeeds;
// the runtime ledger still stores status, attempts, and messageId.

Dry-run never contacts a provider and still records would have fired.

Understand statuses

StatusMeaning
sentFirst (or only) attempt succeeded
fallbackAn earlier attempt failed; a later same-medium driver succeeded
suppressed/opted-outConsent store blocked the address
suppressed/prior-bouncePrior hard bounce on the suppression list
failed / opted-outLegacy aliases kept for older callers

Watch the boot warning

oke boot: Channel suppression/consent/receipts default to process-local memory —
opt-out, bounce, and receipt state on one instance is invisible to others.
Inject shared stores for multi-instance, or run a single Channel consumer, until a
durable driver ships.

Progressive Patterns

Opt-out or prior bounce never hits SMTP / SMS:

// Runtime path (not on fx): consent.optOut(subject, medium | "all")
// Next fx.send → receipt status suppressed/opted-out, driverId "suppression", ok: false

Errors on the receipt: "opted out" or "prior hard bounce".

Receipt shape

FieldMeaning
idRuntime receipt id
templateTemplate name
toRecipient
mediumemail · sms · whatsapp · push · …
locale / localeChainResolved locale + chain steps
statusSuccess, legacy, or outcome state
messageIdProvider / runtime message id
driverIdWinning driver (or suppression)
attemptsEvery try (driverId, ok, error, at)
atEpoch ms
errorAggregated attempt errors when failed
StoreRole
ConsentisOptedOut / optOut / optIn / list per subject + medium
SuppressionReasons "opted-out" | "prior-bounce"; checked on every send

Consequence: suppression is not failure — verdict correct for opted-out and prior-bounce rows. Complaints (delivered-then-complained) outrank many hard bounces in consequence weight.

There is no Flow helper to query receipts today — use Console projection or an injected ledger from operator tooling.

Troubleshooting

Learn more

Next

On this page