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.

Marketing & Social

Social posts, trigger rules, short links and click-to-revenue attribution.

Compose and publish a social post

Write once, send to five channels, and get a tracked short link per platform for free.

Owned by Venue Manager · 11 steps · about 15 minutes

Why this exists

The publishing model is one post, many channels. You write a single body, choose which of the five platforms it goes to, and the platform materialises a separate delivery target per channel with its own state. That is why a post can end up partial: Instagram and Discord sent, X failed on length, and the post itself honestly reports partial rather than pretending it went out.

The reason the per-platform split matters more than it looks is the tracked link. Each target gets its own short link, stable across retries, carrying the platform as its source. That is the entire basis of the attribution report — without a link per platform there is no way to say which channel actually sold tickets, only that some did.

Placeholders are the other half of composing. Curly-brace tokens like event name, doors time, tier name, price and percentage sold are substituted at publish time, not at write time, so a scheduled post says what is true when it goes out rather than what was true when you typed it. Event placeholders require the post to be attached to an event — using one on a general club post is refused at save.

Length is enforced twice, at save and again at publish, because a channel's limit can bite a scheduled post that was fine when written. A target that violates it at publish time is marked failed with a body-too-long error rather than being silently truncated — the platform will not put half your sentence in public.

Before you start

  • A venue manager or admin session.
  • At least one enabled channel. The seed enables all five with the handle @neonclub.
  • For event placeholders: an event to attach the post to, such as demo-event-0001.

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
host_promoterpromoter@demo.club promoter123scoped host on demo-event-0001; owns the seeded Promoter X comp bucket

Steps 1–8 — Venue Manager

their manual →
  1. 1
    Open the marketing dashboard and check the channel row first: which platforms are enabled, and what has been sent recently.
    /admin/marketing marketing
    Expected result Five channels with their handles and post counts, plus recent and scheduled posts.
    Watch out for A disabled channel is refused at save time with channel_disabled. Check before you write, not after.
  2. 2
    Open the compose page. Pick the event if this is about a specific night — that is what enables event placeholders — or leave it as a general club post.
    Expected result The compose form with an event dropdown, a body box, placeholder buttons, platform checkboxes, link target, media ref and a schedule field.
    Watch out for Attaching the event is what unlocks the placeholders. Using an event placeholder on a general post is refused with placeholder_needs_event.
  3. 3
    Write the body and use the placeholder buttons rather than typing tokens by hand. Tick the platforms. Set the link target — a path such as an event page, or a full URL.
    Expected result A body with placeholders and a target set of platforms.
    Watch out for An unrecognised token is refused with unknown_placeholder. Use the buttons; a typo in a placeholder name is not a typo you will spot by rereading.
  4. 4
    Save it. Save draft parks it, Schedule sets it to publish at the time you entered, and Publish now sends immediately.
    /api/marketing/posts POST marketing
    Expected result A post in draft, scheduled or publishing.
    Watch out for A schedule time in the past is refused with scheduled_in_past — the schedule field wants UTC in ISO form. Length limits are checked here too, against the longest platform you ticked.
  5. 5
    Open the post detail and read the Targets table: one row per platform with its state, its attempts and its external link once sent.
    /admin/marketing/posts/{post_id} marketing
    Expected result Targets as pending, sent, failed or skipped, plus a Tracked links panel with a short link per platform.
    Watch out for Skipped means the channel was disabled after you scheduled. Skipped targets are excluded from the status maths — but a post whose targets are ALL skipped ends up failed.
  6. 6
    If the post came back partial or failed, press Retry failed. This re-sends only the failed and skipped targets and never re-sends one that already went.
    /api/marketing/posts/{post_id}/retry POST marketing
    Expected result The failed targets attempted again; the sent ones untouched.
    Watch out for Retry is only available on partial or failed posts — anything else is 409 post_not_retryable. The short links are stable across retries, so your attribution does not fragment.
  7. 7
    To stop a scheduled post that is no longer true, cancel it rather than editing it into something unrelated.
    /api/marketing/posts/{post_id}/cancel POST marketing
    Expected result Status cancelled.
    Watch out for You cannot delete it — deletion is admin-only, and only for drafts, cancelled and failed posts. Cancelling is the manager-grade stop button.
  8. 8
    Edit a post that has not gone out yet — drafts and scheduled posts only.
    /api/marketing/posts/{post_id} PATCH marketing
    Expected result The updated body, platforms or schedule.
    Watch out for 409 post_not_editable means it is publishing or published. Public is public; the fix is a new post, not a rewrite of history.

