Skip to content

Vouchers

Operator endpoints for gift vouchers: configure what guests can buy, issue complimentary or paid vouchers yourself, and look up and redeem codes at the till. All routes are scoped to a venue you can access; issuing and redeeming require the operator role (client). Guest voucher purchase runs through the widget endpoints.

Method Path Purpose Auth
GET /api/my-venues/:venueId/voucher-settings Read voucher configuration operator
PUT /api/my-venues/:venueId/voucher-settings Update voucher configuration operator
GET /api/my-venues/:venueId/vouchers List issued vouchers operator
POST /api/my-venues/:venueId/voucher-intent Start payment for a paid voucher operator
POST /api/my-venues/:venueId/vouchers Issue a voucher (comp or paid) operator
GET /api/my-venues/:venueId/vouchers/lookup Preview a voucher by code operator
POST /api/my-venues/:venueId/vouchers/redeem Redeem a voucher code operator
GET /api/my-venues/:venueId/vouchers/:id/payment A voucher’s payment and refund/cancel eligibility operator
GET /api/my-venues/:venueId/vouchers/:id/history A voucher’s lifecycle timeline operator
POST /api/my-venues/:venueId/vouchers/:id/refund Refund a paid voucher’s payment and void it operator
POST /api/my-venues/:venueId/vouchers/:id/cancel Cancel a voucher without a refund operator
POST /api/my-venues/:venueId/vouchers/:id/resend Re-send a voucher to its recipient or purchaser operator
POST /api/my-venues/:venueId/vouchers/:id/resend-receipt Re-send the purchase receipt to the purchaser operator
POST /api/my-venues/:venueId/vouchers/:id/reassign-purchaser Change who bought a voucher operator

GET returns the current settings merged with defaults; PUT upserts them. Amounts are in pence, fixed_amounts is an array of preset values (or null for none), and min_amount_pence must not exceed max_amount_pence.

Terminal window
curl -X PUT "https://thesidedoor.co/api/my-venues/VENUE_ID/voucher-settings" \
-H "Authorization: Bearer $SIDEDOOR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"enabled": true,
"expiration_months": 12,
"min_amount_pence": 2500,
"max_amount_pence": 50000,
"fixed_amounts": [2500, 5000, 10000],
"allow_custom": true,
"min_qty": 1,
"max_qty": 10,
"terms": "Valid for 12 months. Not redeemable for cash."
}'
{ "success": true }

Reading the settings back:

Terminal window
curl "https://thesidedoor.co/api/my-venues/VENUE_ID/voucher-settings" \
-H "Authorization: Bearer $SIDEDOOR_TOKEN"
{
"data": {
"venue_id": "ven_123",
"enabled": 1,
"expiration_months": 12,
"min_amount_pence": 2500,
"max_amount_pence": 50000,
"fixed_amounts": [2500, 5000, 10000],
"allow_custom": 1,
"min_qty": 1,
"max_qty": 10,
"terms": "Valid for 12 months. Not redeemable for cash."
}
}

Returns vouchers for the venue and every other venue in its group, newest first. The result is paginated (default 25 per page) and filterable:

  • ?status= - only vouchers in that status (e.g. active, redeemed, expired).
  • ?q= - free-text search matching a voucher code or the recipient’s or purchaser’s name or email.
  • ?venue_id= - narrow to a single venue in the group.
  • ?page= / ?limit= (or ?offset=) - page through the results. To read the full set, keep paging while has_more is true.

The response wraps the page in data alongside total, limit, offset and has_more. It also includes stats (a per-status count and balance for the whole group, not just this page) and venues (the distinct venues in the group that have vouchers, handy for building a venue filter).

Terminal window
curl "https://thesidedoor.co/api/my-venues/VENUE_ID/vouchers?status=active&page=1&limit=25" \
-H "Authorization: Bearer $SIDEDOOR_TOKEN"
{
"data": [
{
"id": "vch_1",
"code": "A1B2-C3D4-E5F6",
"amount_pence": 5000,
"status": "active",
"expires_at": "2027-07-03",
"venue_id": "ven_123",
"venue_name": "The Attic"
}
],
"total": 1,
"limit": 25,
"offset": 0,
"has_more": false,
"stats": {
"active": { "n": 1, "bal": 5000 },
"redeemed": { "n": 0, "bal": 0 },
"expired": { "n": 0, "bal": 0 }
},
"venues": [{ "id": "ven_123", "name": "The Attic" }]
}

Issue a comp voucher directly - no payment. The comp/paid selector is the mode field; anything other than "paid" is treated as "comp".

Terminal window
curl -X POST "https://thesidedoor.co/api/my-venues/VENUE_ID/vouchers" \
-H "Authorization: Bearer $SIDEDOOR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"amount_pence": 5000,
"mode": "comp",
"recipient_name": "Sam Lee",
"recipient_email": "sam@example.com",
"message": "Thanks for being a great guest!"
}'
{ "success": true, "id": "vch_2", "code": "G7H8-J9K0-L1M2", "emailed": true }

