Sign in to see your venue's slug and publishable key in every sample.
Your account has no venue yet, so the samples keep their placeholders. Sign out
Signed in as · . Create a publishable key in the console and reload to see it here. Sign out
Signed in as · . The samples show your venue's publishable key. Sign out
Developer docs
Payment intents
Create a provider-agnostic payment intent for a reservation's deposit — what you send, what comes back, and why no card data ever touches this API.
A payment intent records that a deposit is owed for a reservation and hands you what a payment provider needs to collect it. The API never sees card numbers: the intent carries a clientSecret for the provider's own client-side flow, or a checkoutUrl to send the guest to. It follows the same key rules as the rest of /api/venues/**. The embeddable widget calls it from its confirmation's "Pay deposit" step, with an optional gift voucher code (Booking flow); your own page may call it with a publishable key after a reservation with depositRequired: true, exactly as shown below.
Endpoints
POST /api/venues/{venueSlug}/payment-intents
Request body (Content-Type: application/json)
| Field | Required | Meaning |
|---|---|---|
reservationReference |
yes | The reservation's reference (BDP-XXXXXX) |
amount |
yes | Exactly the deposit the booking owes: the reservation's depositAmount (for a group booking, the whole group's). Any other amount is refused with 400 |
currency |
yes | Three-letter ISO 4217 code, the reservation's currency |
provider |
no | Reserved for choosing a provider when more than one is configured; today it is ignored — the provider is decided by server configuration (fake by default, stripe once Stripe:SecretKey is set) |
voucherCode |
no | A gift voucher of this venue to pay the deposit with, fully or partly (With a voucher). Send it here only, never in a URL, and never log it |
Response 201 Created
| Field | Type | Meaning |
|---|---|---|
id |
GUID | The intent |
reservationReference |
string | What it pays for |
amount, currency |
decimal, string | What is owed |
status |
string | The provider's status — provider-specific, e.g. RequiresConfirmation for fake, a Stripe Checkout Session status such as open for stripe |
provider |
string | Which provider created it |
clientSecret |
string | Hand this to the provider's client library on the guest's device — never log it |
checkoutUrl |
string or null | When set, redirect the guest there instead |
createdAt |
ISO 8601 instant | When the intent was created |
voucherAmount |
decimal or null | What the voucher pays; null when the request carried no voucher |
cardAmount |
decimal or null | What the card pays: amount less voucherAmount. 0 means the voucher paid everything; null without a voucher |
{
"id": "79501bb3-1e05-4827-82ed-1086e889b3bd",
"reservationReference": "BDP-KSQS7M",
"amount": 20.00,
"currency": "EUR",
"status": "RequiresConfirmation",
"provider": "fake",
"clientSecret": "pi_fake_156d81370b0445619159a5028cc87bff_secret_82d75f634cbb4beaaf530982b18e492c",
"createdAt": "2026-09-15T12:55:15.2187185+00:00",
"checkoutUrl": null
}A deposit can be paid once, and only while the booking is Pending and waiting for it. The amount is always the booking's own deposit, so a client never decides what the guest is charged.
With a voucher
Add voucherCode and the voucher pays what it can of the deposit; the card pays the rest through the same Checkout as above. Only an amount voucher pays a deposit. The voucher's value is held while the guest is on Stripe's page and taken when the payment lands, so it cannot be spent twice; if the guest gives up, the hold lapses by itself. The card part is at least €0.50: when less would be left, the voucher pays a little less so the card pays exactly €0.50 (Paying with a voucher).
A voucher that covers the whole deposit opens no payment at all: the booking is confirmed at once, provider is voucher, cardAmount is 0 and checkoutUrl is the booking's confirmation page. status is succeeded, or paid_but_unavailable when the slot was taken in the meantime — the venue then resolves the booking, and its refund puts the value back on the voucher.
{
"id": "0b6d2c51-9a7e-4f3b-8c1d-2e4f6a8b0c13",
"reservationReference": "BDP-KSQS7M",
"amount": 20.00,
"currency": "EUR",
"status": "succeeded",
"provider": "voucher",
"clientSecret": "",
"createdAt": "2026-10-09T12:55:15.2187185+00:00",
"checkoutUrl": "https://app.bookdineplay.com/booking/confirmed?ref=BDP-KSQS7M",
"voucherAmount": 20.00,
"cardAmount": 0.00
}With a voucher, the venue must have deposits switched on and a plan that includes them; online payments and a payout account are needed only while a card part is left. A refund — by the venue, on a guest's own cancel when the venue's policy refunds, or in the venue's Stripe dashboard — gives the voucher part back to the voucher and the card part back to the card.
Errors
| Status | When |
|---|---|
400 |
A field fails validation (errors names it), or amount/currency is not exactly the booking's deposit |
403 |
feature-not-in-plan: the tenant's plan does not include online payments or deposits. requiredPlan is "Premium" |
404 |
No venue with that slug, or no reservation with that reference at this venue |
409 |
The venue has not enabled online payments or deposits itself — skip the deposit step and treat the reservation as confirmed by the venue |
409 |
payouts-not-connected: the plan and the venue's switches allow it, but the venue has not connected (or not finished connecting) its Stripe payout account yet |
409 |
The booking is not waiting for a deposit — cancelled, confirmed by the venue, or finished (reason deposit-not-payable) — or its deposit is already paid (reason deposit-already-paid) |
404, 409 |
With a voucher: one of the gift voucher problems, or 409 with reason below-card-minimum when the deposit is €0.50 or less and the voucher does not cover it |
The venue's own switches, the tenant's plan, and the payout account are checked in that order — a venue with payments switched off answers the switch problem first, even on a plan and payout account that would otherwise allow it.
curl
curl -X POST "https://api.bookdineplay.com/api/venues/your-venue/payment-intents" \
-H "X-BookDinePlay-Key: bdp_pk_your_publishable_key" \
-H "Origin: https://www.your-venue.example" \
-H "Content-Type: application/json" \
-d '{ "reservationReference": "BDP-7K2Q9H", "amount": 20.00, "currency": "EUR" }'JavaScript
const intent = await (await fetch('https://api.bookdineplay.com/api/venues/your-venue/payment-intents', {
method: 'POST',
headers: { 'X-BookDinePlay-Key': 'bdp_pk_your_publishable_key', 'Content-Type': 'application/json' },
body: JSON.stringify({ reservationReference: reservation.reference, amount: reservation.depositAmount, currency: reservation.currency, voucherCode }) // voucherCode optional
})).json();
if (intent.checkoutUrl) location.assign(intent.checkoutUrl); // with cardAmount 0 this is the confirmation pageC#
var intent = await client.CreatePaymentIntentAsync("your-venue", new CreatePaymentIntentRequest
{
ReservationReference = reservation.Reference,
Amount = reservation.DepositAmount ?? 0m,
Currency = reservation.Currency,
VoucherCode = voucherCode // optional
}, cancellationToken);Next steps
- Reservations — where
depositAmountcomes from. - Vouchers — the rules every voucher payment shares.
- Errors —
feature-not-in-planandpayouts-not-connectedin detail. - .NET SDK —
CreatePaymentIntentAsyncand the exceptions it throws on403/409.