Steps 9 — Host / Promoter

their manual →

Can read the posts for their own event, and will ask you why theirs has not gone out.

  1. 9
    As a promoter, open the marketing tab for your own event to see what has gone out for your night.
    /admin/marketing/events/{event_id} marketing
    Expected result Posts and rules for that event.
    Watch out for You must be looking at your own event. Hosts have no view across the venue's marketing, only their own night's.

Steps 10–11 — Admin

their manual →

Owns channel settings and post deletion, and can force a publish outside the schedule.

  1. 10
    As an admin, enable or disable a channel and set its handle when the venue's accounts change.
    /api/marketing/channels/{platform} PATCH marketing
    Expected result The channel updated; the dashboard's channel row reflects it immediately.
    Watch out for Disabling a channel does not cancel posts already scheduled to it — those targets turn into skipped at publish time. Check the schedule before you disable.
  2. 11
    Force-publish a draft or scheduled post when you are rehearsing the flow, ignoring its schedule.
    /debug/marketing/posts/{post_id}/force-publish POST marketing
    Expected result The post publishes through the real pipeline.
    Watch out for This goes through the genuine publish routine and records genuine outbound traffic. Do it on a demo post, not on the real weekend announcement.

Build a trigger rule

Post automatically when a tier hits a threshold, cascades or sells out — exactly once.

Owned by Venue Manager · 12 steps · about 16 minutes

Why this exists

Trigger rules exist because the moments worth posting about are the moments nobody is watching for. A tier crossing ninety per cent, a cascade unlocking the next release, a night selling out — these happen at odd hours and they are exactly when urgency is real. A rule turns a sales event into a post without anyone refreshing a dashboard.

The mechanism is worth knowing because it explains the timing. Events publish state changes into an outbox; the marketing tick consumes that outbox, evaluates percentage and countdown rules, and publishes anything due. So rules fire on the tick, not the instant — a rule is prompt, not instantaneous, and that is a design choice in favour of one consistent transaction over five racing ones.

Dedupe is the part that saves you from embarrassment. Every firing is recorded against a trigger reference and the pair is unique, so redelivery of the same underlying event cannot post twice. On top of that, fire once means at most once ever, while leaving it off means once per distinct trigger — so a percentage rule can fire again if the tier reopens after refunds. Choose deliberately: a sell-out announcement should be once ever, a last-release nudge probably should not.

One operational rule to learn now: if a rule fires and its post fails, retry the POST, not the rule. The firing record stays, so re-firing is blocked by the dedupe — which is correct. The post is the thing that failed and the post is the thing to fix.

You do not have to be looking at the page to find out. Since plan 608 a post that ends failed or partial sends one message to the staff channel naming the event, the rule and the reason — once per failure, and again if a retry fails, never on a clean publish. Retry from the event's marketing tab, which is the page the notice is about; the sentence on that tab is the same one a host reads (“failed — not published — discord: the channel was switched off”), and only the Retry control differs by role.

Before you start

  • A venue manager or admin session.
  • An event with tiers. The seed ships three rules on demo-event-0001 already.
  • At least one enabled channel for the rule's post to go to.

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
membermember@club.test member123holds a seeded pass and membership card to practise scans against

Steps 1–8 — Venue Manager

