انتقل إلى المحتوى
EXZIX

Webhooks

Webhooks are a notification transport for immutable server-recorded events. Payment state remains authoritative in the Payment Intent and verified observer lifecycle.

Events

Supported event types are payment.intent.created, payment.confirmed, payment.reorged, payment.cancelled, payment.expired, payment.underpaid, payment.overpaid, payment.late, and webhook.test. Events are scoped to the merchant and API-key environment.

Signature contract

EXZIX signs the exact bytes of timestamp + "." + raw request body with HMAC-SHA256 using the endpoint secret. Headers are X-Exzix-Event-Id, X-Exzix-Timestamp, and X-Exzix-Signature. Compare the expected lowercase hexadecimal signature with constant-time comparison before parsing or processing. The implementation does not impose a timestamp freshness window; receivers may add their own replay policy.

php
$expected = hash_hmac('sha256', $timestamp . '.' . $rawBody, 'YOUR_WEBHOOK_SECRET');
if (!hash_equals($expected, strtolower($receivedSignature))) {
    throw new RuntimeException('Invalid webhook signature');
}

Envelope

Payment event bodies contain id, type, created_at, and data.payment_intent. The payment intent contains server-produced identifiers, status, merchant_reference, network, asset, requested_amount, created_at, and expires_at; observed fields are included only when the emitting operation has those facts. webhook.test contains data.test with synthetic true, environment, and endpoint_id, and no payment intent.

Endpoint management

POST and GET /api/v1/merchants/{merchant}/webhook-endpoints and GET /.../{endpoint} are implemented, plus POST /.../{endpoint}/disable. Creation requires webhooks:write and returns signing_secret once. Reads never return secret material. URLs must be HTTPS on standard port 443 and pass the implemented delivery security policy.

Delivery, retry, and replay

Delivery states are pending, processing, delivered, and failed. HTTP 2xx succeeds; transport errors, timeouts, 408, 425, 429, and 5xx are retryable. Other 3xx/4xx responses and endpoint security rejection are terminal. The configured default maximum is six attempts with delays of 60 seconds, 5 minutes, 30 minutes, 2 hours, and 12 hours. Merchant replay creates a new delivery for the same immutable event and requires webhooks:write plus Idempotency-Key.

Receiver requirements

Preserve raw bytes, verify before parsing, deduplicate by event ID, tolerate retries and out-of-order delivery, return 2xx promptly, and never treat a browser redirect or webhook receipt as blockchain authority. The complete verified examples are maintained in docs/webhooks/README.md and examples/webhooks/.