Browse API docs

Guest list

Guest list admissions are complimentary named parties. They consume real ticket inventory, skip checkout, and are not customers. Use this API instead of a hidden 0€ promo code.

The JSON shape is pinned to the integration tests in Usetix. If a test fails with “API payload shape drifted”, update this page.

Writes with an API token (no signed-in user) are attributed to the account owner. Numbered seats are never auto-assigned: send event_place_ids from ticket_options.available_places. Group tickets, whole tables, and numbered-seat walk-ins are not available here. Scanner walk-ins stay a door action.

Related: orders (origin, delivery_email, staff_note), events (guest-list counts), and scanner tickets.

GET /admin/events/:event_slug/guest_list

Lists guest parties for an event, plus eligible ticket types and currently available inventory.

curl -H "Authorization: Bearer your-token-here" \
  -H "Accept: application/json" \
  "https://app.usetix.io/admin/events/spring-showcase/guest_list"

Query parameters:

Parameter Description
query Guest name, companion name, or delivery email.
filter all (default), expected, or arrived.

Response:

{
  "query": "",
  "filter": "all",
  "expected_count": 2,
  "arrived_count": 0,
  "admission_count": 2,
  "ticket_options": [
    {
      "id": 12,
      "title": "General Admission",
      "inventory_kind": "ga",
      "available_stock": 48,
      "unlimited_stock": false,
      "standing_areas": [],
      "available_places": []
    }
  ],
  "guest_parties": [
    {
      "public_id": "gst_abc123",
      "order_code": "7K3Q9D2A",
      "display_number": "7K3Q-9D2A",
      "status": "paid",
      "origin": "guest_list",
      "customer_name": "Anna Müller",
      "delivery_email": null,
      "staff_note": "Use the side entrance",
      "customer_phone": null,
      "customer_company": null,
      "billing_address": { "street": null, "postal_code": null, "city": null, "country": null, "vat_id": null },
      "custom_field_answers": {},
      "arrival_state": "expected",
      "arrived_count": 0,
      "party_size": 2,
      "cancellable": true,
      "ticket_id": 12,
      "ticket_title": "General Admission",
      "creator_name": "Alex Organizer",
      "paid_at": "2026-08-22T10:15:00Z",
      "created_at": "2026-08-22T10:15:00Z",
      "admissions": [
        {
          "public_id": "itm_lead",
          "attendee_name": "Anna Müller",
          "custom_field_answers": {},
          "place_label": null,
          "check_in_code": "9M5V2H8C",
          "display_check_in_code": "9M5V-2H8C",
          "redeemed": false,
          "redeemed_at": null,
          "admission_status": "active",
          "cancellable": true,
          "seat_exchangeable": false
        },
        {
          "public_id": "itm_plus_one",
          "attendee_name": "Guest of Anna Müller",
          "custom_field_answers": {},
          "place_label": null,
          "check_in_code": "4P8R1L6N",
          "display_check_in_code": "4P8R-1L6N",
          "redeemed": false,
          "redeemed_at": null,
          "admission_status": "active",
          "cancellable": true,
          "seat_exchangeable": false
        }
      ]
    }
  ]
}

inventory_kind is ga, standing, or places. available_stock is the currently available admission quantity after product stock, shared event capacity, seating claims and organizer blocks. Only unbounded availability returns "available_stock": null and "unlimited_stock": true; unlimited product stock can still have a finite available quantity. For standing tickets, standing_areas lists open pools. For numbered tickets, available_places lists currently free seats as { "id", "key", "label" }. key is the stable seat logical key (the same identifier MCP’s places action returns).

GET /admin/events/:event_slug/guest_parties/:public_id

Returns one guest party. HTML requests redirect to the edit screen.

curl -H "Authorization: Bearer your-token-here" \
  -H "Accept: application/json" \
  https://app.usetix.io/admin/events/spring-showcase/guest_parties/gst_abc123

Response: 200 OK with the guest party JSON.

POST /admin/events/:event_slug/guest_parties

Creates a complimentary party and takes inventory immediately.