their manual →
  1. 1
    Open the event's marketing tab. This is a standalone page, reached from the event, not a panel inside the event admin screen.
    /admin/marketing/events/{event_id} marketing
    Expected result The event's posts and rules, each rule with a live preview of its current condition.
    Watch out for The seeded event already has three rules — percentage sold at ninety, event sold out, and a cascade on the VIP Lounge tier. Read those before writing a fourth that duplicates one.
  2. 2
    Create a rule. Name it, then pick the trigger: percent sold, minutes before sale, tier cascade, tier sold out or event sold out.
    /admin/marketing/events/{event_id}/rules/new marketing
    Expected result The form revealing only the fields that trigger needs.
    Watch out for The trigger dictates the configuration. A percentage rule without a threshold is refused with threshold_required; a countdown rule without minutes with minutes_required; and supplying a threshold to a trigger that has no use for one is refused with config_not_allowed.
  3. 3
    Decide the scope: leave the tier blank for an event-level rule, or pick a tier to watch just that release.
    /admin/marketing/events/{event_id}/rules/new marketing
    Expected result A rule bound to the whole event or to one tier.
    Watch out for A tier from a different event is refused with tier_event_mismatch, and some triggers do not accept a tier at all — tier_not_allowed. The form is telling you the trigger's shape, not being awkward.
  4. 4
    Write the template body with placeholders — the same tokens as a manual post — pick the platforms, and set the link target.
    /admin/marketing/events/{event_id}/rules/new marketing
    Expected result A template that will render with live values at firing time.
    Watch out for Placeholder and channel validation happen here, not at firing time. An unknown placeholder or a disabled channel is refused at save, which is exactly when you want to hear about it.
  5. 5
    Set fire once deliberately, then save. Fire once means at most once ever; leaving it off means once per distinct trigger occurrence.
    /api/marketing/events/{event_id}/rules POST marketing
    Expected result The rule listed as active with a condition preview.
    Watch out for A sell-out announcement firing twice because the tier reopened after a refund is a genuinely bad look. When in doubt on a milestone, fire once.
  6. 6
    After the rule has had a chance to fire, read its firing history.
    /api/marketing/rules/{rule_id}/firings marketing
    Expected result Firings with their trigger reference and the post each produced.
    Watch out for A firing with no post attached is a skip — usually a missed drop window on a countdown rule. That is recorded rather than silently dropped, so you can see the rule did evaluate.
  7. 7
    Edit, deactivate or delete a rule that is no longer right. Deactivating leaves its history intact.
    /admin/marketing/rules/{rule_id}/edit marketing
    Expected result The rule updated, inactive, or gone from the list.
    Watch out for Deactivating does not delete the firings, and re-activating does not re-fire anything already recorded. If you genuinely need it to fire again, that is an admin reset. Added 2026-08-30, because the red Delete sits beside these two and this step never mentioned it: Delete is ALSO soft. It hides the rule from the list and leaves every firing and every post it ever produced exactly where they are, readable through the rule's firings endpoint. So the choice between Deactivate and Delete is about whether you expect to switch it back on, not about whether you keep the history — neither loses it.
  8. 8
    When a rule's post comes back failed, open the post and retry it. Do not go back to the rule.
    /admin/marketing/posts/{post_id} marketing
    Expected result The failed targets re-sent from the post.
    Watch out for This is the single most common mistake with rules. The firing succeeded; the delivery did not. Re-firing is blocked by dedupe, and correctly so.

Steps 9 — Member

their manual →

Is the person whose purchase crosses the threshold that fires the rule.

  1. 9
    From the customer side, buy into the tier until it crosses the threshold — this is what actually trips a percentage rule.
    /events/{event_id} events
    Expected result The tier's sold percentage rising past your threshold.
    Watch out for Reserved is not sold. A tier full of open checkout holds has not crossed anything yet — the rule watches committed sales.

Steps 10–12 — Admin

their manual →

Owns the tools that fire a rule on demand and reset its firing history for a re-test.

  1. 10
    As an admin, fire a rule immediately through the real pipeline to test it — this works even on an inactive rule.
    /debug/marketing/rules/{rule_id}/force-fire POST marketing
    Expected result A firing marked as forced, and a real post.
    Watch out for It publishes for real to the mock channels and writes real outbound traffic. Use a demo event.
  2. 11
    Reset a rule's firings when re-testing a fire-once rule. This is the sanctioned way to make it fire again.
    /debug/marketing/rules/{rule_id}/reset POST marketing
    Expected result Firing history cleared and the last-fired stamp removed.
    Watch out for Do not reach into the tables to do this by hand. The reset clears the firings AND the stamp — clearing one without the other leaves a rule that behaves inexplicably.
  3. 12
    Run the marketing tick manually when you do not want to wait for the scheduler.
    /debug/marketing/tick POST marketing
    Expected result A report of outbox rows consumed, rules fired and skipped, and posts published.
    Watch out for The tick is idempotent for the same clock time. Running it twice in a row is safe and is the fastest way to prove a rule did not fire because its condition is false, not because the tick is stuck.

Configure marketing channels and trigger rules

Own the channels, govern the automation, and force-fire a rule safely before an on-sale.

Owned by Admin · 12 steps · about 22 minutes

Why this exists

