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.