Docs · Integrations
Connect a checkout platform.
Each integration ships its own webhook receiver and canonical mapper. HMAC signature verification is mandatory on every webhook route — no exceptions.
HMAC verification, always
Every webhook request must pass HMAC signature verification before Decisa writes anything to the database. We don't accept the trade-off of "just disable it during setup" — a bad webhook secret will return 401 every time, and the diagnostic message tells you which header to check.
The shared secret lives in your workspace settings under Integrations → [provider] → Webhook secret. Rotate it any time; the receiver accepts the previous secret for 5 minutes after rotation so in-flight requests survive the cutover.
Replay safety
All providers retry. We assume duplicate delivery is the default. Idempotency is enforced at two layers:
- raw_payload uniqueness on
(workspace_id, provider, event_id)— the same webhook can't create two raw rows. - Canonical conversion uniqueness on
(workspace_id, external_id)— mapping different raw payloads to the same business event never creates duplicates downstream.
Supported providers
Shopify
Generally availablePOST /api/webhooks/shopify
orders/createorders/paidorders/refunded
Set the webhook in Shopify Admin → Settings → Notifications. Decisa derives external_id from order id and visitor_id from the order note attribute dcs_vid (auto-populated by the pixel on checkout).
Stripe
Generally availablePOST /api/webhooks/stripe
checkout.session.completedinvoice.paidcustomer.subscription.created
Configure a webhook endpoint in Stripe Dashboard → Developers → Webhooks. Visitor stitching uses the metadata.dcs_vid field — set it from the client during checkout creation.
Kiwify
BetaPOST /api/webhooks/kiwify
order.approvedsubscription.renewedorder.refunded
Add the webhook URL in Kiwify → Settings → Webhooks. visitor_id is parsed from the offer URL query parameter ?_v=… that the pixel appends to outbound checkout links.
Custom backend
Always availablePOST /v1/conversions
Any conversion type
When no canonical webhook covers your platform, call /v1/conversions directly from your backend. See the API reference for the full payload contract.
What we deliberately have not abstracted
There is no universal "checkout adapter" interface in the codebase. Each provider lives in its own namespace (App\Integrations\Checkout\Shopify, etc.) with its own mapper, its own raw payload schema, and its own HMAC verification logic. We will not extract a shared adapter until three independent providers have shipped and the patterns are obvious.
This is intentional. Premature abstraction is the most expensive mistake in integration code — once you've generalized the wrong shape, every new provider becomes a puzzle.
Need a provider we haven't shipped? Email [email protected] with a sample webhook payload — we typically ship in under a week. Or use the generic /v1/conversions endpoint from your backend today.