Webhooks and Events
Receive signed webhook events from Stafiel.
Use webhooks to receive asynchronous order events from Stafiel. Configure your webhook endpoint in the Merchant Dashboard.
Receiver Endpoint
In the Merchant Dashboard, set a public HTTPS endpoint for Stafiel events. Use a dedicated route so your application can verify the raw request body before any framework middleware modifies it.
Delivery Headers
Stafiel deliveries include these headers:
| Header | Description |
|---|---|
X-Webhook-Signature |
HMAC-SHA256 signature for the raw request body, formatted as sha256=<hex>. |
X-Webhook-Event-Id |
Unique event ID for idempotency and duplicate detection. |
X-Webhook-Event-Type |
Canonical event type, such as order.payment.received_fullpaid. |
X-Webhook-Timestamp |
Delivery timestamp used for replay checks. |
X-Webhook-Delivery-Attempt |
Delivery attempt number for this event. |
X-App-Network |
Event network: mainnet or testnet. |
Signature Verification
Verify the signature against the raw request body. Do not parse the JSON and then
stringify it again before verification. The signature uses HMAC-SHA256 and is
sent in X-Webhook-Signature as sha256=<hex>.
A typical signature verification flow includes:
- Read
X-Webhook-Signatureand validate thesha256=<hex>format. - Verify against the exact raw request body bytes received by your server.
- Compute HMAC-SHA256 with your webhook signing secret and compare the digest using a constant-time comparison.
- Check
X-Webhook-Timestampagainst your replay tolerance before accepting the event.
Webhook Payload Example
{
"event": "order.payment.received_fullpaid",
"eventId": "evt_your_event_id",
"timestamp": "2026-05-19T12:05:00.000Z",
"network": "mainnet",
"data": {
"order": {
"id": "ord_your_order_id",
"merchantId": "mch_your_merchant_id",
"chainId": 8453,
"chainName": "base",
"tokenAddress": "0x...",
"tokenSymbol": "USDC",
"amountUsd": "49.00",
"orderAddress": "0x...",
"status": "fullpaid",
"totalPaidAmountUsd": "49.00",
"expiresAt": "2026-05-19T12:30:00.000Z",
"createdAt": "2026-05-19T12:00:00.000Z",
"metadata": {
"customerReference": "CUS-8842"
}
},
"oldBalance": "0.00",
"newBalance": "49.00",
"delta": "49.00"
}
}
Webhook Payload Fields
| Field | Type | Description |
|---|---|---|
event |
string | Canonical event type. See Event Types. |
eventId |
string | Unique webhook event ID. Use this for idempotency. |
timestamp |
string | ISO 8601 time when the webhook event payload was created. |
network |
string | mainnet or testnet. |
data |
object | Event payload. Order-related events include data.order. Some events also include event-specific objects or fields. |
data.order.id |
string | Stafiel order ID. |
data.order.merchantId |
string | Merchant ID that owns the order. |
data.order.chainId |
number or null | Numeric chain ID when available. |
data.order.chainName |
string or null | Public chain label. |
data.order.tokenAddress |
string or null | Token contract or mint address. |
data.order.tokenSymbol |
string or null | Token symbol. |
data.order.amountUsd |
string or null | Original checkout amount. |
data.order.orderAddress |
string or null | Payment contract or payment address. |
data.order.status |
string | Order status for this event. |
data.order.totalPaidAmountUsd |
string or null | Total recorded payment amount when token decimals are known. |
data.order.expiresAt |
string or null | ISO 8601 expiration timestamp. |
data.order.createdAt |
string or null | ISO 8601 order creation timestamp. |
data.order.metadata |
object or null | Sanitized order metadata. |
Event-specific fields:
| Field | Events | Description |
|---|---|---|
data.oldBalance |
Payment amount change events | Previous detected order balance. |
data.newBalance |
Payment amount change events | New detected order balance. |
data.delta |
Payment amount change events | Balance change amount. |
data.confirmation |
order.payment.confirmed |
Confirmation details, including transaction hash, block number, confirmation count, and confirmation time. |
data.contract |
order.contract.ready |
Contract readiness details, including contract address, transaction hash, and contract status. |
data.settlement |
order.settled |
Settlement details, including merchant amount, platform fee, transaction hash, chain ID, settlement time, and settlement status. |
data.refund |
Refund events | Refund details, including refund type, amount, transaction hash, recipients, chain ID, and notes. |
Webhook payloads can include event context that is not returned by every query API response for the same order. Treat each API chapter's response field table as the contract for that endpoint.
Event Types
Handle event types as exact strings.
| Event Type | When It Is Sent |
|---|---|
order.payment.detected |
Stafiel detects an incoming payment for the order. |
order.payment.received_fullpaid |
Recorded payment reaches the expected order amount. |
order.payment.received_underpaid |
Recorded payment is below the expected order amount. |
order.payment.received_overpaid |
Recorded payment is above the expected order amount. |
order.payment.confirmed |
A recorded payment reaches Stafiel's confirmation threshold. |
order.contract.ready |
The payment contract or payment address is ready. |
order.settled |
Settlement for the order is recorded. |
order.expired |
The order expires before full payment. |
order.closed |
The order is closed. |
order.compliance_hold |
The order is held by risk or compliance controls. |
order.refund.by_merchant |
A merchant refund is recorded. |
order.refund.by_platform |
A platform-initiated refund is recorded. |
Event Handling and Retries
Use eventId for idempotency. A typical receiver returns a 2xx response after
the event has been recorded or identified as already processed.
Failed deliveries are retried, so integrations generally treat webhook delivery as at-least-once and design for duplicate or out-of-order events.