Overview
Webhooks allow Payviox to send real-time notifications to your server when payment events occur. When a payment is processed, Payviox sends an HTTP POST request to your configured webhook URL with the payment details.Webhook Configuration
Setting Up Your Webhook URL
Configure Your Endpoint
https://yourdomain.com/api/webhook)Add URL to Dashboard
Enter Your Webhook URL
Save Your Webhook Token
Select Webhook Events
succeeded is enabled.Available Events
You can subscribe to the following webhook events:Webhook Payload Structure
Payviox sends webhooks with the following structure:Payload Fields
amount + fees = total. This field is present when fees have been calculated for the transaction.succeeded: Payment completed successfully. You can fulfill the order.pending_review: Payment flagged for fraud review. Do NOT ship until you receivesucceededordeclined.declined: Payment declined by fraud prevention. Customer has been automatically refunded.refunded: A refund has been processed for this transaction.expired: Payment session expired without completion.incomplete: A crypto payment came in short (less than the requested amount). Opt-in event. Includesamount_remaining(how much is still due). Do NOT fulfill until you receivesucceeded.subscription_payment_failed: A subscription renewal charge failed. Opt-in event. Includesfailure_reason. See Subscription events.subscription_canceled: A subscription ended. Opt-in event. See Subscription events.
provider. Examples: credit, apple_pay, google_pay, blik, wechat_pay
with provider: "stripe"; bitcoin, usdt_trc20 with provider: "uniwire";
pix_br, kakaopay_kr with provider: "payssion".incomplete events. The amount still due, in the smallest currency unit (e.g., cents for USD) — how much more the customer must send to complete the payment. The amount already received equals amount - amount_remaining.succeeded onward (a pending_review, declined or expired event on a signup session doesn’t have it). Values are read when the webhook is sent.subscription_payment_failed events. Why the renewal charge failed: a card decline code such as insufficient_funds, expired_card or card_declined, authentication_required when the bank asks the customer to authenticate (3D Secure), or payment_failed when no detail is available. See failed renewals for what to do.Event Types
Payviox sends different webhook events based on the payment lifecycle. Here’s what each event means and how to handle it:succeeded - Payment Successful
✅ Payment Successful
- Customer completes payment
- Payment processor confirms the charge
- You receive
succeededwebhook - Ship the order / provide the service
pending_review - Fraud Review Required
⚠️ Pending Review
- Customer completes payment
- Fraud detection flags the transaction
- You receive
pending_reviewwebhook - Admin reviews the transaction
- You receive either
succeededordeclinedwebhook
declined - Fraud Declined
❌ Declined (Fraud)
- Customer completes payment
- Fraud score exceeds threshold
- Automatic refund is issued
- You receive
declinedwebhook - Do NOT ship the order
refunded - Payment Refunded
↩️ Refunded
- Original payment was successful
- Refund is requested (by you or the customer)
- Refund is processed
- You receive
refundedwebhook
expired - Session Expired
⏰ Expired
- Payment session is created
- Customer does not complete payment within the session lifetime
- Session expires automatically
- You receive
expiredwebhook
incomplete - Crypto Payment Underpaid
⚠️ Incomplete
amount_remaining (how much is still due, in the smallest currency unit). The amount already received equals amount - amount_remaining.Typical flow:- Customer pays a crypto invoice but sends less than the requested amount
- You receive
incomplete(withamount_remaining) - Customer sends the remaining amount to the same address
- You receive
succeeded
succeeded.subscription_payment_failed - Renewal Charge Failed
⚠️ Subscription Payment Failed
failure_reason and the subscription block (status is usually past_due). Its current_period_end is the end of the period that was not paid: don’t extend access from it.Typical flow:- Stripe charges the saved card at the end of the period
- The charge fails (declined, expired card, authentication required…)
- You receive
subscription_payment_failed(once per cycle, even if Stripe retries several times) - Stripe retries automatically. If a retry succeeds, you receive
succeededwith the sameorder_id; if Stripe gives up and cancels, you receivesubscription_canceled
subscription_canceled - Subscription Ended
🛑 Subscription Canceled
order_id is your original order_id and subscription.cycle is 1.What to do: keep access until the end of the last period you were paid for (the subscription.current_period_end of the last succeeded you received), then revoke it.Subscription Events
Subscriptions use the same webhook endpoint, signature and retry policy as one-time payments. Each billing cycle is its own payment session:subscription_payment_failed and subscription_canceled are opt-in: select them in Developers > Webhooks in the dashboard. Scheduling a cancellation (by you or by the customer) sends no event — subscription_canceled arrives when the subscription actually ends. To find subscriptions scheduled to end, use List Subscriptions with status=canceling.- Signup: the first payment goes through the usual flow, fraud review included — it can be
pending_reviewbeforesucceeded. The subscription is created when it succeeds. - Renewals are charged by Stripe and arrive directly as
succeeded(no fraud review).metadatacontains your signup metadata plus the renewal’s ownintegration_session_id.amountis your price per period andfeesthe fees added for the customer. - Idempotency: keep deduplicating on
order_id+type. Each cycle has its ownorder_id, so a renewal never collides with the signup or with another renewal. - Finding your customer: the webhook
customerfield holds the payer’s billing details, not your customer ID. Put your own IDs inmetadatawhen you create the signup session: they’re sent with every event of the subscription.
Example payloads
Handling subscription events
Webhook Headers
Every webhook request includes these headers:Signature Verification
TheSignature header contains an HMAC SHA256 hash of the request body, signed with your webhook token. Here’s how to verify it:
Verification Algorithm
- Get the raw request body (JSON string)
- Compute HMAC SHA256 hash using your webhook token as the secret key
- Compare the computed signature with the
Signatureheader - Only process the webhook if signatures match
Implementation Examples
Retry Logic
Payviox implements an automatic retry mechanism for failed webhook deliveries:First Attempt
Second Attempt
Third Attempt
Fourth Attempt
Success Criteria
A webhook is considered successfully delivered when your endpoint:- Returns HTTP status code
200 - Responds within 30 seconds
Troubleshooting
Common Issues
Signature Verification Failing
Signature Verification Failing
- Using the wrong webhook token
- Parsing/modifying the request body before verification
- Incorrect HMAC algorithm (must be SHA256)
Webhooks Not Being Received
Webhooks Not Being Received
- Incorrect webhook URL in dashboard
- Firewall blocking Payviox IP addresses
- Server not responding within 30 seconds
Duplicate Webhook Processing
Duplicate Webhook Processing
- Not implementing idempotency checks
- Slow response times causing retries
order_id + type (each subscription cycle has its own order_id), and respond quickly with 200 OK.Webhook Timeout
Webhook Timeout
- Processing taking too long before responding
- Database locks or slow queries
Security Checklist
Need Help?
If you’re having trouble with webhook integration:- Check the Webhook Logs in your dashboard
- Review your server logs for errors
- Contact support@payviox.com for assistance