When events fire
| Event | Trigger |
|---|---|
operation_created | A successful POST /v1/request-money that persists a remittance for your partner. |
operation_updated | A successful internal status update (PATCH /v1/internal/remittances/status) for one of your remittances. |
operation_error | Any error raised while handling POST /v1/request-money or the internal status update for your partner — validation failures, OFAC screening blocks, downstream identity-validator outages, missing remittances, etc. |
operation_error events are emitted in addition to whatever HTTP error your client receives synchronously, so background systems that only consume webhooks can still react to failed flows.
Configuring the endpoint
Pick an HTTPS URL
The endpoint must speak HTTPS and accept
POST with a JSON body. Plain http:// values are rejected by the partner portal.Save the URL and a signing secret
Paste your endpoint into Webhook URL. Generate a high-entropy secret (at least 8 characters) and paste it into Webhook secret. The portal stores the secret encrypted; rotating it later is a matter of overwriting the value or clearing it.
Payload envelope
Every event uses the same envelope. Thedata object’s shape depends on event — see Events catalog.
| Field | Type | Description |
|---|---|---|
event | string | One of operation_created, operation_updated, operation_error. |
data | object | Event-specific payload. See Events catalog. |
timestamp | string | ISO 8601 UTC instant the event was enqueued. Frozen at enqueue time, not updated on retries. |
Headers
Every delivery sets these headers:| Header | Purpose |
|---|---|
Content-Type | Always application/json. |
X-Webhook-Event | Mirror of payload.event so you can route on a header before parsing JSON. |
X-Webhook-Delivery-Id | Stable UUID per event. Identical across retries — use it for idempotency. |
X-Webhook-Signature | HMAC-SHA256 signature in the form t=<unix>,v1=<hex>. Present whenever a webhook secret is configured. |
Verifying the signature
TheX-Webhook-Signature header is computed as:
t is the Unix timestamp (seconds) the dispatcher signed the request, secret is the value you configured in Settings → Webhooks, and rawBody is the exact bytes of the JSON payload as received (do not pretty-print or re-serialize before hashing).
Delivery, retries, and dead-lettering
- The API persists every event in an outbox before the source request returns to the client, so you do not miss callbacks if your endpoint is briefly unavailable.
- A worker drains the outbox every 30 seconds and POSTs each due event with a 10-second timeout.
- Any non-2xx response, network failure, or timeout schedules a retry with exponential backoff: 1 minute, 5 minutes, 30 minutes, 2 hours, 12 hours.
- After 5 failed attempts the event moves to a dead-letter state and is no longer retried automatically. Operators can replay it from the database; partners receive no further deliveries for that event.
- Successful deliveries (any 2xx) finalize the event and remove it from the active queue.
Idempotency
UseX-Webhook-Delivery-Id to deduplicate. The same deliveryId can be retried up to five times — your handler must be safe to invoke more than once for the same id (for example, by storing processed ids and short-circuiting).
Configuration freezing
When an event is enqueued, the dispatcher captures the partner’swebhookUrl and webhookSecret at that exact moment. Changing the configuration afterward only affects events enqueued after the change; in-flight retries continue to target the URL and signature key that were active when the source operation occurred. This keeps replays consistent and avoids signing old payloads with new secrets.
Troubleshooting
| Symptom | Likely cause |
|---|---|
| No events arrive | webhookUrl is empty in Settings → Webhooks, or the URL is not HTTPS. |
Receive 401/403 from your endpoint then no more retries after a few hours | The dispatcher exhausted the 5 retries; the event is in dead_letter. |
| Signature does not match | Body was re-serialized before hashing. Always verify against the raw bytes received. |
| Duplicate processing on your side | X-Webhook-Delivery-Id was not used for deduplication; retries reuse the same id. |