# Webhooks and Events

> Receive signed webhook events from Stafiel.

Canonical: https://stafiel.org/documentation/developer-integration/webhooks-and-events
Version: v1.0.0

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-Signature and validate the sha256=<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-Timestamp against 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](#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.