curl -X POST \
  -H "Authorization: Bearer your-token-here" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"guest_party": {"customer_name": "Anna Müller", "party_size": 2, "ticket_id": 12, "staff_note": "Use the side entrance"}}' \
  https://app.usetix.io/admin/events/spring-showcase/guest_parties

Numbered seats:

curl -X POST \
  -H "Authorization: Bearer your-token-here" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"guest_party": {"customer_name": "Anna Müller", "ticket_id": 15, "event_place_ids": [401, 402]}}' \
  https://app.usetix.io/admin/events/spring-showcase/guest_parties

Body parameters (inside guest_party):

Field Required Notes
customer_name yes Door-search name.
ticket_id yes An eligible standard ticket from ticket_options.
party_size no 1–20. Ignored when event_place_ids is present (size is the number of places). Defaults to 1.
event_place_ids numbered tickets IDs from ticket_options.available_places. Required for places tickets. Do not invent them.
event_capacity_pool_id standing, if more than one area From ticket_options.standing_areas. When the ticket has a single standing area, Usetix picks it.
delivery_email no Optional ticket delivery. Not the guest’s identity.
send_to_creator no If true, delivers to the acting organizer (API tokens: the account owner).
staff_note no Internal hint, max 500 characters. Scanner-only.

Response: 201 Created with the guest party JSON and a Location header. 422 Unprocessable Entity with { "errors": { "field": ["..."] } } when the name is blank, the ticket is ineligible, stock is gone, or the seats are no longer free.

Checkout questions and optional billing details

The manual admin form, JSON API, assistant and MCP can record the event’s order-level and per-attendee questions. Upfront required questions and select options use the same validation as checkout; questions configured for completion later remain optional. Failed validation creates no admissions and consumes no inventory. Scanner walk-ins keep their name-based workflow. Signup links can ask the event’s order-level questions as well; see What a link asks.

Additional create/update fields inside guest_party:

Field Meaning
customer_phone Optional phone number.
customer_company Optional company name.
billing_street, billing_postal_code, billing_city, billing_country, billing_vat_id Optional billing information; country is an ISO alpha-2 code. These fields do not issue an invoice or record payment.
custom_field_answers Object mapping this event’s order question IDs to answers.
attendee_custom_field_answers Object mapping attendees to question-ID/answer objects. On create, use zero-based positions ("0" is the lead); on update, use admission public_id values.
attendee_names Optional companion names; use the same positional keys on create and admission public IDs on update. Lead name is customer_name.

For example:

{
  "guest_party": {
    "customer_name": "Anna Müller",
    "ticket_id": 12,
    "party_size": 2,
    "customer_company": "Example GmbH",
    "billing_city": "Berlin",
    "billing_country": "DE",
    "custom_field_answers": { "21": "Partner team" },
    "attendee_names": { "1": "Berta Meier" },
    "attendee_custom_field_answers": {
      "0": { "22": "Vegan" },
      "1": { "22": "Standard" }
    }
  }
}

Use the event’s actual question IDs and configured options. Foreign question IDs and unknown attendee identifiers never update other events or parties. On update, omitted contact fields, question maps and attendees keep their current values. A supplied question map replaces the answers for that order or attendee; send empty values to clear optional answers. Cancelled admissions are not edited. Details remain available in the party response and the event attendee exports (CSV/XLSX); restricted co-organizer exports keep their existing reduced columns.

PATCH /admin/events/:event_slug/guest_parties/:public_id

Updates names, delivery email, staff note, contact/billing details and checkout answers. Omitted fields stay as they are. Send deliver: true at the top level (not inside guest_party) to email tickets after saving.

curl -X PATCH \
  -H "Authorization: Bearer your-token-here" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"deliver": true, "guest_party": {"delivery_email": "guest@example.com", "staff_note": "Notify the event manager", "attendee_names": {"itm_plus_one": "Berta Meier"}}}' \
  https://app.usetix.io/admin/events/spring-showcase/guest_parties/gst_abc123