Marketing automation on this platform is a small, deliberate machine: five fixed channels, a rules engine that watches the event lifecycle, and short links that make the results measurable. This workflow is the part only an admin can do — the channels themselves, the debug controls and the forced firings — with the venue manager present doing the day-to-day composing, because that is how the work is actually split.

Channels are configuration, not content. There are exactly five, they cannot be added, and only an admin may change a handle or disable one. Disabling matters more than it looks: a disabled channel refuses new posts at creation time with a clear error, and a channel disabled after a post was scheduled causes that target to be skipped at publish time rather than failing. A post whose only targets were skipped ends up failed — which is the honest outcome, because nothing was published.

Rules fire from real events, not from a timer. The engine consumes an outbox that the events module writes to, plus percentage-sold and minutes-before-sale conditions evaluated on each tick. Every firing is deduped by a trigger reference, so a replayed outbox row cannot post twice. Fire-once means at most once ever; otherwise a rule fires once per distinct trigger.

A rule post that fails is a post problem, not a rule problem. The firing stays recorded, so retry the post; refiring the rule would either be deduped or produce a duplicate announcement. That distinction is the one thing to take away from this workflow.

The debug force-fire runs a rule through the real pipeline immediately, even if it is inactive, which is how you rehearse an on-sale announcement without waiting for the on-sale. Its companion reset deletes the rule's firings so a fire-once rule can be tested twice — the sanctioned way, rather than editing rows.

Before you start

  • An admin session for the channel and debug steps; a venue manager can do the composing half.
  • An event to hang rules on — the seed ships rules on demo-event-0001.
  • Remember that every published post is a real call to a mock social adapter and is recorded in the wire log.

Practise with

PersonaEmailPasswordNote
adminadmin@club.test admin123the only persona that can configure channels or force-fire a rule
venue_managermanager@club.test manager123composes posts and writes rules day to day
host_promoterhost@club.test host123scoped host on demo-event-0001 — read-only on its marketing

Steps 1–3 — Admin

their manual →
  1. 1
    Open the marketing dashboard: channels, recent posts, what is scheduled, and the channel report.
    /admin/marketing marketing
    Expected result The five channels with their handles and whether they are enabled, plus post activity.
    Watch out for There are exactly five channels and there is no add button. If somebody asks for a sixth network, that is a code change, not a configuration one.
  2. 2
    Pull the channels as JSON and note the per-channel count of posts sent.
    Expected result Each platform with its handle, enabled flag and volume.
    Watch out for Both admins and venue managers can read this. Only admins can change it.
  3. 3
    Change a handle or disable a channel you are not using this season.
    /api/marketing/channels/{platform} PATCH marketing
    Expected result The updated channel.
    Watch out for Disabling refuses NEW posts targeting it with 422 channel_disabled. Posts already scheduled to it are skipped at publish time instead — and a post whose only targets were skipped ends failed. Disable before people schedule, not after.

Steps 4–6 — Venue Manager

their manual →

They write the rules and the copy; the admin owns the channels the copy goes out on.

  1. 4
    As the manager, open the event's marketing tab: its rules, its posts and its funnel in one place.
    /admin/marketing/events/{event_id} marketing
    Expected result Rules with live condition previews, the event's posts, and the click-to-order funnel.
    Watch out for This is a standalone page, deliberately not injected into the event admin template. Link to it from the event rather than expecting it to appear there.
  2. 5
    Open the rule form and choose a trigger: a percentage sold, a number of minutes before sale, a tier cascade, a tier sell-out or an event sell-out.
    /admin/marketing/events/{event_id}/rules/new marketing
    Expected result A form whose required fields change with the trigger you pick.
    Watch out for Placeholders in the copy are checked against what the trigger can actually provide. An unknown placeholder, or an event placeholder on a rule with no event, is refused at creation rather than rendering as an empty string on a public post.
  3. 6
    Create the rule, choosing carefully whether it fires once ever or once per distinct trigger.
    /api/marketing/events/{event_id}/rules POST marketing
    Expected result 201 with the rule and its preview of when it would fire.
    Watch out for Threshold rules need a threshold and drop rules need a minutes value; the wrong combination is a 422 naming the missing field. Fire-once is the safer default for anything that reads like an announcement.

Steps 7–10 — Admin