For a paid voucher, first start payment with POST /api/my-venues/:venueId/voucher-intent (amount_pence, min 50). Sidedoor handles the secure card step; once payment succeeds, issue the voucher with mode: "paid" and the returned payment_intent_id.

Terminal window
# 1. Create the PaymentIntent
curl -X POST "https://thesidedoor.co/api/my-venues/VENUE_ID/voucher-intent" \
-H "Authorization: Bearer $SIDEDOOR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"amount_pence":5000}'
# 2. After payment succeeds, issue the voucher
curl -X POST "https://thesidedoor.co/api/my-venues/VENUE_ID/vouchers" \
-H "Authorization: Bearer $SIDEDOOR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"amount_pence":5000,"mode":"paid","payment_intent_id":"pi_...","recipient_email":"sam@example.com"}'
{ "intent_id": "pi_...", "amount_pence": 5000 }

Preview a code before redeeming - check the balance, status and whether it is redeemable at this venue. Codes are accepted grouped (XXXX-XXXX-XXXX) or as a plain 12-character string. This endpoint is rate-limited (429 + Retry-After).

Terminal window
curl "https://thesidedoor.co/api/my-venues/VENUE_ID/vouchers/lookup?code=A1B2-C3D4-E5F6" \
-H "Authorization: Bearer $SIDEDOOR_TOKEN"
{
"found": true,
"voucher": {
"id": "vch_1",
"code": "A1B2-C3D4-E5F6",
"amount_pence": 5000,
"status": "active",
"expires_at": "2027-07-03",
"venue_name": "The Attic"
},
"redeemable": true,
"reason": "ok"
}

Mark a voucher as redeemed. Send the code and an optional note. The response carries a reason: ok on success, or one of not_found, wrong_venue, refunded, cancelled, already_redeemed or expired on failure (with success: false).

Terminal window
curl -X POST "https://thesidedoor.co/api/my-venues/VENUE_ID/vouchers/redeem" \
-H "Authorization: Bearer $SIDEDOOR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"code":"A1B2-C3D4-E5F6","note":"Redeemed against table 12"}'
{
"success": true,
"reason": "ok",
"voucher": { "id": "vch_1", "code": "A1B2-C3D4-E5F6", "amount_pence": 5000, "status": "redeemed" }
}

These actions work on a single issued voucher, by its id (not its code).

GET .../vouchers/:id/payment reads what was paid, the payment policy locked in at purchase (advisory only - staff can override it), and whether a refund or cancellation is currently allowed.

Terminal window
curl "https://thesidedoor.co/api/my-venues/VENUE_ID/vouchers/vch_1/payment" \
-H "Authorization: Bearer $SIDEDOOR_TOKEN"
{
"payment": {
"amount_pence": 5000,
"amount_paid_pence": 5000,
"paid": true,
"status": "active",
"stripe_ref": "pi_..."
},
"policy": { "refund_type": "full", "cancel_type": "anytime" },
"can_refund": true,
"can_cancel": true,
"refund_amount_pence": 5000
}

GET .../vouchers/:id/history returns its lifecycle as an entries array (created, redeemed, refunded, cancelled or expired, each with an at timestamp and, where relevant, an actor).

POST .../vouchers/:id/refund refunds the full amount paid via Stripe and voids the voucher so it can no longer be redeemed - only an active, paid voucher can be refunded. POST .../vouchers/:id/cancel voids a voucher (paid or complimentary) without a refund.

Terminal window
curl -X POST "https://thesidedoor.co/api/my-venues/VENUE_ID/vouchers/vch_1/refund" \
-H "Authorization: Bearer $SIDEDOOR_TOKEN"
{ "success": true, "status": "refunded", "refunded_pence": 5000 }

cancel returns { "success": true, "status": "cancelled" } the same way.

POST .../vouchers/:id/resend re-sends the voucher by email, to the recipient (default) or the purchaser - handy when the original send bounced or went to the wrong inbox. POST .../vouchers/:id/resend-receipt re-sends the purchase receipt to the purchaser.

Terminal window
curl -X POST "https://thesidedoor.co/api/my-venues/VENUE_ID/vouchers/vch_1/resend" \
-H "Authorization: Bearer $SIDEDOOR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"target":"recipient"}'
{ "success": true, "emailed": true, "channels": ["email"] }

resend-receipt takes no body and returns { "success": true }.

POST .../vouchers/:id/reassign-purchaser changes who bought a voucher - pass a user_id for one of your own guests, or guest_name for a walk-in with no account. The new purchaser must belong to your own roster; a bare call with neither field is rejected.

Terminal window
curl -X POST "https://thesidedoor.co/api/my-venues/VENUE_ID/vouchers/vch_1/reassign-purchaser" \
-H "Authorization: Bearer $SIDEDOOR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"user_id":"usr_def"}'
{ "success": true }