POST to your endpoint the moment it happens, and your app does the corresponding work in your own system: credit a balance, unlock a feature, notify a user, reconcile an order.
The key mental model: a webhook is the trigger for a state change in your product. You don’t poll Etherfuse asking “is it done yet?” — you let the event tell you, then act on the status in the payload.
Webhooks vs. polling. Webhooks fire the instant a state changes. Polling the list endpoints is slower (newly created orders take a moment to index) and wasteful (most requests return “no change”). Use webhooks for anything time-sensitive.
What to do on each event
This is the part most integrations care about: when event X arrives, what should your app do? Each flow below maps the lifecycle to the actions you take in your own system.Onramp — customer buys tokens with MXN
Onramp — customer buys tokens with MXN
Subscribe to
order_updated.Offramp — customer sells tokens for MXN
Offramp — customer sells tokens for MXN
Subscribe to
order_updated.Swap — token to token
Swap — token to token
Subscribe to
swap_updated.Reading the payload (not the status sequence):
sendTransaction is always present in the payload. It contains the transaction the customer needs to sign and submit — once signed, the field remains but is no longer actionable. On completion you get two hashes: sendTransactionHash (the customer’s send to Etherfuse) and receiveTransactionHash (Etherfuse’s delivery to the wallet). Which intermediate statuses fire varies by chain (some emit a distinct funds_received update, others don’t), so key your logic off the fields present in the payload rather than expecting a particular status to arrive.Onboarding & compliance — KYC, KYB, bank accounts
Onboarding & compliance — KYC, KYB, bank accounts
Subscribe to
kyc_updated, customer_updated, and bank_account_updated.Gating access on these events is the most common compliance pattern: don’t let a customer onramp, offramp, or swap until you’ve received
kyc_approved (or customer_verified) for them.How delivery works
1
Register an endpoint
Call POST /ramp/webhook with your HTTPS URL and the event type. The response includes a signing
secret, returned only once — store it securely.2
Receive the event
When the event fires, Etherfuse sends a
POST with the JSON payload to your URL, plus an X-Signature header.3
Verify the signature
Recompute the HMAC-SHA256 signature with your secret and compare. See Verifying Webhooks for Node and Python code.
4
Respond 2xx, then do the work
Acknowledge with a
2xx immediately, then run your business logic asynchronously. A slow handler triggers unnecessary retries.Event types
Payloads
Every webhook payload is a JSON object with a single key matching the event type; the value is the entity that changed, signed with your webhook secret (see Verifying Webhooks). The full schema and a worked example for each event live on its reference page, linked from the Event types table above. Fields are omitted whennull or not applicable to the entity’s current state, so drive your logic off the fields present in the payload rather than expecting a fixed shape. A few specifics worth calling out:
order_updatedcarriesburnTransaction,depositClabe, andconfirmedTxSignatureonly when relevant to the order type and status. For embedded (non-custodial) wallets it also carries the pendingapprovalobject (approvalMessageId,approvalMessage,summary) while the order awaits the owner’s signature; there is no separate embedded-wallet transaction event. Re-read the order right before signing so theapprovalMessagetimestamp is fresh.swap_updated—sendTransactionis always present (the transaction to sign; it stays in the payload but is no longer actionable once signed);receiveTransactionHashappears only on completion.bank_account_updated: the bank is usable once its status isactive; earlier statuses (bank_account_pending,bank_account_awaiting_deposit_verification) mean the SPEI provider hasn’t accepted it yet (see Bank account status).kyc_updated— on approval,approvedistrueandupdateReason/needsWork/userMessageare omitted.kyb_updatedcarries the business’sorganizationIdandstatus. It fires only when the status actually changes, never on individual answer edits. Theapproved/submitted/notStarted/totalcounts cover the customer-facing requirements only, andapprovedAtis set once the business is approved.
Reliability & best practices
- Retries. Failed deliveries (a non-
2xxresponse or connection error) are retried up to 3 times with 5-second delays. Return a2xxpromptly to avoid them. - Acknowledge fast, process async. Hand the payload to a queue and return
2xxright away; don’t block the response on downstream work. - Handle events idempotently. The same event can arrive more than once (e.g. a retry after your
2xxwas lost). Dedupe on the resource ID plus its status so reprocessing is harmless — this pairs naturally with the client-generated UUIDs you already use for orders. - Don’t rely on ordering. Drive your logic off the
statusin the payload, not the order in which deliveries arrive. - Expose a public HTTPS endpoint. For local development, use a tunnel such as ngrok so Etherfuse can reach your handler.
Verifying signatures
Every delivery is signed so you can confirm it’s authentic:X-Signature: sha256={hex}, computed as HMAC-SHA256 over the RFC 8785-canonicalized JSON body using your webhook secret. Full walkthrough with Node/Python code: Verifying Webhooks.
Managing webhooks
- Create a subscription —
POST /ramp/webhook(returns the one-time secret) - List subscriptions —
POST /ramp/webhooks - Get a subscription —
GET /ramp/webhook/{id} - Delete a subscription —
DELETE /ramp/webhook/{id}
If a transaction expires before the customer signs it, fetch a fresh one with POST /ramp/order/{id}/regenerate_tx or POST /ramp/swap/{id}/regenerate_tx.