Quickstart guide
Get up and running with webhooks in just a few minutes:Enable webhooks
Configure your endpoint
- Add your webhook endpoint URL (e.g.,
https://your-domain.com/webhooks/paygentic) - Select which event types to subscribe to
- View the endpoint’s signing secret. Each endpoint has its own secret
Test your endpoint
Verify and process events
Setting up webhooks
Enabling webhooks
- Dashboard
- API
- Access the dashboard: Log in to your Paygentic account and navigate to Developer > Webhooks
- Enable webhooks: Turn on the Enable Webhooks switch
- Access management portal: Under “Manage Webhook Endpoints”, select Open Webhook Portal
Configuring endpoints
In the webhook management portal, you can:- Add endpoints: Specify the URL where you want to receive webhook events
- Select event types: Select which events you want to subscribe to
- View logs: Monitor webhook deliveries and debug any issues
- Retrieve signing secrets: Each endpoint has its own signing secret for verification
Best practices
- Use HTTPS endpoints only (HTTP is not supported for security reasons)
- Implement webhook processing asynchronously to respond quickly
- Handle duplicate events: dedupe on
svix-id, and on the resource ID for events that matter (see Idempotency) - Disable CSRF protection for your webhook endpoint
- Respond with a 2xx status code within 15 seconds
Managing webhooks through the API
Use the API to check whether delivery is on, to pause and resume it, and to get a portal link without a dashboard login. Endpoint URLs, event subscriptions, and signing secrets live in the webhook management portal — the API doesn’t change them. Your API key has the permissions of the user it belongs to. Enabling, updating, and disabling webhooks need write access to webhooks; reading the configuration and getting a portal link need read access. The user who creates a merchant account has both.Reading the configuration
enabled tells you whether delivery is on. If webhooks were never enabled, the response is 404 Not Found.
Pausing and resuming delivery
Setenabled to false to pause delivery, and to true to resume it. It’s the only field, and it’s required.
200 OK with the configuration. DELETE /v0/webhooks has the same effect as PATCH with { "enabled": false } and returns 204 No Content. Neither call deletes anything — your endpoints, their event subscriptions, and their signing secrets stay in the portal.
Getting a portal link
expiresAt. Request a new link each time you need one. Delivery must be enabled, or the response is 404 Not Found.
Security and verification
Webhook security is critical to ensure that the events you receive are legitimate and have not been tampered with. Paygentic signs all webhooks with HMAC-SHA256.Required headers
Every webhook request includes three important headers:svix-id: Unique identifier for the webhook message (use for idempotency)svix-timestamp: Unix timestamp when the webhook was sentsvix-signature: Base64 encoded signature(s) for verification
Signature verification
Use Svix’s verification library for easy and secure webhook verification:Verification examples
Replay attack protection
The timestamp in thesvix-timestamp header protects against replay attacks. The Svix library automatically rejects webhooks with timestamps more than 5 minutes old (past or future). Ensure your server’s clock is synchronized using NTP.
Handling webhooks
Response requirements
- Status code: Return a 2xx status code (200-299) to indicate successful receipt
- Timeout: Respond within 15 seconds or the delivery will be considered failed
- Body: The response body is ignored - a simple “OK” or empty response is fine
Processing best practices
Idempotency
Your endpoint can receive the same event more than once. A retry of one message keeps itssvix-id, so dedupe on svix-id first:
svix-id values, for example invoice.issued.v0. For events that change state in your system, also dedupe on the resource ID in data, such as invoiceId or subscriptionId.
Delivery guarantees
Webhooks tell you that something changed — they aren’t a complete record. Paygentic doesn’t retry an event that it fails to hand to the delivery service, and it doesn’t send events that occur while delivery is paused. When your system needs exact state, such as whether an invoice is paid, read the resource from the API.CSRF protection
Retry policy and failure handling
Automatic retry schedule
If your endpoint does not respond successfully, the delivery is retried with exponential backoff:Failure scenarios
A webhook delivery is considered failed if:- Your endpoint returns a non-2xx status code
- Your endpoint does not respond within 15 seconds
- The endpoint is unreachable (connection error)
- Your endpoint returns a 3xx redirect (not followed)
Endpoint disabling
If an endpoint fails continuously for 5 days, it is automatically disabled. Paygentic does not send a webhook event when this happens, so check the delivery logs in the webhook management portal. You can re-enable the endpoint from the portal.Manual recovery
You can manually retry failed webhooks through the webhook management portal:- Individual retry: Retry a specific failed message
- Bulk recovery: Replay all failed messages from a specific date
- View logs: Inspect delivery attempts and error messages
Event types reference
Paygentic currently supports the following webhook event types:Customer Events
Customer Events
customer.created.v0
customer.created.v0
customer.creation_failed.v0
customer.creation_failed.v0
error.code is the name of the error type, for example ValidationError. Use error.message for display, and do not rely on a fixed list of codes.customer.deleted.v0
customer.deleted.v0
Subscription Events
Subscription Events
subscription.created.v0
subscription.created.v0
subscription.activated.v0
subscription.activated.v0
active state, which happens:- Immediately upon creation for subscriptions without upfront costs
- After successful payment of upfront costs for subscriptions that require them
- Immediately, before payment, for a bank-transfer subscription set to activate immediately. The payload then has
activatedWithoutPayment: true
subscription.created.v0 fires when a subscription is first created (which may be in pending_payment state), subscription.activated.v0 fires when the subscription is ready for use. Use this event to provision access or activate features for customers.subscription.cancelled.v0
subscription.cancelled.v0
endingAt is when the subscription ends. reason is optional free text, so do not branch on its value.subscription.updated.v0
subscription.updated.v0
POST /v0/subscriptions/{id}/versionMigration. updates holds the new version. updates.versionPolicy is always pinned, and updates.effectiveAt can be null. A floating subscription that moves to a new default version at its next billing period does not send this event.Payment Events
Payment Events
payment.completed.v0
payment.completed.v0
payment.failed.v0
payment.failed.v0
error.code and error.message carry the same failure reason: authentication_required, card_declined, insufficient_funds, expired_card, stolen_card, lost_card, card_velocity_exceeded, do_not_honor, fraud_suspected, processing_error, incorrect_details, not_supported, account_update_required, or unknown.payment.expired.v0
payment.expired.v0
Invoice Events
Invoice Events
invoice.issued.v0
invoice.issued.v0
customerId can be null.invoice.issued.v0 for the same invoice. Use invoiceId to ignore duplicates.invoice.paid.v0
invoice.paid.v0
PAID — covers subscription renewals, grant purchases (the grantId is included in the payload), out-of-band payments, and zero-amount invoices.grantId is set when the invoice pays for a grant purchase, for example one made with POST /v1/entitlements/{id}/grants/purchase. Otherwise it is omitted. paymentIntentId is the payment provider’s reference for the payment, for example a Stripe PaymentIntent ID. It is omitted for out-of-band and zero-amount invoices.grandTotal is the authoritative amount paid. subtotal and totalTax are each rounded to 2 decimal places independently, so re-adding them can land a cent off grandTotal — use grandTotal directly rather than re-summing the parts.invoice.paid.v0 more than once for a given invoice — dedupe on invoiceId before acting on it.Source Events
Source Events
source.activated.v0
source.activated.v0
source.activation_failed.v0
source.activation_failed.v0
source.disconnected.v0
source.disconnected.v0
Source Event Processing
Source Event Processing
source_event.pending.v0
source_event.pending.v0
source_event.processed.v0
source_event.processed.v0
source_event.failed.v0
source_event.failed.v0
source_event.rejected.v0
source_event.rejected.v0
Common event fields
All webhook events include these standard fields:Code examples
Complete webhook handler
Here’s a production-ready webhook handler example:Testing webhooks locally
For local development, use a tunneling service to expose your local server:Additional resources
- Webhooks dashboard - Turn webhooks on and open the webhook management portal
- Authentication - API keys and environments for the webhook API
Need help?
If you encounter any issues with webhooks:- Check the delivery logs in the webhook management portal for error messages
- Verify your endpoint is returning a 2xx status code
- Ensure you’re using the correct signing secret
- Confirm your server’s clock is synchronized (for timestamp validation)
- Contact support if you need additional assistance