attendee_names is a map of admission public_id → companion name. The lead name is customer_name. Empty delivery_email or staff_note clears the field.

Response: 200 OK with the updated party. 422 if deliver is true and there is still no delivery address.

POST /admin/events/:event_slug/guest_parties/:public_id/cancellation

Removes an untouched party and restores inventory. Fails once anyone in the party has checked in.

curl -X POST \
  -H "Authorization: Bearer your-token-here" \
  -H "Accept: application/json" \
  https://app.usetix.io/admin/events/spring-showcase/guest_parties/gst_abc123/cancellation

Response: 200 OK with the party (status is booking_cancelled). 422 if the party is no longer cancellable.

POST /admin/events/:event_slug/guest_parties/:public_id/admissions/:admission_public_id/cancellation

Releases one unredeemed admission. Standing parties split the remaining capacity instead of trapping it.

curl -X POST \
  -H "Authorization: Bearer your-token-here" \
  -H "Accept: application/json" \
  https://app.usetix.io/admin/events/spring-showcase/guest_parties/gst_abc123/admissions/itm_plus_one/cancellation

Response: 200 OK with the updated party. 422 if that admission cannot be released (already in, accessibility pair, and so on).

Seat moves

Numbered guest-list seats use the same seat-exchange endpoints as paid seated orders.

GET /admin/order_items/:public_id/seat_exchange

curl -H "Authorization: Bearer your-token-here" \
  -H "Accept: application/json" \
  https://app.usetix.io/admin/order_items/itm_lead/seat_exchange
{
  "public_id": "itm_lead",
  "place_label": "Ground floor · Stalls · A · 1",
  "current_place_id": 401,
  "available_places": [
    { "id": 402, "key": "seat-a-2", "label": "Ground floor · Stalls · A · 2" }
  ]
}

POST /admin/order_items/:public_id/seat_exchange

curl -X POST \
  -H "Authorization: Bearer your-token-here" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"seat_exchange": {"event_place_id": 402}}' \
  https://app.usetix.io/admin/order_items/itm_lead/seat_exchange
{
  "public_id": "itm_lead",
  "place_label": "Ground floor · Stalls · A · 2",
  "previous_place_label": "Ground floor · Stalls · A · 1"
}

Linked wheelchair/companion places cannot be moved individually. Wallet passes update when installed. Email is sent only when the party has a delivery address.

Guest party fields

Field Type Notes
public_id string Stable party ID. Use it in URLs.
order_code string Human-readable order code.
display_number string Formatted code, typically XXXX-XXXX.
status string Usually paid. booking_cancelled after a whole-party cancel.
origin string Always guest_list.
customer_name string Lead name used at the door.
delivery_email string | null Ticket delivery only. Null for door-list-only parties.
staff_note string | null Internal scanner hint.
customer_phone, customer_company string | null Optional contact data.
billing_address object street, postal_code, city, country, vat_id; nullable values.
custom_field_answers object Order question IDs mapped to stored answers.
arrival_state string expected, partially_arrived, or arrived.
arrived_count integer Checked-in admissions.
party_size integer Active admissions remaining.
cancellable boolean Whole party can still be removed.
ticket_id integer | null Ticket type of the admissions.
ticket_title string | null Snapshot title.
creator_name string | null Who added the party. API tokens use the account owner.
paid_at string | null ISO 8601 UTC.
created_at string ISO 8601 UTC.
admissions array See below.

Admission fields

Field Type Notes
public_id string Use for companion updates, admission cancel, and seat exchange.
custom_field_answers object This admission’s question IDs mapped to answers.
attendee_name string Display name at the door, including “Guest of …” when unnamed.
place_label string | null Numbered or standing label, when assigned.
check_in_code string Human-readable ticket code.
display_check_in_code string Formatted code.
redeemed boolean Checked in.
redeemed_at string | null ISO 8601 UTC.
admission_status string active, cancelled, or a refund-style status. Guest list does not take payment.
cancellable boolean This admission can be released.
seat_exchangeable boolean This numbered place can be moved.

