Skip to content

Get tickets

GET{{API_BASE_URL}}/ticketinghub/odata/v1/Tickets?$select=TicketInternalId,FaireventName,ArticleName,ArticleType,TicketGrossPrice,CurrencyShort,SalePaymentStatus,SaleIsTest

One row per owned ticket. The wide, denormalised centre of the model — event, article, sale, buyer and holder all flattened onto each row.

If you load only one dataset, load this one. Most business questions are answerable from it without any join.

Grain and key

Grainone row per ticket
Natural keyMandatorInternalId, TicketInternalId
Page size500
Columns342
Watermarknone — full reload only

The columns most extracts start with

A workable first projection. The families are mapped in Reading the columns, the token sets in Column values.

Identity

ColumnTypeNotes
TicketInternalIdintKey. Join target for usages and surveys.
TicketUniqueIdGuidStable global reference.
TicketNumberstringThe number printed on the ticket.

Status and lifecycle

ColumnTypeNotes
TicketIsCancelledboolUse this for cancellations, not the status column.
TicketStatusTypetokenNONE, FREE, ASSIGNED, BLOCKED, UNKNOWN.
TicketValiditytokenNONE, ONE_DAY, MULTIPLE_DAYS, ALL_DAYS.
TicketIsDayTicket / TicketIsPermanentTicketboolValidity shape as flags.
TicketSoldAt / TicketUsedAtdatetimeoffsetOffset-aware; safe to convert.

Money

ColumnTypeNotes
TicketGrossPricedecimalThe default for revenue questions.
TicketNetPricedecimalOnly when net was explicitly asked for.
CurrencyShortstringAlways carry this alongside any amount.
SalePaymentStatustokenPAID is the honest filter for paid revenue.

Event and article

ColumnTypeNotes
FaireventInternalIdintBest key for splitting large extracts.
FaireventName / FaireventYearstring / intFilter these two separately.
FairBrandNamestringFor year-over-year comparison.
ArticleInternalId / ArticleNameint / stringJoin key to StatisticGroups; main segmentation dimension.
ArticleTypetokenFilter eq 'TICKET' when counting tickets sold.

Who and how it was issued

ColumnTypeNotes
TicketOwner*variousThe person who attends.
Buyer*variousThe person who paid.
TicketIsIssuedByOrganizerboolOrganiser route.
TicketIsIssuedByExhibitorboolExhibitor quota route.
SaleDistributionChainTypetokenSales channel.
Exhibitor*variousWhich exhibitor issued it.

Marketing

ColumnTypeNotes
SaleIsTestboolFilter eq false unless you want test sales.
SaleUtm*stringCampaign attribution, five columns.
PromotionCode*stringDiscount or access code applied.

Traps specific to this dataset

  • Several currencies live in one column. EUR, USD, CHF, QAR and null all occur. Never add amounts across them; group by CurrencyShort.
  • Not every row is a ticket. ArticleType also covers vouchers, service fees and functional features. Filter it when you mean tickets.
  • Buyer is not owner. See People: buyer, holder, exhibitor.
  • Organiser and exhibitor tickets are different populations. Averaging them together distorts every conversion figure.
  • 107 of the columns are your own custom fields with generic labels. See Reading the columns.
  • No per-ticket attendance flag. Attendance reporting goes through StatisticGroups — see Counting visitors.
  • No watermark. Incremental loading is not possible; a nightly full reload is the practical answer.

Joining

ToOnGrain effect
TicketUsagesMandatorInternalId, TicketInternalIdone to many
SurveysMandatorInternalId, TicketInternalIdone to many
StatisticGroupsMandatorInternalId, ArticleInternalIdone to many

Full column catalogue

GET /odata/v1/$metadata — every column with its type, nullability and business label.


Request

No request body. All shaping is done with the query options below.

  • $select(string): the columns to load. A full row is 342 columns and ~10 KB — name what you need.
  • $filter(string): an OData predicate. Start with SaleIsTest eq false.
  • $orderby(string): sort order.
  • $top(integer): maximum rows, capped at 1000.
  • $count(boolean): include the total count. Scans the whole dataset.
  • $skiptoken(string): server-generated paging token. Follow the next link rather than setting this.

Response

  • @odata.context (string): the metadata URL describing the shape of this payload.
  • value (array): the page of ticket rows. Which columns appear depends on $select.
  • @odata.nextLink (string, optional): the next page. Absent on the last page — that is your signal to stop.
  • @odata.count (integer, optional): present only when $count=true.

Before you aggregate what comes back

Three things will otherwise give you wrong numbers, all covered in Getting the numbers right: several currencies live in CurrencyShort, test sales are present in production data, and not every row is a ticketArticleType also covers vouchers, catalogues and service fees.

Notes

Page size is 500. There is no by-key form of this endpoint — Tickets(...) answers 404 by design.

Status columns such as ArticleType and SalePaymentStatus carry UPPER_SNAKE_CASE tokens from a closed set — Datasets → Column values lists every one. 107 of the 342 columns are your own custom registration fields with generic labels; see Reading the columns.

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

$selectTicketInternalId,FaireventName,ArticleName,ArticleType,TicketGrossPrice,CurrencyShort,SalePaymentStatus,SaleIsTestoptional

Comma-separated list of columns to load. The single biggest lever on extract time: a full row is 342 columns and roughly 10 KB, and projecting down also lets the database skip work. Carry CurrencyShort whenever you carry an amount.

$filterSaleIsTest eq false and ArticleType eq 'TICKET'optional

OData predicate. Token values are uppercase and case-sensitive — eq 'TICKET' works, eq 'ticket' matches nothing. Worth knowing: SaleIsTest eq false excludes test sales, ArticleType eq 'TICKET' keeps vouchers and service fees out of a ticket count, and FaireventInternalId eq <id> splits a very large extract into chunks that parallelise.

$orderbyTicketInternalIdoptional

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. A smaller value lowers the page size but cannot raise it above 500.

$counttrueoptional

Include the total row count in @odata.count. Useful once per load to size the job; it scans the whole dataset, so do not ask for it on every page.

$skiptokenoptional

Server-generated keyset paging token, carried in @odata.nextLink. Treat it as opaque and follow the link; hand-crafting one is unsupported.

$skipoptional

Offset paging. Supported but discouraged: cost grows with depth, and rows written while you read can be skipped or repeated. Use @odata.nextLink instead.

Responses#responses

200OKGet tickets
200OKGet tickets (last page, no next link)
400Bad RequestGet tickets (400 – unknown column)
403ForbiddenGet tickets (403 – user token)