Registering an endpoint
An org admin registers the endpoint in the Jenzy portal (Integration settings): one HTTPS URL, one active endpoint per org. Registration mints a signing secret (whsec_…), shown exactly once — store it beside your API key. Replacing the endpoint mints a new secret; deliveries already in flight keep using the old one until they finish, so verify against both secrets while a rotation is in progress.
The event envelope
Every delivery is a JSON POST with the same envelope:id— your dedupe handle. Delivery is at-least-once: the same event can arrive more than once, and events can arrive out of order. Process eachidonce and ignore repeats.balance— a convenience snapshot of your balance as of when the event was prepared. Never do balance math off webhooks — events can arrive out of order;GET /balanceis the authoritative read.data— the resource, rendered byte-identically to the corresponding/v1read endpoint.
Event catalog
| Event | When | data |
|---|---|---|
payout.succeeded | A payout reached its terminal success state. | The payout, as GET /payouts/{id} renders it. |
payout.failed | A payout failed; its hold is already released. | The payout, with failure: { code, message } set — see failure codes. |
trade.settled | An OTC funding trade landed; your balance is credited. | The trade, as GET /trades renders it. |
balance.low | Your available balance is below your configured floor. At most one per cooldown window while the condition holds; no recovery event. | { "balance": …, "floor_mwk": … } |
Verifying signatures
Every delivery carries aSignature header: HMAC-SHA256 of the exact raw request body, keyed with your signing secret, hex-encoded. There are no timestamp headers and nothing else to canonicalize — sign the bytes you received, compare in constant time.
Node.js (Express)
Delivery semantics
- Only a 2xx response counts as delivered. Redirects are failures and are never followed. Respond quickly (within 10 seconds) and do real work asynchronously.
- A failed delivery is re-attempted 5 times over ~6 hours, front-loaded. Every attempt sends the identical bytes — the payload is snapshotted when the event occurs, so the signature stays valid across attempts.
- After the last failed attempt the delivery is dead-lettered and Jenzy ops are alerted; it is never auto-revived. If you missed events during an outage, contact Jenzy to arrange re-delivery — and reconcile against
GET /payoutsin the meantime (polling and webhooks carry the same data, so the list endpoint is always a valid catch-up path).