Skip to main content
After a customer completes a payment, Quidkey delivers the result to your backend via an HTTPS webhook. This guide covers webhook setup, signature verification, fee processing, and a production QA checklist.

Redirect Handling

After bank authentication, the customer is redirected to the URL you specified when creating the payment request:
  • Success: redirected to success_url
  • Failure / Cancel: redirected to failure_url
Do not rely solely on the redirect to confirm payment. Always verify payment status via the webhook. Redirects can fail or be interrupted.

Webhook Setup

Quidkey supports two delivery models:
  • Default webhook: a single per-merchant URL, set via the API below and signed with your merchant secret. It is used for every payment that does not name an endpoint.
  • Named webhook endpoints: multiple destinations, each with its own signing secret and an optional test/live scope. You register them in the Console and route each payment to one or more of them by name. See Named Webhook Endpoints.

Default Webhook: Register and Obtain a Signing Secret

1

Register your webhook URL

The response confirms the URL has been registered.
2

Generate the signing secret

The secret is returned once. Store it safely in a secure vault (AWS Secrets Manager, HashiCorp Vault, etc.).
See the Generate Webhook Secret API for complete details and interactive playground.
3

Revoke the secret (if needed)

Roll or revoke the secret during incident response:

Named Webhook Endpoints

Platforms that create payments on behalf of several businesses (for example, a travel platform handling payments for multiple airlines) can register multiple webhook endpoints, each with its own URL and signing secret, then route each payment to the right one. Endpoints are managed in the Console, not the API.
1

Open Webhooks settings

In the Console, switch into the relevant merchant context, then open Settings → Webhooks.
2

Add an endpoint

Select Add endpoint and provide:
  • Name: a stable, unique identifier you reference per payment (for example wizzair-prod). It cannot be changed after creation.
  • URL: the HTTPS or HTTP destination. Private, loopback, link-local, and metadata addresses are rejected.
  • Signed: leave enabled to receive an X-Signature header (recommended). Disable only for a destination that cannot verify signatures.
  • Environment: choose Test, Live, or Both (default). A test-only endpoint receives webhooks only for test payments, and a live-only endpoint only for live payments, so you can validate an integration against a test receiver without it ever seeing live traffic.
3

Copy the signing secret

A whsec_... secret is generated and shown once. Copy it immediately and share it with the destination out of band.
The secret is revealed only at creation and on rotation. If it is lost, rotate to issue a new one.
4

Rotate or disable later

  • Rotate secret issues a new secret and shows it once. The previous secret stops verifying immediately (there is no grace window), so coordinate rotation with the destination.
  • Disable stops new deliveries to the endpoint. Endpoints are disabled, never deleted, so a payment that already references one always resolves.

Route a payment to one or more endpoints

Reference endpoints by name when you create a payment request, using the optional webhook_endpoints field. You can name up to 10 endpoints, and the payment’s webhook is fanned out to every one of them (for example, the downstream business and your own platform receiver):
Each endpoint receives its own delivery, signed with that endpoint’s secret (an unsigned endpoint receives no X-Signature). A reference that is unknown, disabled, not owned by you, or whose test/live scope does not match the payment is rejected at creation with 400 UNKNOWN_WEBHOOK_ENDPOINT. The payment is not created, so fix the reference and retry.

Resolution order

When a payment does not name an endpoint, Quidkey resolves the destination in order:
  1. The default webhook_url, if set (signed with the merchant secret). Unchanged from today, so existing integrations are never re-routed.
  2. Otherwise, the merchant’s default endpoint, if one is marked as default in the Console (signed with its own secret).
  3. Otherwise, if the merchant has exactly one active endpoint, that endpoint.
  4. Otherwise (no default URL, no default endpoint, and zero or multiple active endpoints) the delivery is recorded as FAILED. Quidkey never guesses between endpoints; mark a default endpoint, or name one per payment, to avoid this.
A payment that names endpoints always uses them. For each named endpoint that is disabled, or whose test/live scope no longer matches the payment, that delivery is recorded as FAILED while the others still deliver; there is no fallback to the default.

Webhook Payload

Quidkey sends a Stripe-style envelope so existing tooling can be reused. The example below is the default webhook payload. Deliveries to a named endpoint use the same shape, except that bank_name is omitted from metadata.
Fee information is only included for successful payments (status: "succeeded"). Failed or cancelled payments do not include fees.

HTTP Headers

The HMAC is SHA-256 over "${timestamp}.${raw_body}", keyed by your webhook signing secret. For a payment routed to a named endpoint, the key is that endpoint’s secret; an endpoint marked unsigned sends no X-Signature header.

Verify Signatures

The X-Signature header lets you confirm that the webhook came from Quidkey and that the payload was not tampered with.

Process Webhook Events

Delivery and recovery: Each event is delivered with a single attempt (15-second timeout). There is no automatic retry today: a failed delivery is recorded and can be manually resent by Quidkey on request. Reconcile important payments against the API as a backstop, and de-duplicate using the top-level id field (a resend reuses it). Durable automatic retries are planned.

Fee Handling

Quidkey automatically calculates and applies fees for successful transactions. Fee information is included in webhook payloads for merchant accounting and billing reconciliation. Fee types:
  • Percentage fees: based on transaction amount (e.g., 1.5% of €100 = €1.50)
  • Fixed fees: flat rate per transaction (e.g., €1.00 per transaction)
  • Currency-specific: fees are calculated in the same currency as the transaction
Each fee in the fees_breakdown array contains:

QA Checklist Before Going Live

  • Serve checkout over HTTPS (wallets such as Apple Pay require it)
  • Use live Stripe keys in production mode (if using Stripe alongside)
  • Ask Quidkey for your production merchant_id and iframe URL
  • Store webhook secret in secure vault
  • Verify that only one payment method can be selected at any time
  • Confirm purchase button enables/disables correctly with bank selection
  • Test post-purchase redirect flows for success and failure
  • Verify dynamic height adjustments work smoothly
  • Verify amount updates work before payment initiation
  • Confirm updates are blocked after customer selects a bank
  • Test error handling for expired tokens
  • Ensure iframe refreshes correctly after updates
  • Verify webhook signature validation works
  • De-duplicate events by id and confirm your recovery path (manual resend) for failed deliveries
  • Verify successful payments include fee information
  • Ensure your system correctly stores fee breakdown data

Next Steps

Embedded Flow Overview

Back to the Embedded Flow overview

Embed the Checkout

Iframe setup, Stripe mutual exclusion, and purchase button routing

Webhook API Reference

Full webhook endpoint documentation

Payment Links

Collect payments via a hosted checkout page instead