Build my booking setup

QR & Access Control

One scan, one entry. Every time.

Redemption is a single conditional write in the database, not a read followed by a write. Two doors scanning the same code within the same second still only ever let one person through.

  • 1 conditional update Redeeming is one SQL write guarded by the ticket's current status, never a read followed by a write
  • Undo lives off the scanner Reversing a redemption is an admin-only action, never available on the scanning screen itself
  • Void is final A voided ticket has no path back. There is no "un-void"

Four pieces of the door.

Each one protects a different part of what happens the moment a code gets scanned.

01

Camera or photo, no heavy library

Scanning works with the browser's own native recognition where available, and falls back to uploading a photo everywhere else, with no bundled scanning library either way.

02

Redeem, atomically

Marking a ticket used is a single write, conditioned on it still being issued. Two near-simultaneous scans of the same code, from two different doors, never both succeed.

03

Void and undo, kept apart on purpose

Only the back office can void a ticket or undo a redemption, never the scanning screen. Giving gate staff both powers would let a used ticket get "undone" on the spot to let a second person in on the same code.

04

External vouchers, downloaded securely

A voucher file is never served from a public URL. Every download goes through an authenticated route that also verifies the file genuinely belongs to the ticket being requested.

How it resolves

How a scan turns into a decision at the door

Five steps, every single time a code gets scanned or entered manually.

  1. 1

    The code gets looked up

    A scanned or manually entered code resolves to its ticket, or returns a clear "not found" without hinting at whether that code ever existed at all.

  2. 2

    The status gets checked inside the same write

    Redemption is one UPDATE with a condition requiring the ticket still be issued. If zero rows are affected, nothing changed, and the reason gets reported back from a fresh read right after.

  3. 3

    Only one scan ever wins the race

    Because the status check and the write happen as a single atomic operation, two doors racing to scan the same code at the same instant can never both succeed.

  4. 4

    An event gets recorded either way

    Every transition, successful or not, writes who triggered it, from where, scan or admin action, and when, so a disputed entry can always be reconstructed.

  5. 5

    Undo and void stay behind their own gate

    Reversing a redemption or voiding a ticket exists only as a back-office action behind its own permission, entirely separate from the permission that lets someone scan at the door.

The API, as it is

What the door actually sees

Product, option, ticket type, date, position in the order, buyer name and fulfillment status. Never a price, never a margin, never anything gate staff doesn't need to make a decision.

POST /api/v1/tickets/redeem
  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
{
  "ticket_code": "AB12CD34EF",
  "status": "redeemed",
  "redeemed_at": "2026-08-14T10:00:00Z",
  "position": 2,
  "quantity": 3,
  "product_name": "City Food Tour",
  "buyer_name": "Jane Buyer",
  "fulfillment_status": "not_required"
}
200 Ticket redeemed

The detail almost nobody explains

Zero rows affected still tells the whole story

When the conditional update touches no rows, that alone doesn't say why. The system immediately re-reads the ticket to report the real cause, already redeemed, with a timestamp and who did it, or voided, rather than a generic failure. That check happens after the write on purpose: doing it before would reopen the exact race the atomic write exists to close.

Frequently asked questions

No. Redemption is a single database write conditioned on the ticket still being issued. Whichever scan reaches the database first wins that condition; the second finds zero rows affected and gets "already redeemed" instead.

Not from the scanning screen. Undoing a redemption exists only as a back-office action behind its own permission. Letting the same staff who scans also undo would open a real path for letting a second person in on an already-used code.

No. Voiding is terminal by design; there is no "un-void" anywhere in the system. A mistaken void needs a new ticket, not a reversal.

No. The redemption response is deliberately limited to what gate staff needs to make a decision: product, option, ticket type, date, buyer name, position within the order and fulfillment status.

They're never served from a public URL at all. Every download goes through an authenticated route that also checks the file genuinely belongs to the ticket being requested, not just that the requester is logged in.

More bookings. More channels. The same calm.

Tiqory keeps availability, pricing, payments and access working together as your operation grows. Tell us where you are headed; we’ll show you how to get there without starting over.