Ticket Pool
Hand out unique numbers or tickets from a finite pool — the next number in line (seat 1..36) or a random unused one (KK-0001..KK-4000). Atomic, one per visitor, with optional claim tokens for checking and redeeming at the counter. Everything is set per pool via endpoints; no code needed.
Try it with your AI assistant
Once WebsitePublisher is connected to your AI assistant, paste one of these into the chat. Replace the parts in [brackets] with your own details.
@WebsitePublisher create a giveaway pool of [number] random codes like [prefix]-0001 that each signed-in visitor can claim once@WebsitePublisher show the attendee list for [pool name] and which tickets were already redeemed@WebsitePublisher void tickets [codes] in [pool name] and raise the pool to [number] placesWith WebsitePublisher, create a giveaway pool of [number] random codes like [prefix]-0001 that each signed-in visitor can claim onceWith WebsitePublisher, show the attendee list for [pool name] and which tickets were already redeemedWith WebsitePublisher, void tickets [codes] in [pool name] and raise the pool to [number] placesWith WebsitePublisher, create a giveaway pool of [number] random codes like [prefix]-0001 that each signed-in visitor can claim onceWith WebsitePublisher, show the attendee list for [pool name] and which tickets were already redeemedWith WebsitePublisher, void tickets [codes] in [pool name] and raise the pool to [number] placesEndpoints (10)
Create a ticket pool. Choose mode "sequential" (next number in line, e.g. seats) or "random" (random unused number, e.g. a giveaway). Choose access explicitly: "anonymous" lets any visitor get a ticket without signing in (one per browser session, limited per IP); "verified" requires a signed-in visitor or tenant (one per email). Mode, range and code format cannot change after the first ticket is issued; range_max can only go up.
| Field | Type | Required | Description |
|---|---|---|---|
pool_key |
string | ✓ Yes | Short id for this pool, lowercase letters, digits, - and _. Example: "giveaway" or "led-event". |
label |
string | ✓ Yes | Human-readable name. |
mode |
string | ✓ Yes | "sequential" or "random". |
range_max |
integer | ✓ Yes | Highest number in the pool. Capacity = range_max - range_min + 1 (max 100000). |
range_min |
integer | No | Lowest number (default 1). |
access |
string | ✓ Yes | "anonymous" or "verified". No default: choose deliberately. |
code_prefix |
string | No | Text before the number, e.g. "KK-". Default empty. |
code_pad |
integer | No | Zero-pad the number to this many digits, e.g. 4 gives KK-0007. Default 0 (no padding). |
per_visitor_limit |
integer | No | Tickets per visitor (per session when anonymous, per email when verified). Default 1. |
per_ip_hourly |
integer | No | Anonymous pools only: max new tickets per IP address per hour (0 = off, max 1000). Default 10. |
per_ip_daily |
integer | No | Anonymous pools only: max new tickets per IP address per day (UTC), 0 = off, max 10000. Default 50 (pools created before this setting existed have 0). Stops one script from emptying the pool from one network. Visitors who share an IP (office, school, mobile network) count together: raise it or set 0 if they get blocked. |
claim_token |
boolean | No | Give every ticket a secret claim token for verify-ticket / redeem-ticket. Default true. |
reissue_on_reload |
boolean | No | When the same visitor asks again, return the same ticket including its claim token. Default true. If false the token is shown only once. |
meta_fields |
array | No | Which extra fields a visitor may send with issue-ticket, e.g. ["name","email"]. Default none. |
show_remaining |
boolean | No | Show capacity, issued and remaining publicly. Default true. |
visitor_issue |
boolean | No | Default true: visitors get a ticket straight from the page (issue-ticket) or a form. Set false for paid or invite-only tickets: then only the owner or a server-side chain (for example order.paid -> issue-ticket) issues them, and a page or form gets 403. |
owner_issue_when_closed |
boolean | No | Default false. True: the owner or a server-side chain (for example after payment) may still issue while the pool is paused or outside opens_at/closes_at, so a paying customer always gets a ticket. Visitors and forms never. Sold out still applies. |
opens_at |
string | No | Optional start (ISO 8601). Before this no tickets are issued. |
closes_at |
string | No | Optional end (ISO 8601). After this no tickets are issued. |
Change pool settings. Only send what changes. After the first ticket: mode, range_min, code_prefix and code_pad are fixed, and range_max can only be raised. Set is_active false to pause.
| Field | Type | Required | Description |
|---|---|---|---|
pool_key |
string | ✓ Yes | |
label |
string | No | |
mode |
string | No | |
range_min |
integer | No | |
range_max |
integer | No | |
access |
string | No | |
code_prefix |
string | No | |
code_pad |
integer | No | |
per_visitor_limit |
integer | No | |
per_ip_hourly |
integer | No | |
per_ip_daily |
integer | No | |
claim_token |
boolean | No | |
reissue_on_reload |
boolean | No | |
meta_fields |
array | No | |
show_remaining |
boolean | No | |
is_active |
boolean | No | |
visitor_issue |
boolean | No | false = only the owner or a server-side chain issues tickets (paid or invite-only pools); true = visitors too. |
owner_issue_when_closed |
boolean | No | true = the owner or a server-side chain may still issue while the pool is paused or outside its window (paid flows). |
opens_at |
string | No | ISO 8601, or empty string to clear. |
closes_at |
string | No | ISO 8601, or empty string to clear. |
All settings of one pool (or all pools when pool_key is omitted), which settings can still change, current counts, and the platform limits.
| Field | Type | Required | Description |
|---|---|---|---|
pool_key |
string | No |
Issued tickets of a pool with number, code, meta, redeemed and voided status — the attendee list. Paginated.
| Field | Type | Required | Description |
|---|---|---|---|
pool_key |
string | ✓ Yes | |
status |
string | No | "all" (default), "open" (not redeemed and not voided), "redeemed" or "voided". |
page |
integer | No | Default 1. |
per_page |
integer | No | Default 50, max 200. |
Check whether a ticket is genuine and whether it was already redeemed. Needs the claim token when the pool uses claim tokens. A voided ticket returns valid false and voided true.
| Field | Type | Required | Description |
|---|---|---|---|
pool_key |
string | ✓ Yes | |
code |
string | ✓ Yes | |
claim_token |
string | No |
Mark a ticket as redeemed. Works once per ticket; a second call reports it was already redeemed. Needs the claim token when the pool uses claim tokens. A voided ticket is refused (TICKET_VOIDED).
| Field | Type | Required | Description |
|---|---|---|---|
pool_key |
string | ✓ Yes | |
code |
string | ✓ Yes | |
claim_token |
string | No |
Void tickets, for example ones taken by a script or a cancellation, or make them valid again with restore true. Find the codes with list-tickets. A voided ticket keeps its number (codes never change meaning) and still counts as issued and for per_visitor_limit; raise range_max with update-pool to make room for new tickets. verify-ticket then returns valid false and redeem-ticket refuses it. Returns changed, unchanged and not_found.
| Field | Type | Required | Description |
|---|---|---|---|
pool_key |
string | ✓ Yes | |
codes |
array | No | Ticket codes, e.g. ["KK-0007","KK-0012"]. Max 200 per call. |
code |
string | No | One ticket code, instead of codes. |
restore |
boolean | No | true = make voided tickets valid again. Default false. |
Public status of a pool: label, whether it is open, and (if show_remaining) capacity, issued and remaining. Never returns tickets.
| Field | Type | Required | Description |
|---|---|---|---|
pool_key |
string | ✓ Yes |
Give the current visitor a ticket. Asking again returns the same ticket (already_issued: true) instead of a new one. Verified pools require a signed-in visitor. Called by the site owner (not a visitor) it always issues a new ticket, for manual bookings. Pools with visitor_issue false refuse requests from a page or form (403).
| Field | Type | Required | Description |
|---|---|---|---|
pool_key |
string | ✓ Yes | |
meta |
array | No | Extra fields allowed by the pool's meta_fields, e.g. {"name":"Jane"}. Max 2 KB, plain values only. |
Tickets the current visitor already holds in a pool (by session when anonymous, by email when verified).
| Field | Type | Required | Description |
|---|---|---|---|
pool_key |
string | ✓ Yes |
MCP Tool Names
When using this integration through an AI assistant (Claude, ChatGPT, Cursor, etc.), the endpoints are available as MCP tools:
| Endpoint | MCP Tool Name |
|---|---|
| create-pool | ticket-pool_create_pool |
| update-pool | ticket-pool_update_pool |
| get-pool-config | ticket-pool_get_pool_config |
| list-tickets | ticket-pool_list_tickets |
| verify-ticket | ticket-pool_verify_ticket |
| redeem-ticket | ticket-pool_redeem_ticket |
| void-ticket | ticket-pool_void_ticket |
| get-pool | ticket-pool_get_pool |
| issue-ticket | ticket-pool_issue_ticket |
| my-tickets | ticket-pool_my_tickets |
Website