Skip to content

API reference

General rules are in Integration conventions.

Base: https://test-api.finnsbali.com · Authorization: Bearer <gate token>

POST /api/v1/gate/check-ins HTTP/1.1
Host: test-api.finnsbali.com
Authorization: Bearer <gate token>
Content-Type: application/json
{ "gateId": "beach-club-main-1", "qr": "FINNS1:q3V0…" }
Field Rule
gateId Your gate’s id, [a-z0-9-]{1,64}, agreed with FINNS
qr The scanned text, verbatim
Status Body Meaning
200 {"result": "granted"} Let them in. Points were credited.
200 {"result": "denied", "reason": "expired"} QR too old; ask the member to refresh
200 {"result": "denied", "reason": "used"} QR already used
200 {"result": "denied", "reason": "unknown"} Not a QR core issued
200 {"result": "denied", "reason": "malformed"} Not a valid QR
400 problem detail, malformed Bad gateId or missing field: a bug in the gate
401 empty Wrong or missing gate token

A denial is a normal 200, not an error. Treat unknown future reason values as a generic denial.

The timings below are examples. What matters is the behaviour: one scan at a time, and no entry without granted.

  • Set a timeout (for example 5 seconds) and treat it as “unavailable”; never let a guest in without granted.
  • Handle one scan at a time; ignore the same text for a short while after its result (for example 10 seconds).
  • Refuse locally, without calling core, anything that doesn’t start with FINNS; show “this gate can’t read this code yet” for an unknown FINNSn: version (the gate needs an update).
  • Never log the QR text or the token.

Internal and confidential. Share partner sections only as partner builds (pnpm build:partner).