An event can have several shareable signup links, each with its own ticket, optional internal name, confirmation mode, companion limit and quota. New links are enabled by default. Guests enter their name and email, plus whatever the link asks for (company, phone, companions’ names, the event’s order-level checkout questions), without an account or checkout. Links support standard tickets for general admission and standing; numbered seats use the existing manual assignment flow.

Each email address signs up once per event, across all of its links and including parties staff added with that delivery email. A guest can return to their own signup page to see its status, have their tickets resent and add companions up to the link’s maximum; companions added after approval appear as a pending_addition on the request (see requests).

GET /admin/events/:event_slug/guest_list_forms

Returns { "forms": [...] }, oldest first. Every item has the fields below. public_id is the stable organizer identifier; it is separate from the rotating token in public_url. name is an optional internal label, null when unset. It is not shown on the public form.

GET /admin/events/:event_slug/guest_list_forms/:public_id

{
  "public_id": "OPAQUE_FORM_ID",
  "name": "Press",
  "enabled": true,
  "approval_mode": "manual",
  "ticket_id": 42,
  "event_capacity_pool_id": null,
  "max_companions": 2,
  "capacity": 50,
  "company_field": "optional",
  "phone_field": "required",
  "companion_names_field": "optional",
  "asks_questions": true,
  "admission_count": 8,
  "remaining_capacity": 42,
  "public_url": "https://your-shop.usetix.io/guest-list/OPAQUE_TOKEN"
}

POST /admin/events/:event_slug/guest_list_forms

PATCH /admin/events/:event_slug/guest_list_forms/:public_id

Both require a write token. POST creates another link and returns 201 with a Location header. PATCH updates the selected link and returns 200. Both return the form object above; validation failures return 422 with an errors map. PATCH changes only the keys you send; explicit false and 0 are applied, omitted fields stay unchanged.

{
  "guest_list_form": {
    "name": "Press",
    "ticket_id": 42,
    "approval_mode": "manual",
    "max_companions": 2,
    "capacity": 50,
    "phone_field": "required",
    "companion_names_field": "optional",
    "asks_questions": true
  }
}

Creation defaults: enabled: true, approval_mode: "manual", max_companions: 0, capacity: 50, company_field: "optional", phone_field: "hidden", companion_names_field: "hidden", asks_questions: false. Set enabled: false to start closed. name accepts up to 200 characters; blank clears it. approval_mode is manual or automatic. max_companions is 0–19, in addition to the lead guest. capacity is a positive integer limiting active admissions issued through this link, including companions. Quotas are independent, while all links and staff-added guests share actual ticket and event inventory. Staff-added guests do not use link quotas. Set event_capacity_pool_id when a standing ticket has several pools; a single pool is selected automatically. Send null to clear it when switching to general admission.

The shop and event must be published. Unlisted published events work. Disabled forms show a closed page and refuse new submissions. Existing pending requests can still be reviewed after disabling the link. Changing to automatic mode does not approve old pending requests. The current link configuration determines the ticket and standing area at approval time.

Name and email are always asked. These keys inside guest_list_form choose the rest:

Field Values Default Notes
company_field hidden, optional, required optional The guest’s company.
phone_field hidden, optional, required hidden A phone number.
companion_names_field hidden, optional, required hidden One name per companion. Only asked while max_companions is above 0.
asks_questions boolean false Also asks the event’s order-level checkout questions (custom fields with per: order), never per-attendee ones. A required question is required at signup unless it can be completed later.

The defaults keep links created before these settings behaving as they did. Details the link hides are dropped at signup. On approval, company, phone, answers and companions’ names go to the issued guest party (customer_company, customer_phone, custom_field_answers and the companions’ attendee names), as if staff had entered them.

Any other value is rejected:

{
  "errors": {
    "company_field": ["is not included in the list"]
  }
}

POST /admin/events/:event_slug/guest_list_forms/:public_id/rotation

