Developers · Events & webhooks

Events & webhooks

Digital Treasury pushes an event to your endpoint whenever something happens to money you're moving. Every delivery is a signed JSON envelope, sent at-least-once from a durable outbox — so your handler must verify the signature and dedupe on the event id.

The envelope

Every event — whatever its type — arrives in the same envelope. The type tells you what happened; data is the resource in the same shape the REST API returns it.

Shape

{ "id": "evt_1f4c…",
  "type": "payment_order.completed",
  "created_at": "2026-07-27T14:03:11Z",
  "data": { /* the resource */ } }

Headers

POST /your/endpoint
Content-Type: application/json
X-DigitalTreasury-Signature: 9f86d08…
X-DigitalTreasury-Event: payment_order.completed
X-DigitalTreasury-Delivery: 1

The signature is HMAC-SHA256 over the raw body. During a secret rotation the header carries several comma-separated signatures — accept if any matches.

Event catalogue

The events shipping on /v1 today. Vertical-specific events (for example fuel-tax remittances) only reach tenants on that vertical.

Payment orders

EventFires whendata
payment_order.pendingAn order passed risk/approval and was submitted to a rail — it's now in flight.PaymentOrder
payment_order.completedThe rail settled the payment. Terminal — funds moved.PaymentOrder
payment_order.failedThe order was declined — risk decline, validation failure, or a rail rejection before settlement.PaymentOrder + failureReason
payment_order.returnedThe payment settled and was later returned by the receiving bank (e.g. ACH R01/R03).PaymentOrder + returnCode
payment_order.cancelledA not-yet-submitted order was cancelled via the API or the console.PaymentOrder

Check deposits

EventFires whendata
check_deposit.postedA remotely-deposited check cleared and the funds posted to the ledger account.CheckDeposit
check_deposit.rejectedThe deposit was rejected — unreadable image, amount mismatch, or a return.CheckDeposit + reason

Fuel-tax remittances Fuelry vertical

EventFires whendata
fuel_tax.remittance_clearedA scheduled IFTA/fuel-tax remittance settled with the jurisdiction.Remittance
fuel_tax.remittance_returnedA remittance was returned unpaid and needs to be re-originated.Remittance + returnCode

Testing

EventFires whendata
webhook.testYou trigger a test delivery from the console — a real signed delivery to confirm your endpoint before go-live.{ message }

Delivery & retries

At-least-once

A retry or replay reuses the same id. Deduplicate on it and make your handler idempotent — never assume exactly-once.

Backoff & dead-letter

Respond 2xx to acknowledge. Anything else is retried with backoff (1m, 5m, 30m) and dead-lettered after three attempts.

Replay

Dead-lettered events can be replayed from the console once your endpoint is healthy — no event is ever silently dropped.

Verifying signatures

Full HMAC verification code in Node, Python and C#, plus how lossless secret rotation works, lives in the API reference. Verify the signature before you trust the body.