Use your membership card at the bar (VIP)

Mint a membership card, see what VIP adds to it, and understand what a bar scan does and does not do.

Owned by VIP Member · 8 steps · about 12 minutes

Why this exists

A membership card is a pass with no ticket behind it. It exists so that being a member is itself a credential: it opens the zones your groups map to, plus the bar pseudo-zone, and it is re-issued automatically whenever your groups change.

This is where VIP status stops being a label. The zone map gives an ordinary member the general zone and a VIP member the general zone and Zone B — so the same card, scanned at the same reader, opens a room for one person and not the other. Nothing about the scan is a judgement call by staff.

The bar reader is a special case in the scan pipeline: it returns green with your credit summary attached — prepaid balance and remaining tab headroom — and it deliberately does not record a check-in. It is a look-up, not a turnstile, and above all it charges nothing. The scan tells the bartender what you are good for; the actual spend is a separate transaction on the ledger. Read that twice before you demo it, because "the scan took my money" is a misconception that spreads fast.

The plumbing behind the re-issue is worth knowing: any grant or revoke of a zone-carrying group fires a pass refresh, which revokes the old card and mints a new one with your current zones. That is why losing VIP takes Zone B away immediately rather than at the end of the month.

Corrected 2026-08-24 (end2end). This section used to warn of "one documented gap — editing the zone map for a whole group does not refresh cards that are already issued". Plan 21 closed it. set_group_zones now fans a refresh out to existing holders, queued rather than run inline so that re-zoning a four-thousand-member tier does not block the admin's request. A card in a wallet catches up on the next sweep, not on the next re-issue.

Before you start

  • A member or VIP session.
  • For the scan step: an employee session (door staff, venue manager or admin) or a provisioned bar reader.
  • An admin session for the tab step.

Practise with

PersonaEmailPasswordNote
vip_membervip@club.test vip123seeded membership card, $250 tab limit with $80 used
membermember@club.test member123an ordinary card, for the side-by-side zone comparison
door_staffdoor@club.test door123works the bar reader
adminadmin@club.test admin123sets and freezes tab limits

Steps 1–2 — Member

their manual →

Holds the same card without Zone B — the contrast is the lesson.

  1. 1
    As an ordinary member with no card yet, open your wallet and press Get my membership card.
    Expected result A card appears with the general zone and the bar zone.
    Watch out for Corrected 2026-08-24 (end2end): this used to say the no-script fallback posted to a route that does not exist. It posts to the real endpoint and carries a CSRF field, so it works without script. What it does not do is come back to a page — the endpoint answers with JSON, so a browser with script blocked lands on the raw record instead of the wallet. Use the button.
  2. 2
    Call the issuing endpoint yourself to see that it is idempotent.
    Expected result The same live card returned again, not a second one.
    Watch out for One live membership card per user is a database constraint, not a convention. You cannot accumulate cards.

Steps 3–4 — VIP Member

their manual →
  1. 3
    Now do the same as the VIP account and compare the zone list on the two cards.
    Expected result The VIP card carries Zone B in addition to the general zone and the bar zone.
    Watch out for The zones are snapshotted into the card when it is minted. This is why the platform re-mints on every group change instead of computing zones at scan time.
  2. 4
    Pull the rotating code for the card, exactly as for a ticket pass.
    /api/access/passes/{pass_id}/qr access
    Expected result A payload with the seconds remaining on the current 15-second step.

Steps 5 — Door Staff

their manual →

Scans the card at the bar and reads the credit summary off the verdict.

  1. 5
    At the bar reader, scan the card.
    /api/access/scan POST access
    Expected result Green, the holder's name, and a credit block showing prepaid balance and remaining tab headroom.
    Watch out for This scan records no check-in and moves no money. It authorises; it does not charge. Serving the drink and charging the tab are separate acts, and the second one is not this endpoint.

Steps 6 — VIP Member

their manual →
  1. 6
    Open your credit page and confirm the numbers the bartender just saw.
    /my/credit ledger
    Expected result Prepaid, earned, and the tab with its limit, used and headroom.
    Watch out for The tab is a limit on what you may owe, not a balance you hold. Headroom shrinking is you borrowing more, not you spending savings.

Steps 7–8 — Admin

their manual →

Owns the tab limit and its frozen state; VIP status alone creates no headroom.

  1. 7
    As an admin, set the VIP's tab limit — or freeze it.
    /api/admin/credit/users/{user_id}/tab PUT ledger
    Expected result The tab row with its new limit or status.
    Watch out for Freezing stops further spending; it does not forgive the balance. Revoking VIP status freezes the tab automatically for the same reason, and the money stays owed.
  2. 8
    Revoke the VIP grant on a throwaway account and then look at that account's wallet.
    /admin/users/{user_id} rbac
    Expected result The old card is revoked and superseded by a fresh card without Zone B.
    Watch out for Corrected 2026-08-24 (end2end): the refresh fires on grant and revoke, AND on a zone-map edit — plan 21 added the fan-out that this line used to say was missing. The fan-out is queued, so a card in a wallet catches up on the next sweep rather than the instant an admin saves the map.