Skip to main content
VENTRY has two distinct door operations, and you probably need both:

Accreditation

Happens once per attendee. The ticket QR is read and a physical wristband is linked to it. From then on, the wristband is their identity.

Zone control

Happens every time someone crosses an inner door. Only the wristband is read, and it is checked against that zone.
Scopes needed: checkins.write (requires manual activation) and, to read the history, checkins.read.
These calls go from your server, never straight from the door application. An API key embedded in a mobile app is, for practical purposes, published. Have your app talk to your backend and let the backend call VENTRY.

Accreditation

The operator scans the ticket QR and then the new wristband:
The wristband is born with the zones of the ticket type plus that specific ticket’s extra_zones, and with its valid days. There is nothing to configure: it all comes from the ticket.
Send the originality signature even when it fails to verify. It is stored anyway, and it is what lets the organiser audit afterwards which wristbands actually got into the event.

Retries

The Idempotency-Key identifies the physical scan. Generate it when the QR is read and keep it for every retry of that accreditation:
If the network drops right after VENTRY redeems the ticket, the retry returns the same wristband instead of issuing a second one.

What can go wrong

Double accreditation. When two doors try to accredit the same ticket, only one wins. The second gets 409 ticket_already_claimed and the wristband just issued is left in pending_review: it can be scanned — so security is alerted — but it cannot spend balance.VENTRY does not decide blindly which one is right: it may be the same operator retrying at another door, or a duplicated QR. A supervisor resolves it from the dashboard. Your application should show the message and ask staff to call someone, not retry.

Zone control

The operator scans only the wristband, at the door of an inner zone:
Denying is not an error. The response is always 200, with allowed: true or false and the reason. A 403 would mean your API key lacks permission, which is something else entirely: if you lump both cases into the same catch, you will end up denying legitimate entries when your key expires.
Denial reasons you will see (returned in Spanish): Every call is recorded in the scan history, so the operation shows up in the organiser’s statistics attributed to your integration.

Reading the history

Reference implementation