Skip to main content
Collect the buyer’s details on your own site, create a payment from your backend, and send the buyer to a Quidkey-hosted page to pick their bank and approve. No iframe and no checkout UI to build: one API call and a redirect.
Amounts are integer minor units. 2550 = £25.50, 1000 = €10.00. The same format is used across the Payment API. See Amounts & Currencies.

How It Works

Prerequisites

  • A Quidkey merchant account with client_id and client_secret (sign up)
  • An access token (see Authentication)
  • The buyer’s name, email, phone number, and billing address

Step 1: Authenticate

Exchange your credentials for an access token. The token is valid for 15 minutes.
curl -X POST 'https://core.quidkey.com/api/v1/oauth2/token' \
  -H 'Content-Type: application/json' \
  -d '{
    "client_id": "your-client-id",
    "client_secret": "your-client-secret"
  }'
See the Authentication API reference for the full token lifecycle and an interactive playground.

Step 2: Create a Redirect Payment

Call POST /api/v1/payment-requests:redirect with a Bearer token and an Idempotency-Key. The request body carries the buyer, the billing address, the amount, and where to send the buyer afterwards.
curl -X POST 'https://core.quidkey.com/api/v1/payment-requests:redirect' \
  -H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
  -H 'Idempotency-Key: order-1001-attempt-1' \
  -H 'Content-Type: application/json' \
  -d '{
    "merchant_id": "your-merchant-id",
    "customer": {
      "name": "Jane Buyer",
      "email": "jane@example.com",
      "phone_number": "+447700900123"
    },
    "billing_address": {
      "address_line1": "1 Market Street",
      "city": "London",
      "postal_code": "EC1A 1AA",
      "country": "GB"
    },
    "amount": 2550,
    "currency": "GBP",
    "payment_reference": "ORDER1001",
    "order_id": "1001",
    "locale": "en-GB",
    "success_url_redirect": "https://yoursite.com/success",
    "fail_url_redirect": "https://yoursite.com/failure",
    "test_transaction": true
  }'

Response

{
  "success": true,
  "data": {
    "redirect_url": "https://core.quidkey.com/redirect/9f8c7b6a5e4d..."
  }
}
A successful call returns 201 Created. Save the redirect_url: it’s the bank page you’ll send the buyer to next.

Request Body Reference

FieldTypeRequiredDescription
merchant_idstringNoUUID of the merchant collecting the payment. Optional for merchant tokens; required only for admin/global tokens
customer.namestringYesBuyer’s full name
customer.emailstringYesBuyer’s email address
customer.phone_numberstringNoE.164 format phone number
billing_address.address_line1stringYesFirst line of the billing address
billing_address.citystringYesCity
billing_address.postal_codestringYesPostal or ZIP code
billing_address.countrystringYesISO 3166-1 alpha-2 country code
amountintegerYesAmount in minor units (2550 = £25.50). Min 1, max 9999999 (≈ £99,999.99)
currencystringYesISO 4217 currency code (e.g., GBP, EUR)
localestringYesBCP-47 locale tag for the hosted page (e.g., en-GB)
payment_referencestringNoMax 18 characters, alphanumeric only ([A-Za-z0-9]). Shown on the buyer’s bank statement.
order_idstringNoYour internal order identifier for reconciliation
success_url_redirectstringNoWhere to send the buyer after a successful payment
fail_url_redirectstringNoWhere to send the buyer after a failed or cancelled payment
selected_bank_idstringNoPre-select a bank and skip the picker. See Deep-link to a bank
test_transactionbooleanNoSet true in development so no real money moves
Strict schema. This endpoint rejects unknown fields and rejects decimal amounts. Send only the fields above, and send amount as a whole integer in minor units. 25.50 is invalid; 2550 is correct.

Step 3: Redirect the Buyer