their manual →
  1. 7
    Rehearse it: force the rule to fire now, through the real pipeline, before the real condition is anywhere near true.
    /debug/marketing/rules/{rule_id}/force-fire POST marketing
    Expected result A firing recorded with a forced trigger reference, and a real post published to the enabled channels.
    Watch out for This publishes for real to the mock adapters and it works even on an inactive rule. Rehearse on a test event, not on the one that goes on sale on Friday.
  2. 8
    Read the rule's firing log and see what it produced, including firings that were skipped.
    /api/marketing/rules/{rule_id}/firings marketing
    Expected result One entry per firing, with its trigger reference and the post it created, if any.
    Watch out for A firing with no post and a skipped note means the window had already passed — the rule fired and correctly decided not to announce. That is not a failure to investigate.
  3. 9
    Reset the rule's firings when you need to test a fire-once rule a second time.
    /debug/marketing/rules/{rule_id}/reset POST marketing
    Expected result The firings are deleted and the last-fired stamp cleared.
    Watch out for This is the sanctioned way to re-test. Editing the firing rows in the data suite to achieve the same thing will leave the dedupe index and the rule disagreeing.
  4. 10
    Run a marketing tick by hand to see the whole pipeline in one call: consume the outbox, evaluate the rules, publish what is due.
    /debug/marketing/tick POST marketing
    Expected result A report of rows consumed, rules fired and skipped, posts published, and per-target sends and failures.
    Watch out for The outbox is single-consumer: every row read is stamped, matched or not. Marketing runs after the events lifecycle in a tick, which is why a cascade and its announcement can land together.

Steps 11 — Host / Promoter

their manual →

They may read their own event's marketing and firings, and nothing else — the scope is the event.

  1. 11
    As the promoter, open your own event's marketing tab and confirm what you can see.
    /admin/marketing/events/{event_id} marketing
    Expected result Your event's posts, rules and funnel, read-only.
    Watch out for Another event id is a 403. A host grant is a grant over one event's marketing, not over the venue's.

Steps 12 — Admin

their manual →
  1. 12
    Finish in the social wire log and confirm what was really sent, to which platform, with which text.
    Expected result Outbound social calls joined to their posts.
    Watch out for The text sent always carries the SHORT link, never the expanded tracked URL. If you see a raw long URL in a post, something bypassed the link builder.

Trace a click to revenue

Follow a short link from the tap through the order and read the channel report honestly.

Owned by Venue Manager · 10 steps · about 14 minutes

Why this exists

Attribution here is deliberately simple and deliberately honest, and knowing exactly how simple it is stops you over-reading the numbers. Every published post gets a tracked short link per platform. When somebody taps it the platform records the click, drops a visitor cookie and an attribution cookie, and redirects them to the tagged destination. When an order is later paid, the attribution cookie is read and, if the click is inside the attribution window, a conversion row is written.

Three consequences follow, and every argument about these reports comes back to one of them. First, last click wins — the redirect overwrites the cookie, so a customer who taps Instagram then X is credited to X. Second, one conversion per order, first write wins, so revenue is never double-counted across channels. Third, the recorded revenue is a gross snapshot at attribution time and refunds do not remove it. A cancelled event does not empty this report, and that is a documented choice, not a bug.

What the report is genuinely good for is comparing channels against each other over the same window: posts sent, links, clicks, unique clicks, orders, revenue and conversion rate, per platform. What it is not good for is a net revenue figure — that lives in the ledger, which is admin-only, and for good reason.

These reports are computed live from the click and conversion tables with no denormalised counters anywhere. There is nothing to rebuild and nothing that can silently drift; a number that looks wrong is a question about the underlying rows, not about a cache.

Before you start

  • A venue manager or admin session.
  • A published post with tracked links. The seed publishes a three-platform post on demo-event-0001 with simulated clicks.

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

Steps 1–7 — Venue Manager