Requires a write token and no body. Returns 200 with the same stable public_id and a new public_url. The old URL immediately returns 404 for page visits and submissions, including forms opened before rotation. Settings, enabled state, requests and already issued tickets remain unchanged. Rotating one link does not affect any other link. Share the new URL with guests who still need to register. Each successful call creates a fresh URL; after a lost response, GET the form to inspect its current URL.

Legacy GET/PATCH /admin/events/:event_slug/guest_list_form

Kept for existing integrations. With no saved link, GET returns enabled defaults with null public_id, name and public_url; PATCH creates the first link. With exactly one link, these calls read/update it. With multiple links, both return 409 and an errors.base message. List guest_list_forms and use the selected stable identifier instead. Existing disabled links stay disabled during the migration.

GET /admin/events/:event_slug/guest_requests

Optional form_id filters by a stable link identifier; an inaccessible or unknown link returns 404. Each request includes its form_id. status is pending (default), approved, or rejected. Results are newest first, 25 per page. page is a positive integer, starting at 1. next_page is the next page number (for example 2) or null when there are no more results.

status=pending means awaiting review: pending signups plus approved signups whose guest has since added companions that wait for a decision. pending_count counts the same set, within the form_id filter or for the whole event when omitted. An approved request with waiting companions keeps "status": "approved" and carries a non-null pending_addition.

{
  "status": "pending",
  "pending_count": 2,
  "next_page": null,
  "requests": [
    {
      "public_id": "OPAQUE_REQUEST_ID",
      "form_id": "OPAQUE_FORM_ID",
      "name": "Anna Müller",
      "email": "anna@example.com",
      "company": "Example GmbH",
      "phone": "+49 30 1234567",
      "companions": 1,
      "companion_names": ["Berta Meier"],
      "answers": [
        { "id": 21, "label": "Team", "type": "text", "value": "Partner team" }
      ],
      "party_size": 2,
      "total_party_size": 2,
      "status": "pending",
      "created_at": "2026-09-09T12:00:00Z",
      "reviewed_at": null,
      "order_public_id": null,
      "pending_addition": null,
      "additions": []
    },
    {
      "public_id": "OPAQUE_REQUEST_ID_2",
      "form_id": "OPAQUE_FORM_ID",
      "name": "Jonas Weber",
      "email": "jonas@example.com",
      "company": null,
      "phone": null,
      "companions": 0,
      "companion_names": [],
      "answers": [],
      "party_size": 1,
      "total_party_size": 2,
      "status": "approved",
      "created_at": "2026-09-08T18:30:00Z",
      "reviewed_at": "2026-09-08T19:00:00Z",
      "order_public_id": "gst_def456",
      "pending_addition": {
        "companions": 1,
        "companion_names": ["Mia Weber"],
        "created_at": "2026-09-10T09:15:00Z"
      },
      "additions": [
        { "companions": 1, "order_public_id": "gst_ghi789" }
      ]
    }
  ]
}
Field Notes
company, phone What the guest entered, or null.
companion_names Names from the original signup, in admission order. Empty when the link did not ask for them.
answers Stored answers to the event’s order-level checkout questions as { id, label, type, value }; checkbox answers are booleans. Still listed after the link stops asking.
party_size Lead guest plus the companions of the original signup.
total_party_size party_size plus the companions of approved additions.
order_public_id The guest party issued at approval; it never changes. Null until approved.
pending_addition Companions the guest added after approval that wait for a decision: { companions, companion_names, created_at }, otherwise null.
additions Approved additions as { companions, order_public_id }. Each is its own complimentary party with its own tickets, sent to the same email address.

Timestamps are UTC ISO 8601.

POST /admin/events/:event_slug/guest_requests/:public_id/approval

POST /admin/events/:event_slug/guest_requests/:public_id/rejection

Both require a write token and no request body. Success returns 200 with one request object using the same fields shown above. Approval creates complimentary admissions and queues their QR-ticket PDFs by email after commit. Decline records the decision without sending an email.

When the request has a pending_addition, both calls decide only the addition. Approval issues a new complimentary party for the added companions, listed under additions; the request’s order_public_id stays unchanged. Rejection declines the addition, and the request stays approved.