Send the buyer’s browser to the redirect_url. It opens a Quidkey-hosted page that shows only banks (no card option), where the buyer selects their bank and approves the payment inside their banking app or web flow. When they finish, Quidkey returns them to your success_url_redirect or fail_url_redirect.
Node.js
// In your route handler, after creating the payment:
res.redirect(303, data.redirect_url);
The browser redirect back to your site only means the buyer returned. It does not confirm the payment settled. Always wait for the webhook before fulfilling the order. See Verify with webhooks.
After the bank flow, Quidkey sends the buyer back to your success_url_redirect or fail_url_redirect. Treat these strictly as UX: a place to show the buyer a confirmation or retry screen. They are not proof of the outcome. Confirm the result authoritatively via the webhook, or by polling the merchant status endpoint GET /api/v1/payment-requests/{paymentRequestId}/status.

Idempotency

Send a unique Idempotency-Key header on every create request. If the request is retried, for example after a network timeout, Quidkey returns the original result instead of creating a second payment. Use a value tied to the buyer’s intent, such as your order ID plus an attempt counter.
Reuse the same key when retrying the same logical request. Use a new key only when the buyer genuinely starts a new payment. See Idempotency for the full semantics.
To skip the bank picker, pass a selected_bank_id at create time when the buyer has already chosen their bank in your own UI. The hosted page takes them straight to that bank.
curl -X POST 'https://core.quidkey.com/api/v1/payment-requests:redirect' \
  -H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
  -H 'Idempotency-Key: order-1001-attempt-1' \
  -H 'Content-Type: application/json' \
  -d '{
    "merchant_id": "your-merchant-id",
    "customer": {
      "name": "Jane Buyer",
      "email": "jane@example.com",
      "phone_number": "+447700900123"
    },
    "billing_address": {
      "address_line1": "1 Market Street",
      "city": "London",
      "postal_code": "EC1A 1AA",
      "country": "GB"
    },
    "amount": 2550,
    "currency": "GBP",
    "locale": "en-GB",
    "selected_bank_id": "38c39d03-8df3-4980-b0a8-7e283c8c62dd",
    "test_transaction": true
  }'

Build a Bank Button

To show the buyer’s most popular banks in your own UI before they reach the hosted page, fetch the top banks for their country and currency, then pass the chosen id as selected_bank_id. This endpoint is public and cacheable at the market level, so it needs no access token.
curl 'https://core.quidkey.com/api/v1/banks/top?country=GB&currency=GBP&limit=3'
Response
{
  "success": true,
  "data": {
    "banks": [
      {
        "id": "38c39d03-8df3-4980-b0a8-7e283c8c62dd",
        "displayName": "Example Bank",
        "logoUrl": "https://img.logo.dev/example-bank.com"
      }
    ]
  }
}
country is required (ISO 3166-1 alpha-2); currency and limit (1-50) are optional. Render buttons from displayName and logoUrl, then pass the matching id as selected_bank_id. This step is optional: let the buyer choose on the hosted page if you prefer.

Verify with Webhooks

The webhook is the authoritative record of what happened. When a payment reaches a final state, Quidkey sends an event to your registered endpoint:
EventMeaning
quidkey.payment_request.succeededPayment completed. Fulfil the order.
quidkey.payment_request.failedPayment failed at the bank.
quidkey.payment_request.canceledBuyer abandoned or cancelled the payment.
quidkey.payment_request.pendingPayment is in progress, not yet final.
quidkey.payment_request.reversedA completed payment was later reversed.
Fulfil orders on quidkey.payment_request.succeeded, not on the browser redirect. The redirect can be interrupted; the webhook cannot.

Set Up Webhooks

Register your endpoint, verify signatures, and handle every payment status event

Next Steps

Quickstart

The condensed end-to-end version of this flow

Embedded (with Stripe)

Prefer an inline checkout alongside Stripe? Use the Embedded flow

Hosted Checkout

Just need a shareable link? Use Hosted Checkout

API Reference

Explore every endpoint with an interactive playground