Skip to content

Refund a booking

POST /v1/bookings/{id}/refunds refunds all or part of a booking’s succeeded payment back to the guest’s original payment method.

Omit amountMinorUnits to refund whatever remains on the payment:

Terminal window
curl -X POST https://api.<domain>/v1/bookings/<RESERVATION_ID>/refunds \
-H "Authorization: Bearer sk_test_..." \
-H "Content-Type: application/json" \
-d '{}'
{
"id": "...",
"reservationId": "<RESERVATION_ID>",
"amountMinorUnits": "4500000",
"currency": "IDR",
"state": "succeeded",
"stripeRefundId": "re_..."
}

Pass amountMinorUnits as a string of minor units, same convention as every other amount on this API — see Quotes on why it’s a string, not a number:

Terminal window
curl -X POST https://api.<domain>/v1/bookings/<RESERVATION_ID>/refunds \
-H "Authorization: Bearer sk_test_..." \
-H "Content-Type: application/json" \
-d '{ "amountMinorUnits": "1500000" }'

You can refund the same booking more than once — for example, one night at a time — as long as the running total of successful refunds never exceeds what was actually paid. Ask for more than what’s left and you get 409 refund_exceeds_payment, which carries the actual remaining amount so you can retry with a corrected value.

  • A booking with a succeeded payment. A booking that never took a payment, or whose payment failed, returns 409 no_succeeded_payment.
  • The tenant needs a connected Stripe account. If they don’t, 409 stripe_not_configured.
  • Your sk_ key needs the payment:refund:create scope. Ask your operator contact if a refund call comes back 404 and you’re sure the booking ID is right — a scope-less key and a wrong tenant look identical from the outside, by design (see Errors’s 404 policy).
Status code Meaning
404 booking_not_found Wrong ID, wrong tenant’s key, or a pk_ key (refunds never reach pk_)
409 no_succeeded_payment This booking has nothing paid to refund
409 stripe_not_configured The tenant has no Stripe Connect account yet
409 refund_exceeds_payment You asked for more than what’s left — retry with a smaller amount
409 stripe_refund_failed Stripe refused the refund; the response’s detail carries Stripe’s own reason
409 nothing_to_refund Nothing is left to refund on this payment — a repeat call after a prior full refund

GET /v1/payments (sk_ with payments:read, or an operator session) lists the tenant’s payment intents, each with its own refundedMinorUnits — the running total refunded on that payment so far. Check it before a partial refund if you’re not sure how much is left, rather than guessing and hitting refund_exceeds_payment.

  • Errors — the full RFC 9457 error shape and the 404 policy.
  • Holds and confirmation — how a booking gets to a succeeded payment in the first place.