POST request with a JSON payload.
Webhook structure
Every webhook delivery contains the event type, a unique event ID, a timestamp, and adata object with order, customer, and geo information.
Webhook headers
Every delivery includes these headers for verification and deduplication:| Header | Description |
|---|---|
X-Pandabase-Signature | HMAC-SHA256 hex digest of the JSON body, signed with your webhook secret |
X-Pandabase-Timestamp | Unix timestamp (milliseconds) of when the delivery was sent |
X-Pandabase-Idempotency | Unique delivery identifier — use this to deduplicate retried deliveries |
Content-Type | Always application/json |
User-Agent | Pandabase (https://pandabase.io) |
Verifying signatures
Always verify theX-Pandabase-Signature header to confirm the webhook was sent by Pandabase and hasn’t been tampered with.
Retries
Failed deliveries are retried up to 5 times with exponential backoff starting at 1 second (1s, 2s, 4s, 8s, 16s). Your endpoint should return a2xx status code to acknowledge receipt. Any other status code or a timeout (15 seconds) is treated as a failure and triggers a retry.
Use the X-Pandabase-Idempotency header to deduplicate deliveries — the same event may be delivered more than once due to retries.
Event types
PAYMENT_PENDING
Fired when a customer initiates payment at checkout. The order has been created and a payment intent is awaiting confirmation.
At this stage, geo data (
city, region, country) may be null — it is
enriched asynchronously after checkout. Subsequent events will include full
geo data.PAYMENT_COMPLETED
Fired when a payment is successfully collected. This is the primary event to listen for when fulfilling orders.
The order status will be PROCESSING (if fulfillment is in progress) or COMPLETED (if already fulfilled). The items array contains all purchased products, customFields includes any data the customer submitted at checkout, and metadata contains any developer-defined key-value pairs set when creating the checkout session.
PAYMENT_FAILED
Fired when a payment fails, is canceled by the customer, or expires without being completed. The order is moved to CANCELLED status. If a coupon was applied, its usage count is automatically restored.
PAYMENT_REFUNDED
Fired when a charge is refunded, whether initiated through the Pandabase dashboard or detected from an external refund. The order status is set to REFUNDED.
PAYMENT_DISPUTED
Fired when a customer opens a chargeback dispute on a payment. The order moves to CHARGEBACK status and the disputed amount plus a $20.00 dispute fee is deducted from the store’s available balance.
PAYMENT_DISPUTE_WON
Fired when a dispute is resolved in the merchant’s favor. The disputed amount and fee are restored to the store’s available balance and the order returns to COMPLETED status.
PAYMENT_DISPUTE_LOST
Fired when a dispute is resolved against the merchant. The deducted funds remain lost and the order stays in CHARGEBACK status.
Best practices
- Return 200 quickly. Process webhook logic asynchronously if it takes more than a few seconds. Pandabase times out after 15 seconds.
- Deduplicate with idempotency keys. Store the
X-Pandabase-Idempotencyheader value and skip events you’ve already processed. - Verify signatures. Always validate
X-Pandabase-Signaturebefore processing the payload. - Use event filtering. Subscribe only to the events you need to reduce noise and processing overhead.
- Handle out-of-order delivery. In rare cases, events may arrive out of order (e.g.
PAYMENT_COMPLETEDbeforePAYMENT_PENDING). Use thetimestampfield and order status to handle this gracefully.
