Pass API
Reference

/api/dashboard

The merchant web dashboard — 41 routes behind a session cookie.

Session-authenticated, OWNER or MANAGER only. The tenant comes from the session and never from the URL, so a signed-in user can only ever reach their own merchant. A session opened on the scanner is refused here with a 403 even when its role would otherwise pass.

Some writes narrow further to OWNER — the business profile, the API key, images, and firing a notice at every pass. Those return 403 for a MANAGER.

Session

MethodPath
POST/api/dashboard/loginEmail and password, scoped by tenant slug
POST/api/dashboard/logout204
GET/api/dashboard/meThe signed-in user, their role and branch

Programs

A Program is one scheme with one type — STAMPS, POINTS, COUPON or TICKET.

MethodPath
GET/api/dashboard/programsList
POST/api/dashboard/programsCreate. 201
GET/api/dashboard/programs/{id}One Program with its rules, card fields and images
PUT/api/dashboard/programs/{id}Full replacement, child collections included
DELETE/api/dashboard/programs/{id}204. DRAFT only — a published Google class is permanent
POST/api/dashboard/programs/{id}/publishDRAFT → LIVE. Irreversible
POST/api/dashboard/programs/{id}/archiveStop issuing without deleting
POST/api/dashboard/programs/{id}/unarchiveBack to LIVE, reusing the same Google class
GET/api/dashboard/programs/{id}/card-layout-upgradePreview what an upgrade would change
POST/api/dashboard/programs/{id}/card-layout-upgradeApply it. A no-op on anything past layout version 1

PUT replaces everything except slug and, on a TICKET, the venue trio's opt-in rules. An omitted slug keeps the one the Program has — there is no way to un-print a poster.

Card design

MethodPath
POST/api/dashboard/programs/{programId}/images/{kind}Upload. Replaces the kind if present. 201
DELETE/api/dashboard/programs/{programId}/images/{imageId}204
GET/api/dashboard/programs/{programId}/apple-sample.pkpassA signed sample pass for previewing. 503 without a signing certificate

Notices

MethodPath
POST/api/dashboard/programs/{programId}/noticesSend to a program or one pass. 202 — it queues
POST/api/dashboard/programs/{programId}/notices/previewRender the tokens without sending
GET/api/dashboard/programs/{programId}/noticesThe send report. Paginates; filters on status and batchId

Firing at every pass is OWNER only — it is unbounded and cannot be recalled.

Customers

MethodPath
GET/api/dashboard/customersPaginated CRM list. Filters: phone, name, enrolledFrom, enrolledTo, hasConsent, sort
GET/api/dashboard/customers/{id}One customer, their passes and their form answers
GET/api/dashboard/passes/{passId}/transactionsThe append-only ledger for one pass

Branches

MethodPath
GET/api/dashboard/locationsList
POST/api/dashboard/locationsCreate. 201
GET/api/dashboard/locations/{id}One branch with its business hours
PUT/api/dashboard/locations/{id}Update. Re-pushes every live Program that pins it
DELETE/api/dashboard/locations/{id}Close (soft delete). 204

Staff

MethodPath
GET/api/dashboard/staffList
POST/api/dashboard/staffCreate. 201
GET/api/dashboard/staff/{id}One staff member
PUT/api/dashboard/staff/{id}Update
DELETE/api/dashboard/staff/{id}204
POST/api/dashboard/staff/{id}/pairing-tokenMint the QR a scanner device pairs with
DELETE/api/dashboard/staff/{id}/deviceUnpair — the "lost phone" button. Idempotent, never a 404

Merchant profile

MethodPath
GET/api/dashboard/tenantThe public business page's content
PUT/api/dashboard/tenantFull replacement. OWNER only
POST/api/dashboard/tenant/images/{kind}Logo or cover. 201. OWNER only
DELETE/api/dashboard/tenant/images/{imageId}204. OWNER only
GET/api/dashboard/tenant/api-keyPartner key status
POST/api/dashboard/tenant/api-keyMint or rotate. OWNER only
DELETE/api/dashboard/tenant/api-keyRevoke. OWNER only

Custom fields

MethodPath
GET/api/dashboard/custom-fieldsList the merchant's question bank
POST/api/dashboard/custom-fieldsCreate. 201
PUT/api/dashboard/custom-fields/{id}Update
DELETE/api/dashboard/custom-fields/{id}204

A field is defined once per merchant and selected per Program; the answers belong to the enrollment, not to the person.

On this page