their manual →
  1. 1
    Open the marketing reports and filter to the event and the date range you care about.
    Expected result A Channels table with posts sent, links, clicks, unique, orders, revenue and conversion rate, plus a Rule effectiveness table underneath.
    Watch out for Compare like with like. A channel that only received two posts in the window will have a flattering conversion rate off almost no traffic.
  2. 2
    Pull the same figures as data when you need them elsewhere — the endpoint takes the event, a date range, and a CSV format option.
    Expected result Per-platform rows and a totals row.
    Watch out for The event's own scoped host can read this too, but only for their own event id. If a promoter asks for the venue-wide numbers, that is a no.
  3. 3
    For one night, read the event funnel report and its per-rule breakdown to see whether automated posts or manual ones did the work.
    /api/marketing/reports/events/{event_id} marketing
    Expected result A funnel plus a rule-by-rule breakdown.
    Watch out for Rule effectiveness compares automated posts against each other. It does not prove causation — a sell-out rule fires because the night was already selling.
  4. 4
    List the tracked links to find the short code for a specific post and platform.
    Expected result Links with their short code, campaign, source platform and the post they belong to.
    Watch out for The link is stable per post and platform, including across retries. Two codes for what looks like one post usually means two posts.
  5. 5
    Tap a short link yourself in a fresh browser to see the customer's path: the click is recorded, cookies are set, and you are redirected to the tagged destination.
    /l/{short_code} marketing
    Expected result A redirect to the event page with the campaign parameters attached.
    Watch out for Your own tap is a real click in the report. Use a private window and expect to see yourself in the unique-click count.
  6. 6
    Close the loop on a real conversion: find the order the report credits and confirm the amount against the recorded revenue.
    /admin/orders/{order_id} payments
    Expected result An order whose gross matches the attributed figure.
    Watch out for If the order was later refunded the attributed revenue still stands. That is the gross-snapshot rule — the marketing report is not an accounting surface.
  7. 7
    Know where the real numbers live and that you cannot reach them. Net revenue, refunds and the double-entry ledger are admin-only. Quote this report as marketing performance, never as takings.
    Expected result The right report used for the right question.
    Watch out for The 403 on the ledger is deliberate. If somebody needs a revenue figure for a settlement, that is an admin's number to give, not yours to estimate from clicks.

Steps 8–10 — Admin

their manual →

Owns the per-link forensics and the simulators that let you prove the chain end to end.

  1. 8
    As an admin, run the single-link forensics when a manager disputes a figure: the link, every click on it, and every conversion attributed to it.
    /debug/marketing/links/{short_code} marketing
    Expected result The full chain for one short code.
    Watch out for Clicks outside the attribution window are recorded but never convert. That gap between clicks and orders is usually the answer to 'why is our conversion rate so low'.
  2. 9
    Simulate clicks against a short code when demonstrating or testing the chain, optionally as a repeat visitor.
    Expected result Click ids you can then attribute an order to.
    Watch out for Repeat clicks from the same visitor count once as unique and every time as total. That is exactly the distinction the report's two columns exist to show.
  3. 10
    Attribute an order to a click through the real attribution path and read the reason it gives back.
    Expected result Whether a conversion was written, and why not if not.
    Watch out for The reasons are the whole lesson: unknown click, expired window, duplicate order. Attribution never raises an error — it silently declines, which is why proving it needs this endpoint.

Report on marketing attribution

Follow one click through to revenue, and understand exactly what the number does and does not mean.

Owned by Admin · 10 steps · about 18 minutes

Why this exists

Attribution here is deliberately simple, and understanding the simplifications is the difference between a useful report and a misleading one.

Every post gets a tracked short link per platform. The public redirect records the click, flags whether this visitor has clicked this link before, sets two cookies — a long-lived visitor id and a short-lived attribution id — and sends the person on to the tagged destination. When an order is later paid, the payments module hands the attribution cookie to marketing, and if the click is recent enough a conversion row is written. CORRECTED 2026-08-30: that last handshake is not wired. The cookie is set on every click and read by nothing — payments does not import this module, and the only callers of attribute_order are the seed, the debug simulate-conversion endpoint and the test suite. So outside a seeded database there are no conversions at all, and every orders / revenue / conversion-rate figure in the reports below is structurally zero. Plan 647 wires it; read the rest of this workflow knowing which half runs.

Four rules follow, and each one is a caveat you should say out loud when you present the numbers. Last click wins, because the redirect overwrites the cookie. The window is finite — a click older than the configured number of days attributes nothing. One conversion per order, first write wins, enforced by a unique constraint. And revenue is a gross snapshot taken at attribution time: a later refund does not remove the conversion or reduce the figure.

Attribution is also never allowed to break a purchase. The attribution call cannot raise — an unknown click, an expired window, a duplicate order, even a missing table all return quietly false. Nobody's checkout has ever failed because a marketing cookie was odd, and that is a deliberate ordering of priorities.

The reports are pure read-time SQL over those rows. There are no denormalised counters anywhere, so there is nothing to drift and nothing to rebuild — a report is always a straight answer about what is in the tables right now.

