Skip to content

Get ticket usages

GET{{API_BASE_URL}}/ticketinghub/odata/v1/TicketUsages?$select=TicketActionInternalId,TicketInternalId,Timestamp,IsEntry,IsFirstOfDay,Entrance

One row per scan. This is where the gap between sold and attended becomes measurable, and it is the dataset that makes entrance and staffing analysis possible.

Grain and key

Grainone row per scan event
Natural keyMandatorInternalId, TicketActionInternalId
Page size1000
Columns119
WatermarkLastRefreshedAt — incremental loading possible

The columns most extracts start with

ColumnTypeNotes
TicketActionInternalIdintKey.
TicketInternalIdintJoin key back to Tickets.
TimestampdatetimeoffsetWhen the scan happened. Offset-aware.
TypestringThe kind of action. Pass-through — read the distinct values from your data.
IsEntry / IsExitboolDirection through the door.
IsFirstOfDayboolFirst scan that day — the basis for daily unique attendance.
IsFirstOfFaireventboolFirst scan of the whole event — first-time arrival.
EntrancestringWhich door.
EntranceTerminalNamestringWhich device.
LocationNamestringWhich location.
UsedTicketMediumstringPrint, mobile, wallet. Pass-through.
IsOfflineboolCaptured offline and synced later.
LastRefreshedAtdatetimeWatermark. No offset — do not convert.

A slice of ticket, article and event columns is repeated here, so common questions can be answered without joining back. Those repeated status columns carry the same tokens as on Tickets — see Column values.

Traps specific to this dataset

  • Rows are scans, not people. A visitor attending three days produces at least three rows. Count distinct TicketInternalId when you mean people, and use IsFirstOfDay for daily unique attendance.
  • Zero usages is normal and meaningful. A sold ticket that was never used has no row here at all. An inner join to Tickets silently drops exactly the population you need for no-show analysis — use a left join.
  • Exits count too. If you want arrivals, filter IsEntry eq true; otherwise a visitor who left and returned inflates your figure.
  • Offline scans arrive late. IsOffline rows are captured on the device and synced afterwards, so a very recent incremental load can miss them. They arrive with a later LastRefreshedAt, so a watermark load does pick them up eventually.

What this dataset makes possible

  • No-show rate — tickets with no usage, over tickets sold.
  • Daily attendance — distinct tickets with IsFirstOfDay eq true, per day.
  • Entrance load over time — count by Entrance and hour, which is where queueing and staffing decisions come from.
  • Repeat visit behaviour — usages per ticket across the event days.
  • Medium adoption — how many actually used the mobile ticket you built.

Recipes shows the queries.

Joining

Join to Tickets on MandatorInternalId, TicketInternalId. One ticket, many usages.


Request

No request body.

  • $select(string): the columns to load.
  • $filter(string): an OData predicate. This dataset carries LastRefreshedAt, so it can be loaded incrementally.
  • $orderby(string): sort order.
  • $top(integer): maximum rows, capped at 1000.
  • $count(boolean): include the total count.
  • $skiptoken(string): server-generated paging token.

Response

  • @odata.context (string): the metadata URL describing this payload.
  • value (array): the page of usage rows.
  • @odata.nextLink (string, optional): the next page; absent on the last one.
  • @odata.count (integer, optional): present only when $count=true.

Counting correctly

Rows are scans, not people. A visitor attending three days and stepping out for lunch produces many rows, and a ticket that was never used has no row here at all. Count distinct TicketInternalId for people, use IsFirstOfDay for daily unique attendance, and left-join from Tickets when you are measuring no-shows.

See Recipes for the worked queries.

Notes

Page size is 1000. This is the fastest-growing dataset during an event, which makes it the best candidate for watermark-based incremental loading.

Type and UsedTicketMedium are pass-through columns — their value sets come from the source system rather than from a fixed list, so read the distinct values from your own extract. See Datasets → Column values.

Authentication#auth

This endpoint does not require authentication.

Headers#headers

AuthorizationBearer {{ACCESS_TOKEN}}

Required. A client-credentials token carrying the scope ticketinghub-api and no subject. See Authentication.

Acceptapplication/json

Optional. JSON is returned by default.

Query parameters#query

$selectTicketActionInternalId,TicketInternalId,Timestamp,IsEntry,IsFirstOfDay,Entranceoptional

Comma-separated list of columns to load. Timestamp, Entrance and EntranceTerminalName are what entrance-load analysis needs; IsFirstOfDay is the basis for daily unique attendance.

$filterLastRefreshedAt gt 2026-01-01T00:00:00Zoptional

OData predicate. This dataset exposes LastRefreshedAt, so a watermark filter gives you an incremental load. Filter IsEntry eq true when you want arrivals rather than every movement through a door.

$orderbyTimestampoptional

Sort order. Note that it also changes the order the keyset walk runs in.

$top1000optional

Maximum number of rows. Capped at 1000; a higher value is rejected with 400.

$counttrueoptional

Include the total row count in @odata.count. Note this counts scans, not visitors. Scans the whole dataset; ask once per load.

$skiptokenoptional

Server-generated keyset paging token, carried in @odata.nextLink. Treat it as opaque.

$skipoptional

Offset paging. Supported but discouraged — use @odata.nextLink instead.

Responses#responses

200OKGet ticket usages
401UnauthorizedGet ticket usages (401 – expired token)