Membership Club — Training Manual

The complete manual in one document: every persona, then every workflow by area. Filtered to one area. Generated 2026-08-31T04:05:12Z · content revision 2026-08-30T21:54:00Z.

Back to training

Contents

Part 1 — By persona

Part 2 — By area

Appendices

Customer (Guest)

Anyone on the public site who has not logged in yet.

You are the public. You have no account, no groups and no session — and a surprising amount of the platform is deliberately open to you: the event catalogue, an event's tier and price breakdown, the resale exchange window, the host application form, a comp-invite claim link and a contract signing link.

That is a design decision, not an oversight. Every gate in this platform is enforced at the moment of the action, never by hiding the page. A customer must be able to see what is on sale, and a prospective promoter must be able to apply, before either of them has an account.

The moment you need to own something — a ticket, house credit, a listing — you become a Member. Registering is the boundary.

Core workflows (4)

Takes part in (2)

What this persona cannot do

Without a session you cannot:

  • hold a reservation, check out or pay — the cart and checkout pages require the member group;
  • see anyone's tickets, orders, credit balance or wallet passes;
  • open any /admin/* surface or the door scanner.

Anonymous requests that need a session get an HTML redirect to /login?next=…, or a 401 envelope for JSON.

Member

A registered customer: buys, holds tickets, house credit and resale listings.

You are the platform's centre of gravity. Registering grants the member group automatically, and with it every customer-owned surface: the cart and checkout, your orders and tickets, your wallet passes, your house credit balance and statement, and the resale exchange as both a seller and a buyer.

Your hub is /my. Everything you own hangs off it — /my/tickets, /my/orders, /my/credit, /account/passes. Note the shape of those URLs: the member portal lives under /my/* and /account/*, and every one of those routes scopes its query to your user id. A member cannot read another member's order even by guessing the id — the lookup 404s rather than 403s, so ids cannot be probed.

Core workflows (13)

Takes part in (18)

  • Browse events as a guest — owned by Customer (Guest), your step 9. Shows the same pages with a session, so the difference is visible rather than described.
  • Create your member account — owned by Customer (Guest), your steps 3–6. The account you just made — everything after the redirect is theirs, including the verification the first purchase waits on.
  • Create and launch an event — owned by Host / Promoter, your step 15. The reason the whole thing exists — they are who finally sees it on sale.
  • Buy a ticket — owned by Customer (Guest), your steps 6–13. Everything from the cart onwards needs a session — the buying half is theirs.
  • Understand your event's tiers, prices and releases — owned by Host / Promoter, your step 11. The buyer the whole release schedule is designed for.
  • Refund a ticket or an order — owned by Admin, your steps 1–8. It is their money and their ticket — and where it lands depends on the policy, not on what they ask for.
  • Read the scanner screen — owned by Door Staff, your steps 9–10. Presents the credential — and can show you what the rotating QR looks like from their side.
  • Diagnose a red scan — owned by Door Staff, your step 9. Is the guest at the window, and usually holds the fix on their own phone.
  • Use your membership card at the bar (VIP) — owned by VIP Member, your steps 1–2. Holds the same card without Zone B — the contrast is the lesson.
  • Open or close the resale exchange — owned by Admin, your step 5. They are the seller and the buyer: the bounds you set are the prices they are allowed to type.
  • Process a payout run — owned by Admin, your steps 1–3. It is their money leaving the platform: they request it and they are the one the identity gate applies to.
  • Post a house credit adjustment — owned by Admin, your step 5. It is their balance that moves, and the correction lands on their statement in full view.
  • Claim your comp invite and name your plus-ones — owned by Customer (Guest), your steps 5–7. The same invite addressed to an account is claimed from the member portal instead of a token link.
  • Build a trigger rule — owned by Venue Manager, your step 9. Is the person whose purchase crosses the threshold that fires the rule.
  • Build a role from capabilities, and tune a membership tier — owned by Admin, your steps 18–19. Is the person a tier is for — and the only one who can confirm the benefit actually landed.
  • Grant and revoke roles — owned by Admin, your step 4. It is their account: the grant is what changes what they can buy and where they can walk.
  • Deactivate a user — owned by Admin, your step 3. It is their account: they are the one who suddenly cannot log in, and they are told nothing.
  • Run the feedback backlog as a build list — owned by Venue Manager, your step 1. Supplies the backlog, and is the only person besides an admin who may edit their own words.

What this persona cannot do

You cannot:

  • reach any /admin/* page, the door scanner, or the debug console;
  • refund your own order at will — self-cancellation is only offered when the event's refund policy sets a cancellation deadline;
  • see or edit another member's data, in any module;
  • issue yourself a comp, a door override or a role.

VIP Member

A member with a house tab and Zone B access. Implies everything a member can do.

You are a member with two extra things: a VIP tab (a credit limit you can spend against and settle later) and a wider door credential — your membership card opens Zone B, not just the general zone.

The group logic matters here. vip_member implies member: the platform's group check expands vip_member to include member, so you are never granted both and never lose member surfaces. Everything on the Member page is yours too — this page only covers the difference.

The tab is deliberately not a wallet. It is an obligation recorded on the double-entry ledger: spending against it raises what you owe, and a scheduled monthly settlement sweeps your prepaid balance first and then charges your card for the remainder. Nothing about it is a discount.

Core workflows (2)

Takes part in (7)

What this persona cannot do

VIP status does not grant staff powers. You cannot:

  • set or raise your own tab limit — only an admin can, and revoking VIP freezes the tab while the balance stays owed;
  • skip the door — a VIP card is scanned like every other credential;
  • reach any admin, scanner or ledger surface.

Host / Promoter

An outside promoter running an event at the venue. Scoped to that one event.

You are an outside party who wants to put on a night at the venue. You are not staff, and the platform is emphatic about that: your grant is a scoped one. A host grant carries an event_id, and the permission check only passes for that event. Two promoters with host grants cannot see each other's events at all.

Your journey starts before you have an account: the application form is public. Approval is what creates your user and your scoped grant — in that order, and never by hand.

Inside your event you are effectively read-only. You can see your event and its sales, you sign the contract, you invite guests against the comp buckets allocated to you. You do not price it, transition it, refund it or touch its money. That separation is the whole point of the contract: it is the record of what the venue agreed to do on your behalf.

Core workflows (11)

Takes part in (11)

What this persona cannot do

Even on your own event you cannot:

  • create the event yourself — it is converted from your approved application by staff;
  • change tiers, prices, capacity or the event's status;
  • issue refunds, read the ledger, or take a payout outside the contracted royalty;
  • see any other promoter's event, or any venue-wide report.

Door Staff

Works the door: scans credentials, searches the guest list, checks people in.

You are the last mile. Your job is two screens — the scanner and the guest list — and a single question per person: green or red.

The design intent is that you never have to decide. The scan endpoint returns a verdict and a reason, and the screen is deliberately loud and colour-coded so it reads at arm's length in the dark. A red scan is not an accusation; it is a reason code (already used, wrong event, outside the door window, listed for resale, revoked) and each one has a different answer.

You are one of the three employee groups. That is a pseudo-group — a gate meaning "door staff or venue manager or admin" — and it is what opens the scanner. It is not a grantable group: nobody is ever given "employee", they are given door_staff, venue_manager or admin.

Core workflows (5)

Takes part in (14)

  • Find your way around as staff — owned by Venue Manager, your steps 8–9. Learns the two screens their role actually opens, and what a 403 there means.
  • Monitor live sales on the night — owned by Venue Manager, your step 9. Supplies the other half of the picture — how many of the sold tickets actually walked in.
  • Get through the door — owned by Member, your steps 5–6. Scans the credential and reads the verdict out loud.
  • Use your membership card at the bar (VIP) — owned by VIP Member, your step 5. Scans the card at the bar and reads the credit summary off the verdict.
  • Run the door offline — owned by Venue Manager, your steps 5–7. Actually works the queue in offline mode and presses Sync now when the network returns.
  • Resell a ticket you can't use — owned by Member, your step 6. Shows the consequence of listing: the seller's own credential now scans red.
  • Buy a ticket on the resale exchange — owned by Member, your step 9. Confirms the new pass works and the seller's old one does not.
  • Allocate comps to a promoter — owned by Venue Manager, your step 9. Turns the names in the bucket into people in the room, and lives with your plus-one decisions.
  • Claim your comp invite and name your plus-ones — owned by Customer (Guest), your steps 8–9. Finds the guest by name on the night and checks them in with their plus-ones.
  • Invite a guest and track plus-ones — owned by Host / Promoter, your steps 11–12. Finds the name on the night and counts the plus-ones in.
  • Revoke a comp — owned by Venue Manager, your step 6. Meets the consequence at the door if the revocation lands after the guest arrives.
  • Grant and revoke roles — owned by Admin, your step 8. A door_staff grant is the thing that opens the scanner at all.
  • Map groups to door zones — owned by Admin, your steps 4–7. The map decides which reader turns green for them and for the guests they scan.
  • Deactivate a user — owned by Admin, your step 4. The revoked credential fails at their reader and they must not mistake it for a broken scanner.

What this persona cannot do

Your access is narrow on purpose. You cannot:

  • open any admin dashboard, ledger, payout or tax surface;
  • download the offline sync bundle or the push feed from a browser — those carry every pass secret, so they need a venue manager session or a provisioned reader's device token;
  • create or revoke passes, refund anything, or change a role;
  • allocate comps — you check in the guests a manager or promoter listed.

Venue Manager

Runs the floor and the calendar: intake review, live sales, the door, marketing.

You run the venue day to day. venue_manager implies door_staff, so everything on the Door Staff page is yours as well — plus the surfaces a shift lead actually needs: the host application queue, the live sales dashboards, the guest list allocations, the door overrides, the access-control readers view and the marketing tools.

What you will notice is where the platform stops you, and it is worth understanding why rather than filing a ticket about it. You are trusted with operations; you are not trusted with money and identity. Payouts, refunds, the ledger, the tax office, role management and the universal data suite are all admin-only. That boundary means a manager can be hired, trained and given the floor on day one without ever being able to move a cent or grant themselves a group.

Core workflows (17)

Takes part in (24)

What this persona cannot do

You are a 403 on all of these, by design:

  • the ledger, trial balance and adjustments;
  • refunds and the payout queue;
  • the tax office;
  • role grants and revocations;
  • the universal admin data suite and its audit log;
  • transitioning an event's status and editing tiers or prices.

You can read most of the dashboards those things feed — the boundary is on writing, and on the surfaces where money is decided.

Admin

Owns money, identity and configuration. Implies every other group.

Admin is not "manager plus a bit". The permission check special-cases it: admin implies everything, including every event-scoped host grant. There is no surface in this platform you cannot open.

What is genuinely yours alone is the set of decisions that are hard to reverse: money out (refunds, payouts, ledger adjustments), identity (who is in which group), the contract counter-signature that binds the venue, the tax filings that go to an agency in the post, and the universal data suite that can edit any row in the database.

Two habits the design assumes of you. First, the ledger is append-only — enforced by database triggers, not convention — so you correct a mistake by posting a compensating entry, never by editing history. Second, everything you do through the data suite and the debug console is audited with a full before/after row snapshot. Both exist so that "the admin fixed it by hand" is always a readable event rather than a mystery.

Core workflows (24)

Takes part in (43)

What this persona cannot do

There is no group above you, so the limits are structural rather than permission-based:

  • you cannot UPDATE or DELETE an append-only table — the ledger, the audit logs and the sealed contract documents refuse the write at the database level, even from the data suite;
  • you cannot un-send a mailed tax filing or un-seal a signed contract;
  • you cannot grant the pseudo-group employee — it is a gate, not a grantable group.

Guest List & VIP

Comp allocations, invites, plus-ones and door overrides.

Allocate comps to a promoter

Create buckets with hard caps, hand one to a promoter, and watch the utilisation.

Owned by Venue Manager · 10 steps · about 16 minutes

Why this exists

Comps are allocated in buckets, and the bucket is the unit of trust. Rather than granting a promoter the abstract right to add names, you give them a named allotment with a hard total, a tier, and a default plus-one allowance, and then let them fill it themselves. The venue keeps the ceiling; the promoter keeps the list.

The counting rule is the thing people get wrong, so learn it first: allocation counts plus-one ALLOWANCES at the moment the entry is created, not the plus-ones that actually get named. An entry with a two-plus-one allowance consumes three from the bucket immediately, whether or not anyone is ever named. That is what makes the ceiling real — a bucket of ten cannot turn into thirty on the night — and it is why a promoter who hands out generous allowances runs out of names faster than they expect.

The tier on the bucket is not just a price label; it determines the zones the resulting pass opens. A comp issued against the VIP tier gets VIP zones at the door. Putting a promoter's bucket on the VIP tier because it was the first one in the dropdown is how you end up with fifty people in a room built for twenty.

Everything a bucket produces is real: a zero-value ticket on a zero-value paid order, drawing on the same inventory a paying customer draws on, with a genuine door pass. No money moves and no ledger entry is written, but capacity absolutely does — a sold-out tier will refuse a comp with insufficient inventory.

Before you start

  • A venue manager or admin session.
  • An event with at least one tier — the bucket must point at a tier of that event.
  • For the promoter half: a scoped host user on the event. The seed ships promoter@demo.club on demo-event-0001.

Practise with

PersonaEmailPasswordNote
venue_managermanager@club.test manager123shift lead: implies door_staff, plus intake, sales, guest list, marketing
host_promoterpromoter@demo.club promoter123scoped host on demo-event-0001; owns the seeded Promoter X comp bucket
adminadmin@club.test admin123the only account that can touch money, identity and contracts
door_staffdoor@club.test door123door shift account: scanner + guest list, nothing else

Steps 1–6 — Venue Manager

their manual →
  1. 1
    Open the guest-list index and pick the event you are allocating for.
    /admin/guestlist guestlist
    Expected result Events with their guest-list activity.
    Watch out for Door staff get a 403 on this index. It is a planning surface, not a door surface.
  2. 2
    On the event dashboard, read the existing buckets first: each shows its allocation total, consumed and remaining, and its status.
    /admin/guestlist/{event_id} guestlist
    Expected result The seeded Promoter X bucket (10 allocated, one plus-one by default) and Artist Guest List (15, manual issue policy).
    Watch out for Consumed is recomputed live from the entries, not stored as a counter. If it disagrees with your head, the entries are right.
  3. 3
    Use the Create bucket form: give it a name, an owner type (promoter, artist, house, staff or other), the owning host user if it belongs to one, the tier, the allocation total, the default plus-ones and the issue policy.
    /api/guestlist/events/{event_id}/buckets POST guestlist
    Expected result A new bucket at zero consumed.
    Watch out for Choose the tier deliberately — it decides the door zones on every pass this bucket ever produces. A tier belonging to a different event is refused with 422 tier_not_of_event.
  4. 4
    Choose the issue policy on purpose. On_claim means the guest's ticket is minted when they claim their invite link. Manual means somebody has to press Issue for each one — slower, but nothing is minted until a human has looked at it.
    Expected result A policy that matches how much you trust the list.
    Watch out for Manual policy plus a busy promoter equals a queue of unticketed names at the door. That is survivable — the door can Issue and Check In — but only if you told the door that is what is coming.
  5. 5
    Adjust an allocation when a promoter asks for more, or freeze a bucket to stop further names without touching what is already issued.
    /api/guestlist/buckets/{bucket_id} PATCH guestlist
    Expected result The bucket updates, or freezes.
    Watch out for Lowering an allocation below what is already consumed is refused with 409 allocation_below_consumed. And freezing is not retroactive — already-issued tickets keep scanning green, because tickets are independent once minted.
  6. 6
    Watch utilisation through the event build-up: consumed against remaining per bucket, with the per-status counts.
    /api/guestlist/events/{event_id}/buckets guestlist
    Expected result Live numbers, with expiry and check-in sync swept before the read.
    Watch out for Remaining is null for the door-override house bucket. That bucket is allocation-exempt on purpose — walk-ins are governed by the override cap instead.

Steps 7–8 — Host / Promoter

their manual →

Fills the bucket you allocated, and can only ever see and spend their own.

  1. 7
    As the promoter, open the same dashboard. You see only the buckets you own.
    /admin/guestlist/{event_id} guestlist
    Expected result Your bucket, your entries, and nothing belonging to another promoter.
    Watch out for Scoping is on the bucket owner, not on the event. Being a host on the event does not show you the house or artist lists.
  2. 8
    Add a guest — invite mode sends them a claim link, direct mode issues to a known member straight away.
    /api/guestlist/buckets/{bucket_id}/entries POST guestlist
    Expected result An entry, and the bucket's consumed figure rising by one plus the plus-one allowance.
    Watch out for 409 allocation_exceeded means the allowance arithmetic caught up with you, not that the system miscounted. 409 duplicate_guest means that email or member is already on some bucket for this event — one live entry per guest per event, across all buckets.

Steps 9 — Door Staff

their manual →

Turns the names in the bucket into people in the room, and lives with your plus-one decisions.

  1. 9
    On the night, search the names the promoter added and check them in.
    /api/guestlist/door/{event_id}/search guestlist
    Expected result Entries with their bucket shown, so you know whose list a guest is on.
    Watch out for The bucket name is worth reading aloud when there is a dispute. 'You are on Artist Guest List with one plus-one' ends most of them.

Steps 10 — Admin

their manual →

Is the only role that can delete a bucket outright.

  1. 10
    Delete a bucket created in error. Only an admin can, and only when it is empty.
    /api/guestlist/buckets/{bucket_id} DELETE guestlist
    Expected result The bucket goes.
    Watch out for 409 bucket_not_empty is the normal answer. The right move for a bucket with history is to close it, not to try to erase it.

Claim your comp invite and name your plus-ones

Turn an invite link into a real $0 ticket and a door pass, with your guests named.

Owned by Customer (Guest) · 9 steps · about 12 minutes

Why this exists

A comp invite is designed for the person who has never heard of your platform. The link contains a token, and the token is the credential — no account, no password, no app. That is a deliberate trade: guest-list conversion dies at the login screen, and an invite that cannot be forwarded is an invite that gets forwarded as a screenshot instead. The token is scoped to one entry and expires, so its blast radius is one seat.

What claiming actually does is more than reserving a name. It mints a real $0 ticket through the same inventory guard as a paid one, on its own zero-value order, and issues a real door pass. Comp inventory is real inventory — a sold-out tier makes a claim fail, which is exactly the behaviour you want when a promoter is quietly giving away the room.

Plus-ones are named, not counted. Each named guest becomes their own ticket and their own credential, so the door admits people rather than a number, and a guest who does not turn up does not silently become a spare entry for someone else. You can rename and remove your guests up to the cutoff, which defaults to when doors open.

Two consequences of comps being real tickets: they can never be resold (zero face value is rejected by the exchange), and revoking one returns its seat to the tier.

Before you start

  • An invite link with a live token. The seed ships one — the entry named Gala Guest on the demo event.
  • For the member path: an account that the invite was addressed to.
  • For the door steps: an employee session.

Practise with

PersonaEmailPasswordNote
vip_membervip@club.test vip123has a directly-issued comp visible on the member comps page
door_staffdoor@club.test door123checks the guest in on the night

Steps 1–4 — Customer (Guest)

their manual →
  1. 1
    Open the invite link exactly as a guest would: no account, on a phone.
    /guestlist/claim/{token} guestlist
    Expected result A styled page naming the event and who put you down, with a form for your name and your plus-one slots.
    Watch out for The four failure pages are distinct and they mean different things: not found, expired, no longer valid (revoked), and temporarily paused (the bucket is frozen). Only the last one is worth waiting on.
  2. 2
    Claim your spot. Enter your name and the full names of your guests.
    /api/guestlist/claim/{token} POST guestlist
    Expected result The entry moves to claimed and — when the bucket issues on claim — a $0 ticket and a pass serial come back immediately.
    Watch out for Some buckets are set to manual issue: you will be claimed but not ticketed until staff release it. The page says so. Do not claim twice trying to force it.
  3. 3
    Change your mind about a guest: add, rename or remove until the cutoff.
    /api/guestlist/claim/{token}/plus-ones POST guestlist
    Expected result The plus-one list updated, each named guest holding their own ticket.
    Watch out for Past the cutoff (doors open, unless the bucket sets its own) this is refused. So is exceeding the allowance you were given, and so is removing a guest who has already walked in.
  4. 4
    Understand the credential you now hold. Claiming with no account creates a shadow user behind the scenes, because a ticket and a pass must have an owner — your pass serial comes back on the claim page and that page stays your way back to it.
    Expected result A comp pass with the bucket's tier zones, issued the moment the ticket was.
    Watch out for Keep the link. With no account there is no wallet page to fall back on — this page is the only route to the pass. It does NOT expire once claimed: `_expire_entry_if_stale` returns early for any status other than `invited`, so the claim URL is permanent. It is the UNCLAIMED invite that expires, one step earlier.

Steps 5–7 — Member

their manual →

The same invite addressed to an account is claimed from the member portal instead of a token link.

  1. 5
    Now the member path: log in as the account the invite was addressed to and open your comps.
    /me/comps guestlist
    Expected result Your entries with flags for whether you can still claim them and still manage plus-ones.
    Watch out for An invite addressed to a member account is claimed here with your session — you do not need the emailed token at all, and the token path would still work if you did.
  2. 6
    Claim it from your session.
    /api/guestlist/my/entries/{entry_id}/claim POST guestlist
    Expected result The same result as the token path: a ticket and a pass.
    Watch out for Claiming someone else's entry is a 403, even with a valid session. The entry has to be addressed to you.
  3. 7
    Open your wallet, where a claimed comp lands alongside anything you paid for.
    Expected result A comp pass with the bucket's tier zones and the same rotating code as a bought ticket.
    Watch out for A comp pass is an ordinary pass in every respect except one: it can never be listed for sale, because its face value is zero and the exchange rejects it.

Steps 8–9 — Door Staff

their manual →

Finds the guest by name on the night and checks them in with their plus-ones.

  1. 8
    On the night, search the list by the name on the invite.
    /api/guestlist/door/{event_id}/search guestlist
    Expected result Matching entries with their bucket, plus-one allowance and whether they are already in.
    Watch out for Search by the name the promoter wrote down, not the name on the ID. Comps are listed by whoever invited them.
  2. 9
    Check the guest in, and each named plus-one as they arrive.
    /api/guestlist/door/{event_id}/entries/{entry_id}/checkin POST guestlist
    Expected result The entry flips to checked in and the named guest is marked individually.
    Watch out for A door check-in still runs the real scan pipeline underneath. Only two refusals are waived here — the doors-not-open-yet window and the manual reader's zone. A revoked, refunded or suspended guest is refused with the scanner's own reason and no green row is written.

Invite a guest and track plus-ones

Spend your comp allocation: invite guests, send claim links, and keep plus-ones honest.

Owned by Host / Promoter · 13 steps · about 20 minutes

Why this exists

Your comps live in a bucket: a named allocation on your event with a hard cap, a tier, and a default plus-one count. The venue creates and sizes that bucket — you cannot create one, resize one, or move allocation between them. That is the whole point of an allocation, and it is why bucket creation is staff-only while inviting into your own bucket is yours.

The number that surprises people is how allocation is counted: consumed = 1 + the plus-ones you allowed, summed over every live entry, and it is counted the moment you invite, not when the guest turns up. Invite ten people with two plus-ones each out of a bucket of ten and you are refused on the fourth. Revoking or letting an entry expire gives the allocation back.

A comp is not a name on a clipboard. When it is claimed, the platform mints a real ticket at zero face value through the normal payments path — its own $0 paid order, zero ledger postings — and a real door pass with the zones of the bucket's tier. That means comps consume real inventory: a sold-out tier makes a comp fail with an inventory error, exactly as it would for a paying customer. It also means comp tickets are never resalable, by design.

The claim link is a token and the token is the credential: your guest needs no account to claim, name their plus-ones, and walk in.

Before you start

  • A comp bucket on your event with you as its owner (the venue creates it).
  • Enough remaining allocation for the guest plus the plus-ones you intend to allow.
  • A tier with inventory left — comps consume real inventory.

Practise with

PersonaEmailPasswordNote
host_promoterpromoter@demo.club promoter123scoped host on demo-event-0001, owns the 'Promoter X' bucket (allocation 10, one plus-one by default)
venue_managermanager@club.test manager123creates and sizes the buckets
door_staffdoor@club.test door123checks your guests in on the night

Steps 1 — Venue Manager

their manual →

Creates and sizes your comp bucket — how many comps you get is the venue's decision.

  1. 1
    Create the promoter's bucket: a name, owner type promoter, the host as owner, a tier, a total allocation and a default plus-one count.
    /api/guestlist/events/{event_id}/buckets POST guestlist
    Expected result 201 with the bucket, its allocation and its consumed and remaining counts.
    Watch out for The tier you pick decides the door zones the comp pass will open, so a guest-list ticket on a general admission tier does not open the VIP room. Admin and venue manager only — the host cannot create or resize their own bucket.

Steps 2–5 — Host / Promoter

their manual →
  1. 2
    Open the guest list dashboard for your event.
    /admin/guestlist/{event_id} guestlist
    Expected result Your buckets with allocation, consumed, remaining and a status breakdown, plus an entries table and an audit tab.
    Watch out for You see only the buckets you own. The venue's house buckets and the artist list are on the same event and invisible to you, so 'remaining' on your screen is your allowance, not the room's.
  2. 3
    Read the same allocation figures as JSON before a big invite run.
    /api/guestlist/events/{event_id}/buckets guestlist
    Expected result Consumed and remaining per bucket, recomputed live.
    Watch out for Remaining comes back as null for the venue's door-override bucket, because overrides are exempt from allocation. You will not see that bucket anyway.
  3. 4
    Invite a guest from your bucket: name, email, and how many plus-ones they may bring. On the dashboard that is the + Invite Guest form on the bucket.
    /api/guestlist/buckets/{bucket_id}/entries POST guestlist
    Expected result 201 with the entry in status invited, a claim token, and an invite email recorded to the guest.
    Watch out for 409 allocation_exceeded counts the plus-one allowance, not the plus-ones actually named — one guest with three plus-ones spends four. Also 409 duplicate_guest (one live entry per email per event, across all buckets), and 409 bucket_frozen or bucket_closed. Sending allow_duplicate deliberately overrides the duplicate guard and is audited with your name on it.
  4. 5
    Send the invite. Use Copy claim link on the entry if you would rather send it yourself over a direct message than rely on the email.
    Expected result A /guestlist/claim/ link carrying the entry's token.
    Watch out for That link is the credential. Anyone holding it can claim the comp, so do not post it publicly. If it leaks, revoke the entry and re-invite — a resend rotates the token.

Steps 6–7 — Customer (Guest)

their manual →

Claims the invite from a tokenised link and names their own plus-ones, with no account.

  1. 6
    As the guest, open the claim link. No account, no password.
    /guestlist/claim/{token} guestlist
    Expected result A styled claim page naming the event, the host and the plus-ones allowed.
    Watch out for 404 for an unknown token, 410 when the invite expired or was revoked, and 423 when the bucket has been frozen. Claiming closes at the bucket's cutoff, which defaults to the event's doors-open time — a link that worked yesterday can be dead at 9pm.
  2. 7
    Claim it, and name your plus-ones while you are there.
    /api/guestlist/claim/{token} POST guestlist
    Expected result A zero-value ticket and a door pass, with a pass serial returned. Named plus-ones each get their own ticket and pass.
    Watch out for 409 plus_one_limit if you name more than you were allowed. If you have no member account the platform creates a shadow user row for you so the ticket and pass have an owner — it grants you no groups and no login. Members who claim can see the comp afterwards on their comps page.

Steps 8–10 — Host / Promoter

their manual →
  1. 8
    Track the list as it moves: invited, claimed, ticketed, checked in — plus revoked and expired.
    /api/guestlist/events/{event_id}/entries guestlist
    Expected result Your entries only, filtered to the buckets you own, with plus-one counts.
    Watch out for Entries expire quietly at the claim cutoff and hand their allocation back. If your list looks smaller than you remember, check for expired rows before you blame the system.
  2. 9
    Chase a guest who never claimed: resend the invite, rotating the token by default.
    /api/guestlist/entries/{entry_id}/resend POST guestlist
    Expected result A fresh claim link and a new invite email.
    Watch out for Resend is also the only way to revive an expired entry — and the allocation is re-checked when you do, so a full bucket will refuse the revival. Rotating the token kills the old link immediately, which is the right move after a leak.
  3. 10
    Take a comp back when plans change. Give a reason.
    /api/guestlist/entries/{entry_id}/revoke POST guestlist
    Expected result The entry, its plus-ones, their tickets and their passes are all revoked together, and the tier inventory is returned.
    Watch out for You cannot revoke a guest who has already walked in: that needs an admin with force, and you get 403 'hosts cannot revoke checked-in guests'. Revocation is a cascade, so a guest with three plus-ones loses four passes, not one.

Steps 11–12 — Door Staff

their manual →

Finds the name on the night and counts the plus-ones in.

  1. 11
    On the night, open the guest list surface from the scanner and search for the name.
    /scanner/guestlist guestlist
    Expected result Matching entries with their bucket, plus-one allowance and whether they are already in.
    Watch out for Search by the name on the list, not the name on the ID — the promoter invited whoever they invited.
  2. 12
    Check the guest in, and check their plus-ones in with them.
    /api/guestlist/door/{event_id}/entries/{entry_id}/checkin POST guestlist
    Expected result The entry flips to checked in and the plus-one count comes down.
    Watch out for 409 already_checked_in is the anti-passback guard doing its job, not a broken list. A check-in runs the real access pipeline underneath, so a revoked or refunded credential is refused with the scanner's own reason code even here.

Steps 13 — Host / Promoter

their manual →
  1. 13
    After the night, come back and read the audit tab for your buckets.
    /admin/guestlist/{event_id} guestlist
    Expected result Every invite, resend, claim, revoke, expiry and check-in with its actor and timestamp.
    Watch out for That log is append-only — it cannot be edited or deleted by anyone, including admins. It is what settles the 'we had more people on the list than that' conversation.

Check in a guest from the list

Search the guest list, check in an entry and its plus-ones, and issue a ticket on the spot.

Owned by Door Staff · 10 steps · about 14 minutes

Why this exists

A comp is a real ticket. When a promoter's guest claims their invite the platform mints a genuine zero-value ticket on a zero-value paid order, and issues a genuine door pass from it. That is why guest-list check-in is not a separate honour system: the person on the list has a credential just like a paying customer, and this screen exists for the case where they have not got it on their phone.

The important design decision is that manual check-in still runs the real scan pipeline. Pressing Check In does not write a check-in flag; it validates the guest's pass through exactly the gate chain behind the scan endpoint, and only then records a green scan through a bookkeeping reader named Guestlist Manual Check-in. That means anti-passback, revocation, resale suspension and refunds all still apply here — you cannot route around a red scan by searching the name instead.

Exactly two refusals are waived, because a door check-in is a deliberate act by a member of staff. The first is the doors-open time window: staff legitimately work the list before doors, so a not-yet-open event does not block you. The second is wrong zone, because the manual reader is a bookkeeping reader in zone A rather than a real turnstile. Everything else about the guest's right to enter is not overridable and comes back as a refusal carrying the scanner's own reason code — a cancelled or completed event, a revoked or resold or suspended pass, a revoked ticket, or a refunded order.

Plus-ones are the other half of the screen and they are an allowance, not a suggestion. Each named plus-one is its own row with its own ticket and its own check-in button. Admitting more people than the promoter was allocated is what makes the whole allocation system meaningless by the third event.

Before you start

  • An employee session (door staff, venue manager or admin).
  • An event in announced, on_sale, sold_out or in_progress — draft events never appear in the picker.
  • A guest list with entries. The seed ships Promoter X and Artist Guest List buckets on demo-event-0001.

Practise with

PersonaEmailPasswordNote
door_staffdoor@club.test door123door shift account: scanner + guest list, nothing else
venue_managermanager@club.test manager123shift lead: implies door_staff, plus intake, sales, guest list, marketing
host_promoterpromoter@demo.club promoter123scoped host on demo-event-0001; owns the seeded Promoter X comp bucket

Steps 1–7 — Door Staff

their manual →
  1. 1
    Open the guest-list door screen and select tonight's event from the dropdown. The page reloads with the list bound to that event.
    /scanner/guestlist guestlist
    Expected result The event name, its status, and an override counter reading used / cap.
    Watch out for Selecting the event is not optional — the search endpoint is scoped per event, and an unselected page has nothing to search.
  2. 2
    Type at least two characters of the guest's name or email into the search box. Results appear as you type, capped at twenty-five rows.
    /api/guestlist/door/{event_id}/search guestlist
    Expected result Matching entries with their bucket, status, plus-one allowance and a set of action buttons.
    Watch out for One character does nothing at all — the endpoint requires two. Search by the name the promoter put on the list, not the name on the ID; comps are listed by whoever invited them.
  3. 3
    Read the buttons on the row before pressing anything. Check In appears when the entry already has a ticket. Issue and Check In appears when it does not — the entry was invited or claimed but never ticketed. Reinstate and Check In appears on an expired entry, and is manager-only.
    Expected result Exactly the buttons that apply to that row's state, and no others.
    Watch out for If a row you expected shows no button at all, it is usually already checked in or revoked. Read the status chip rather than clicking twice.
  4. 4
    Press Check In for a ticketed guest.
    /api/guestlist/door/{event_id}/entries/{entry_id}/checkin POST guestlist
    Expected result The row flips to checked in, and a green scan row is written through the manual check-in reader.
    Watch out for A second press comes back 409 already_checked_in. That is anti-passback reaching you through this screen too — the same guard the scanner uses, not a separate one.
  5. 5
    Check the plus-ones in individually using their own named buttons — one per named guest — as they actually arrive.
    /api/guestlist/door/{event_id}/entries/{entry_id}/checkin POST guestlist
    Expected result Each named plus-one flips to checked in separately.
    Watch out for Plus-ones arriving separately from their host is normal. Do not check them all in at once to save time; the counts are what the promoter's next allocation is based on.
  6. 6
    For a guest on the list who never claimed their invite, press Issue and Check In. This mints the comp ticket, issues its pass and checks them in as one transaction.
    /api/guestlist/door/{event_id}/entries/{entry_id}/issue-and-checkin POST guestlist
    Expected result A ticket, a pass and a check-in, all in one go.
    Watch out for Comp inventory is real. If the tier is sold out this refuses with 409 insufficient_inventory — a guest list does not conjure capacity, it spends it.
  7. 7
    Learn the refusals that are NOT overridable here, so you escalate instead of retrying: a cancelled or completed event, a revoked or resold pass, a pass suspended because the ticket is listed for resale, a revoked ticket, and a refunded order. Each comes back with the scanner's own reason code and writes no green row.
    Expected result A 409 carrying a familiar reason code rather than a check-in.
    Watch out for Two refusals ARE waived on purpose and will surprise you the other way: the doors-open window, and wrong zone. So yes, you can legitimately work the list an hour before doors.

Steps 8–9 — Venue Manager

their manual →

Allocated the list you are working, and is the only one who can revive an expired invite at the door.

  1. 8
    When the door hits an expired invite, come over and use Reinstate and Check In yourself — reviving an expired entry needs venue_manager or above.
    /api/guestlist/door/{event_id}/entries/{entry_id}/issue-and-checkin POST guestlist
    Expected result The entry revives, tickets and checks in.
    Watch out for Revival re-checks the bucket's allocation. If the bucket is full it refuses, and the honest answer is a walk-in override against the house bucket instead.
  2. 9
    Watch the same list from the event dashboard during the shift, where the entries tab shows live statuses and the audit tab shows every action with who did it.
    /admin/guestlist/{event_id} guestlist
    Expected result Buckets with consumed and remaining counts, entries with statuses, and an append-only audit log.
    Watch out for The audit log cannot be edited or deleted by anyone, admins included — database triggers abort the attempt. Treat it as the record of the night, because that is exactly what it is.

Steps 10 — Admin

their manual →

Holds the escalations the door cannot resolve — a revoked comp, a cancelled event, a settings change.

  1. 10
    If a check-in is disputed after the fact, pull the raw audit tail for the event filtered by action.
    /debug/guestlist/audit/{event_id} guestlist
    Expected result Rows for manual_checkin, door_override, entry_revoke and the rest, with actor and timestamp.
    Watch out for Guest token actions have no actor user id — they carry the entry token id instead. A blank actor is a guest acting on their own claim link, not a missing record.

Issue a VIP walk-in override

Let somebody in who is on no list — recorded as an override, with a reason and a name against it.

Owned by Door Staff · 10 steps · about 12 minutes

Why this exists

Every venue has the moment: someone the owner knows walks up, they are on no list, and they are coming in. The platform's position is that this is fine and entirely normal — and that it must leave a record. So instead of a back door, there is an override: a first-class action that mints a real comp ticket and a real pass, checks the guest in, and writes a row naming who authorised it, why, and on which device.

The difference this makes is only visible weeks later. 'We let forty people in on the list' and 'we let forty people in and here is who authorised each one' are very different conversations to have with an owner or an auditor, and the second one is only possible if the door never had a way to admit somebody silently.

The cap is the interesting piece of design. Overrides run against a per-event house bucket that is exempt from normal allocation, but door staff are limited by a per-event cap, defaulting to ten. Managers and admins are not blocked by the cap — their overrides still count toward it and are audited identically, they just are not refused. The cap is therefore not a security control, it is a forcing function: past ten, a manager has to be physically involved in the decision.

Note what the built system does not let a manager do. Turning overrides off, or changing the cap, is admin-only — the settings panel does not even render for a venue manager. If the cap is wrong for your venue, that is a conversation with an admin before doors, not a fix at the door.

Before you start

  • An employee session and an event selected on the guest-list door screen.
  • The event must be live — a draft, cancelled or completed event refuses an override outright.
  • Overrides must be enabled for the event (they are on by default, cap 10).

Practise with

PersonaEmailPasswordNote
door_staffdoor@club.test door123door shift account: scanner + guest list, nothing else
venue_managermanager@club.test manager123shift lead: implies door_staff, plus intake, sales, guest list, marketing
adminadmin@club.test admin123the only account that can touch money, identity and contracts

Steps 1–5 — Door Staff

their manual →
  1. 1
    Search the guest first. An override is for someone who is genuinely on no list — not a shortcut past a red scan.
    /scanner/guestlist guestlist
    Expected result No matching entry.
    Watch out for If they ARE on the list but the check-in refused, an override is the wrong tool. Read the refusal reason: a revoked pass or a refunded order is not fixed by minting a second ticket.
  2. 2
    Read the override counter on the event card before you start: it shows used against cap, and turns amber with Cap reached — get a manager when you are out.
    /scanner/guestlist guestlist
    Expected result A counter such as overrides 3 / 10.
    Watch out for If the card shows overrides disabled, stop. The endpoint will refuse with 403 overrides_disabled for everyone below admin, and no amount of retrying changes that.
  3. 3
    Press + VIP Walk-in to open the form. Fill in the guest's name, optionally their email, the tier the comp should be issued against, the number of extra guests, and — required — the reason.
    /scanner/guestlist guestlist
    Expected result The Add VIP Walk-in form with name and reason marked required.
    Watch out for The reason field is not decoration and it is server-enforced: a missing name or reason is a 422. Write what you would want to read in three weeks — 'owner guest', 'artist manager', 'comped after door error' — not 'ok'.
  4. 4
    Submit with Issue pass and check in. In one transaction this creates the entry against the house override bucket, mints the comp tickets, issues their passes and checks the party in.
    /api/guestlist/door/{event_id}/override POST guestlist
    Expected result An override id, the entry, the tickets, and the passes with their serials and zones.
    Watch out for Extra guests are capped at five per override. If somebody wants a party of nine through this form, that is a manager decision, not five overrides in a row.
  5. 5
    Understand the two refusals you will actually hit. 409 override_cap_reached means you personally are out of overrides — get a manager, whose own override will go through. 409 event_not_active means the event is not live, and it is checked before any comp inventory is spent.
    Expected result A clear refusal rather than a half-created guest.
    Watch out for The cap only blocks door staff. A manager standing next to you is not exempt from being recorded — their override is audited identically — they are just not refused.

Steps 6–8 — Venue Manager

their manual →

Is not blocked by the door cap, and owns the override report the next morning.

  1. 6
    When the door is capped out, issue the override yourself from the same screen, with your own reason.
    /api/guestlist/door/{event_id}/override POST guestlist
    Expected result The override goes through, with your account recorded as the actor and your role snapshotted on the row.
    Watch out for Your override still increments the used counter. The cap is a signal about the night, so do not treat your exemption as a reason to stop counting.
  2. 7
    The morning after, pull the override report for the event. This is the canonical walk-in record.
    /api/guestlist/events/{event_id}/overrides guestlist
    Expected result One row per override with the guest, the tier, the plus count, the reason, the device and who authorised it.
    Watch out for Comp inventory is real, so overrides show up in the event's sold numbers. If the sales board looks off by a dozen, check here before you go looking for a bug.
  3. 8
    Cross-check the audit tab on the event's guest-list dashboard, which carries the door_override actions alongside every other guest-list action of the night.
    /admin/guestlist/{event_id} guestlist
    Expected result An append-only timeline.
    Watch out for The door-override settings panel is not on this page for you — it renders for admins only. You can see the cap on the door screen; you cannot change it.

Steps 9–10 — Admin

their manual →

Is the only role that can enable, disable or re-cap overrides for an event.

  1. 9
    As an admin, review the per-event override settings: whether overrides are allowed, the door-staff cap, and the default tier comps are issued against.
    /api/guestlist/events/{event_id}/settings guestlist
    Expected result The three settings, with defaults of allowed, cap 10 and no explicit tier.
    Watch out for With no default tier set, overrides fall back to the event's first tier. On an event whose first tier is the expensive one, that quietly comps VIP seats — set the tier before a big night.
  2. 10
    When rehearsing the flow in a demo, reset the override cap rather than burning through it.
    /debug/guestlist/reset-override-cap/{event_id} POST guestlist
    Expected result The usage figures back to a workable state.
    Watch out for Resetting the cap does not delete the overrides you already issued — the audit rows and the comp tickets stay. It only makes the counter stop refusing.

Revoke a comp

Pull a name off the list, kill its pass, and give the capacity back.

Owned by Venue Manager · 7 steps · about 8 minutes

Why this exists

Revoking a comp is a cascade, not a delete, and the cascade is the point. One action marks the entry revoked, revokes every named plus-one under it, marks the underlying tickets revoked, revokes their door passes through the access module, and returns the tier inventory. Any one of those left undone would produce a familiar failure: a name off the list who still scans green, or capacity the venue has silently lost.

The pass revocation is terminal. A revoked credential is blacklisted by serial and by payload hash and its time-code secret is killed, so it fails loudly at the door with Pass Revoked rather than quietly not working. If you revoke the wrong guest, the fix is to invite them again — a new entry, a new ticket, a new pass — not to undo anything.

The one deliberate speed bump is a guest who has already walked in. Revoking a checked-in entry refuses with already_checked_in unless an admin forces it. That is not squeamishness: someone is physically in the building, and a system that lets a list edit quietly contradict the door count is a system whose numbers you cannot use.

Before you start

  • A venue manager or admin session.
  • A live entry on a bucket for the event.

Practise with

PersonaEmailPasswordNote
venue_managermanager@club.test manager123shift lead: implies door_staff, plus intake, sales, guest list, marketing
adminadmin@club.test admin123the only account that can touch money, identity and contracts
door_staffdoor@club.test door123door shift account: scanner + guest list, nothing else

Steps 1–5 — Venue Manager

their manual →
  1. 1
    Find the entry in the Entries table and check its status chip before acting: invited, claimed, ticketed, checked in, revoked or expired.
    /admin/guestlist/{event_id} guestlist
    Expected result The entry with its bucket, plus-ones and status.
    Watch out for An expired entry does not need revoking — it has already released its allocation. Revoking it just adds noise to the audit log.
  2. 2
    Press Revoke and give a reason. This cascades to the plus-ones, the tickets and the passes, and returns the inventory.
    /api/guestlist/entries/{entry_id}/revoke POST guestlist
    Expected result The entry and its plus-ones flip to revoked; the bucket's remaining figure rises again.
    Watch out for 409 already_checked_in means the guest is inside. Only an admin can force past that, and they should have a reason better than tidiness.
  3. 3
    Confirm the allocation actually came back by re-reading the bucket's consumed and remaining figures.
    /api/guestlist/events/{event_id}/buckets guestlist
    Expected result Consumed down by one plus the revoked entry's plus-one allowance.
    Watch out for It drops by the ALLOWANCE, not by the number of named plus-ones — the same asymmetry that governed the allocation on the way in.
  4. 4
    If you revoked in error, do not go looking for an undo. Invite the guest again as a fresh entry.
    /admin/guestlist/{event_id} guestlist
    Expected result A new entry, a new claim link, and eventually a new pass.
    Watch out for The old pass stays dead forever. Revocation is terminal by design, and re-issuing on the same ticket is refused with 409 pass_revoked rather than minting a serial the blacklist would not cover.
  5. 5
    For the softer case — a guest who let their invite expire — use Resend with a rotated token instead of revoking anything. This is the only way to revive an expired entry.
    /api/guestlist/entries/{entry_id}/resend POST guestlist
    Expected result A fresh claim link and the entry back in play.
    Watch out for Resend re-checks the allocation. If the bucket filled up while they were slow, the revival is refused — which is the correct answer, not a bug.

Steps 6 — Door Staff

their manual →

Meets the consequence at the door if the revocation lands after the guest arrives.

  1. 6
    On the night, expect a revoked guest to scan red with Pass Revoked. Read it out and send them to a manager; do not re-scan hopefully.
    /scanner access
    Expected result A red panel reading Pass Revoked.
    Watch out for If the device has been offline since before the revocation, its cached bundle may not know. This is exactly what the live push feed exists to prevent — and why a manager-grade session on the door device matters.

Steps 7 — Admin

their manual →

Is the only role that can force a revocation on a guest who is already inside.

  1. 7
    As an admin, force a revocation on a checked-in guest when it is genuinely necessary — an ejection, say.
    /api/guestlist/entries/{entry_id}/revoke POST guestlist
    Expected result The revocation completes despite the check-in.
    Watch out for The check-in row is not deleted. The night's door count still says they came in, because they did — the audit log is a history, not a current-state summary.

Appendix A — Persona ↔ RBAC group

PersonaRBAC groupAuthenticatedScoped OwnsTakes part in
Customer (Guest) no no 4 2
Member member yes no 13 18
VIP Member vip_member yes no 2 7
Host / Promoter host yes yes 11 11
Door Staff door_staff yes no 5 14
Venue Manager venue_manager yes no 17 24
Admin admin yes no 24 43

Appendix B — Route index

Every application route this manual references, and the workflows that use it. A test asserts each of these resolves against the mounted router, so the manual cannot silently rot when a route moves.

RouteUsed by
DELETE /api/admin/resale/events/{event_id}/lock open-or-close-the-exchange
DELETE /api/guestlist/buckets/{bucket_id} allocate-comps-to-a-promoter
DELETE /api/reservations/{reservation_id} hold-a-checkout-reservation
DELETE /debug/mock-behaviors/{behavior_id} script-a-mock-failure
GET / browse-events-as-a-guest, buy-a-ticket
GET /account convert-an-application-into-an-event, grant-and-revoke-roles, build-a-role-from-capabilities, create-your-member-account, manage-your-account-and-sessions
GET /account/passes read-the-scanner-screen, diagnose-a-red-scan, map-groups-to-door-zones, self-cancel-a-ticket, add-your-ticket-to-your-wallet, use-your-membership-card-at-the-bar, resell-a-ticket-you-cant-use, buy-a-resale-ticket, claim-your-comp-invite, get-through-the-door
GET /admin find-your-way-around-as-staff, edit-any-row-with-admin-crud, find-anything-in-admin
GET /admin/access read-the-scanner-screen, diagnose-a-red-scan, run-the-door-offline, map-groups-to-door-zones, manage-your-account-and-sessions, add-your-ticket-to-your-wallet, get-through-the-door, scan-guests-at-the-door, find-anything-in-admin
GET /admin/annotations leave-feedback-on-the-app, run-the-feedback-backlog, preview-the-site-as-a-guest
GET /admin/annotations/export leave-feedback-on-the-app, run-the-feedback-backlog
GET /admin/annotations/{annotation_id} run-the-feedback-backlog, preview-the-site-as-a-guest
GET /admin/announcements get-into-a-member-only-drop
GET /admin/audit grant-and-revoke-roles, deactivate-a-user, create-your-member-account
GET /admin/capabilities build-a-role-from-capabilities
GET /admin/contract-riders author-a-rider-so-a-host-can-ask-for-it
GET /admin/contract-riders/new author-a-rider-so-a-host-can-ask-for-it
GET /admin/contract-riders/recent author-a-rider-so-a-host-can-ask-for-it
GET /admin/contract-riders/{rider_key} author-a-rider-so-a-host-can-ask-for-it
GET /admin/contracts review-the-riders-approval-created, sign-and-countersign-a-contract, approve-a-host-application
GET /admin/contracts/{contract_id} review-the-riders-approval-created, sign-and-countersign-a-contract, create-and-launch-an-event, approve-a-host-application
GET /admin/credit/users/{user_id} post-a-house-credit-adjustment, pay-with-house-credit
GET /admin/data edit-any-row-with-admin-crud
GET /admin/data/audit edit-any-row-with-admin-crud, delete-rows-safely
GET /admin/data/ledger_entries edit-any-row-with-admin-crud, read-the-trial-balance
GET /admin/data/qa_invariant_violations run-the-qa-invariant-sweep
GET /admin/data/sandbox_parents edit-any-row-with-admin-crud
GET /admin/data/{table}/new edit-any-row-with-admin-crud
GET /admin/data/{table}/{pk} edit-any-row-with-admin-crud, delete-rows-safely
GET /admin/events find-your-way-around-as-staff, monitor-live-sales-on-the-night, understand-your-events-tiers-and-releases
GET /admin/events/backload understand-your-events-tiers-and-releases
GET /admin/events/{event_id} monitor-live-sales-on-the-night, convert-an-application-into-an-event, grant-and-revoke-roles, get-into-a-member-only-drop, get-your-host-account-and-event-access, understand-your-events-tiers-and-releases, watch-your-event-sell-live, create-and-launch-an-event
GET /admin/events/{event_id}/record keep-the-permanent-event-record
GET /admin/events/{event_id}/record/documents/{doc_id} keep-the-permanent-event-record
GET /admin/events/{event_id}/refund-policy refund-a-ticket-or-order, self-cancel-a-ticket
GET /admin/groups find-your-way-around-as-staff, map-groups-to-door-zones, build-a-role-from-capabilities
GET /admin/groups/new build-a-role-from-capabilities
GET /admin/groups/{slug} build-a-role-from-capabilities
GET /admin/guestlist find-your-way-around-as-staff, allocate-comps-to-a-promoter
GET /admin/guestlist/{event_id} check-in-a-guest-from-the-list, issue-a-vip-walk-in-override, allocate-comps-to-a-promoter, revoke-a-comp, get-your-host-account-and-event-access, invite-a-guest-and-track-plus-ones
GET /admin/intake find-your-way-around-as-staff, convert-an-application-into-an-event, apply-to-host-an-event, build-your-run-of-show-backwards, create-and-launch-an-event, approve-a-host-application, run-the-staff-channel-on-live-telegram
GET /admin/intake/rider-requests author-a-rider-so-a-host-can-ask-for-it
GET /admin/intake/{app_id} fast-track-from-telegram, review-the-riders-approval-created, convert-an-application-into-an-event, apply-to-host-an-event, re-apply-with-autofill, respond-to-a-request-for-more-information, author-a-rider-so-a-host-can-ask-for-it, build-your-run-of-show-backwards, create-and-launch-an-event, approve-a-host-application, run-the-staff-channel-on-live-telegram
GET /admin/ledger read-the-trial-balance, reconcile-tax-accruals, top-up-your-house-credit, read-your-credit-statement, run-the-quarterly-tax-filing
GET /admin/ledger/transactions refund-a-ticket-or-order, read-the-trial-balance, process-a-payout-run, run-the-vip-tab-settlement, reconcile-tax-accruals, pay-with-house-credit, use-and-settle-your-vip-tab
GET /admin/ledger/transactions/{txn_id} post-a-house-credit-adjustment, read-the-trial-balance, top-up-your-house-credit
GET /admin/marketing find-your-way-around-as-staff, compose-and-publish-a-social-post, configure-marketing-channels-and-rules
GET /admin/marketing/events/{event_id} compose-and-publish-a-social-post, build-a-trigger-rule, configure-marketing-channels-and-rules
GET /admin/marketing/events/{event_id}/rules/new build-a-trigger-rule, configure-marketing-channels-and-rules
GET /admin/marketing/posts/new compose-and-publish-a-social-post
GET /admin/marketing/posts/{post_id} compose-and-publish-a-social-post, build-a-trigger-rule
GET /admin/marketing/reports trace-a-click-to-revenue, report-marketing-attribution
GET /admin/marketing/rules/{rule_id}/edit build-a-trigger-rule
GET /admin/orders monitor-live-sales-on-the-night, refund-a-ticket-or-order, watch-your-event-sell-live
GET /admin/orders/{order_id} diagnose-a-red-scan, monitor-live-sales-on-the-night, trace-a-click-to-revenue, refund-a-ticket-or-order, self-cancel-a-ticket, buy-a-ticket
GET /admin/payouts process-a-payout-run, get-paid-your-host-royalty
GET /admin/qa run-the-qa-invariant-sweep
GET /admin/records keep-the-permanent-event-record
GET /admin/records/devices keep-the-permanent-event-record
GET /admin/records/metrics keep-the-permanent-event-record
GET /admin/resale open-or-close-the-exchange
GET /admin/resale/{event_id} open-or-close-the-exchange, resell-a-ticket-you-cant-use, get-paid-your-host-royalty, buy-a-resale-ticket, understand-your-credit-and-the-exchange
GET /admin/tab-settlements script-a-mock-failure, run-the-vip-tab-settlement, use-and-settle-your-vip-tab
GET /admin/tax approve-a-filing-from-telegram, reconcile-tax-accruals, run-the-quarterly-tax-filing
GET /admin/tax/periods/{period_id} approve-a-filing-from-telegram, run-the-quarterly-tax-filing
GET /admin/tax/rates maintain-the-tax-rate-matrix
GET /admin/tax/settings approve-a-filing-from-telegram
GET /admin/telegram run-the-staff-channel-on-live-telegram
GET /admin/users grant-and-revoke-roles
GET /admin/users/{user_id} convert-an-application-into-an-event, grant-and-revoke-roles, deactivate-a-user, build-a-role-from-capabilities, create-your-member-account, manage-your-account-and-sessions, use-your-membership-card-at-the-bar, get-your-host-account-and-event-access
GET /admin/venues set-up-a-venue-and-its-door-zones
GET /admin/venues/new set-up-a-venue-and-its-door-zones
GET /admin/venues/{slug} set-up-a-venue-and-its-door-zones
GET /admin/venues/{venue_id}/layout draw-a-venue-map
GET /api/access/passes/mine add-your-ticket-to-your-wallet
GET /api/access/passes/{pass_id}/gpass add-your-ticket-to-your-wallet
GET /api/access/passes/{pass_id}/pkpass add-your-ticket-to-your-wallet, get-through-the-door
GET /api/access/passes/{pass_id}/qr read-the-scanner-screen, add-your-ticket-to-your-wallet, use-your-membership-card-at-the-bar, get-through-the-door
GET /api/access/scan-logs read-the-scanner-screen, diagnose-a-red-scan, run-the-door-offline, monitor-live-sales-on-the-night, get-through-the-door, scan-guests-at-the-door
GET /api/access/sync/bundle run-the-door-offline, scan-guests-at-the-door
GET /api/access/sync/push run-the-door-offline
GET /api/access/tickets/{ticket_id}/secret add-your-ticket-to-your-wallet
GET /api/admin/data/{table}/rows/{pk}/dependencies delete-rows-safely
GET /api/admin/events/{event_id}/reservations monitor-live-sales-on-the-night, hold-a-checkout-reservation, watch-your-event-sell-live
GET /api/admin/events/{event_id}/sales monitor-live-sales-on-the-night, watch-your-event-sell-live
GET /api/admin/ledger/accounts read-the-trial-balance
GET /api/admin/ledger/transactions read-the-trial-balance
GET /api/admin/ledger/trial-balance read-the-trial-balance
GET /api/admin/ledger/users/{user_id} post-a-house-credit-adjustment
GET /api/admin/refunds refund-a-ticket-or-order
GET /api/admin/resale/settlements get-paid-your-host-royalty
GET /api/annotations/list run-the-feedback-backlog
GET /api/annotations/pages run-the-feedback-backlog
GET /api/contracts/riders/selectable author-a-rider-so-a-host-can-ask-for-it
GET /api/credit/balance pay-with-house-credit, top-up-your-house-credit, read-your-credit-statement, get-paid-your-host-royalty, use-and-settle-your-vip-tab
GET /api/credit/statement read-your-credit-statement
GET /api/events/{event_id}/availability browse-events-as-a-guest, get-into-a-member-only-drop, understand-your-events-tiers-and-releases
GET /api/events/{event_id}/refund-policy self-cancel-a-ticket
GET /api/events/{event_id}/zones set-up-a-venue-and-its-door-zones
GET /api/guestlist/door/{event_id}/search check-in-a-guest-from-the-list, allocate-comps-to-a-promoter, claim-your-comp-invite
GET /api/guestlist/events/{event_id}/buckets allocate-comps-to-a-promoter, revoke-a-comp, invite-a-guest-and-track-plus-ones
GET /api/guestlist/events/{event_id}/entries invite-a-guest-and-track-plus-ones
GET /api/guestlist/events/{event_id}/overrides issue-a-vip-walk-in-override
GET /api/guestlist/events/{event_id}/settings issue-a-vip-walk-in-override
GET /api/intake/public/applications/{app_id}/edit respond-to-a-request-for-more-information
GET /api/marketing/channels configure-marketing-channels-and-rules
GET /api/marketing/links trace-a-click-to-revenue, report-marketing-attribution
GET /api/marketing/reports/channels trace-a-click-to-revenue, report-marketing-attribution
GET /api/marketing/reports/events/{event_id} trace-a-click-to-revenue, report-marketing-attribution
GET /api/marketing/rules/{rule_id}/firings build-a-trigger-rule, configure-marketing-channels-and-rules
GET /api/rbac/groups grant-and-revoke-roles
GET /api/rbac/matrix build-a-role-from-capabilities
GET /api/rbac/users/{user_id}/capabilities build-a-role-from-capabilities
GET /api/records/compare keep-the-permanent-event-record
GET /api/records/{event_id}/seal-check keep-the-permanent-event-record
GET /api/records/{event_id}/verify keep-the-permanent-event-record
GET /api/resale/events/{event_id} buy-a-resale-ticket
GET /api/resale/my/purchases buy-a-resale-ticket
GET /api/reservations/{reservation_id} hold-a-checkout-reservation
GET /api/tax/agencies maintain-the-tax-rate-matrix
GET /api/tax/documents/{doc_id} approve-a-filing-from-telegram
GET /api/tax/liability reconcile-tax-accruals, run-the-quarterly-tax-filing
GET /api/tax/periods reconcile-tax-accruals
GET /api/tax/quote maintain-the-tax-rate-matrix
GET /api/tax/rates maintain-the-tax-rate-matrix
GET /api/venues/{venue_id}/zones set-up-a-venue-and-its-door-zones
GET /apply/edit/{token} fast-track-from-telegram, respond-to-a-request-for-more-information, author-a-rider-so-a-host-can-ask-for-it, build-your-run-of-show-backwards, approve-a-host-application
GET /apply/thanks/{app_id} apply-to-host-an-event, re-apply-with-autofill, build-your-run-of-show-backwards, create-and-launch-an-event
GET /auth/me manage-your-account-and-sessions
GET /cart hold-a-checkout-reservation
GET /checkout/{order_id} hold-a-checkout-reservation, pay-with-house-credit, get-into-a-member-only-drop, buy-a-ticket, use-and-settle-your-vip-tab
GET /clips/{workflow_slug} leave-feedback-on-the-app
GET /contracts/{contract_id}/preview review-the-riders-approval-created
GET /contracts/{contract_id}/redlines review-the-riders-approval-created, sign-and-countersign-a-contract
GET /contracts/{contract_id}/sealed sign-and-countersign-a-contract
GET /debug use-the-debug-console
GET /debug/access/totp/{ticket_id} diagnose-a-red-scan
GET /debug/adminsuite/dependencies delete-rows-safely
GET /debug/adminsuite/policies edit-any-row-with-admin-crud
GET /debug/annotations/audit run-the-feedback-backlog
GET /debug/annotations/orphans run-the-feedback-backlog
GET /debug/audit use-the-debug-console, script-a-mock-failure
GET /debug/events/reservations/sweep-preview hold-a-checkout-reservation
GET /debug/events/{event_id}/state watch-your-event-sell-live
GET /debug/frontend/preview preview-the-site-as-a-guest
GET /debug/frontend/preview/gate preview-the-site-as-a-guest
GET /debug/guestlist/audit/{event_id} check-in-a-guest-from-the-list
GET /debug/intake/deeplinks run-the-staff-channel-on-live-telegram
GET /debug/intake/rate-limits re-apply-with-autofill
GET /debug/intake/timeline build-your-run-of-show-backwards
GET /debug/intake/timeline-render/{app_id} build-your-run-of-show-backwards
GET /debug/intake/tz build-your-run-of-show-backwards
GET /debug/ledger/integrity post-a-house-credit-adjustment, read-the-trial-balance
GET /debug/marketing/links/{short_code} trace-a-click-to-revenue, report-marketing-attribution
GET /debug/marketing/outbound configure-marketing-channels-and-rules
GET /debug/mock-behaviors script-a-mock-failure
GET /debug/outbound-calls fast-track-from-telegram, use-the-debug-console, script-a-mock-failure, approve-a-filing-from-telegram, apply-to-host-an-event, run-the-staff-channel-on-live-telegram
GET /debug/qa/health run-the-qa-invariant-sweep
GET /debug/qa/invariants run-the-qa-invariant-sweep
GET /debug/qa/invariants/runs run-the-qa-invariant-sweep
GET /debug/qa/journeys run-the-qa-invariant-sweep
GET /debug/rbac/graph build-a-role-from-capabilities
GET /debug/rbac/pass-refresh-queue build-a-role-from-capabilities
GET /debug/rbac/state grant-and-revoke-roles, deactivate-a-user
GET /debug/rbac/zones map-groups-to-door-zones
GET /debug/record/verify-all keep-the-permanent-event-record
GET /debug/record/{event_id} keep-the-permanent-event-record
GET /debug/resale/integrity/{event_id} open-or-close-the-exchange
GET /debug/resale/split-preview open-or-close-the-exchange, resell-a-ticket-you-cant-use
GET /debug/scheduler/runs use-the-debug-console
GET /debug/settings use-the-debug-console
GET /debug/state use-the-debug-console
GET /debug/tax/rate-resolution maintain-the-tax-rate-matrix
GET /debug/tax/reconcile reconcile-tax-accruals
GET /debug/telegram/webhook-info run-the-staff-channel-on-live-telegram
GET /debug/venues/zone-map set-up-a-venue-and-its-door-zones
GET /events build-a-role-from-capabilities, browse-events-as-a-guest, leave-feedback-on-the-app, preview-the-site-as-a-guest, buy-a-ticket
GET /events/{event_id} monitor-live-sales-on-the-night, build-a-trigger-rule, browse-events-as-a-guest, create-your-member-account, get-into-a-member-only-drop, sign-and-countersign-a-contract, get-your-host-account-and-event-access, understand-your-events-tiers-and-releases, watch-your-event-sell-live, preview-the-site-as-a-guest, create-and-launch-an-event, buy-a-ticket, understand-your-credit-and-the-exchange
GET /events/{event_id}/buy browse-events-as-a-guest
GET /events/{event_id}/checkout hold-a-checkout-reservation, get-into-a-member-only-drop, buy-a-ticket
GET /events/{event_id}/exchange open-or-close-the-exchange, buy-a-resale-ticket, get-paid-your-host-royalty, understand-your-credit-and-the-exchange
GET /exchange browse-events-as-a-guest, buy-a-resale-ticket
GET /guestlist/claim/{token} claim-your-comp-invite, invite-a-guest-and-track-plus-ones
GET /host/apply browse-events-as-a-guest, apply-to-host-an-event, re-apply-with-autofill, author-a-rider-so-a-host-can-ask-for-it, build-your-run-of-show-backwards, create-and-launch-an-event
GET /l/{short_code} trace-a-click-to-revenue, report-marketing-attribution
GET /login deactivate-a-user, browse-events-as-a-guest, create-your-member-account, get-your-host-account-and-event-access
GET /me/comps claim-your-comp-invite
GET /my create-your-member-account, get-into-a-member-only-drop, preview-the-site-as-a-guest
GET /my/annotations leave-feedback-on-the-app, run-the-feedback-backlog
GET /my/credit refund-a-ticket-or-order, run-the-vip-tab-settlement, open-or-close-the-exchange, pay-with-house-credit, self-cancel-a-ticket, use-your-membership-card-at-the-bar, resell-a-ticket-you-cant-use, top-up-your-house-credit, read-your-credit-statement, get-paid-your-host-royalty, buy-a-ticket, use-and-settle-your-vip-tab, understand-your-credit-and-the-exchange
GET /my/credit/payouts process-a-payout-run, get-paid-your-host-royalty, understand-your-credit-and-the-exchange
GET /my/credit/statement post-a-house-credit-adjustment, pay-with-house-credit, top-up-your-house-credit, read-your-credit-statement, get-paid-your-host-royalty, use-and-settle-your-vip-tab
GET /my/orders self-cancel-a-ticket
GET /my/orders/{order_id} refund-a-ticket-or-order, self-cancel-a-ticket
GET /my/tickets add-your-ticket-to-your-wallet, resell-a-ticket-you-cant-use, buy-a-ticket, get-through-the-door, understand-your-credit-and-the-exchange
GET /register create-your-member-account, buy-a-ticket
GET /resale/my/listings resell-a-ticket-you-cant-use, understand-your-credit-and-the-exchange
GET /resale/sell/{ticket_id} open-or-close-the-exchange, resell-a-ticket-you-cant-use, understand-your-credit-and-the-exchange
GET /scanner find-your-way-around-as-staff, read-the-scanner-screen, diagnose-a-red-scan, run-the-door-offline, revoke-a-comp, grant-and-revoke-roles, map-groups-to-door-zones, deactivate-a-user, get-through-the-door, scan-guests-at-the-door
GET /scanner/guestlist find-your-way-around-as-staff, diagnose-a-red-scan, check-in-a-guest-from-the-list, issue-a-vip-walk-in-override, invite-a-guest-and-track-plus-ones, scan-guests-at-the-door
GET /sign/{token} sign-and-countersign-a-contract, create-and-launch-an-event
GET /sign/{token}/status sign-and-countersign-a-contract
GET /training/role/host_promoter find-your-way-around-as-staff
GET /ui/preview preview-the-site-as-a-guest
GET /venues/{venue_id}/map draw-a-venue-map
PATCH /api/admin/data/{table}/rows/{pk} edit-any-row-with-admin-crud
PATCH /api/contracts/riders/{rider_key} author-a-rider-so-a-host-can-ask-for-it
PATCH /api/guestlist/buckets/{bucket_id} allocate-comps-to-a-promoter
PATCH /api/marketing/channels/{platform} compose-and-publish-a-social-post, configure-marketing-channels-and-rules
PATCH /api/marketing/posts/{post_id} compose-and-publish-a-social-post
PATCH /api/tax/rates/{rate_id} maintain-the-tax-rate-matrix
PATCH /api/tiers/{tier_id} understand-your-events-tiers-and-releases
PATCH /api/venues/{venue_id}/zones/{zone_id} set-up-a-venue-and-its-door-zones
PATCH /contracts/{contract_id}/sections/{section_id} review-the-riders-approval-created
PATCH /contracts/{contract_id}/variables review-the-riders-approval-created
POST /admin/annotations/{annotation_id} leave-feedback-on-the-app, run-the-feedback-backlog
POST /admin/annotations/{annotation_id}/delete run-the-feedback-backlog
POST /admin/annotations/{annotation_id}/reply run-the-feedback-backlog
POST /admin/annotations/{annotation_id}/restore run-the-feedback-backlog
POST /admin/announcements get-into-a-member-only-drop
POST /admin/venues/new set-up-a-venue-and-its-door-zones
POST /api/access/membership-card use-your-membership-card-at-the-bar
POST /api/access/readers run-the-door-offline, scan-guests-at-the-door
POST /api/access/readers/{reader_id}/rotate-token run-the-door-offline
POST /api/access/scan read-the-scanner-screen, use-your-membership-card-at-the-bar, resell-a-ticket-you-cant-use, buy-a-resale-ticket, get-through-the-door, scan-guests-at-the-door
POST /api/access/scan/batch run-the-door-offline
POST /api/admin/credit/users/{user_id}/kyc/revoke process-a-payout-run
POST /api/admin/data/{table}/delete delete-rows-safely
POST /api/admin/data/{table}/rows/{pk}/restore delete-rows-safely
POST /api/admin/events/{event_id}/refund-all refund-a-ticket-or-order
POST /api/admin/ledger/adjustments post-a-house-credit-adjustment, read-your-credit-statement
POST /api/admin/orders/{order_id}/refunds refund-a-ticket-or-order
POST /api/admin/payouts/{payout_id}/process process-a-payout-run, get-paid-your-host-royalty
POST /api/admin/resale/events/{event_id}/lock open-or-close-the-exchange
POST /api/admin/tab-settlements/run run-the-vip-tab-settlement, use-and-settle-your-vip-tab
POST /api/admin/tab-settlements/{settlement_id}/retry run-the-vip-tab-settlement
POST /api/admin/tab-settlements/{settlement_id}/waive run-the-vip-tab-settlement
POST /api/annotations leave-feedback-on-the-app, run-the-feedback-backlog, preview-the-site-as-a-guest
POST /api/annotations/mode leave-feedback-on-the-app
POST /api/cart/items hold-a-checkout-reservation, buy-a-ticket
POST /api/checkout hold-a-checkout-reservation, buy-a-ticket
POST /api/contracts/rider-versions/{template_id}/approve author-a-rider-so-a-host-can-ask-for-it
POST /api/contracts/rider-versions/{template_id}/reject author-a-rider-so-a-host-can-ask-for-it
POST /api/contracts/rider-versions/{template_id}/submit author-a-rider-so-a-host-can-ask-for-it
POST /api/contracts/riders/{rider_key}/promote author-a-rider-so-a-host-can-ask-for-it
POST /api/credit/kyc process-a-payout-run, get-paid-your-host-royalty
POST /api/credit/payouts process-a-payout-run, get-paid-your-host-royalty
POST /api/credit/topup top-up-your-house-credit, understand-your-credit-and-the-exchange
POST /api/events/{event_id}/capacity-override set-up-a-venue-and-its-door-zones
POST /api/events/{event_id}/reservations hold-a-checkout-reservation
POST /api/events/{event_id}/tiers get-into-a-member-only-drop, understand-your-events-tiers-and-releases
POST /api/events/{event_id}/transition monitor-live-sales-on-the-night, understand-your-events-tiers-and-releases, create-and-launch-an-event
POST /api/events/{event_id}/zones set-up-a-venue-and-its-door-zones
POST /api/events/{event_id}/zones/{zone_ref}/activate set-up-a-venue-and-its-door-zones
POST /api/events/{event_id}/zones/{zone_ref}/retire set-up-a-venue-and-its-door-zones
POST /api/guestlist/buckets/{bucket_id}/entries allocate-comps-to-a-promoter, invite-a-guest-and-track-plus-ones
POST /api/guestlist/claim/{token} claim-your-comp-invite, invite-a-guest-and-track-plus-ones
POST /api/guestlist/claim/{token}/plus-ones claim-your-comp-invite
POST /api/guestlist/door/{event_id}/entries/{entry_id}/checkin check-in-a-guest-from-the-list, claim-your-comp-invite, invite-a-guest-and-track-plus-ones, scan-guests-at-the-door
POST /api/guestlist/door/{event_id}/entries/{entry_id}/issue-and-checkin check-in-a-guest-from-the-list
POST /api/guestlist/door/{event_id}/override issue-a-vip-walk-in-override
POST /api/guestlist/entries/{entry_id}/resend revoke-a-comp, invite-a-guest-and-track-plus-ones
POST /api/guestlist/entries/{entry_id}/revoke revoke-a-comp, invite-a-guest-and-track-plus-ones
POST /api/guestlist/events/{event_id}/buckets allocate-comps-to-a-promoter, invite-a-guest-and-track-plus-ones
POST /api/guestlist/my/entries/{entry_id}/claim claim-your-comp-invite
POST /api/intake/applications/{app_id}/approve fast-track-from-telegram, respond-to-a-request-for-more-information, create-and-launch-an-event, approve-a-host-application
POST /api/intake/applications/{app_id}/author-rider author-a-rider-so-a-host-can-ask-for-it
POST /api/intake/applications/{app_id}/convert convert-an-application-into-an-event, get-your-host-account-and-event-access, create-and-launch-an-event
POST /api/intake/applications/{app_id}/decline fast-track-from-telegram
POST /api/intake/applications/{app_id}/notes fast-track-from-telegram
POST /api/intake/applications/{app_id}/recompute-viability fast-track-from-telegram
POST /api/intake/applications/{app_id}/request-info respond-to-a-request-for-more-information, approve-a-host-application
POST /api/intake/public/applications apply-to-host-an-event, re-apply-with-autofill, author-a-rider-so-a-host-can-ask-for-it, build-your-run-of-show-backwards, create-and-launch-an-event, run-the-staff-channel-on-live-telegram
POST /api/intake/public/prefill/start re-apply-with-autofill
POST /api/intake/public/prefill/verify re-apply-with-autofill
POST /api/intake/public/rider-requests author-a-rider-so-a-host-can-ask-for-it
POST /api/intake/public/timeline/preview build-your-run-of-show-backwards
POST /api/intake/rider-requests/{request_id}/author author-a-rider-so-a-host-can-ask-for-it
POST /api/intake/rider-requests/{request_id}/decline author-a-rider-so-a-host-can-ask-for-it
POST /api/intake/rider-requests/{request_id}/triage author-a-rider-so-a-host-can-ask-for-it
POST /api/marketing/events/{event_id}/rules build-a-trigger-rule, configure-marketing-channels-and-rules
POST /api/marketing/posts compose-and-publish-a-social-post
POST /api/marketing/posts/{post_id}/cancel compose-and-publish-a-social-post
POST /api/marketing/posts/{post_id}/retry compose-and-publish-a-social-post
POST /api/orders/{order_id}/cancel hold-a-checkout-reservation, self-cancel-a-ticket
POST /api/orders/{order_id}/pay hold-a-checkout-reservation, pay-with-house-credit, buy-a-ticket
POST /api/rbac/groups build-a-role-from-capabilities
POST /api/rbac/tiers/reorder build-a-role-from-capabilities
POST /api/rbac/users/{user_id}/deactivate deactivate-a-user
POST /api/rbac/users/{user_id}/groups grant-and-revoke-roles, build-a-role-from-capabilities, get-your-host-account-and-event-access
POST /api/rbac/users/{user_id}/groups/{grant_id}/revoke grant-and-revoke-roles
POST /api/rbac/users/{user_id}/reactivate deactivate-a-user
POST /api/rbac/users/{user_id}/sessions/revoke-all deactivate-a-user
POST /api/record/devices keep-the-permanent-event-record
POST /api/record/devices/{device_id}/rotate-token keep-the-permanent-event-record
POST /api/record/ingest keep-the-permanent-event-record
POST /api/record/metrics keep-the-permanent-event-record
POST /api/records/{event_id}/amendments keep-the-permanent-event-record
POST /api/records/{event_id}/measurements keep-the-permanent-event-record
POST /api/records/{event_id}/measurements/import keep-the-permanent-event-record
POST /api/records/{event_id}/open keep-the-permanent-event-record
POST /api/records/{event_id}/seal keep-the-permanent-event-record
POST /api/resale/listings resell-a-ticket-you-cant-use
POST /api/resale/listings/{listing_id}/purchase buy-a-resale-ticket
POST /api/tax/packages/{package_id}/approve run-the-quarterly-tax-filing
POST /api/tax/packages/{package_id}/retry-mail approve-a-filing-from-telegram
POST /api/tax/packages/{package_id}/send-approval approve-a-filing-from-telegram, run-the-quarterly-tax-filing
POST /api/tax/periods/{period_id}/regenerate reconcile-tax-accruals
POST /api/tax/rates maintain-the-tax-rate-matrix
POST /api/telegram/test-send run-the-staff-channel-on-live-telegram
POST /api/telegram/webhook/delete run-the-staff-channel-on-live-telegram
POST /api/telegram/webhook/register run-the-staff-channel-on-live-telegram
POST /api/venues/{venue_id}/archive set-up-a-venue-and-its-door-zones
POST /api/venues/{venue_id}/default set-up-a-venue-and-its-door-zones
POST /api/venues/{venue_id}/layout draw-a-venue-map
POST /api/venues/{venue_id}/shapes draw-a-venue-map
POST /api/venues/{venue_id}/zones set-up-a-venue-and-its-door-zones
POST /api/venues/{venue_id}/zones/{zone_id}/attach set-up-a-venue-and-its-door-zones
POST /auth/login get-your-host-account-and-event-access
POST /auth/password manage-your-account-and-sessions
POST /auth/register create-your-member-account, buy-a-ticket
POST /auth/sessions/{session_id}/revoke manage-your-account-and-sessions
POST /contracts/{contract_id}/countersign sign-and-countersign-a-contract, create-and-launch-an-event
POST /contracts/{contract_id}/lock review-the-riders-approval-created, sign-and-countersign-a-contract, create-and-launch-an-event
POST /contracts/{contract_id}/resync-riders review-the-riders-approval-created
POST /debug/access/simulate-scan diagnose-a-red-scan
POST /debug/adminsuite/sandbox/seed delete-rows-safely
POST /debug/adminsuite/sql edit-any-row-with-admin-crud
POST /debug/clock use-the-debug-console
POST /debug/db/reset use-the-debug-console
POST /debug/events/tiers/{tier_id}/force-cascade get-into-a-member-only-drop, understand-your-events-tiers-and-releases
POST /debug/guestlist/reset-override-cap/{event_id} issue-a-vip-walk-in-override
POST /debug/intake/press-button fast-track-from-telegram
POST /debug/intake/resend-telegram fast-track-from-telegram
POST /debug/ledger/attempt-mutation post-a-house-credit-adjustment
POST /debug/ledger/promote-payouts process-a-payout-run
POST /debug/ledger/run-tab-settlement script-a-mock-failure, run-the-vip-tab-settlement
POST /debug/ledger/simulate-ach process-a-payout-run
POST /debug/marketing/posts/{post_id}/force-publish compose-and-publish-a-social-post
POST /debug/marketing/rules/{rule_id}/force-fire build-a-trigger-rule, configure-marketing-channels-and-rules
POST /debug/marketing/rules/{rule_id}/reset build-a-trigger-rule, configure-marketing-channels-and-rules
POST /debug/marketing/simulate-click trace-a-click-to-revenue, report-marketing-attribution
POST /debug/marketing/simulate-conversion trace-a-click-to-revenue, report-marketing-attribution
POST /debug/marketing/tick build-a-trigger-rule, configure-marketing-channels-and-rules
POST /debug/mock-behaviors script-a-mock-failure
POST /debug/payments/expire-holds hold-a-checkout-reservation
POST /debug/qa/invariants/run run-the-qa-invariant-sweep, process-a-payout-run, reconcile-tax-accruals
POST /debug/rbac/simulate build-a-role-from-capabilities
POST /debug/scheduler/tick use-the-debug-console
POST /debug/tax/replay-telegram-callback approve-a-filing-from-telegram
POST /debug/tax/run-scheduler run-the-quarterly-tax-filing
POST /debug/tax/seed-accruals reconcile-tax-accruals
POST /debug/webhooks/simulate script-a-mock-failure
POST /debug/webhooks/{webhook_id}/replay script-a-mock-failure
POST /preview/enter preview-the-site-as-a-guest
POST /preview/exit preview-the-site-as-a-guest
POST /resale/listings/{listing_id}/delist resell-a-ticket-you-cant-use
POST /resale/sell/{ticket_id} resell-a-ticket-you-cant-use
POST /sign/{token} sign-and-countersign-a-contract, create-and-launch-an-event
POST /webhooks/telegram run-the-staff-channel-on-live-telegram
POST /webhooks/telegram/tax approve-a-filing-from-telegram
PUT /api/admin/credit/users/{user_id}/tab post-a-house-credit-adjustment, run-the-vip-tab-settlement, use-your-membership-card-at-the-bar, use-and-settle-your-vip-tab
PUT /api/admin/events/{event_id}/refund-policy refund-a-ticket-or-order, self-cancel-a-ticket
PUT /api/admin/resale/events/{event_id}/config open-or-close-the-exchange, resell-a-ticket-you-cant-use, get-paid-your-host-royalty
PUT /api/admin/resale/tiers/{tier_id}/mode open-or-close-the-exchange
PUT /api/intake/public/applications/{app_id} respond-to-a-request-for-more-information, build-your-run-of-show-backwards, approve-a-host-application
PUT /api/intake/settings apply-to-host-an-event
PUT /api/rbac/groups/{group_name}/zones map-groups-to-door-zones, build-a-role-from-capabilities
PUT /api/rbac/groups/{slug}/capabilities build-a-role-from-capabilities
PUT /api/rbac/groups/{slug}/implications build-a-role-from-capabilities
PUT /api/rbac/tiers/{slug}/benefits build-a-role-from-capabilities
PUT /api/tax/packages/{package_id}/allocations approve-a-filing-from-telegram, run-the-quarterly-tax-filing
PUT /api/tiers/{tier_id}/zones understand-your-events-tiers-and-releases
PUT /debug/settings/{key} use-the-debug-console

Appendix C — Demo accounts

Practice logins on the demo/test data set only. These render only outside production and only while training.show_demo_accounts is on.

PersonaEmailPasswordNote
Membermember@club.testmember123 A registered customer: buys, holds tickets, house credit and resale listings.
VIP Membervip@club.testvip123 A member with a house tab and Zone B access. Implies everything a member can do.
Host / Promoterhost@club.testhost123 An outside promoter running an event at the venue. Scoped to that one event.
Door Staffdoor@club.testdoor123 Works the door: scans credentials, searches the guest list, checks people in.
Venue Managermanager@club.testmanager123 Runs the floor and the calendar: intake review, live sales, the door, marketing.
Adminadmin@club.testadmin123 Owns money, identity and configuration. Implies every other group.