Before you start

  • An admin session for the debug forensics; a venue manager can read the same reports.
  • At least one published post with short links (the seed ships one with simulated clicks).
  • An honest willingness to quote the caveats along with the conversion rate.

Practise with

PersonaEmailPasswordNote
adminadmin@club.test admin123reads the reports and the per-link forensics
venue_managermanager@club.test manager123reads the same reports; the debug forensics are admin-only

Steps 1 — Admin

their manual →
  1. 1
    List the tracked links and pick one to follow: note its short code, the post and platform it belongs to, and its campaign tags.
    Expected result Links with their short codes, targets and UTM parameters.
    Watch out for A link is stable per post and platform. Retrying a post reuses the same link, which is why retries do not fragment your reporting.

Steps 2 — Customer (Guest)

their manual →

The click that starts the whole chain is made by a stranger with no account at all.

  1. 2
    Open the short link the way a stranger would, from a phone, with no account and no session.
    /l/{short_code} marketing
    Expected result A redirect to the tagged destination, a click recorded, and two cookies set.
    Watch out for This is the only public route in the whole workflow, and it works with no login by design — a marketing link that demanded a session would convert nobody. An unknown code is a 404 that records nothing and sets no cookies.

Steps 3–8 — Admin

their manual →
  1. 3
    Look at that single link's forensics: the link row, every click on it, and every conversion attributed to it.
    /debug/marketing/links/{short_code} marketing
    Expected result The whole chain for one link in one response.
    Watch out for Admin-only. This is the tool for 'why did this campaign report nothing'. CORRECTED 2026-08-30: it used to say that clicks with no conversions is a landing page problem and not a tracking one. Until plan 647 lands it is ALWAYS a tracking problem — nothing reads the attribution cookie, so no purchase can ever produce a conversion. Read clicks-with-no-conversions as the known gap first, and only look at the landing page once the chain is wired.
  2. 4
    Open the channel report and read it per platform: posts published, links, clicks, unique clicks, orders, revenue and conversion rate, plus totals.
    Expected result One row per platform, filterable by event and date range.
    Watch out for Unique clicks are per visitor per link. The gap between clicks and unique clicks is people re-opening the same link, not new reach.
  3. 5
    Pull the same report as JSON, or ask for CSV when somebody wants it in a spreadsheet.
    Expected result The per-platform figures and totals in the format you asked for.
    Watch out for A scoped host may call this only for their own event id. If you are building a shared report, remember that the same endpoint answers differently depending on who calls it.
  4. 6
    Switch from channels to one event's funnel, broken down per rule.
    /api/marketing/reports/events/{event_id} marketing
    Expected result The funnel from clicks through to attributed orders and revenue, plus which rules produced which.
    Watch out for Rule-driven posts and hand-written posts appear side by side. A rule that produced clicks but no orders is worth more attention than one that produced neither.
  5. 7
    In training, simulate clicks on a link so the report has something in it, giving a visitor id and a count.
    Expected result The created click ids.
    Watch out for Simulated clicks are indistinguishable from real ones in the reports. Do this on a demo database only, or you will be explaining your own traffic to somebody next quarter.
  6. 8
    Attribute one of those clicks to an order through the real attribution path, with a revenue figure.
    Expected result A written flag and, when it is false, the reason: unknown click, expired window, duplicate order.
    Watch out for The reason codes are the fastest way to learn the rules. Try it with a click older than the window and read what it tells you, rather than trusting this page.

Steps 9 — Venue Manager

their manual →

They own the campaign and read the same report — without the debug tooling.

  1. 9
    As the manager who ran the campaign, read the same report — and notice you get the numbers without the debug tooling.
    Expected result The identical report page.
    Watch out for Every /debug route in this workflow is 404 or 403 for you. If a number looks wrong, the escalation is to an admin, and this page is the evidence you bring.

Steps 10 — Admin

their manual →
  1. 10
    Before you present anything, say the caveats out loud: last click wins, the window is finite, one conversion per order, and revenue is a gross figure that refunds never reduce — and, until plan 647 lands, the biggest one of all: no real purchase is attributed at all, so a non-zero conversion figure on this platform came from the seed or from a debug simulation.
    Expected result A report you can defend rather than one you have to withdraw.
    Watch out for The commonest mistake is comparing attributed revenue to actual takings. They are different numbers measuring different things, and the gap is refunds, unattributed sales and the attribution window — not an error.

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.