Skip to content
LoyaltyCheckout reservations

Loyalty

Checkout reservations

Hold part of a balance during checkout.

Pilotv1

Hold a benefit during checkout without spending it

POST/programs/{id}/reservations

Scopeloyalty:write

Requires loyalty:write and an Idempotency-Key. Holds part of one customer's balance while a payment is pending: a Stamp program holds its reward's stamps, a Points (or Points and tiers) program the named reward's points, a Subscription program one included use, a Cashback or Prepaid program amount of its balance (minor units, currency the program's, never converted). The balance does not move; what the customer can spend is the balance less active holds (available), and the counter, actions and a void all leave active holds funded (409 BENEFIT_RESERVED). Concurrent holds queue on the membership: they can never over-commit it (409 INSUFFICIENT_AVAILABLE when other holds are what is in the way, otherwise the card's own refusal code). reference is your checkout or order id and makes the hold happen once under any key; the same reference for something else is 409 SOURCE_EVENT_CONFLICT. The hold lasts expiresInSeconds (60 to 86,400), default 15 minutes (DEVELOPER_RESERVATION_TTL_SECONDS). A Tiered program has nothing to hold (422 UNSUPPORTED_ACTION).

Send an Idempotency-Key header. Safe to retry.

Path

iduuidRequired

Body

externalCustomerIdstringRequired
referencestringRequired
Your checkout or order id; makes the hold happen once.
branchIduuid
rewardIdstring
Points programs.
rewardNamestring
Points programs, by exact name.
amountinteger
Cashback and Prepaid, minor units of the program's currency.
currencyenum
ISO 4217. Fixed per program once money has moved. Minor-unit digits are 0 for JPY, KRW and VND, 3 for BHD, JOD, KWD and OMR, else 2. One of AED, BDT, BHD, EUR, GBP, INR, JOD, JPY, KRW, KWD, MYR, OMR, SGD, USD, VND.
expiresInSecondsinteger
Default 900 (15 minutes). 60 to 86400.

Returns 201

reservationIdstringRequired
stateenumRequired
Read from the clock. One of active, confirmed, released, expired.
amountintegerRequired
Balance units held.
balanceintegerRequired
The membership's balance now; a hold never moves it.
reservedintegerRequired
Held by every active hold on the membership now.
availableintegerRequired
balance less reserved, never below zero.
balanceAfterinteger or nullRequired
currencystring or nullRequired
customerIdstring or nullRequired
Null for a gift card with no customer.
externalCustomerIdstringRequired
giftCardIdstring or nullRequired
Set when the hold is on a gift card; then programId and membershipId are null.
membershipIdstring or nullRequired
programIdstring or nullRequired
referencestringRequired
rewardNamestring or nullRequired
transactionIdstring or nullRequired
The ledger row of the confirmed spend (the counter's pass event for a gift card).
createdAtstringRequired
expiresAtstringRequired
decidedAtstring or nullRequired
duplicatebooleanRequired

Errors

  • 409BENEFIT_RESERVEDpart of the balance is held by a checkout reservation, so a counter or API spend would leave a hold unfunded. Nothing changed; confirm or release the hold, or let it expire.
  • 409INSUFFICIENT_AVAILABLEnot enough is available (the balance less active holds) to hold or spend this. Nothing changed.
  • 409SOURCE_EVENT_CONFLICTthis source event id was already applied with different content (another customer, program, action or amount). Nothing changed.
  • 422UNSUPPORTED_ACTIONthe action is not one a service may take (top-up, spend, set or adjust a balance, void) or the program's card type does not take earning and redeeming from the API yet. Nothing changed.
Request
curl -X POST "https://app.revisit.cards/v1/developer/programs/e01b010d-2c65-48e1-83a0-acad79f8d3b4/reservations" \
  -H "Authorization: Bearer $DEVELOPER_API_KEY" \
  -H "Idempotency-Key: 5f0c2a8e-7b1d-4c3e-9a6f-0d4b8e67f78c" \
  -H "Content-Type: application/json" \
  -d '{
    "externalCustomerId": "user-42",
    "reference": "order-2041"
  }'
Response
{
  "data": {
    "amount": 1250,
    "available": 7,
    "balance": 7,
    "balanceAfter": 7,
    "createdAt": "2026-11-03T08:41:12.000Z",
    "currency": "BDT",
    "customerId": "eb83b9c0-5619-432d-b857-cef7fcf84edb",
    "decidedAt": "2026-11-03T08:41:12.000Z",
    "duplicate": false,
    "expiresAt": "2026-11-03T08:41:12.000Z",
    "externalCustomerId": "user-42",
    "giftCardId": "9c83a2c5-ee43-4698-bd57-cbed81fdc409",
    "membershipId": "b53ca741-1e76-4ddb-b6a5-998b65c4aff3",
    "programId": "d7595bbd-4342-41b4-9037-2e61a9f8403f",
    "reference": "order-2041",
    "reservationId": "checkout-1001",
    "reserved": 0,
    "rewardName": "Free chai",
    "state": "active",
    "transactionId": "add73925-4de9-412c-8cc2-582b074074ca"
  },
  "requestId": "31af666a-e95c-4e2b-9fb7-27d3f5f65935",
  "success": true
}

Hold part of a gift card's balance during checkout

POST/gift-cards/{id}/reservations

Scopepasses:write

Requires passes:write and an Idempotency-Key; confirming or releasing it later needs loyalty:write (and passes:write), reading it loyalty:read (and passes:read). Gift card holds need a key without program or branch limits. Holds amount (the card's currency minor unit, currency must match, never converted) without moving the balance: GiftCard.available is balance less reserved, and the counter, POST /gift-cards/{id}/actions spends and the counter's void of a top-up all leave active holds funded (409 BENEFIT_RESERVED). Concurrent holds queue on the card's row lock (the one the counter's spend takes) and can never over-commit it: 409 INSUFFICIENT_BALANCE when the card itself is short, 409 INSUFFICIENT_AVAILABLE when other holds are in the way. The card's PIN is asked for at confirm, not here. reference makes the hold happen once under any key; the same reference for something else is 409 SOURCE_EVENT_CONFLICT. Same expiry, confirm, release and recovery rules as a program hold. Only gift cards are reservable among the issued passes: offers, generic passes, event tickets, boarding passes and transit passes answer POST /{family}/{id}/reservations with 422 UNSUPPORTED_ACTION and write nothing.

Send an Idempotency-Key header. Safe to retry.

Path

iduuidRequired

Body

amountintegerRequired
The part of the balance to hold, in the currency's minor unit.
currencystringRequired
The card's currency (ISO 4217).
referencestringRequired
Your checkout or order id.
branchIduuid
The branch the spend will happen at. Omitted: the business's only open branch (400 BRANCH_REQUIRED with several).
expiresInSecondsinteger
60 to 86400.

Returns 201

reservationIdstringRequired
stateenumRequired
Read from the clock. One of active, confirmed, released, expired.
amountintegerRequired
Balance units held.
balanceintegerRequired
The membership's balance now; a hold never moves it.
reservedintegerRequired
Held by every active hold on the membership now.
availableintegerRequired
balance less reserved, never below zero.
balanceAfterinteger or nullRequired
currencystring or nullRequired
customerIdstring or nullRequired
Null for a gift card with no customer.
externalCustomerIdstringRequired
giftCardIdstring or nullRequired
Set when the hold is on a gift card; then programId and membershipId are null.
membershipIdstring or nullRequired
programIdstring or nullRequired
referencestringRequired
rewardNamestring or nullRequired
transactionIdstring or nullRequired
The ledger row of the confirmed spend (the counter's pass event for a gift card).
createdAtstringRequired
expiresAtstringRequired
decidedAtstring or nullRequired
duplicatebooleanRequired

Errors

  • 409BENEFIT_RESERVEDpart of the balance is held by a checkout reservation, so a counter or API spend would leave a hold unfunded. Nothing changed; confirm or release the hold, or let it expire.
  • 409INSUFFICIENT_BALANCE
  • 409INSUFFICIENT_AVAILABLEnot enough is available (the balance less active holds) to hold or spend this. Nothing changed.
  • 409SOURCE_EVENT_CONFLICTthis source event id was already applied with different content (another customer, program, action or amount). Nothing changed.
  • 422UNSUPPORTED_ACTIONthe action is not one a service may take (top-up, spend, set or adjust a balance, void) or the program's card type does not take earning and redeeming from the API yet. Nothing changed.
Request
curl -X POST "https://app.revisit.cards/v1/developer/gift-cards/e01b010d-2c65-48e1-83a0-acad79f8d3b4/reservations" \
  -H "Authorization: Bearer $DEVELOPER_API_KEY" \
  -H "Idempotency-Key: 5f0c2a8e-7b1d-4c3e-9a6f-0d4b8eb27ce5" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 1250,
    "currency": "BDT",
    "reference": "order-2041"
  }'
Response
{
  "data": {
    "amount": 1250,
    "available": 7,
    "balance": 7,
    "balanceAfter": 7,
    "createdAt": "2026-11-03T08:41:12.000Z",
    "currency": "BDT",
    "customerId": "eb83b9c0-5619-432d-b857-cef7fcf84edb",
    "decidedAt": "2026-11-03T08:41:12.000Z",
    "duplicate": false,
    "expiresAt": "2026-11-03T08:41:12.000Z",
    "externalCustomerId": "user-42",
    "giftCardId": "9c83a2c5-ee43-4698-bd57-cbed81fdc409",
    "membershipId": "b53ca741-1e76-4ddb-b6a5-998b65c4aff3",
    "programId": "d7595bbd-4342-41b4-9037-2e61a9f8403f",
    "reference": "order-2041",
    "reservationId": "checkout-1001",
    "reserved": 0,
    "rewardName": "Free chai",
    "state": "active",
    "transactionId": "add73925-4de9-412c-8cc2-582b074074ca"
  },
  "requestId": "fe0e74fc-fddf-408f-aa6c-2625aa3866b6",
  "success": true
}

Not supported - an offer cannot be reserved

POST/offers/{id}/reservations

Scopepasses:write

Requires passes:write. Always 422 UNSUPPORTED_ACTION (404 for an unknown id). The same route exists, with the same answer, under /generic-passes/{id}, /event-tickets/{id}, /boarding-passes/{id} and /transit-passes/{id}: those passes are used once, checked in or ridden, not drawn down like a balance, so there is nothing safe to hold. Nothing is written.

Path

iduuidRequired

Errors

  • 422UNSUPPORTED_ACTIONthe action is not one a service may take (top-up, spend, set or adjust a balance, void) or the program's card type does not take earning and redeeming from the API yet. Nothing changed.
Request
curl -X POST "https://app.revisit.cards/v1/developer/offers/e01b010d-2c65-48e1-83a0-acad79f8d3b4/reservations" \
  -H "Authorization: Bearer $DEVELOPER_API_KEY"
Response
{
  "error": {
    "code": "UNSUPPORTED_ACTION",
    "message": "Not supported - an offer cannot be reserved"
  },
  "requestId": "3e87a6b0-eae0-4130-b0f3-1df6436ee81a",
  "success": false
}

Not supported - a generic pass cannot be reserved

POST/generic-passes/{id}/reservations

Scopepasses:write

Requires passes:write. Always 422 UNSUPPORTED_ACTION (404 for an unknown id). The same route exists, with the same answer, under /generic-passes/{id}, /event-tickets/{id}, /boarding-passes/{id} and /transit-passes/{id}: those passes are used once, checked in or ridden, not drawn down like a balance, so there is nothing safe to hold. Nothing is written.

Path

iduuidRequired

Errors

  • 422UNSUPPORTED_ACTIONthe action is not one a service may take (top-up, spend, set or adjust a balance, void) or the program's card type does not take earning and redeeming from the API yet. Nothing changed.
Request
curl -X POST "https://app.revisit.cards/v1/developer/generic-passes/e01b010d-2c65-48e1-83a0-acad79f8d3b4/reservations" \
  -H "Authorization: Bearer $DEVELOPER_API_KEY"
Response
{
  "error": {
    "code": "UNSUPPORTED_ACTION",
    "message": "Not supported - a generic pass cannot be reserved"
  },
  "requestId": "db4dbdad-ebc5-4020-a587-a3de74bd0cc5",
  "success": false
}

Not supported - an event ticket cannot be reserved

POST/event-tickets/{id}/reservations

Scopepasses:write

Requires passes:write. Always 422 UNSUPPORTED_ACTION (404 for an unknown id). The same route exists, with the same answer, under /generic-passes/{id}, /event-tickets/{id}, /boarding-passes/{id} and /transit-passes/{id}: those passes are used once, checked in or ridden, not drawn down like a balance, so there is nothing safe to hold. Nothing is written.

Path

iduuidRequired

Errors

  • 422UNSUPPORTED_ACTIONthe action is not one a service may take (top-up, spend, set or adjust a balance, void) or the program's card type does not take earning and redeeming from the API yet. Nothing changed.
Request
curl -X POST "https://app.revisit.cards/v1/developer/event-tickets/e01b010d-2c65-48e1-83a0-acad79f8d3b4/reservations" \
  -H "Authorization: Bearer $DEVELOPER_API_KEY"
Response
{
  "error": {
    "code": "UNSUPPORTED_ACTION",
    "message": "Not supported - an event ticket cannot be reserved"
  },
  "requestId": "441aca7a-f6ca-4d69-b01b-82882f96b2dd",
  "success": false
}

Not supported - a boarding pass cannot be reserved

POST/boarding-passes/{id}/reservations

Scopepasses:write

Requires passes:write. Always 422 UNSUPPORTED_ACTION (404 for an unknown id). The same route exists, with the same answer, under /generic-passes/{id}, /event-tickets/{id}, /boarding-passes/{id} and /transit-passes/{id}: those passes are used once, checked in or ridden, not drawn down like a balance, so there is nothing safe to hold. Nothing is written.

Path

iduuidRequired

Errors

  • 422UNSUPPORTED_ACTIONthe action is not one a service may take (top-up, spend, set or adjust a balance, void) or the program's card type does not take earning and redeeming from the API yet. Nothing changed.
Request
curl -X POST "https://app.revisit.cards/v1/developer/boarding-passes/e01b010d-2c65-48e1-83a0-acad79f8d3b4/reservations" \
  -H "Authorization: Bearer $DEVELOPER_API_KEY"
Response
{
  "error": {
    "code": "UNSUPPORTED_ACTION",
    "message": "Not supported - a boarding pass cannot be reserved"
  },
  "requestId": "2e334bb4-118f-401d-9c72-55a80e67648a",
  "success": false
}

Not supported - a transit pass cannot be reserved

POST/transit-passes/{id}/reservations

Scopepasses:write

Requires passes:write. Always 422 UNSUPPORTED_ACTION (404 for an unknown id). The same route exists, with the same answer, under /generic-passes/{id}, /event-tickets/{id}, /boarding-passes/{id} and /transit-passes/{id}: those passes are used once, checked in or ridden, not drawn down like a balance, so there is nothing safe to hold. Nothing is written.

Path

iduuidRequired

Errors

  • 422UNSUPPORTED_ACTIONthe action is not one a service may take (top-up, spend, set or adjust a balance, void) or the program's card type does not take earning and redeeming from the API yet. Nothing changed.
Request
curl -X POST "https://app.revisit.cards/v1/developer/transit-passes/e01b010d-2c65-48e1-83a0-acad79f8d3b4/reservations" \
  -H "Authorization: Bearer $DEVELOPER_API_KEY"
Response
{
  "error": {
    "code": "UNSUPPORTED_ACTION",
    "message": "Not supported - a transit pass cannot be reserved"
  },
  "requestId": "884f42e1-3dd2-4011-b6b5-a409cf2322c0",
  "success": false
}

List this application's reservations, newest first

GET/reservations

Scopeloyalty:read

Requires loyalty:read. state follows the clock, so a hold past its time reads expired before the worker writes it down. At most 100 per page.

Query

externalCustomerIdstring
programIduuid
giftCardIduuid
Only the holds on this gift card. Gift card holds are listed only to a key with passes:read and no program or branch limits.
stateenum
One of active, confirmed, released, expired.
limitinteger
1 to 100.
offsetinteger

Returns 200

hasMorebooleanRequired
itemsobject[]Required
items[].reservationIdstringRequired
items[].stateenumRequired
Read from the clock. One of active, confirmed, released, expired.
items[].amountintegerRequired
Balance units held.
items[].balanceintegerRequired
The membership's balance now; a hold never moves it.
items[].reservedintegerRequired
Held by every active hold on the membership now.
items[].availableintegerRequired
balance less reserved, never below zero.
items[].balanceAfterinteger or nullRequired
items[].currencystring or nullRequired
items[].customerIdstring or nullRequired
Null for a gift card with no customer.
items[].externalCustomerIdstringRequired
items[].giftCardIdstring or nullRequired
Set when the hold is on a gift card; then programId and membershipId are null.
items[].membershipIdstring or nullRequired
items[].programIdstring or nullRequired
items[].referencestringRequired
items[].rewardNamestring or nullRequired
items[].transactionIdstring or nullRequired
The ledger row of the confirmed spend (the counter's pass event for a gift card).
items[].createdAtstringRequired
items[].expiresAtstringRequired
items[].decidedAtstring or nullRequired
items[].duplicatebooleanRequired
limitintegerRequired
offsetintegerRequired
Request
curl "https://app.revisit.cards/v1/developer/reservations" \
  -H "Authorization: Bearer $DEVELOPER_API_KEY"
Response
{
  "data": {
    "hasMore": false,
    "items": [
      {
        "amount": 1250,
        "available": 7,
        "balance": 7,
        "balanceAfter": 7,
        "createdAt": "2026-11-03T08:41:12.000Z",
        "currency": "BDT",
        "customerId": "eb83b9c0-5619-432d-b857-cef7fcf84edb",
        "decidedAt": "2026-11-03T08:41:12.000Z",
        "duplicate": false,
        "expiresAt": "2026-11-03T08:41:12.000Z",
        "externalCustomerId": "user-42",
        "giftCardId": "9c83a2c5-ee43-4698-bd57-cbed81fdc409",
        "membershipId": "b53ca741-1e76-4ddb-b6a5-998b65c4aff3",
        "programId": "d7595bbd-4342-41b4-9037-2e61a9f8403f",
        "reference": "order-2041",
        "reservationId": "checkout-1001",
        "reserved": 0,
        "rewardName": "Free chai",
        "state": "active",
        "transactionId": "add73925-4de9-412c-8cc2-582b074074ca"
      }
    ],
    "limit": 50,
    "offset": 0
  },
  "requestId": "bad43710-25ae-42bd-bb6e-3e37db4205c6",
  "success": true
}

Read one reservation

GET/reservations/{id}

Scopeloyalty:read

Requires loyalty:read. A reservation belongs to the application that made it; another application or business reads it as 404.

Path

iduuidRequired

Returns 200

reservationIdstringRequired
stateenumRequired
Read from the clock. One of active, confirmed, released, expired.
amountintegerRequired
Balance units held.
balanceintegerRequired
The membership's balance now; a hold never moves it.
reservedintegerRequired
Held by every active hold on the membership now.
availableintegerRequired
balance less reserved, never below zero.
balanceAfterinteger or nullRequired
currencystring or nullRequired
customerIdstring or nullRequired
Null for a gift card with no customer.
externalCustomerIdstringRequired
giftCardIdstring or nullRequired
Set when the hold is on a gift card; then programId and membershipId are null.
membershipIdstring or nullRequired
programIdstring or nullRequired
referencestringRequired
rewardNamestring or nullRequired
transactionIdstring or nullRequired
The ledger row of the confirmed spend (the counter's pass event for a gift card).
createdAtstringRequired
expiresAtstringRequired
decidedAtstring or nullRequired
duplicatebooleanRequired
Request
curl "https://app.revisit.cards/v1/developer/reservations/e01b010d-2c65-48e1-83a0-acad79f8d3b4" \
  -H "Authorization: Bearer $DEVELOPER_API_KEY"
Response
{
  "data": {
    "amount": 1250,
    "available": 7,
    "balance": 7,
    "balanceAfter": 7,
    "createdAt": "2026-11-03T08:41:12.000Z",
    "currency": "BDT",
    "customerId": "eb83b9c0-5619-432d-b857-cef7fcf84edb",
    "decidedAt": "2026-11-03T08:41:12.000Z",
    "duplicate": false,
    "expiresAt": "2026-11-03T08:41:12.000Z",
    "externalCustomerId": "user-42",
    "giftCardId": "9c83a2c5-ee43-4698-bd57-cbed81fdc409",
    "membershipId": "b53ca741-1e76-4ddb-b6a5-998b65c4aff3",
    "programId": "d7595bbd-4342-41b4-9037-2e61a9f8403f",
    "reference": "order-2041",
    "reservationId": "checkout-1001",
    "reserved": 0,
    "rewardName": "Free chai",
    "state": "active",
    "transactionId": "add73925-4de9-412c-8cc2-582b074074ca"
  },
  "requestId": "f269bdb9-d91c-47a0-a110-4b38c7441f07",
  "success": true
}

Spend a held benefit after the checkout succeeded

POST/reservations/{id}/confirm

Scopeloyalty:write

Requires loyalty:write and an Idempotency-Key. Runs the ordinary redeem or spend and marks the reservation confirmed in one transaction, so the ledger row (transactionId, the one the merchant app shows) and the state commit together. A repeat, under any key, answers the same confirmed reservation (duplicate: true) and spends once; many at once spend once. A reservation that ran out is 409 RESERVATION_EXPIRED and nothing was spent: reconcile the checkout (refund the payment, or reserve again). A released one is 409 RESERVATION_NOT_ACTIVE. This is not one transaction with your payment gateway: Punchd never claims it is. A gift card hold is spent through the counter's own planner, PIN guard and ledger: send the card's pin in the optional body when it has one (403 PIN_REQUIRED / WRONG_PIN leave the hold active); the PIN is compared on the server and is never stored, echoed or part of the retry fingerprint.

Send an Idempotency-Key header. Safe to retry.

Path

iduuidRequired

Body

pinstring
Gift card holds only.

Returns 200

reservationIdstringRequired
stateenumRequired
Read from the clock. One of active, confirmed, released, expired.
amountintegerRequired
Balance units held.
balanceintegerRequired
The membership's balance now; a hold never moves it.
reservedintegerRequired
Held by every active hold on the membership now.
availableintegerRequired
balance less reserved, never below zero.
balanceAfterinteger or nullRequired
currencystring or nullRequired
customerIdstring or nullRequired
Null for a gift card with no customer.
externalCustomerIdstringRequired
giftCardIdstring or nullRequired
Set when the hold is on a gift card; then programId and membershipId are null.
membershipIdstring or nullRequired
programIdstring or nullRequired
referencestringRequired
rewardNamestring or nullRequired
transactionIdstring or nullRequired
The ledger row of the confirmed spend (the counter's pass event for a gift card).
createdAtstringRequired
expiresAtstringRequired
decidedAtstring or nullRequired
duplicatebooleanRequired

Errors

  • 409RESERVATION_EXPIREDthe reservation ran out before it was confirmed. Nothing was spent: reconcile the checkout (refund the payment, or reserve again).
  • 409RESERVATION_NOT_ACTIVEthe reservation is already in another terminal state (confirmed, or released) than this call needs.
  • 403PIN_REQUIRED
Request
curl -X POST "https://app.revisit.cards/v1/developer/reservations/e01b010d-2c65-48e1-83a0-acad79f8d3b4/confirm" \
  -H "Authorization: Bearer $DEVELOPER_API_KEY" \
  -H "Idempotency-Key: 5f0c2a8e-7b1d-4c3e-9a6f-0d4b8e7d6c43" \
  -H "Content-Type: application/json" \
  -d '{
    "pin": "••••"
  }'
Response
{
  "data": {
    "amount": 1250,
    "available": 7,
    "balance": 7,
    "balanceAfter": 7,
    "createdAt": "2026-11-03T08:41:12.000Z",
    "currency": "BDT",
    "customerId": "eb83b9c0-5619-432d-b857-cef7fcf84edb",
    "decidedAt": "2026-11-03T08:41:12.000Z",
    "duplicate": false,
    "expiresAt": "2026-11-03T08:41:12.000Z",
    "externalCustomerId": "user-42",
    "giftCardId": "9c83a2c5-ee43-4698-bd57-cbed81fdc409",
    "membershipId": "b53ca741-1e76-4ddb-b6a5-998b65c4aff3",
    "programId": "d7595bbd-4342-41b4-9037-2e61a9f8403f",
    "reference": "order-2041",
    "reservationId": "checkout-1001",
    "reserved": 0,
    "rewardName": "Free chai",
    "state": "active",
    "transactionId": "add73925-4de9-412c-8cc2-582b074074ca"
  },
  "requestId": "3961adf9-f2c5-45c0-b66a-8e3e24cac265",
  "success": true
}

Free a held benefit after a failed or abandoned checkout

POST/reservations/{id}/release

Scopeloyalty:write

Requires loyalty:write and an Idempotency-Key. Frees the hold at once. Safe to repeat (a released or expired reservation answers its state, 200). A confirmed one is 409 RESERVATION_NOT_ACTIVE: the benefit was spent. Confirm, release and expiry are mutually exclusive terminal transitions of one row: whichever commits first wins.

Send an Idempotency-Key header. Safe to retry.

Path

iduuidRequired

Returns 200

reservationIdstringRequired
stateenumRequired
Read from the clock. One of active, confirmed, released, expired.
amountintegerRequired
Balance units held.
balanceintegerRequired
The membership's balance now; a hold never moves it.
reservedintegerRequired
Held by every active hold on the membership now.
availableintegerRequired
balance less reserved, never below zero.
balanceAfterinteger or nullRequired
currencystring or nullRequired
customerIdstring or nullRequired
Null for a gift card with no customer.
externalCustomerIdstringRequired
giftCardIdstring or nullRequired
Set when the hold is on a gift card; then programId and membershipId are null.
membershipIdstring or nullRequired
programIdstring or nullRequired
referencestringRequired
rewardNamestring or nullRequired
transactionIdstring or nullRequired
The ledger row of the confirmed spend (the counter's pass event for a gift card).
createdAtstringRequired
expiresAtstringRequired
decidedAtstring or nullRequired
duplicatebooleanRequired

Errors

  • 409RESERVATION_NOT_ACTIVEthe reservation is already in another terminal state (confirmed, or released) than this call needs.
Request
curl -X POST "https://app.revisit.cards/v1/developer/reservations/e01b010d-2c65-48e1-83a0-acad79f8d3b4/release" \
  -H "Authorization: Bearer $DEVELOPER_API_KEY" \
  -H "Idempotency-Key: 5f0c2a8e-7b1d-4c3e-9a6f-0d4b8e64fe17"
Response
{
  "data": {
    "amount": 1250,
    "available": 7,
    "balance": 7,
    "balanceAfter": 7,
    "createdAt": "2026-11-03T08:41:12.000Z",
    "currency": "BDT",
    "customerId": "eb83b9c0-5619-432d-b857-cef7fcf84edb",
    "decidedAt": "2026-11-03T08:41:12.000Z",
    "duplicate": false,
    "expiresAt": "2026-11-03T08:41:12.000Z",
    "externalCustomerId": "user-42",
    "giftCardId": "9c83a2c5-ee43-4698-bd57-cbed81fdc409",
    "membershipId": "b53ca741-1e76-4ddb-b6a5-998b65c4aff3",
    "programId": "d7595bbd-4342-41b4-9037-2e61a9f8403f",
    "reference": "order-2041",
    "reservationId": "checkout-1001",
    "reserved": 0,
    "rewardName": "Free chai",
    "state": "active",
    "transactionId": "add73925-4de9-412c-8cc2-582b074074ca"
  },
  "requestId": "0fe18884-8567-42eb-8ae1-bf65db3f76b8",
  "success": true
}