API · Events
Events are the top-level objects in your account: a date and venue customers can buy tickets to.
GET /admin/events
Returns the events in your account, split into upcoming and past, plus aggregate stats for the period filter.
curl -H "Authorization: Bearer your-token-here" \
-H "Accept: application/json" \
https://app.usetix.io/admin/events
Query parameters:
| Parameter | Description |
|---|---|
period |
One of today, week, month, year, all. Filters past events and the stats. Upcoming events are not affected. Defaults to all (no time restriction). The period applies only to the current request. |
Response:
{
"upcoming_events": [
{
"id": 42,
"slug": "spring-showcase",
"title": "Spring Showcase",
"description": "Our annual seasonal event.",
"attendee_note": "This is a black and white party. Please fill in your menu by Friday.",
"starts_at": "2026-05-01T19:00:00Z",
"doors_open_at": "2026-05-01T18:00:00Z",
"ends_at": "2026-05-01T23:00:00Z",
"show_end_time": true,
"sales_starts_at": null,
"sales_ends_at": "2026-05-01T19:00:00Z",
"published": true,
"listed": true,
"capacity": 500,
"checkout_fees": {
"policy": "account_default",
"platform_fee_payer": "organizer",
"custom_fee_fixed_amount": { "amount": "0.00", "currency": "EUR" },
"custom_fee_percentage": "0.0"
},
"venue": {
"id": 7,
"name": "The Venue",
"city": "Berlin"
}
}
],
"past_events": [],
"stats": {
"upcoming_count": 1,
"revenue": { "amount": "0.00", "currency": "EUR" },
"tickets_sold": 0
}
}
GET /admin/events/:slug
Returns a single event by its URL slug, plus live sales stats and a per-ticket-type breakdown, the same numbers your admin dashboard shows for that event.
curl -H "Authorization: Bearer your-token-here" \
-H "Accept: application/json" \
https://app.usetix.io/admin/events/spring-showcase
Response:
{
"id": 42,
"slug": "spring-showcase",
"title": "Spring Showcase",
"description": "Our annual seasonal event.",
"attendee_note": "This is a black and white party. Please fill in your menu by Friday.",
"starts_at": "2026-05-01T19:00:00Z",
"doors_open_at": "2026-05-01T18:00:00Z",
"ends_at": "2026-05-01T23:00:00Z",
"show_end_time": true,
"sales_starts_at": null,
"sales_ends_at": "2026-05-01T19:00:00Z",
"published": true,
"listed": true,
"capacity": 500,
"checkout_fees": {
"policy": "account_default",
"platform_fee_payer": "organizer",
"custom_fee_fixed_amount": { "amount": "0.00", "currency": "EUR" },
"custom_fee_percentage": "0.0"
},
"venue": {
"id": 7,
"name": "The Venue",
"city": "Berlin"
},
"stats": {
"sold_count": 142,
"admission_count": 145,
"checkout_admissions_count": 142,
"guest_list_admissions_count": 3,
"remaining_count": 358,
"sell_through_percentage": 28,
"total_orders": 87,
"total_revenue": { "amount": "3550.00", "currency": "EUR" },
"redemption_rate": 0.0,
"sales_velocity": 7.1,
"capacity_consumed": 145,
"capacity_remaining": 355
},
"tickets_breakdown": [
{
"title": "Early Bird",
"kind": "StandardTicket",
"color": "#3B82F6",
"sold": 100,
"admissions": 102,
"checkout_sold": 100,
"guest_list": 2,
"reserved": 2,
"stock": 0,
"capacity": 102,
"price": { "amount": "20.00", "currency": "EUR" },
"average_sold_price": { "amount": "20.00", "currency": "EUR" },
"revenue": { "amount": "2000.00", "currency": "EUR" }
},
{
"title": "Regular",
"kind": "StandardTicket",
"color": "#10B981",
"sold": 42,
"admissions": 43,
"checkout_sold": 42,
"guest_list": 1,
"reserved": 1,
"stock": 355,
"capacity": 398,
"price": { "amount": "25.00", "currency": "EUR" },
"average_sold_price": { "amount": "25.00", "currency": "EUR" },
"revenue": { "amount": "1050.00", "currency": "EUR" }
}
],
"performers": [
{
"id": 17,
"event_performer_id": 89,
"name": "DJ Snake",
"performer_type": "person",
"role": "headliner",
"genre": "Techno",
"position": 1,
"starts_at": "2026-05-01T22:00:00Z",
"ends_at": "2026-05-01T23:30:00Z",
"bio": "House DJ since 2010.",
"bio_html": "<div class=\"trix-content\"><p>House DJ since 2010.</p></div>",
"website_url": "https://djsnake.example.com",
"instagram_url": null,
"spotify_url": null,
"soundcloud_url": null,
"tiktok_url": null,
"youtube_url": null,
"image_url": null
}
],
"faq_items": [],
"custom_fields": [],
"page_sections": [
{ "id": 201, "kind": "tickets", "position": 1 },
{ "id": 202, "kind": "lineup", "position": 2 },
{ "id": 203, "kind": "description", "position": 3 },
{ "id": 204, "kind": "sponsors", "position": 4 },
{ "id": 205, "kind": "faq", "position": 5 },
{ "id": 206, "kind": "downloads", "position": 6 },
{ "id": 207, "kind": "video", "position": 7 },
{ "id": 208, "kind": "gallery", "position": 8 }
]
}
Page sections
page_sections is returned by the event show endpoint in display order. Every event has eight sections: tickets, lineup, description, sponsors, faq, downloads, video, and gallery. Empty sections stay hidden on the shop page; the event header remains first.
| Field | Type | Notes |
|---|---|---|
id |
integer | Section ID used by the position endpoint below. |
kind |
string | One of the eight section names above. |
position |
integer | Display position, starting at 1. |
Stats fields
| Field | Type | Notes |
|---|---|---|
sold_count |
integer | Tickets sold to date (paid checkout orders only). For group tickets, each individual seat counts. Guest-list comps are not included. |
admission_count |
integer | Active admissions from paid checkout and guest list. |
checkout_admissions_count |
integer | Active admissions from paid checkout only. |
guest_list_admissions_count |
integer | Active complimentary guest-list admissions. |
remaining_count |
integer | Tickets still available across all types. -1 means at least one ticket type has unlimited stock. |
sell_through_percentage |
integer | null | Percentage of finite-stock tickets sold (0: 100). null if the event has any unlimited-stock ticket or no stock at all. |
total_orders |
integer | Distinct paid orders for this event. |
total_revenue |
object | { "amount": "...", "currency": "..." }. Sum of paid order totals. |
redemption_rate |
decimal | Percentage of sold tickets already scanned at the door (0.0: 100.0). |
sales_velocity |
decimal | Tickets sold per day since the first paid order. 0 for past or unsold events. |
capacity_consumed |
integer | Seats currently held against the event’s capacity (paid + reserved). Only present when capacity is set. |
capacity_remaining |
integer | capacity - capacity_consumed, floored at 0. Only present when capacity is set. |
Tickets breakdown
tickets_breakdown is an array, one entry per ticket type on the event, in display order. Use it to render a sell-through view per ticket type.
| Field | Type | Notes |
|---|---|---|
title |
string | Ticket title. |
kind |
string | StandardTicket or GroupTicket. |
color |
string | Hex color code used in the admin dashboard. |
sold |
integer | Paid checkout units. For GroupTicket, this counts bundles, not individual seats, matches the stock unit. |
admissions |
integer | Active admissions including guest list. |
checkout_sold |
integer | Paid checkout units only. |
guest_list |
integer | Complimentary guest-list admissions of this ticket type. |
reserved |
integer | Units currently held in pending checkouts. |
average_sold_price |
object | null | { "amount": "...", "currency": "..." } when this type has paid sales, otherwise null. |
stock |
integer | Remaining stock. -1 means unlimited. |
capacity |
integer | Original allocation, reconstructed as sold + reserved + stock. -1 for unlimited tickets. |
price |
object | { "amount": "...", "currency": "..." } for the ticket price. |
revenue |
object | { "amount": "...", "currency": "..." }. Total paid for this ticket type. |
Performers
performers is an array, one entry per performer assigned to the event, in display order (position ascending). The shape mirrors the standalone performers endpoint with extra fields describing the assignment (role, set time, etc.).
| Field | Type | Notes |
|---|---|---|
id |
integer | Internal performer ID, the same value used by GET /admin/performers/:id. |
event_performer_id |
integer | Internal ID of the assignment row, in case you need to PATCH/DELETE it directly. |
name |
string | Performer display name. |
performer_type |
string | person or performing_group. |
role |
string | headliner, support, or guest. |
genre |
string | null | Free-form genre tag set on the assignment. |
position |
integer | Sort order within the event’s lineup, lower first. |
starts_at |
string | null | ISO 8601 UTC. Set time within the event, if scheduled. |
ends_at |
string | null | ISO 8601 UTC. |
bio |
string | null | Plain-text bio (rich text body stripped of HTML). |
bio_html |
string | null | Sanitized HTML version of the bio, ready to embed. |
website_url |
string | null | External URL. |
instagram_url |
string | null | External URL. |
spotify_url |
string | null | External URL. |
soundcloud_url |
string | null | External URL. |
tiktok_url |
string | null | External URL. |
youtube_url |
string | null | External URL. |
image_url |
string | null | URL to the performer’s image, if attached. |
GET /admin/events/:slug/open_answers
Returns the follow-up worklist for paid buyers who still owe required checkout answers. This includes answers whose editing deadline has passed so organizers can resolve them manually.
Query parameters:
| Parameter | Description |
|---|---|
status |
all, uncontacted, contacted, or locked. Defaults to all. Internal notes do not count as contact. |
query |
Search by customer name, email, or order number. |
page |
Numeric page number. Each page contains up to 25 buyers. |
{
"event": { "id": "spring-showcase", "title": "Spring Showcase" },
"stats": { "buyers": 1, "answers": 2, "uncontacted": 1, "locked": 0 },
"pagination": { "page": 1, "pages": 1, "per_page": 25, "total_count": 1 },
"groups": [
{
"order_id": "abcd1234efgh5678",
"order_number": "7K3Q-9D2A",
"customer": { "id": 17, "name": "Jane Doe", "email": "jane@example.com" },
"contacted": false,
"locked": false,
"fully_locked": false,
"last_contact_at": null,
"missing_answers": [
{
"custom_field_id": 8,
"label": "Menu choice",
"per": "order",
"order_item_id": null,
"attendee_name": null,
"deadline": "2026-04-30T19:00:00Z",
"locked": false
}
]
}
]
}
locked means at least one missing answer is past its deadline. fully_locked means none of the missing answers can still be completed by the buyer.
External co-organizer dashboard sessions and personal API tokens can access this worklist for assigned events. For these credentials, order_id contains the order code and order_item_id contains the check-in code instead of public purchase or ticket tokens. The shared answer editor and contact form require the assigned event_slug; they expose and change only that event’s answers and contact context. Account API tokens retain the response shown above.
POST /admin/events
Creates a new draft event. Requires a write token. To attach an image, direct-upload the file first and pass its signed_id as the image field.
curl -X POST \
-H "Authorization: Bearer your-token-here" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{"title": "Spring Showcase", "venue_id": 7, "starts_at": "2026-05-01T19:00:00Z", "doors_open_at": "2026-05-01T18:00:00Z", "ends_at": "2026-05-01T23:00:00Z", "sales_ends_at": "2026-05-01T19:00:00Z"}' \
https://app.usetix.io/admin/events
Body parameters:
| Field | Required | Notes |
|---|---|---|
title |
yes | Event title. |
venue_id |
yes | Internal ID of an existing venue in your account. |
starts_at |
yes | ISO 8601. Parsed in the venue’s timezone if no zone is included. |
doors_open_at |
no | ISO 8601. When guests may enter. Must be at or before starts_at; parsed in the venue’s timezone if no zone is included. |
ends_at |
no | ISO 8601. Omit it to show only the start publicly; Usetix keeps an internal five-hour event window. |
show_end_time |
no | Whether the end time is shown publicly in the shop and embed. Defaults to true when ends_at is supplied and false when Usetix creates the internal end time. |
sales_ends_at |
no | ISO 8601. When ticket sales close. Defaults to ends_at. |
sales_starts_at |
no | ISO 8601. When sales open. Omit to open immediately. |
description |
no | Plain-text description. |
attendee_note |
no | HTML note for ticket holders after purchase, shown on the order page and in confirmation and guest-list emails. Later edits appear on existing order pages but do not change emails already sent. Send "" or null to remove. |
video_url |
no | YouTube video URL for the event page. |
video_title |
no | Optional video section heading in the shop. Leading/trailing whitespace is trimmed; "", whitespace, or null restores the localized “Video” heading. Returned in media.video_title on event detail responses and retained when duplicating an event. |
slug |
no | URL slug. Auto-generated from title if omitted. |
listed |
no | Whether the event appears in public shop overviews once published. Defaults to true. |
capacity |
no | Total seats across ticket types. Omit for uncapped. |
minimum_age |
no | Age restriction. |
customer_vat_rate_override |
no | Per-event VAT override (decimal percentage). |
checkout_fee_policy |
no | account_default inherits account checkout fees. custom uses this event’s payer and extra fee. Defaults to account_default. |
platform_fee_payer |
no | When checkout_fee_policy is custom: organizer or buyer. Omitted custom fields copy the account defaults. |
custom_fee_fixed_amount |
no | When checkout_fee_policy is custom: extra fee charged once per order. Send "" or "0" to clear. |
custom_fee_percentage |
no | When checkout_fee_policy is custom: extra percentage of the discounted ticket subtotal. Range 0–100. |
image |
no | signed_id from a direct upload. |
background_image |
no | signed_id from a direct upload. |
Response: 201 Created with the event JSON and a Location header pointing at GET /admin/events/:slug.
PATCH /admin/events/:slug
Updates an existing event. Send only the fields you want to change.
curl -X PATCH \
-H "Authorization: Bearer your-token-here" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{"listed": false}' \
https://app.usetix.io/admin/events/spring-showcase
Accepts the same body parameters as POST /admin/events.
Set doors_open_at to null or an empty string to remove the separate doors time. The event will then show only its start time.
Set listed to false to hide a published event from shop overviews and the public events index without taking its direct URL or checkout offline. Set it back to true to restore it. Listing and publication are independent: changing listed never publishes or unpublishes the event.
Set show_end_time to false to show only the start time in the public shop and ticket embed. Set it back to true to restore the end-time display. The operational ends_at value remains stored and returned by the API for event status, scanners, and calendar exports.
Checkout fees
checkout_fees is always present on event JSON. policy is account_default or custom. The other fields are the effective values used at checkout: inherited account defaults when the event inherits, or this event’s own values when policy is custom.
This example charges the Usetix fee to the buyer for one event only:
curl -X PATCH \
-H "Authorization: Bearer your-token-here" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{"checkout_fee_policy": "custom", "platform_fee_payer": "buyer"}' \
https://app.usetix.io/admin/events/spring-showcase
Send checkout_fee_policy as account_default to inherit the account again. Fee changes apply only to future orders.
Response: 200 OK with the updated event JSON.
DELETE /admin/events/:slug
Deletes an event. Events with paid orders cannot be deleted; the API returns 422 Unprocessable Entity in that case.
curl -X DELETE \
-H "Authorization: Bearer your-token-here" \
-H "Accept: application/json" \
https://app.usetix.io/admin/events/spring-showcase
Response: 204 No Content on success.
POST /admin/events/:slug/publication
Publishes the event, making its direct shop page and checkout live. A published event appears in public shop overviews when listed is true; an unlisted published event remains available by direct URL. Publishing requires a description and at least one ticket, otherwise it returns 422 with the missing requirements.
curl -X POST \
-H "Authorization: Bearer your-token-here" \
-H "Accept: application/json" \
https://app.usetix.io/admin/events/spring-showcase/publication
Response: 200 OK with the event JSON (published: true).
DELETE /admin/events/:slug/publication
Unpublishes the event, removing it from the public shop. Existing orders are unaffected.
curl -X DELETE \
-H "Authorization: Bearer your-token-here" \
-H "Accept: application/json" \
https://app.usetix.io/admin/events/spring-showcase/publication
Response: 200 OK with the event JSON (published: false).
PATCH /admin/events/:slug/page_sections/:id/position
Moves a section to a new display position, using the same position resource as ticket sorting. The other sections shift automatically. Use a section ID from GET /admin/events/:slug; a write token is required. The endpoint also accepts PUT.
For example, move the gallery directly below the description when the description is at position 3:
curl -X PATCH \
-H "Authorization: Bearer your-token-here" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{"position": 4}' \
https://app.usetix.io/admin/events/spring-showcase/page_sections/208/position
Response: 204 No Content. A missing position returns 400; an event or section outside the token’s account returns 404. Read-only tokens cannot write (401).
GET /admin/events/:slug/attendees
Returns a participant table for one event. Accepts a read or write account token. Each row contains only that event’s admission data and custom-field answers, including when the purchase contains tickets for several events or gift vouchers. Full order totals, billing addresses, ticket codes, and order links are omitted.
curl -H "Authorization: Bearer your-token-here" \
-H "Accept: application/json" \
'https://app.usetix.io/admin/events/spring-showcase/attendees?page=1&q=Jane'
| Parameter | Description |
|---|---|
page |
Page number, starting at 1. Each page contains up to 100 admissions. |
q |
Optional participant search. Results stay within the requested event. |
The response has columns (localized display labels), rows (arrays in the same column order), and next_page (the next page number, or null). The fixed columns are admission name, customer name, customer email, ticket, place, redemption timestamp, and admission status. Event-specific order and admission questions follow these columns. Display labels and status values are localized and should not be used as stable field identifiers.
External co-organizers can use this endpoint with their dashboard session or personal API token for assigned events only. Their dashboard also offers these event-scoped columns as CSV and Excel downloads, plus the existing event attendee PDF. Complete order exports remain unavailable to this role. Removing an event assignment applies to subsequent requests and downloads.
Event fields
| Field | Type | Notes |
|---|---|---|
id |
integer | Internal numeric ID. Stable. |
slug |
string | URL slug, used as the path parameter. The event’s public URL is https://<your-subdomain>.usetix.io/events/<slug>. |
title |
string | Event title. |
description |
string | null | Plain-text description. May contain newlines. |
attendee_note |
string | null | Plain-text of the after-purchase note. null when unset. |
starts_at |
string | ISO 8601 UTC. When the event begins. |
doors_open_at |
string | null | ISO 8601 UTC. When guests may enter. null when no separate doors time is set. |
ends_at |
string | ISO 8601 UTC. Operational end time, including the internal five-hour default when no public end was supplied. |
show_end_time |
boolean | Whether public event displays should show ends_at. |
sales_starts_at |
string | null | When ticket sales open. null means sales are open immediately. |
sales_ends_at |
string | When ticket sales close. Always set; defaults to ends_at if you didn’t pick a custom value. |
published |
boolean | true if the event is live on the public shop, false for drafts. |
listed |
boolean | true if the event appears in public shop overviews. A published event with listed: false remains available by direct URL. |
capacity |
integer | null | Total seats across all ticket types. null means uncapped. |
venue.id |
integer | Internal venue ID. |
venue.name |
string | Venue name. |
venue.city |
string | Venue city. |
Event media and duplication
Event detail responses (GET /admin/events/:slug) include a media object with video_url, optional video_title, image and background_image filename objects (or null), ordered gallery_images (id, filename, position), and documents (id, filename, signed_id).
Use the existing PATCH /admin/events/:slug endpoint for media updates. Upload file bytes through the direct-upload API first. Pass signed blob IDs in image, background_image, gallery_images: [], documents: [], or private_documents: []. For personal tokens, use files uploaded under your own credentials. Reorder with gallery_order: [gallery_image_id, ...]; remove with remove_gallery_images: [gallery_image_id], remove_documents: [attachment_signed_id], remove_image: true, or remove_background_image: true.
POST /admin/events/:slug/duplication returns 201 with the new draft event and a Location header. Co-organizers cannot duplicate events: personal API tokens receive 403 Forbidden, and the duplication tool is unavailable through their assistant and MCP access. Existing event publication and listing endpoints work with personal write tokens for assigned events. Creating events, including copies of existing events, remains a venue operation.
usetix events duplicate friday-night
usetix events publish friday-night
usetix events update friday-night --listed=false
Admission and arrivals
Read GET /admin/events/:slug/arrivals for event-day and historical check-ins, redemption rate, the busiest interval and chronological counts. The same report is available through event_arrivals in the assistant/MCP and usetix events arrivals SLUG in the CLI. Event arrivals API reference.