A ticket is the durable artifact of a guest’s registration to an event. It carries the barcode, attendee details, custom field answers, scan/check-in state, and links to the underlying line item and order.
Default response fields
Unless ?fields= is specified:
id, kind, created_at, updated_at, number, status, name, email, barcode_id, barcode, note, event_id, ticket_type_id, event_ticket_type_id, list_id, contact_id, sent_at, dispatched_at, downloaded_at, registered_at, checkin_at, expires_at, source_type, source_id.
sent_at is when the ticket was last emailed to the attendee, or null if it never was. dispatched_at carries the same value and is kept only for existing integrations; use sent_at.
source_type is one of line_item (purchased), rsvp (registered to a free event), or invite (issued via guest list). source_id points at the corresponding record.
Relationships (contact, line_item, event_ticket_type, custom_fields, scans, emails, related_emails, sessions, sent_transfers, received_transfer, links, transfer_link, registration_link, photo) are returned only when listed in ?include=.
List tickets
GET /tickets
List tickets
curl -X GET \
'https://app.guestmanager.com/api/public/v2/tickets?page[cursor]=&page[size]=50' \
-H 'Authorization: Token abcdefg' \
-H 'Content-Type: application/json'
List checked-in tickets for specific events
curl -X GET \
'https://app.guestmanager.com/api/public/v2/tickets?filter[event_ids]=12345&filter[status]=checked_in&include=contact,scans&sort[checkin_at]=desc' \
-H 'Authorization: Token abcdefg' \
-H 'Content-Type: application/json'
Request parameters
| Parameter | Type | Description |
|---|---|---|
page[cursor] |
string |
Opaque cursor token. Send empty for first page. See Pagination. |
page[size] |
integer |
Records per page. Default 10, maximum 100. |
sort[{field}] |
string |
Sort by id, created_at, updated_at, checkin_at, downloaded_at, sent_at. Value is asc or desc. |
fields |
string |
Comma separated list of fields to return. |
include |
string |
Comma separated relationships. See Relationships. |
filter[id] |
string |
Comma separated ticket IDs. |
filter[search] |
string |
Full-text search across attendee name, email, barcode, and order number. Routes through Elasticsearch when available. |
filter[status] |
string |
Comma separated statuses: confirmed, checked_in, checked_out, voided, transferred, pending. See Status filter. |
filter[event_ids] |
string |
Comma separated event IDs. |
filter[list_ids] |
string |
Comma separated list IDs. |
filter[ticket_type_ids] |
string |
Comma separated ticket type IDs. |
filter[kind] |
string |
ticket or pass. |
filter[archived] |
boolean |
true returns only archived tickets, false excludes them. |
filter[photo] |
boolean |
true returns only tickets with an uploaded photo (e.g., for check-in identity verification), false only tickets without one. |
filter[sent] |
boolean |
true returns only tickets that have been emailed (sent_at is set), false only tickets that haven’t. |
filter[expired] |
boolean |
true returns only tickets past their expires_at, false only tickets still valid or with no expiry. |
filter[deleted] |
boolean |
true returns only deleted tickets. Omit (or false) to exclude them. Useful for mirroring deletions on an updated_at cursor. |
filter[created_at][from] |
date |
Tickets created on or after this date. |
filter[created_at][to] |
date |
Tickets created on or before this date. A date with no time covers that whole day. |
Status filter
| Value | Meaning |
|---|---|
confirmed |
Valid and not checked in yet. Most tickets are in this state until scanned. |
checked_in |
Currently checked in (most recent scan was a check-in). |
checked_out |
Was checked in, then checked out. |
voided |
Voided. The barcode is rejected at check-in. |
transferred |
Handed to someone else. The recipient holds a new ticket; see Ticket transfers. |
pending |
Created for an order that hasn’t been confirmed yet. It has no usable barcode. |
Whether a ticket has been emailed or has expired is not a status. Use filter[sent] and filter[expired] for those.
Relationships
| Relationship | Notes |
|---|---|
contact |
The attendee’s contact record. |
line_item |
The order line item that produced this ticket (when purchased). |
line_item.order |
A brief view of the order behind the line item — id, number, and total. The number matches what merchants see in the Shopify admin (e.g. 1004) for Shopify-sourced orders. |
event_ticket_type |
The ticket-type-on-event link, including PDF/wallet template config. |
event_ticket_type.event |
Above plus the event with venue. |
event_ticket_type.ticket_type |
Above plus the underlying ticket type config. |
custom_fields |
Form responses captured against this ticket. |
scans |
Check-in / check-out history for this ticket. Same records as Arrivals, which can be filtered and paged on their own. |
sessions |
Sub-tickets when the ticket is a parent (e.g., a multi-session pass). |
sessions.scans |
Scans of each session ticket — useful for multi-day pass dashboards. |
emails |
Delivery history (sent emails for this ticket). |
related_emails |
Every email that carried this ticket, including order-level receipts that listed it. Detail views only: it is one query per ticket. |
sent_transfers |
Transfers started from this ticket, newest last. See Ticket transfers. |
sent_transfers.recipient |
Above plus the recipient contact on each transfer. |
received_transfer |
The accepted transfer that issued this ticket, or null if it was not created by a transfer. |
received_transfer.recipient |
Above plus the recipient contact (this ticket’s holder at the time of the transfer). |
links |
Includes pdf, wallet and google_wallet download URLs in the response. |
transfer_link |
{ url, blocked_reason }: the URL that starts a transfer of this ticket, or why there is none. See Ticket transfers. |
registration_link |
The buyer-facing page that completes this ticket’s registration. |
photo |
Includes a transformed photo URL (use images[ticket][photo]=...). |
Ticket transfers
A transfer hands a ticket to another person. The recipient accepts by email; on acceptance the app issues them a new ticket and the original changes to transferred. Transfers are only reachable through a ticket, via sent_transfers (the ticket is the source) and received_transfer (the ticket was issued by the transfer).
A transferred ticket with its history and the link state
curl -X GET \
'https://app.guestmanager.com/api/public/v2/tickets/8472134?include=sent_transfers.recipient,received_transfer,transfer_link' \
-H 'Authorization: Token abcdefg' \
-H 'Content-Type: application/json'
{
"id": 8472134,
"status": "transferred",
"sent_transfers": [
{
"id": 651630,
"status": "accepted",
"origin": "manual",
"created_at": "2026-09-04T10:40:30Z",
"updated_at": "2026-09-04T10:41:33Z",
"ticket_id": 8472134,
"replacement_ticket_id": 8472190,
"recipient_id": 9921,
"recipient_name": "Bizzy Bone",
"sender_id": 9880,
"recipient": { "id": 9921, "name": "Bizzy Bone", "email": "bizzy@example.com" }
}
],
"received_transfer": null,
"transfer_link": { "url": null, "blocked_reason": "transferred" }
}
| Field | Description |
|---|---|
status |
pending (waiting on the recipient), accepted, declined, or canceled (by the sender before acceptance). |
origin |
manual (a person started it) or auto (the app started it because the buyer named a companion at checkout). |
ticket_id |
The ticket being transferred. |
replacement_ticket_id |
The ticket issued to the recipient. null until the transfer is accepted. |
recipient_id |
The contact the ticket is going to. recipient is the contact record, returned with .recipient in include. |
recipient_name |
The name the sender gave for this transfer; the ticket issued on acceptance carries it. Can differ from recipient.name when one contact (one email) receives several tickets for different people. Falls back to the contact’s name on transfers that recorded none. |
sender_id |
The contact who held the ticket when the transfer started (the source ticket’s contact). |
transfer_link.url is present only when a transfer can be started right now; otherwise blocked_reason says why. A pending transfer blocks a second one until it is accepted, declined or canceled.
blocked_reason |
Meaning |
|---|---|
transferred |
Already transferred. The link lives on the ticket at replacement_ticket_id. |
pending_transfer |
A transfer is pending on this ticket. |
checked_in, checked_out, voided, pending |
Only confirmed tickets can be transferred. |
event_ended |
The event is over. |
downloaded |
The ticket was downloaded and its ticket type does not allow changes after download. |
not_transferable |
The ticket type does not allow transfers. |
Get ticket
GET /tickets/{id}
curl -X GET \
'https://app.guestmanager.com/api/public/v2/tickets/8472134?include=contact,event_ticket_type.event,scans' \
-H 'Authorization: Token abcdefg' \
-H 'Content-Type: application/json'
Create ticket
POST /tickets
Creates a ticket directly — used for backend issuance (comps, invites, manual additions). Tickets created here have source: backend. Tickets created via the checkout flow are produced from line items and use source: line_item.
Create a comp ticket
curl -X POST \
https://app.guestmanager.com/api/public/v2/tickets \
-H 'Authorization: Token abcdefg' \
-H 'Content-Type: application/json' \
-d '{
"ticket": {
"event_id": 12345,
"ticket_type_id": 2217,
"name": "Jane Doe",
"email": "jane@example.com",
"list_id": 5678,
"dispatch": true
}
}'
Request parameters
You can either pass event_id + ticket_type_id (and the API resolves them to an event_ticket_type_id), or pass event_ticket_type_id directly if you already have it.
A ticket created here has no order line item, so it has no ticket tier: the tier (the product variant a customer bought) comes only from an order. The Ticket column on the Event Ticketing app’s Attendees page and the Tier column in the Guest Manager dashboard stay blank for these tickets. To carry the tier when importing tickets from another system, create a ticket type per tier and pass its ticket_type_id, or store the tier name in a custom field.
Each ticket created here uses 1 credit from the account’s balance, whether or not it’s emailed. If you’re migrating existing bookings from another system, contact support before the import with roughly how many tickets you’re bringing over, and we’ll add a one-time credit to cover it.
A ticket type that’s archived can’t be used: the request returns 422. Unarchive it or choose another ticket type.
| Parameter | Type | Description |
|---|---|---|
ticket[event_id] |
integer |
Event the ticket belongs to. Required if event_ticket_type_id is not provided. |
ticket[ticket_type_id] |
integer |
Ticket type. Required if event_ticket_type_id is not provided. |
ticket[event_ticket_type_id] |
integer |
The pre-resolved event-ticket-type link. Alternative to event_id + ticket_type_id. |
ticket[name] |
string |
Attendee name. |
ticket[email] |
string |
Attendee email. |
ticket[contact_id] |
integer |
Existing contact to attach the ticket to. |
ticket[list_id] |
integer |
Event list to add the ticket to. Defaults to the event’s primary list. |
ticket[permanent_list_id] |
integer |
Permanent list (cross-event) to associate with this ticket. |
ticket[barcode_id] |
integer |
Pre-allocated barcode pool entry. For events using enforce_barcode_pool. |
ticket[barcode] |
string |
Specific barcode value to assign. Use only when intentionally overriding the auto-generated barcode. |
ticket[dispatch] |
boolean |
true to immediately email the ticket on creation. Defaults to false — the ticket is created silently, no email is sent. Use PATCH /tickets/{id}/email to send it later. |
ticket[custom_fields] |
array |
Array of { id?, label, value } form responses. See Custom fields. |
Custom fields
Custom fields capture event-specific responses (e.g., dietary restrictions, t-shirt size). Pass as an array of {label, value} pairs. Labels must be unique within a single ticket.
{
"ticket": {
"event_id": 12345,
"ticket_type_id": 2217,
"name": "Jane Doe",
"custom_fields": [
{ "label": "T-shirt size", "value": "L" },
{ "label": "Dietary", "value": "Vegetarian" }
]
}
}
The API resolves each label to the appropriate question configured on the event. Unknown labels are silently ignored (validate labels client-side before submitting).
Update ticket
PATCH /tickets/{id}
Same field shape as create. Common updates: changing the attendee name/email, adding/updating custom field responses, attaching a barcode.
curl -X PATCH \
https://app.guestmanager.com/api/public/v2/tickets/8472134 \
-H 'Authorization: Token abcdefg' \
-H 'Content-Type: application/json' \
-d '{
"ticket": {
"name": "Jane Smith",
"custom_fields": [
{ "label": "T-shirt size", "value": "M" }
]
}
}'
Moving a ticket to another event
To change a ticket’s date, pass the new event’s event_ticket_type_id (or event_id + ticket_type_id) along with a list_id on that event. Without one, the request returns 422 with “List does not belong to this event.”
These tickets can’t be moved to another event, and the request returns 422 with type invalid_state:
- Tickets that belong to an order. Exchange them on the order instead.
- Tickets in a party, whether the party’s leader or a member.
Moving a ticket doesn’t email the attendee. Use PATCH /tickets/{id}/email to resend it.
Delete ticket
DELETE /tickets/{id}
Soft-deletes (discards) the ticket. Returns 204 No Content. The ticket can be restored from the admin UI; deleted tickets do not appear in GET /tickets unless you pass filter[deleted]=true.
Void ticket
PATCH /tickets/{id}/void
Voids the ticket: the barcode is rejected at check-in and the ticket stays on its order for your records. Voiding does not refund the order and does not release the seat in Shopify. Only tickets with status confirmed, checked_in or checked_out can be voided.
| Parameter | Type | Description |
|---|---|---|
notify |
boolean |
Email the ticket holder that the ticket was voided. Default true. |
reason |
string |
Optional. Stored as a note on the ticket (Voided: <reason>), visible in the Guest Manager dashboard. |
| Status | Meaning |
|---|---|
200 |
Voided. Returns the ticket. |
422 |
type: invalid_state. The ticket is already voided, transferred or pending. |
404 |
The ticket does not exist or was deleted. |
Resend ticket email
PATCH /tickets/{id}/email
Sends the ticket email to the current email address on the ticket. Useful for “I lost my ticket” support flows.
Set ticket photo
PATCH /tickets/{id}/photo
Attaches a photo to the ticket — typically a headshot for identity verification at check-in.
| Parameter | Type | Description |
|---|---|---|
image |
string |
Base64-encoded image data. The server processes via Base64ImageProcessor. |
ticket[photo] |
multipart |
Alternative: send photo as a multipart upload field on the standard update endpoint. |
Check-in operations
The check-in endpoints are designed for high-throughput on-site scanning — typically called by the iOS scanner app or a purpose-built kiosk integration.
Device, station, employee headers
All check-in endpoints accept three optional request headers that attribute the scan:
| Header | Description |
|---|---|
X-Device-Id |
The scanning device’s ID (registered in the company’s device list). |
X-Station-Id |
The check-in station’s ID. |
X-Employee-Id |
The employee performing the scan. |
Including these headers populates the scan record’s audit trail and enables per-station / per-employee reporting.
Check in a ticket
PATCH /tickets/{id_or_barcode}/check_in
Checks in a ticket by ID or by barcode (set ?barcode=true and pass the barcode value as the id segment).
Check in by ID
curl -X PATCH \
https://app.guestmanager.com/api/public/v2/tickets/8472134/check_in \
-H 'Authorization: Token abcdefg' \
-H 'X-Device-Id: 42' \
-H 'X-Station-Id: 7' \
-H 'X-Employee-Id: 99' \
-H 'Content-Type: application/json'
Check in by barcode
curl -X PATCH \
'https://app.guestmanager.com/api/public/v2/tickets/ABC123XYZ/check_in?barcode=true' \
-H 'Authorization: Token abcdefg' \
-H 'X-Device-Id: 42'
Response shape
The response includes the ticket plus a meta block with the scan record, a confirmation message, and (when applicable) the linked Shopify order ID:
{
"data": { /* ticket */ },
"meta": {
"scan": {
"id": 99812,
"action": "checkin",
"successful": true,
"scanned_at": "2026-09-15T20:14:33Z"
},
"shopify_order_id": "gid://shopify/Order/4231887",
"message": "Jane Doe's GA (Standard Entry) to Tasting Tour on September 15, 2026"
}
}
Status codes
| Code | Meaning |
|---|---|
202 |
Successful scan. |
412 |
Scan rejected — ticket voided, expired, already checked in, or barcode unrecognized. Check meta.scan.action. |
If the barcode is unrecognized entirely, the response is 412 with meta.scan.action: "unknown" and no data field.
Check out a ticket
PATCH /tickets/{id_or_barcode}/check_out
Records a check-out scan. Use for events that track re-entry windows.
Undo check-in
DELETE /tickets/{id}/check_in
Reverses the most recent check-in scan. Use for accidental scans.
Bulk check-in
PATCH /tickets/check_in
Checks in many tickets in a single request — useful for “scan a group all at once” workflows.
curl -X PATCH \
https://app.guestmanager.com/api/public/v2/tickets/check_in \
-H 'Authorization: Token abcdefg' \
-H 'X-Device-Id: 42' \
-H 'Content-Type: application/json' \
-d '{ "ids": [8472134, 8472135, 8472136] }'
Response is a collection of tickets plus a meta.scans array with one scan record per ticket.
Bulk operations
Bulk email
PATCH /tickets/bulk_email
Sends a custom email to many ticket holders in one call. Backed by an Email::CompanyEmail::TicketMultipleEmail job; the response returns the email job record.
| Parameter | Type | Description |
|---|---|---|
ids |
array |
Array (or comma separated string) of ticket IDs. |
email_template_id |
integer |
Required. The email template to use. |
subject |
string |
Override the template subject. |
body |
string |
Optional body override (rich text / HTML). |
email |
string |
Override the recipient email (defaults to each ticket’s email). |