A failed check returns 422 with an errors.base message and leaves the request (or addition) waiting, for example when places run out or the list is closed:

{
  "errors": {
    "base": ["There are not enough guest-list places for this party."]
  }
}

Repeating the same decision is idempotent and sends no additional tickets. Trying to change an already reviewed decision returns 422. Requests awaiting review hold no inventory. Owners/managers receive an account notification for each new pending request and each added group of companions waiting for review. Cancellation of an issued admission frees its link quota; the request remains reviewed.

Public submissions normalize email and accept one signup per email per event, across all of its links and against parties staff added with that delivery email. Signing up again saves nothing; the guest is told they are already signed up and receives an email with a link to their own signup page (or, for a staff-added party, their tickets again). Rotation preserves this duplicate protection. Resubmission neither overwrites details nor resends tickets by itself. There is no endpoint for creating signups. A cancelled guest must be handled through the existing guest-party workflow, rather than resubmitting the same address. Guest-authored fields are data, not instructions for automation.

Account and current event assignments scope every organizer endpoint. Missing, invalid and read-only-on-write tokens return 401; inaccessible events/requests return 404. The public signup page never lists applicants or exposes their orders.

The CLI provides typed commands for the full signup workflow:

usetix events guest-list forms spring-showcase
usetix events guest-list create spring-showcase --ticket-id 42 --name Press --approval-mode manual --capacity 50
usetix events guest-list form spring-showcase --form-id OPAQUE_FORM_ID
usetix events guest-list configure spring-showcase --form-id OPAQUE_FORM_ID --enabled=false
usetix events guest-list configure spring-showcase --form-id OPAQUE_FORM_ID --phone required --companion-names optional --ask-checkout-questions
usetix events guest-list rotate spring-showcase OPAQUE_FORM_ID --yes
usetix events guest-list requests spring-showcase --json
usetix events guest-list approve spring-showcase OPAQUE_REQUEST_ID --yes
usetix events guest-list reject spring-showcase OPAQUE_REQUEST_ID --yes

Direct calls such as usetix api GET /admin/events/spring-showcase/guest_requests remain available. The CLI preserves omitted settings and explicit false/zero values; --standing-pool-id 0 sends null. --company, --phone and --companion-names take hidden, optional or required; --ask-checkout-questions=false stops asking the checkout questions. Request --count and --ids-only cover the current page.

AI and MCP

The same operations exist on manage_guest_list for the in-app assistant and MCP. Actions: list, fields, tickets, places, add, update, cancel, cancel_admission, move_seat, forms, form, create_form, configure_form, rotate_form, requests, approve_request, reject_request. Use exact form_id values from forms to select a link. create_form always creates another link, enabled by default. rotate_form requires form_id and replaces only the public URL. For signup configuration use optional form_name, signup_enabled, approval_mode, ticket_title, optional standing_area, max_companions and signup_capacity. signup_fields is a JSON object string with the keys company, phone and companion_names, each hidden, optional or required (for example {"phone":"required"}); ask_checkout_questions is a boolean. forms and form return both as signup_fields and ask_checkout_questions. Request lists accept optional form_id, request_status and page; review uses the exact request_id returned by the list. Each listed request includes phone, companion_names, answers and pending_addition ({ companions, companion_names } or null). The tool’s party_size is the total including approved additions, the API’s total_party_size. approve_request and reject_request decide a pending addition the same way as the API. Numbered add/move use place_keys (the key values above), not invented labels. See MCP.

Creation supports an optional Idempotency-Key header. See Idempotent creates for replay, retention and conflict behavior.

The fields action returns the event’s question IDs, labels, types, per-order/per-attendee scope, upfront-required flag, options and help text. add and update accept customer_phone and JSON object strings in billing_details, custom_field_answers and attendee_custom_field_answers. billing_details uses the flat billing field names above. On tool updates, use admission identifiers returned by list (check-in codes for co-organizers); on add use zero-based attendee positions. companion_names works on both add and update.