Webhooks and Events

Receive signed webhook events from Stafiel.

Receive signed, asynchronous order events from Stafiel at your HTTPS endpoint.

Configure the Endpoint

In the Merchant Dashboard, open **Merchants > select merchant > Merchant Settings

Webhook Configuration**. Save a public HTTPS endpoint. The signing secret is generated on first save and shown in the same section.

Delivery Headers

Every webhook delivery includes the following headers:

Header Description
X-Webhook-Signature HMAC-SHA256 signature for the raw request body, formatted as sha256=<hex>.
X-Webhook-Event-Id Event ID within the network identified by X-App-Network.
X-Webhook-Event-Type Canonical event type, such as order.payment.received_fullpaid.
X-Webhook-Timestamp Delivery-attempt time as a Unix timestamp in milliseconds, for example 1782777600000.
X-Webhook-Delivery-Attempt Delivery attempt number for this event, starting at 1.
X-App-Network Event network: mainnet or testnet.

Signature Verification

X-Webhook-Signature authenticates the exact raw request body. Verify it before parsing the JSON. Compute HMAC-SHA256 with your webhook signing secret and compare the result using a constant-time comparison.

After verification, require every listed header and confirm that X-Webhook-Event-Id, X-Webhook-Event-Type, and X-App-Network match the payload. Reject missing, malformed, or mismatched values.

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.after_sales.available After-sales functionality becomes available for the order.
order.expired The order enters the expired state.
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 completed.
order.refund.by_platform A platform-initiated refund is completed.

For payment stages and merchant handling guidance, see Payment Flow and Order Lifecycle and Payment Status.

Webhook Payload Example

{
  "event": "order.payment.received_fullpaid",
  "eventId": "wh_your_event_id",
  "timestamp": "2026-06-30T00:00:00.000Z",
  "network": "mainnet",
  "data": {
    "order": {
      "id": "ord_your_order_id",
      "merchantId": "mch_your_merchant_id",
      "chainId": 8453,
      "chainName": "base-main",
      "tokenAddress": "0x...",
      "tokenSymbol": "USDC",
      "amountUsd": "49.00",
      "orderAddress": "0x...",
      "status": "fullpaid",
      "totalPaidAmountUsd": "49.00",
      "expiresAt": "2026-06-30T00:15:00.000Z",
      "createdAt": "2026-06-29T23:30: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 Event ID within the payload's network.
timestamp string Event creation time in ISO 8601 format, for example 2026-06-30T00:00:00.000Z.
network string mainnet or testnet.
data object Contains data.order and any applicable conditional fields listed below.
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 Normalized chain name, such as base-main, solana-main, or bsc-testnet.
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.

Conditional Payload Fields

These fields are included only for the listed events:

Field Events Description
data.oldBalance, data.newBalance, data.delta order.payment.detected, order.payment.received_fullpaid, order.payment.received_underpaid, order.payment.received_overpaid; also order.expired when a recorded balance is available Previous balance, current balance, and balance change as decimal strings.
data.confirmation order.payment.confirmed Contains transactionHash, blockNumber, confirmationCount, and confirmedAt.
data.contract order.after_sales.available Contains contractAddress, transactionHash, and contractStatus.
data.refund order.refund.by_merchant, order.refund.by_platform Contains refundType, refundAmountUsd, transactionHash, recipients, chainId, and notes.

Acknowledgement and Retries

Return a 2xx response after durably accepting the event; no response body is required. Redirects are not followed. Redirects, non-2xx responses, timeouts, and connection failures are retried.

Use (network, eventId) as the durable idempotency key. Apply each event once and return 2xx for duplicates. A retry keeps the same signed payload and eventId; X-Webhook-Delivery-Attempt increases and X-Webhook-Timestamp records the new delivery time. Verify every delivery independently.

Events may be duplicated, delayed, or delivered out of order. Process each event against the current order state.