API reference
Every endpoint of the ShowTix Partner API v1 — events, ticket types, venues, checkout sessions, orders, tickets, comps, check-ins and webhooks.
For developersLast updated
On this page
- Introduction
- Errors
- Pagination
- Idempotency
- Rate limits
- Incremental sync
- Account
- Retrieve API key info
- Retrieve the OpenAPI document
- Events
- List events
- Retrieve an event
- List ticket types
- Venues
- List venues
- Retrieve a venue
- Checkout sessions
- Create a checkout session
- Retrieve a checkout session
- Orders
- List orders
- Retrieve an order
- Tickets & attendees
- Retrieve a ticket
- List attendees
- Issue comp tickets
- Check in a ticket
- Webhook endpoints
- List webhook endpoints
- Create a webhook endpoint
- Retrieve a webhook endpoint
- Update a webhook endpoint
- Delete a webhook endpoint
- Send a test event
- Objects
- Event
- Ticket type
- Venue
- Checkout session
- Order
- Ticket
- Comp ticket batch
- Check-in
- Webhook endpoint
All requests use HTTPS, JSON bodies and an API key; all responses are JSON.
The machine-readable OpenAPI 3.1 document is at https://api.showtix-nonprod.link/openapi.json — import it into Postman, Insomnia or a code generator.
Introduction#
| Topic | Detail |
|---|---|
| Base URL | https://api.showtix-nonprod.link |
| Auth | Authorization: Bearer stx_live_… or stx_test_… |
| Money | Strings of decimal dollars ("49.00"), currency AUD. Prices are fee-inclusive. |
| Times | ISO-8601 UTC strings (2026-11-02T09:00:00Z). |
| Version | ShowTix-Version: 2026-10-18 |
Response headers
| Header | Description |
|---|---|
Request-Id | Unique id for the request — include it when contacting support. Also in error bodies as request_id. |
ShowTix-Version | API version that served the request — currently 2026-10-18. |
RateLimit-Limit | Requests allowed per 60-second window for this key. |
RateLimit-Remaining | Requests left in the current window. |
RateLimit-Reset | Seconds until the window resets. |
Retry-After | On 429 only — seconds to wait before retrying. |
Idempotent-Replayed | true when the response is a replay of an earlier idempotent request. |
Every object has an object field naming its type. Clients must ignore unknown fields — we add fields without notice (see the versioning policy).
Errors#
Every non-2xx response has the same envelope. Branch on error.code (stable, machine-readable); show error.message to developers, not customers. param names the offending field when there is one. doc_url links back to this section.
{
"error": {
"type": "invalid_request_error",
"code": "exceeds_availability",
"message": "Only 3 tickets remain in General Admission",
"param": "items",
"request_id": "F7xq2LmN8vRt",
"doc_url": "https://showtix.com.au/help/partners/api-reference#errors"
}
}| Type | Status | Code | Meaning |
|---|---|---|---|
authentication_error | 401 | missing_api_key | No Authorization: Bearer header. |
authentication_error | 401 | invalid_api_key | Key malformed or unknown. |
authentication_error | 401 | api_key_revoked | Key was revoked. |
authentication_error | 401 | api_key_expired | Key was rolled and its grace period ended. |
permission_error | 403 | insufficient_scope | Key lacks the scope the endpoint requires. |
permission_error | 403 | ip_not_allowed | Caller IP isn't on the key's allowlist. |
permission_error | 403 | browser_request_blocked | Request came from a web browser — keys are server-side only. |
not_found_error | 404 | resource_missing | No such object in your organisation (ids from other organisations also return this). |
not_found_error | 404 | route_not_found | No such endpoint. |
invalid_request_error | 400 | parameter_missing | A required parameter is missing (see param). |
invalid_request_error | 400 | parameter_invalid | A parameter has an invalid value (see param). |
invalid_request_error | 422 | event_not_on_sale | The event isn't currently selling tickets. |
invalid_request_error | 422 | ticket_type_unavailable | The ticket type is hidden, not yet on sale or its sale has ended. |
invalid_request_error | 422 | exceeds_availability | Not enough tickets left for the requested quantity. |
invalid_request_error | 422 | exceeds_max_per_order | Quantity is above the ticket type's maximum per order. |
invalid_request_error | 422 | seat_selection_required | Seated ticket types can only be bought via ShowTix checkout. |
invalid_request_error | 422 | ticket_void | Check-in of a refunded or voided ticket. |
invalid_request_error | 422 | idempotency_key_reused | Idempotency-Key reused with a different request body. |
conflict_error | 409 | idempotency_request_in_progress | A request with this Idempotency-Key is still running. |
conflict_error | 409 | ticket_wrong_event | Ticket belongs to a different event than the check-in URL. |
rate_limit_error | 429 | rate_limited | Too many requests — wait Retry-After seconds. |
api_error | 500 | hold_failed | Tickets couldn't be held for a checkout session. Safe to retry with the same Idempotency-Key. |
api_error | 500 | test_event_failed | A test webhook event couldn't be sent. |
api_error | 500 | — | Something else went wrong on our side. Safe to retry with the same Idempotency-Key. |
No existence leaks
An id that belongs to another organisation always returns 404 resource_missing — never 403.
Pagination#
List endpoints use cursor pagination. Pass limit (1–100, default 25); when has_more is true, pass next_cursor back as cursor to get the next page. Cursors are opaque — don't parse or build them.
{
"object": "list",
"data": [
"…"
],
"has_more": true,
"next_cursor": "eyJpZCI6MTMxLCJzIjoiMjAyNi0xMS0xNFQwOTozMDowMFoifQ"
}async function listAll(path, params = {}) {
const all = [];
let cursor = null;
do {
const qs = new URLSearchParams({ ...params, limit: "100", ...(cursor ? { cursor } : {}) });
const res = await fetch(`https://api.showtix-nonprod.link${path}?${qs}`, {
headers: { Authorization: `Bearer ${process.env.SHOWTIX_API_KEY}` },
});
const page = await res.json();
if (!res.ok) throw new Error(page.error.message);
all.push(...page.data);
cursor = page.has_more ? page.next_cursor : null;
} while (cursor);
return all;
}
const orders = await listAll("/orders", { event_id: "123" });Idempotency#
Any POST, PATCH or DELETE may send an Idempotency-Key header (any unique string of 1–255 characters — a UUID or your own cart id). It makes retries safe: you'll never hold tickets twice or issue duplicate comps after a timeout. Keys are remembered per API key for 24 hours.
| Situation | Result |
|---|---|
| Same key + same body within 24 hours | The original response is replayed, with header Idempotent-Replayed: true. |
| Same key + different body | 422 idempotency_key_reused |
| Same key while the first request is still running | 409 idempotency_request_in_progress — retry shortly. |
| The first request returned 5xx | Not stored — retrying with the same key runs the request again. |
| Key longer than 255 characters | 400 parameter_invalid (param: Idempotency-Key). |
Rate limits#
Limits apply per key in a fixed 60-second window: 120 requests/minute for live keys and 60/minute for test keys by default (a key may carry a custom limit set by ShowTix). Every response reports your budget in RateLimit-Limit, RateLimit-Remaining and RateLimit-Reset. Over the limit you get 429 rate_limited with Retry-After.
async function showtix(path, init = {}, attempt = 0) {
const res = await fetch(`https://api.showtix-nonprod.link${path}`, {
...init,
headers: { Authorization: `Bearer ${process.env.SHOWTIX_API_KEY}`, ...init.headers },
});
if (res.status === 429 && attempt < 5) {
const wait = Number(res.headers.get("Retry-After") ?? 2 ** attempt);
await new Promise((r) => setTimeout(r, wait * 1000 + Math.random() * 250));
return showtix(path, init, attempt + 1);
}
return res;
}Need more headroom? Email support@showtix.com.au with your use case.
Incremental sync#
To mirror data into your own system, backfill once, then poll with updated_since — supported by GET /events, GET /orders and GET /events/{id}/attendees. Store the time you started each sync and pass it next time, so nothing that changes mid-sync is missed. Upsert on id. For near-real-time updates, combine this with webhooks and keep polling as a safety net.
const startedAt = new Date().toISOString();
const changed = await listAll("/orders", { updated_since: lastSyncAt });
for (const o of changed) await db.orders.upsert({ id: o.id }, o);
lastSyncAt = startedAt; // persist for the next runAccount#
Retrieve API key info#
GET / · Scope: any valid key
Returns the organisation, mode and scopes of the key making the request — a handy health check and the first call to make after creating a key.
curl https://api.showtix-nonprod.link/ \
-H "Authorization: Bearer $SHOWTIX_API_KEY"{
"object": "api_key_info",
"organisation": {
"id": 12,
"name": "Corner Presents",
"slug": "corner-presents"
},
"key": {
"prefix": "stx_live_Ab3dE9x",
"mode": "live",
"scopes": [
"events:read",
"orders:read",
"orders:write"
]
},
"livemode": true,
"api_version": "2026-10-18"
}Retrieve the OpenAPI document#
GET /openapi.json · Scope: none (public)
The machine-readable OpenAPI 3.1 description of this API — import it into Postman, Insomnia or a code generator. No key needed.
curl https://api.showtix-nonprod.link/openapi.json -o showtix-openapi.jsonEvents#
Your organisation's events — only events created under your organisation, never events its members run for other organisations. Requires events:read.
List events#
GET /events · Scope: events:read
Query parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
status | enum | No | published (default) · draft · pending_review · cancelled · ended · all |
time | enum | No | upcoming (default) · past · all. Upcoming is sorted by starts_at ascending, past descending. |
q | string | No | Free-text search on the title and summary. |
updated_since | string (ISO-8601) | No | Only return records changed at or after this time. See incremental sync. |
limit | integer | No | 1–100, default 25. |
cursor | string | No | Opaque next_cursor from the previous page. See pagination. |
curl "https://api.showtix-nonprod.link/events?time=upcoming&limit=2" \
-H "Authorization: Bearer $SHOWTIX_API_KEY"{
"object": "list",
"data": [
{
"object": "event",
"id": 123,
"slug": "late-night-cabaret-melbourne",
"title": "Late Night Cabaret",
"summary": "Songs, sketches and sequins — a late-night variety bill in Richmond.",
"description": "Late Night Cabaret returns to the Corner Hotel for one night only. 18+. Doors 7pm.",
"status": "published",
"starts_at": "2026-11-02T09:00:00Z",
"ends_at": "2026-11-02T13:00:00Z",
"timezone": "Australia/Melbourne",
"doors": "7:00pm",
"url": "https://showtix.com.au/shows/late-night-cabaret-melbourne",
"image_url": "https://showtix.com.au/uploads/events/123/feature.jpg",
"sold_out": false,
"on_sale_at": null,
"venue": {
"object": "venue",
"id": 9,
"name": "Corner Hotel",
"slug": "corner-hotel",
"address": {
"line1": "57 Swan St",
"line2": null,
"locality": "Richmond",
"state": "VIC",
"postal_code": "3121",
"country": "AU",
"formatted": "57 Swan St, Richmond VIC 3121"
},
"lat": -37.8253,
"lng": 144.9932,
"url": "https://cornerhotel.com",
"phone": null
},
"ticketing": {
"currency": "AUD",
"min_price": "49.00",
"max_price": "89.00",
"tickets_remaining": 412
},
"categories": [
"cabaret",
"comedy"
],
"created_at": "2026-09-14T02:31:07Z",
"updated_at": "2026-10-17T23:12:45Z"
},
{
"object": "event",
"id": 131,
"slug": "sydney-comedy-showcase",
"title": "Sydney Comedy Showcase",
"summary": "Six stand-ups, one big night, with a special guest MC.",
"description": "The Sydney Comedy Showcase takes over the Metro Theatre. All ages.",
"status": "published",
"starts_at": "2026-11-14T09:30:00Z",
"ends_at": "2026-11-14T13:00:00Z",
"timezone": "Australia/Sydney",
"doors": "7:30pm",
"url": "https://showtix.com.au/shows/sydney-comedy-showcase",
"image_url": "https://showtix.com.au/uploads/events/131/feature.jpg",
"sold_out": false,
"on_sale_at": null,
"venue": {
"object": "venue",
"id": 14,
"name": "Metro Theatre",
"slug": "metro-theatre",
"address": {
"line1": "624 George St",
"line2": null,
"locality": "Sydney",
"state": "NSW",
"postal_code": "2000",
"country": "AU",
"formatted": "624 George St, Sydney NSW 2000"
},
"lat": -33.8763,
"lng": 151.2066,
"url": "https://metrotheatre.com.au",
"phone": null
},
"ticketing": {
"currency": "AUD",
"min_price": "59.90",
"max_price": "59.90",
"tickets_remaining": null
},
"categories": [
"comedy"
],
"created_at": "2026-09-20T05:02:11Z",
"updated_at": "2026-10-16T08:40:00Z"
}
],
"has_more": true,
"next_cursor": "eyJpZCI6MTMxLCJzIjoiMjAyNi0xMS0xNFQwOTozMDowMFoifQ"
}Errors
| Status | Code | When |
|---|---|---|
| 400 | parameter_invalid | An unknown status/time value, limit outside 1–100, a bad cursor or updated_since. |
Retrieve an event#
GET /events/{id} · Scope: events:read
Path parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | integer | string | Yes | Event id or slug. |
curl https://api.showtix-nonprod.link/events/late-night-cabaret-melbourne \
-H "Authorization: Bearer $SHOWTIX_API_KEY"{
"object": "event",
"id": 123,
"slug": "late-night-cabaret-melbourne",
"title": "Late Night Cabaret",
"summary": "Songs, sketches and sequins — a late-night variety bill in Richmond.",
"description": "Late Night Cabaret returns to the Corner Hotel for one night only. 18+. Doors 7pm.",
"status": "published",
"starts_at": "2026-11-02T09:00:00Z",
"ends_at": "2026-11-02T13:00:00Z",
"timezone": "Australia/Melbourne",
"doors": "7:00pm",
"url": "https://showtix.com.au/shows/late-night-cabaret-melbourne",
"image_url": "https://showtix.com.au/uploads/events/123/feature.jpg",
"sold_out": false,
"on_sale_at": null,
"venue": {
"object": "venue",
"id": 9,
"name": "Corner Hotel",
"slug": "corner-hotel",
"address": {
"line1": "57 Swan St",
"line2": null,
"locality": "Richmond",
"state": "VIC",
"postal_code": "3121",
"country": "AU",
"formatted": "57 Swan St, Richmond VIC 3121"
},
"lat": -37.8253,
"lng": 144.9932,
"url": "https://cornerhotel.com",
"phone": null
},
"ticketing": {
"currency": "AUD",
"min_price": "49.00",
"max_price": "89.00",
"tickets_remaining": 412
},
"categories": [
"cabaret",
"comedy"
],
"created_at": "2026-09-14T02:31:07Z",
"updated_at": "2026-10-17T23:12:45Z"
}Errors
| Status | Code | When |
|---|---|---|
| 404 | resource_missing | No event with that id or slug in your organisation. |
List ticket types#
GET /events/{id}/ticket_types · Scope: events:read
Every ticket type for the event, in one page (has_more is always false). price is what the customer pays, booking fee included.
Path parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | integer | string | Yes | Event id or slug. |
curl https://api.showtix-nonprod.link/events/123/ticket_types \
-H "Authorization: Bearer $SHOWTIX_API_KEY"{
"object": "list",
"data": [
{
"object": "ticket_type",
"id": 55,
"pool_id": 31,
"pool_name": "General Admission",
"event_id": 123,
"name": "Early Bird",
"description": null,
"price": "49.00",
"booking_fee": "3.95",
"currency": "AUD",
"fees_included": true,
"gst_applies": true,
"min_per_order": 1,
"max_per_order": 10,
"status": "on_sale",
"sale_starts_at": null,
"sale_ends_at": "2026-10-25T13:00:00Z",
"available": 120,
"capacity": 500,
"seated": false
},
{
"object": "ticket_type",
"id": 56,
"pool_id": 31,
"pool_name": "General Admission",
"event_id": 123,
"name": "General Admission",
"description": null,
"price": "69.00",
"booking_fee": "4.95",
"currency": "AUD",
"fees_included": true,
"gst_applies": true,
"min_per_order": 1,
"max_per_order": 10,
"status": "not_yet_on_sale",
"sale_starts_at": "2026-10-25T13:00:00Z",
"sale_ends_at": null,
"available": 292,
"capacity": 500,
"seated": false
},
{
"object": "ticket_type",
"id": 57,
"pool_id": 32,
"pool_name": "Balcony",
"event_id": 123,
"name": "Balcony Reserved",
"description": "Allocated seating upstairs.",
"price": "89.00",
"booking_fee": "5.95",
"currency": "AUD",
"fees_included": true,
"gst_applies": true,
"min_per_order": 1,
"max_per_order": 6,
"status": "on_sale",
"sale_starts_at": null,
"sale_ends_at": null,
"available": 64,
"capacity": 80,
"seated": true
}
],
"has_more": false,
"next_cursor": null
}Errors
| Status | Code | When |
|---|---|---|
| 404 | resource_missing | No such event. |
Venues#
Venues hosting your organisation's events. Requires events:read.
List venues#
GET /venues · Scope: events:read
Sorted by id. Venues that have been removed from ShowTix are left out of the list, but GET /venues/{id} still returns one your existing events point at.
Query parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
limit | integer | No | 1–100, default 25. |
cursor | string | No | Opaque next_cursor from the previous page. See pagination. |
curl "https://api.showtix-nonprod.link/venues?limit=25" \
-H "Authorization: Bearer $SHOWTIX_API_KEY"{
"object": "list",
"data": [
{
"object": "venue",
"id": 9,
"name": "Corner Hotel",
"slug": "corner-hotel",
"address": {
"line1": "57 Swan St",
"line2": null,
"locality": "Richmond",
"state": "VIC",
"postal_code": "3121",
"country": "AU",
"formatted": "57 Swan St, Richmond VIC 3121"
},
"lat": -37.8253,
"lng": 144.9932,
"url": "https://cornerhotel.com",
"phone": null
},
{
"object": "venue",
"id": 14,
"name": "Metro Theatre",
"slug": "metro-theatre",
"address": {
"line1": "624 George St",
"line2": null,
"locality": "Sydney",
"state": "NSW",
"postal_code": "2000",
"country": "AU",
"formatted": "624 George St, Sydney NSW 2000"
},
"lat": -33.8763,
"lng": 151.2066,
"url": "https://metrotheatre.com.au",
"phone": null
}
],
"has_more": false,
"next_cursor": null
}Errors
| Status | Code | When |
|---|---|---|
| 400 | parameter_invalid | Bad limit or cursor. |
Retrieve a venue#
GET /venues/{id} · Scope: events:read
Path parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | integer | Yes | Venue id. |
curl https://api.showtix-nonprod.link/venues/9 \
-H "Authorization: Bearer $SHOWTIX_API_KEY"{
"object": "venue",
"id": 9,
"name": "Corner Hotel",
"slug": "corner-hotel",
"address": {
"line1": "57 Swan St",
"line2": null,
"locality": "Richmond",
"state": "VIC",
"postal_code": "3121",
"country": "AU",
"formatted": "57 Swan St, Richmond VIC 3121"
},
"lat": -37.8253,
"lng": 144.9932,
"url": "https://cornerhotel.com",
"phone": null
}Errors
| Status | Code | When |
|---|---|---|
| 404 | resource_missing | No such venue among your events. |
Checkout sessions#
A checkout session holds tickets for a customer and hands you a ShowTix-hosted checkout_url. Card data never touches your systems. When the customer pays, the session becomes completed, its order_id is set and order.completed fires.
Create a checkout session#
POST /checkout_sessions · Scope: orders:write
Tickets are held for the customer until expires_at (about 15 minutes), then released. Redirect the customer to checkout_url. Totals are fee-inclusive: total_fees is the booking-fee portion already inside subtotal, and total = subtotal − discount.
Test keys
Validated in full but nothing is held: "id": null, "dry_run": true, "livemode": false, "expires_at": null and checkout_url is the public event page. Coupons aren't applied in a dry run, so discount is always "0.00".
Body (JSON)
| Parameter | Type | Required | Description |
|---|---|---|---|
event_id | integer | Yes | The event (id or slug). |
items | object[] | Yes | Up to 20 lines, one per ticket type: ticket_type_id (required), quantity (required, 1–100) and pool_id — only needed when a ticket type is sold from several pools. Lines for the same ticket type are merged. |
customer | object | No | Pre-fills checkout: email, first_name, last_name, phone. |
coupon_code | string | No | A promo code to apply. |
metadata | object | No | Up to 20 keys (≤ 40 characters each) with string values (≤ 500 characters each; numbers and booleans are converted to strings). Echoed on the session and copied to the order — ideal for your CRM contact or cart id. |
curl https://api.showtix-nonprod.link/checkout_sessions \
-H "Authorization: Bearer $SHOWTIX_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: cart-48211-001" \
-d '{
"event_id": 123,
"items": [
{
"ticket_type_id": 55,
"quantity": 2,
"pool_id": 31
}
],
"customer": {
"email": "alex.ng@example.com",
"first_name": "Alex",
"last_name": "Ng",
"phone": "+61412345678"
},
"coupon_code": "EARLY10",
"metadata": {
"crm_contact_id": "cus_48211"
}
}'{
"object": "checkout_session",
"id": "f3a9c2d1-7b4e-4e0a-8c56-1d2e3f4a5b6c",
"status": "open",
"livemode": true,
"dry_run": false,
"event_id": 123,
"checkout_url": "https://showtix.com.au/checkout/f3a9c2d1-7b4e-4e0a-8c56-1d2e3f4a5b6c",
"expires_at": "2026-10-18T03:29:00Z",
"currency": "AUD",
"subtotal": "98.00",
"total_fees": "7.90",
"discount": "0.00",
"total": "98.00",
"items": [
{
"ticket_type_id": 55,
"pool_id": 31,
"name": "Early Bird",
"quantity": 2,
"unit_price": "49.00",
"total": "98.00"
}
],
"customer": {
"email": "alex.ng@example.com",
"first_name": "Alex",
"last_name": "Ng",
"phone": null
},
"order_id": null,
"metadata": {
"crm_contact_id": "cus_48211"
},
"created_at": "2026-10-18T03:14:00Z"
}Errors
| Status | Code | When |
|---|---|---|
| 400 | parameter_missing | No event_id or items, or a ticket type sold from several pools without pool_id. |
| 400 | parameter_invalid | Bad items (more than 20 lines, quantity outside 1–100), customer email, coupon or metadata (see param). |
| 404 | resource_missing | The event or a ticket type isn't in your organisation. |
| 422 | event_not_on_sale | The event isn't published, or tickets aren't on sale yet. |
| 422 | ticket_type_unavailable | A ticket type is hidden, not yet on sale or its sale has ended. |
| 422 | exceeds_availability | Not enough tickets left. |
| 422 | exceeds_max_per_order | Quantity above the ticket type's maximum per order. |
| 422 | parameter_invalid | Quantity below the ticket type's minimum per order. |
| 422 | seat_selection_required | A seated ticket type — send the customer to the event page instead. |
| 422 | idempotency_key_reused | Same Idempotency-Key, different body. |
| 409 | idempotency_request_in_progress | The first request with this key hasn't finished. |
Retrieve a checkout session#
GET /checkout_sessions/{id} · Scope: orders:read
Poll this (or listen for order.completed) to learn when the customer has paid. status is open, expired or completed.
Path parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string (uuid) | Yes | Checkout session id. |
curl https://api.showtix-nonprod.link/checkout_sessions/f3a9c2d1-7b4e-4e0a-8c56-1d2e3f4a5b6c \
-H "Authorization: Bearer $SHOWTIX_API_KEY"{
"object": "checkout_session",
"id": "f3a9c2d1-7b4e-4e0a-8c56-1d2e3f4a5b6c",
"status": "completed",
"livemode": true,
"dry_run": false,
"event_id": 123,
"checkout_url": "https://showtix.com.au/checkout/f3a9c2d1-7b4e-4e0a-8c56-1d2e3f4a5b6c",
"expires_at": "2026-10-18T03:29:00Z",
"currency": "AUD",
"subtotal": "98.00",
"total_fees": "7.90",
"discount": "0.00",
"total": "98.00",
"items": [
{
"ticket_type_id": 55,
"pool_id": 31,
"name": "Early Bird",
"quantity": 2,
"unit_price": "49.00",
"total": "98.00"
}
],
"customer": {
"email": "alex.ng@example.com",
"first_name": "Alex",
"last_name": "Ng",
"phone": null
},
"order_id": "f3a9c2d1-7b4e-4e0a-8c56-1d2e3f4a5b6c",
"metadata": {
"crm_contact_id": "cus_48211"
},
"created_at": "2026-10-18T03:14:00Z"
}Errors
| Status | Code | When |
|---|---|---|
| 404 | resource_missing | No such session. |
Orders#
Completed purchases — from your checkout sessions and every other sales channel for your events. Requires orders:read.
List orders#
GET /orders · Scope: orders:read
Newest first.
Query parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
event_id | integer | No | Only orders for this event. |
status | enum | No | completed (no refunded tickets) · refunded (at least one refunded ticket, including partial refunds) · all. Default: all orders. |
updated_since | string (ISO-8601) | No | Only return records changed at or after this time. See incremental sync. |
limit | integer | No | 1–100, default 25. |
cursor | string | No | Opaque next_cursor from the previous page. See pagination. |
curl "https://api.showtix-nonprod.link/orders?event_id=123&limit=25" \
-H "Authorization: Bearer $SHOWTIX_API_KEY"{
"object": "list",
"data": [
{
"object": "order",
"id": "f3a9c2d1-7b4e-4e0a-8c56-1d2e3f4a5b6c",
"event_id": 123,
"status": "completed",
"customer": {
"email": "alex.ng@example.com",
"first_name": "Alex",
"last_name": "Ng",
"phone": null
},
"currency": "AUD",
"subtotal": "98.00",
"total_fees": "7.90",
"discount": "0.00",
"total": "98.00",
"refunded_amount": "0.00",
"payment_method": "stripe",
"checkout_session_id": "f3a9c2d1-7b4e-4e0a-8c56-1d2e3f4a5b6c",
"sales_channel": "api",
"channel_origin": null,
"metadata": {
"crm_contact_id": "cus_48211"
},
"tickets": [
{
"object": "ticket",
"id": 8812,
"barcode": "5e0c6f2a-91d4-4b8e-a3c1-7f20d9b4c611",
"order_id": "f3a9c2d1-7b4e-4e0a-8c56-1d2e3f4a5b6c",
"event_id": 123,
"ticket_type_id": 55,
"ticket_type_name": "Early Bird",
"pool_id": 31,
"attendee": {
"first_name": "Alex",
"last_name": "Ng",
"email": "alex.ng@example.com"
},
"price": "49.00",
"status": "valid",
"comp": false,
"seat_label": null,
"checked_in_at": null,
"created_at": "2026-10-18T03:14:22Z",
"updated_at": "2026-10-18T03:14:22Z"
},
{
"object": "ticket",
"id": 8813,
"barcode": "c47b1e09-2f6a-4d35-8e0b-51a9d3f7e284",
"order_id": "f3a9c2d1-7b4e-4e0a-8c56-1d2e3f4a5b6c",
"event_id": 123,
"ticket_type_id": 55,
"ticket_type_name": "Early Bird",
"pool_id": 31,
"attendee": {
"first_name": "Priya",
"last_name": "Sharma",
"email": "priya.sharma@example.com"
},
"price": "49.00",
"status": "valid",
"comp": false,
"seat_label": null,
"checked_in_at": null,
"created_at": "2026-10-18T03:14:22Z",
"updated_at": "2026-10-18T03:14:22Z"
}
],
"created_at": "2026-10-18T03:14:00Z",
"completed_at": "2026-10-18T03:16:41Z",
"updated_at": "2026-10-18T03:16:41Z"
}
],
"has_more": true,
"next_cursor": "eyJpZCI6MTMxLCJzIjoiMjAyNi0xMS0xNFQwOTozMDowMFoifQ"
}Errors
| Status | Code | When |
|---|---|---|
| 400 | parameter_invalid | Non-integer event_id, bad limit, cursor or updated_since. |
Retrieve an order#
GET /orders/{id} · Scope: orders:read
Path parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string (uuid) | Yes | Order id. |
curl https://api.showtix-nonprod.link/orders/f3a9c2d1-7b4e-4e0a-8c56-1d2e3f4a5b6c \
-H "Authorization: Bearer $SHOWTIX_API_KEY"{
"object": "order",
"id": "f3a9c2d1-7b4e-4e0a-8c56-1d2e3f4a5b6c",
"event_id": 123,
"status": "completed",
"customer": {
"email": "alex.ng@example.com",
"first_name": "Alex",
"last_name": "Ng",
"phone": null
},
"currency": "AUD",
"subtotal": "98.00",
"total_fees": "7.90",
"discount": "0.00",
"total": "98.00",
"refunded_amount": "0.00",
"payment_method": "stripe",
"checkout_session_id": "f3a9c2d1-7b4e-4e0a-8c56-1d2e3f4a5b6c",
"sales_channel": "api",
"channel_origin": null,
"metadata": {
"crm_contact_id": "cus_48211"
},
"tickets": [
{
"object": "ticket",
"id": 8812,
"barcode": "5e0c6f2a-91d4-4b8e-a3c1-7f20d9b4c611",
"order_id": "f3a9c2d1-7b4e-4e0a-8c56-1d2e3f4a5b6c",
"event_id": 123,
"ticket_type_id": 55,
"ticket_type_name": "Early Bird",
"pool_id": 31,
"attendee": {
"first_name": "Alex",
"last_name": "Ng",
"email": "alex.ng@example.com"
},
"price": "49.00",
"status": "valid",
"comp": false,
"seat_label": null,
"checked_in_at": null,
"created_at": "2026-10-18T03:14:22Z",
"updated_at": "2026-10-18T03:14:22Z"
},
{
"object": "ticket",
"id": 8813,
"barcode": "c47b1e09-2f6a-4d35-8e0b-51a9d3f7e284",
"order_id": "f3a9c2d1-7b4e-4e0a-8c56-1d2e3f4a5b6c",
"event_id": 123,
"ticket_type_id": 55,
"ticket_type_name": "Early Bird",
"pool_id": 31,
"attendee": {
"first_name": "Priya",
"last_name": "Sharma",
"email": "priya.sharma@example.com"
},
"price": "49.00",
"status": "valid",
"comp": false,
"seat_label": null,
"checked_in_at": null,
"created_at": "2026-10-18T03:14:22Z",
"updated_at": "2026-10-18T03:14:22Z"
}
],
"created_at": "2026-10-18T03:14:00Z",
"completed_at": "2026-10-18T03:16:41Z",
"updated_at": "2026-10-18T03:16:41Z"
}Errors
| Status | Code | When |
|---|---|---|
| 404 | resource_missing | No such order. |
Tickets & attendees#
Store the ticket id, not the barcode
barcode is what the QR code encodes and it rotates when a ticket is transferred. Use the integer id as your key.
Retrieve a ticket#
GET /tickets/{id} · Scope: orders:read or attendees:read
Path parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | integer | Yes | Ticket id. |
curl https://api.showtix-nonprod.link/tickets/8812 \
-H "Authorization: Bearer $SHOWTIX_API_KEY"{
"object": "ticket",
"id": 8812,
"barcode": "5e0c6f2a-91d4-4b8e-a3c1-7f20d9b4c611",
"order_id": "f3a9c2d1-7b4e-4e0a-8c56-1d2e3f4a5b6c",
"event_id": 123,
"ticket_type_id": 55,
"ticket_type_name": "Early Bird",
"pool_id": 31,
"attendee": {
"first_name": "Alex",
"last_name": "Ng",
"email": "alex.ng@example.com"
},
"price": "49.00",
"status": "valid",
"comp": false,
"seat_label": null,
"checked_in_at": null,
"created_at": "2026-10-18T03:14:22Z",
"updated_at": "2026-10-18T03:14:22Z"
}Errors
| Status | Code | When |
|---|---|---|
| 404 | resource_missing | No such ticket. |
List attendees#
GET /events/{id}/attendees · Scope: attendees:read
Every ticket for the event as a list of ticket objects, sorted by id — download it before doors for offline scanning. Voided tickets are left out; refunded tickets are included with status: "refunded".
Path parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | integer | string | Yes | Event id or slug. |
Query parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
checked_in | boolean | No | true or false to filter by check-in state. |
updated_since | string (ISO-8601) | No | Only return records changed at or after this time. See incremental sync. |
limit | integer | No | 1–100, default 25. |
cursor | string | No | Opaque next_cursor from the previous page. See pagination. |
curl "https://api.showtix-nonprod.link/events/123/attendees?checked_in=false&limit=100" \
-H "Authorization: Bearer $SHOWTIX_API_KEY"{
"object": "list",
"data": [
{
"object": "ticket",
"id": 8812,
"barcode": "5e0c6f2a-91d4-4b8e-a3c1-7f20d9b4c611",
"order_id": "f3a9c2d1-7b4e-4e0a-8c56-1d2e3f4a5b6c",
"event_id": 123,
"ticket_type_id": 55,
"ticket_type_name": "Early Bird",
"pool_id": 31,
"attendee": {
"first_name": "Alex",
"last_name": "Ng",
"email": "alex.ng@example.com"
},
"price": "49.00",
"status": "valid",
"comp": false,
"seat_label": null,
"checked_in_at": null,
"created_at": "2026-10-18T03:14:22Z",
"updated_at": "2026-10-18T03:14:22Z"
},
{
"object": "ticket",
"id": 8813,
"barcode": "c47b1e09-2f6a-4d35-8e0b-51a9d3f7e284",
"order_id": "f3a9c2d1-7b4e-4e0a-8c56-1d2e3f4a5b6c",
"event_id": 123,
"ticket_type_id": 55,
"ticket_type_name": "Early Bird",
"pool_id": 31,
"attendee": {
"first_name": "Priya",
"last_name": "Sharma",
"email": "priya.sharma@example.com"
},
"price": "49.00",
"status": "valid",
"comp": false,
"seat_label": null,
"checked_in_at": null,
"created_at": "2026-10-18T03:14:22Z",
"updated_at": "2026-10-18T03:14:22Z"
}
],
"has_more": false,
"next_cursor": null
}Errors
| Status | Code | When |
|---|---|---|
| 404 | resource_missing | No such event. |
| 400 | parameter_invalid | Bad limit, cursor or updated_since. |
Issue comp tickets#
POST /comp_tickets · Scope: orders:write
Issues complimentary tickets; each guest is emailed their ticket. Guests that can't be issued are listed in failed with a reason — the rest still succeed. Test keys validate the batch and return dry_run: true without issuing or emailing.
Body (JSON)
| Parameter | Type | Required | Description |
|---|---|---|---|
event_id | integer | Yes | The event (id or slug). |
ticket_type_id | integer | Yes | Ticket type to issue. |
pool_id | integer | No | Only when the ticket type sells from several pools. |
attendees | object[] | Yes | 1–50 guests, each { email, name } (email required). |
note | string | No | Internal note, e.g. Performer guest list. |
curl https://api.showtix-nonprod.link/comp_tickets \
-H "Authorization: Bearer $SHOWTIX_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: guestlist-123-performers" \
-d '{
"event_id": 123,
"ticket_type_id": 55,
"pool_id": 31,
"attendees": [
{
"email": "sam.guest@example.com",
"name": "Sam Guest"
},
{
"email": "plus.one@example.com",
"name": "Jo Plus-One"
}
],
"note": "Performer guest list"
}'{
"object": "comp_ticket_batch",
"livemode": true,
"dry_run": false,
"issued": 1,
"failed": [
{
"email": "plus.one@example.com",
"reason": "exceeds_stock"
}
],
"tickets": [
{
"object": "ticket",
"id": 8920,
"barcode": "0d8e2b7c-4a19-4f63-b2d5-9c1e7a3f6b08",
"order_id": null,
"event_id": 123,
"ticket_type_id": 55,
"ticket_type_name": "Early Bird",
"pool_id": 31,
"attendee": {
"first_name": "Sam",
"last_name": "Guest",
"email": "sam.guest@example.com"
},
"price": "0.00",
"status": "valid",
"comp": true,
"seat_label": null,
"checked_in_at": null,
"created_at": "2026-10-18T04:02:10Z",
"updated_at": "2026-10-18T04:02:10Z"
}
]
}Errors
| Status | Code | When |
|---|---|---|
| 400 | parameter_missing | No event_id or ticket_type_id, or a ticket type sold from several pools without pool_id. |
| 400 | parameter_invalid | attendees missing, empty or more than 50, or an attendee without a valid email. |
| 404 | resource_missing | The event or ticket type isn't in your organisation. |
| 422 | exceeds_availability | More guests than tickets left in the pool. |
Check in a ticket#
POST /events/{id}/check_ins · Scope: check_in:write
Scanning is safe to repeat: a second scan returns 200 with result: "already_checked_in" (and the original checked_in_at) so door staff can spot a duplicate. Each successful check-in fires ticket.checked_in. With a test key the scan is classified the same way but nothing is recorded (dry_run: true).
Path parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | integer | string | Yes | Event id or slug. |
Body (JSON)
| Parameter | Type | Required | Description |
|---|---|---|---|
code | string | No | The scanned QR payload or barcode. Send this or ticket_id. |
ticket_id | integer | No | Check in by ticket id instead of a scan. |
curl https://api.showtix-nonprod.link/events/123/check_ins \
-H "Authorization: Bearer $SHOWTIX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"code": "5e0c6f2a-91d4-4b8e-a3c1-7f20d9b4c611"
}'{
"object": "check_in",
"result": "checked_in",
"livemode": true,
"dry_run": false,
"ticket": {
"object": "ticket",
"id": 8812,
"barcode": "5e0c6f2a-91d4-4b8e-a3c1-7f20d9b4c611",
"order_id": "f3a9c2d1-7b4e-4e0a-8c56-1d2e3f4a5b6c",
"event_id": 123,
"ticket_type_id": 55,
"ticket_type_name": "Early Bird",
"pool_id": 31,
"attendee": {
"first_name": "Alex",
"last_name": "Ng",
"email": "alex.ng@example.com"
},
"price": "49.00",
"status": "checked_in",
"comp": false,
"seat_label": null,
"checked_in_at": "2026-11-02T08:47:12Z",
"created_at": "2026-10-18T03:14:22Z",
"updated_at": "2026-11-02T08:47:12Z"
}
}Errors
| Status | Code | When |
|---|---|---|
| 400 | parameter_missing | Neither code nor ticket_id was sent. |
| 404 | resource_missing | Unknown code or ticket. |
| 409 | ticket_wrong_event | The ticket is for a different event. |
| 422 | ticket_void | The ticket was refunded or voided — refuse entry. |
Webhook endpoints#
Manage webhook subscriptions programmatically (you can also do this in the Developers dashboard). Requires webhooks:manage.
List webhook endpoints#
GET /webhook_endpoints · Scope: webhooks:manage
Every endpoint for your organisation in one page (has_more is always false).
curl https://api.showtix-nonprod.link/webhook_endpoints \
-H "Authorization: Bearer $SHOWTIX_API_KEY"{
"object": "list",
"data": [
{
"object": "webhook_endpoint",
"id": 4,
"url": "https://partner.example/hooks/showtix",
"description": "CRM sync",
"event_types": [
"order.completed",
"ticket.checked_in"
],
"enabled": true,
"status": "enabled",
"mode": "live",
"consecutive_failures": 0,
"disabled_at": null,
"disabled_reason": null,
"last_success_at": "2026-10-18T03:16:43Z",
"last_failure_at": null,
"secret_hint": "whsec_…9fA2",
"created_at": "2026-10-18T01:00:00Z",
"updated_at": "2026-10-18T01:00:00Z"
}
],
"has_more": false,
"next_cursor": null
}Create a webhook endpoint#
POST /webhook_endpoints · Scope: webhooks:manage
Body (JSON)
| Parameter | Type | Required | Description |
|---|---|---|---|
url | string | Yes | HTTPS URL that will receive events (max 2,048 characters). Private, loopback and internal addresses are rejected. |
event_types | string[] | No | Types to subscribe to, from the catalogue, or ["*"] for all. Default ["*"]. |
description | string | No | Your label (max 255 characters). |
mode | enum | No | live (default) or test. Test endpoints only receive test events you send. |
The secret is returned once by the API
Store secret (whsec_…) from this response — you need it to verify signatures. Later API reads only show secret_hint. Owners and admins can reveal it again in the Developers dashboard.
curl https://api.showtix-nonprod.link/webhook_endpoints \
-H "Authorization: Bearer $SHOWTIX_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: crm-endpoint-v1" \
-d '{
"url": "https://partner.example/hooks/showtix",
"description": "CRM sync",
"event_types": [
"order.completed",
"ticket.checked_in"
]
}'{
"object": "webhook_endpoint",
"id": 4,
"url": "https://partner.example/hooks/showtix",
"description": "CRM sync",
"event_types": [
"order.completed",
"ticket.checked_in"
],
"enabled": true,
"status": "enabled",
"mode": "live",
"consecutive_failures": 0,
"disabled_at": null,
"disabled_reason": null,
"last_success_at": null,
"last_failure_at": null,
"secret_hint": "whsec_…9fA2",
"created_at": "2026-10-18T01:00:00Z",
"updated_at": "2026-10-18T01:00:00Z",
"secret": "whsec_EXAMPLE_ONLY_not_a_real_secret_000"
}Errors
| Status | Code | When |
|---|---|---|
| 400 | parameter_invalid | Missing or invalid url (not HTTPS, or a private address), an empty or unknown event type, or a bad mode. |
Retrieve a webhook endpoint#
GET /webhook_endpoints/{id} · Scope: webhooks:manage
Path parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | integer | Yes | Endpoint id. |
curl https://api.showtix-nonprod.link/webhook_endpoints/4 \
-H "Authorization: Bearer $SHOWTIX_API_KEY"{
"object": "webhook_endpoint",
"id": 4,
"url": "https://partner.example/hooks/showtix",
"description": "CRM sync",
"event_types": [
"order.completed",
"ticket.checked_in"
],
"enabled": true,
"status": "enabled",
"mode": "live",
"consecutive_failures": 0,
"disabled_at": null,
"disabled_reason": null,
"last_success_at": "2026-10-18T03:16:43Z",
"last_failure_at": null,
"secret_hint": "whsec_…9fA2",
"created_at": "2026-10-18T01:00:00Z",
"updated_at": "2026-10-18T01:00:00Z"
}Errors
| Status | Code | When |
|---|---|---|
| 404 | resource_missing | No such endpoint. |
Update a webhook endpoint#
PATCH /webhook_endpoints/{id} · Scope: webhooks:manage
Path parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | integer | Yes | Endpoint id. |
Body (JSON)
| Parameter | Type | Required | Description |
|---|---|---|---|
url | string | No | New URL. |
description | string | No | New label. |
event_types | string[] | No | Replaces the subscription list. |
enabled | boolean | No | false pauses deliveries; true re-enables a disabled endpoint and resets its failure count. |
curl -X PATCH https://api.showtix-nonprod.link/webhook_endpoints/4 \
-H "Authorization: Bearer $SHOWTIX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"event_types": [
"*"
],
"enabled": true
}'{
"object": "webhook_endpoint",
"id": 4,
"url": "https://partner.example/hooks/showtix",
"description": "CRM sync",
"event_types": [
"*"
],
"enabled": true,
"status": "enabled",
"mode": "live",
"consecutive_failures": 0,
"disabled_at": null,
"disabled_reason": null,
"last_success_at": "2026-10-18T03:16:43Z",
"last_failure_at": null,
"secret_hint": "whsec_…9fA2",
"created_at": "2026-10-18T01:00:00Z",
"updated_at": "2026-10-18T01:00:00Z"
}Errors
| Status | Code | When |
|---|---|---|
| 404 | resource_missing | No such endpoint. |
| 400 | parameter_invalid | Invalid URL or an unknown event type. |
Delete a webhook endpoint#
DELETE /webhook_endpoints/{id} · Scope: webhooks:manage
Stops all deliveries to the endpoint immediately.
Path parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | integer | Yes | Endpoint id. |
curl -X DELETE https://api.showtix-nonprod.link/webhook_endpoints/4 \
-H "Authorization: Bearer $SHOWTIX_API_KEY"(empty body)Errors
| Status | Code | When |
|---|---|---|
| 404 | resource_missing | No such endpoint. |
Send a test event#
POST /webhook_endpoints/{id}/test · Scope: webhooks:manage
Sends a signed sample payload (livemode: false) to the endpoint right away and returns the delivery result — the same as Send test event in the dashboard. Test events are delivered once and never retried.
Path parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | integer | Yes | Endpoint id. |
Body (JSON)
| Parameter | Type | Required | Description |
|---|---|---|---|
type | string | No | Event type to simulate. Default order.completed; an unrecognised type also falls back to order.completed. |
curl https://api.showtix-nonprod.link/webhook_endpoints/4/test \
-H "Authorization: Bearer $SHOWTIX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"type": "ticket.checked_in"
}'{
"object": "webhook_delivery",
"id": 3301,
"endpoint_id": 4,
"endpoint_url": "https://partner.example/hooks/showtix",
"event_id": "evt_3kTq9WmZpL2vX8rNa4Hs6dQe",
"event_type": "ticket.checked_in",
"attempt": 1,
"status": "succeeded",
"response_status": 200,
"duration_ms": 182,
"error": null,
"manual": true,
"next_retry_at": null,
"created_at": "2026-10-18T04:10:00Z"
}Errors
| Status | Code | When |
|---|---|---|
| 404 | resource_missing | No such endpoint. |
| 500 | test_event_failed | The test event couldn't be sent. |
Objects#
Every object returned by the API. Fields typed … | null may be null.
Event#
| Field | Type | Description |
|---|---|---|
object | string | "event" |
id | integer | Unique identifier. Endpoints that take an event id also accept its slug. |
slug | string | URL-friendly identifier. |
title | string | Event title, usually the headline act. |
summary | string | null | One-line summary. |
description | string | null | Long description. |
status | enum | published (public, not ended) · draft (not public) · pending_review (held for platform approval) · cancelled · ended (end time has passed). |
starts_at | string (ISO-8601) | Start time, UTC. |
ends_at | string | null | End time, UTC. |
timezone | string | IANA timezone of the venue, e.g. Australia/Melbourne. |
doors | string | null | Doors time as displayed locally, e.g. 7:00pm. |
url | string | Public event page. |
image_url | string | null | Feature image. |
sold_out | boolean | True when every ticket pool is sold out. |
on_sale_at | string | null | When tickets go on sale, if set. |
venue | venue | null | The venue object. |
ticketing | object | currency (AUD), min_price and max_price (fee-inclusive, decimal-dollar strings) and tickets_remaining — null when any pool is uncapped. |
categories | string[] | Category tags (slugs). |
created_at, updated_at | string | ISO-8601 UTC timestamps. |
{
"object": "event",
"id": 123,
"slug": "late-night-cabaret-melbourne",
"title": "Late Night Cabaret",
"summary": "Songs, sketches and sequins — a late-night variety bill in Richmond.",
"description": "Late Night Cabaret returns to the Corner Hotel for one night only. 18+. Doors 7pm.",
"status": "published",
"starts_at": "2026-11-02T09:00:00Z",
"ends_at": "2026-11-02T13:00:00Z",
"timezone": "Australia/Melbourne",
"doors": "7:00pm",
"url": "https://showtix.com.au/shows/late-night-cabaret-melbourne",
"image_url": "https://showtix.com.au/uploads/events/123/feature.jpg",
"sold_out": false,
"on_sale_at": null,
"venue": {
"object": "venue",
"id": 9,
"name": "Corner Hotel",
"slug": "corner-hotel",
"address": {
"line1": "57 Swan St",
"line2": null,
"locality": "Richmond",
"state": "VIC",
"postal_code": "3121",
"country": "AU",
"formatted": "57 Swan St, Richmond VIC 3121"
},
"lat": -37.8253,
"lng": 144.9932,
"url": "https://cornerhotel.com",
"phone": null
},
"ticketing": {
"currency": "AUD",
"min_price": "49.00",
"max_price": "89.00",
"tickets_remaining": 412
},
"categories": [
"cabaret",
"comedy"
],
"created_at": "2026-09-14T02:31:07Z",
"updated_at": "2026-10-17T23:12:45Z"
}Ticket type#
| Field | Type | Description |
|---|---|---|
object | string | "ticket_type" |
id | integer | Unique identifier. |
pool_id | integer | The capacity pool this ticket type sells from. |
pool_name | string | Pool name, e.g. General Admission. |
event_id | integer | Owning event. |
name | string | Ticket type name. |
description | string | null | Optional description. |
price | string | Fee-INCLUSIVE price the customer pays per ticket, as a string of decimal dollars, e.g. "49.00". |
booking_fee | string | Informational booking-fee portion already included in price. |
currency | string | AUD |
fees_included | boolean | Whether price already includes the booking fee (always true). |
gst_applies | boolean | Whether GST applies to the ticket. |
min_per_order, max_per_order | integer | Per-order quantity limits. |
status | enum | on_sale · not_yet_on_sale · sale_ended · sold_out · hidden |
sale_starts_at, sale_ends_at | string | null | Sales window, UTC. |
available | integer | null | Tickets still available; null = unlimited. |
capacity | integer | null | Total capacity; null = unlimited. |
seated | boolean | Seated types can only be bought through ShowTix checkout (seat map). Checkout sessions reject them with seat_selection_required. |
{
"object": "ticket_type",
"id": 55,
"pool_id": 31,
"pool_name": "General Admission",
"event_id": 123,
"name": "Early Bird",
"description": null,
"price": "49.00",
"booking_fee": "3.95",
"currency": "AUD",
"fees_included": true,
"gst_applies": true,
"min_per_order": 1,
"max_per_order": 10,
"status": "on_sale",
"sale_starts_at": null,
"sale_ends_at": "2026-10-25T13:00:00Z",
"available": 120,
"capacity": 500,
"seated": false
}Venue#
| Field | Type | Description |
|---|---|---|
object | string | "venue" |
id | integer | Unique identifier. |
name, slug | string | Venue name and URL slug. |
address | object | line1, line2, locality, state, postal_code, country (ISO code, e.g. AU) and a display-ready formatted string. |
lat, lng | number | null | Coordinates. |
url | string | null | Venue website. |
phone | string | null | Venue phone. |
{
"object": "venue",
"id": 9,
"name": "Corner Hotel",
"slug": "corner-hotel",
"address": {
"line1": "57 Swan St",
"line2": null,
"locality": "Richmond",
"state": "VIC",
"postal_code": "3121",
"country": "AU",
"formatted": "57 Swan St, Richmond VIC 3121"
},
"lat": -37.8253,
"lng": 144.9932,
"url": "https://cornerhotel.com",
"phone": null
}Checkout session#
| Field | Type | Description |
|---|---|---|
object | string | "checkout_session" |
id | string (uuid) | null | Unique identifier; null for test-key dry runs. Once paid, the order has the same id. |
status | enum | open (tickets held) · expired (hold released) · completed (paid — order_id is set). |
livemode | boolean | False for test keys. |
dry_run | boolean | True when nothing was held (test keys). |
event_id | integer | The event. |
checkout_url | string | Hosted checkout to redirect the customer to. Test keys get the public event page. |
expires_at | string | null | When the hold is released if unpaid; null for test-key dry runs. |
currency | string | AUD |
subtotal | string | Sum of item totals (fee-inclusive), as a string of decimal dollars, e.g. "49.00". |
total_fees | string | Informational booking-fee portion already inside subtotal. |
discount | string | Coupon discount. |
total | string | Amount the customer pays (subtotal − discount). |
items | object[] | ticket_type_id, pool_id, name, quantity, unit_price, total. |
customer | object | null | email, first_name, last_name, phone. |
order_id | string | null | Set once the session completes. |
metadata | object | Your key/value pairs, echoed back and copied to the order. |
created_at | string | ISO-8601 UTC. |
{
"object": "checkout_session",
"id": "f3a9c2d1-7b4e-4e0a-8c56-1d2e3f4a5b6c",
"status": "open",
"livemode": true,
"dry_run": false,
"event_id": 123,
"checkout_url": "https://showtix.com.au/checkout/f3a9c2d1-7b4e-4e0a-8c56-1d2e3f4a5b6c",
"expires_at": "2026-10-18T03:29:00Z",
"currency": "AUD",
"subtotal": "98.00",
"total_fees": "7.90",
"discount": "0.00",
"total": "98.00",
"items": [
{
"ticket_type_id": 55,
"pool_id": 31,
"name": "Early Bird",
"quantity": 2,
"unit_price": "49.00",
"total": "98.00"
}
],
"customer": {
"email": "alex.ng@example.com",
"first_name": "Alex",
"last_name": "Ng",
"phone": null
},
"order_id": null,
"metadata": {
"crm_contact_id": "cus_48211"
},
"created_at": "2026-10-18T03:14:00Z"
}Order#
| Field | Type | Description |
|---|---|---|
object | string | "order" |
id | string (uuid) | Unique identifier. For orders created through the API it equals the checkout session id. |
event_id | integer | The event. |
status | enum | completed · partially_refunded · refunded |
customer | object | email, first_name, last_name, phone. |
currency | string | AUD |
subtotal, total_fees, discount, total | string | Same meaning as on the checkout session. |
refunded_amount | string | Total refunded so far. |
payment_method | enum | stripe · paypal · free · comp · other |
checkout_session_id | string | null | The API checkout session that created it, if any. |
sales_channel | enum | Where the order was placed: api (a checkout session) · embed (the embeddable checkout on your site) · storefront (your storefront) · web (ShowTix directly). |
channel_origin | string | null | For embed and storefront orders, the website it came from, e.g. https://www.yourvenue.com.au. |
metadata | object | Copied from the checkout session. |
tickets | ticket[] | Tickets in the order. |
created_at, completed_at, updated_at | string | ISO-8601 UTC. |
{
"object": "order",
"id": "f3a9c2d1-7b4e-4e0a-8c56-1d2e3f4a5b6c",
"event_id": 123,
"status": "completed",
"customer": {
"email": "alex.ng@example.com",
"first_name": "Alex",
"last_name": "Ng",
"phone": null
},
"currency": "AUD",
"subtotal": "98.00",
"total_fees": "7.90",
"discount": "0.00",
"total": "98.00",
"refunded_amount": "0.00",
"payment_method": "stripe",
"checkout_session_id": "f3a9c2d1-7b4e-4e0a-8c56-1d2e3f4a5b6c",
"sales_channel": "api",
"channel_origin": null,
"metadata": {
"crm_contact_id": "cus_48211"
},
"tickets": [
{
"object": "ticket",
"id": 8812,
"barcode": "5e0c6f2a-91d4-4b8e-a3c1-7f20d9b4c611",
"order_id": "f3a9c2d1-7b4e-4e0a-8c56-1d2e3f4a5b6c",
"event_id": 123,
"ticket_type_id": 55,
"ticket_type_name": "Early Bird",
"pool_id": 31,
"attendee": {
"first_name": "Alex",
"last_name": "Ng",
"email": "alex.ng@example.com"
},
"price": "49.00",
"status": "valid",
"comp": false,
"seat_label": null,
"checked_in_at": null,
"created_at": "2026-10-18T03:14:22Z",
"updated_at": "2026-10-18T03:14:22Z"
},
{
"object": "ticket",
"id": 8813,
"barcode": "c47b1e09-2f6a-4d35-8e0b-51a9d3f7e284",
"order_id": "f3a9c2d1-7b4e-4e0a-8c56-1d2e3f4a5b6c",
"event_id": 123,
"ticket_type_id": 55,
"ticket_type_name": "Early Bird",
"pool_id": 31,
"attendee": {
"first_name": "Priya",
"last_name": "Sharma",
"email": "priya.sharma@example.com"
},
"price": "49.00",
"status": "valid",
"comp": false,
"seat_label": null,
"checked_in_at": null,
"created_at": "2026-10-18T03:14:22Z",
"updated_at": "2026-10-18T03:14:22Z"
}
],
"created_at": "2026-10-18T03:14:00Z",
"completed_at": "2026-10-18T03:16:41Z",
"updated_at": "2026-10-18T03:16:41Z"
}Ticket#
| Field | Type | Description |
|---|---|---|
object | string | "ticket" |
id | integer | Stable identifier — use this as your key. |
barcode | string | What the QR code encodes. It rotates when a ticket is transferred — don't store it as a key. |
order_id | string | null | null for comp tickets. |
event_id, ticket_type_id, pool_id | integer | Relations. |
ticket_type_name | string | Ticket type name at issue. |
attendee | object | first_name, last_name, email. |
price | string | Fee-inclusive price paid. |
status | enum | valid · checked_in · refunded · void |
comp | boolean | Complimentary ticket. |
seat_label | string | null | Seat, for seated tickets. |
checked_in_at | string | null | When it was scanned. |
created_at, updated_at | string | ISO-8601 UTC. |
{
"object": "ticket",
"id": 8812,
"barcode": "5e0c6f2a-91d4-4b8e-a3c1-7f20d9b4c611",
"order_id": "f3a9c2d1-7b4e-4e0a-8c56-1d2e3f4a5b6c",
"event_id": 123,
"ticket_type_id": 55,
"ticket_type_name": "Early Bird",
"pool_id": 31,
"attendee": {
"first_name": "Alex",
"last_name": "Ng",
"email": "alex.ng@example.com"
},
"price": "49.00",
"status": "valid",
"comp": false,
"seat_label": null,
"checked_in_at": null,
"created_at": "2026-10-18T03:14:22Z",
"updated_at": "2026-10-18T03:14:22Z"
}Comp ticket batch#
| Field | Type | Description |
|---|---|---|
object | string | "comp_ticket_batch" |
livemode, dry_run | boolean | Mode flags. |
issued | integer | Number of tickets issued. |
failed | object[] | email and reason (e.g. exceeds_stock) for each guest not issued. |
tickets | ticket[] | The issued tickets (empty for test-key dry runs). |
{
"object": "comp_ticket_batch",
"livemode": true,
"dry_run": false,
"issued": 1,
"failed": [
{
"email": "plus.one@example.com",
"reason": "exceeds_stock"
}
],
"tickets": [
{
"object": "ticket",
"id": 8920,
"barcode": "0d8e2b7c-4a19-4f63-b2d5-9c1e7a3f6b08",
"order_id": null,
"event_id": 123,
"ticket_type_id": 55,
"ticket_type_name": "Early Bird",
"pool_id": 31,
"attendee": {
"first_name": "Sam",
"last_name": "Guest",
"email": "sam.guest@example.com"
},
"price": "0.00",
"status": "valid",
"comp": true,
"seat_label": null,
"checked_in_at": null,
"created_at": "2026-10-18T04:02:10Z",
"updated_at": "2026-10-18T04:02:10Z"
}
]
}Check-in#
| Field | Type | Description |
|---|---|---|
object | string | "check_in" |
result | enum | checked_in (first scan) · already_checked_in (repeat scan — warn the door staff). |
livemode, dry_run | boolean | Mode flags. |
ticket | ticket | The ticket after the scan. |
{
"object": "check_in",
"result": "checked_in",
"livemode": true,
"dry_run": false,
"ticket": {
"object": "ticket",
"id": 8812,
"barcode": "5e0c6f2a-91d4-4b8e-a3c1-7f20d9b4c611",
"order_id": "f3a9c2d1-7b4e-4e0a-8c56-1d2e3f4a5b6c",
"event_id": 123,
"ticket_type_id": 55,
"ticket_type_name": "Early Bird",
"pool_id": 31,
"attendee": {
"first_name": "Alex",
"last_name": "Ng",
"email": "alex.ng@example.com"
},
"price": "49.00",
"status": "checked_in",
"comp": false,
"seat_label": null,
"checked_in_at": "2026-11-02T08:47:12Z",
"created_at": "2026-10-18T03:14:22Z",
"updated_at": "2026-11-02T08:47:12Z"
}
}Webhook endpoint#
| Field | Type | Description |
|---|---|---|
object | string | "webhook_endpoint" |
id | integer | Unique identifier. |
url | string | Where events are POSTed. |
description | string | null | Your label. |
event_types | string[] | Subscribed types; ["*"] = all. |
enabled | boolean | Whether deliveries are sent. |
status | enum | enabled · failing (≥ 1 consecutive failure) · disabled |
mode | enum | live · test |
consecutive_failures | integer | Resets on success. |
disabled_at, disabled_reason | string | null | Set when disabled. |
last_success_at, last_failure_at | string | null | Delivery health. |
secret_hint | string | Masked secret, e.g. whsec_…9fA2. |
secret | string | Only in the create response: whsec_ + 32 base62 characters. |
created_at, updated_at | string | ISO-8601 UTC. |
{
"object": "webhook_endpoint",
"id": 4,
"url": "https://partner.example/hooks/showtix",
"description": "CRM sync",
"event_types": [
"order.completed",
"ticket.checked_in"
],
"enabled": true,
"status": "enabled",
"mode": "live",
"consecutive_failures": 0,
"disabled_at": null,
"disabled_reason": null,
"last_success_at": "2026-10-18T03:16:43Z",
"last_failure_at": null,
"secret_hint": "whsec_…9fA2",
"created_at": "2026-10-18T01:00:00Z",
"updated_at": "2026-10-18T01:00:00Z"
}Questions? Email support@showtix.com.au — include the Request-Id.
Was this article helpful?