BillyDocumentation

Filtering

Narrow list results with range, multi-value and tag filters.

🔍 Learn how to narrow down list results using query parameters on Billy's API.

List endpoints support filtering through query parameters. This page describes the filtering syntax and how to combine filters with pagination. For the exact set of filters a given endpoint accepts, see its query parameters in the API sandbox.

🔄 Filters always operate on fields that are present in the response payload — so the value you filtered on appears on every returned item. For example, filtering events by startAt returns events whose sessions expose a startAt, and filtering orders by status returns orders that carry a status field. This lets you verify each result against your filter criteria client-side. Two groups of filters depart from this — ones that also narrow what each item carries, and one that filters on a field not every item reports. Both are listed below.

Range filters

Some fields support range filtering using dot-notation suffixes, following Stripe's convention. Each suffix maps to a comparison operator:

SuffixOperatorMeaning
.gtStrictly greater thanReturn results where the field is strictly after (or greater than) the value.
.gteGreater than or equalReturn results where the field is at or after (or greater than or equal to) the value.
.ltStrictly less thanReturn results where the field is strictly before (or less than) the value.
.lteLess than or equalReturn results where the field is at or before (or less than or equal to) the value.

For example, updatedAt.gte returns results updated at or after the given value, while updatedAt.lt returns results updated strictly before it.

🕒 Datetime format — For datetime fields, use ISO 8601 format with a timezone offset. Example: 2026-03-01T00:00:00+02:00. Always include an offset to avoid ambiguity.

Only a subset of operators is exposed per field. Suffixes not exposed for a given field are ignored.

Multi-value filters

Some fields accept multiple values as a comma-separated list. Values are combined with OR semantics — a result matches if it equals any of the supplied values. Each list is limited to 10 values.

This pattern is already in use today: eventIds and sessionIds on the orders and tickets endpoints both accept comma-separated IDs, qrCodes on the tickets endpoint accepts comma-separated QR codes (the value reported as qrCode, matched exactly), and tags on the events endpoint accepts comma-separated tags (see Filtering by tags).

?eventIds=331704d8-50bf-4e99-8d82-95c4974bxxxx,168c36ec-2e28-4312-be93-8893f0ccxxxx

Filters that narrow what an item carries

Most filters only decide which items come back. A few also narrow what those items carry, and a response to one of them is a partial view of the resource rather than the resource itself.

EndpointFilterWhat it narrows
GET /catalog/offersresaleEnabledSelects offers with at least one matching pricing, and returns each of them carrying only those pricings.
GET /catalog/offerssessionIdLeaves the list of offers unchanged, and narrows inventory on ticket offers to that session.

Do not cache a filtered response as the resource

The same offerId has different contents depending on the query. An integrator who caches GET /catalog/offers?resaleEnabled=true as the offer's pricing list will conclude that its non-resellable pricings do not exist.

The single-resource route takes no filter and is always the complete view:

curl "https://platform.billyapp.live/v1/catalog/offers/331704d8-50bf-4e99-8d82-95c4974bxxxx" \
  -H "Authorization: Bearer billy:o:yyyyyyyyyyyyyyyy:xxxxxxxxxxxxxxxxx" \
  -H "Billy-API-Version: preview"

Filters on a field an item may not report

One filter narrows on something the returned item does not echo back, so you cannot verify those results client-side.

EndpointFilterWhy
GET /catalog/offerseventIdSelects everything the event currently holds. Only a TICKET offer reports eventId; a PRODUCT or a BUNDLE comes back without it.

Products are attached to an event today, but that is where the storage puts them rather than a promise — merchandise is planned to move to the organization. Rather than publish an eventId on products that will stop being true, the field is reported only where it is part of what the offer is: a ticket admits to an event. The filter keeps working on all three types meanwhile, so ?eventId= remains the way to pull one event's whole catalogue.

Negation

Some fields support negation through the .ne suffix, returning results that do not match the given value. As with multi-value filters, .ne accepts a comma-separated list (max 10) and excludes results matching any of the listed values.

For example, tags.ne=sport,football returns results tagged with neither sport nor football.

🚧 Planned — The .ne suffix is not yet available on any field. tags (see below) is expected to be the first field to support it, and it may be extended to other fields later.

Examples

Filter by a date range

Bound a datetime field on both sides to get a time window. This returns events with at least one session starting within March 2026:

curl "https://platform.billyapp.live/v1/events?startAt.gte=2026-03-01T00:00:00%2B02:00&startAt.lte=2026-03-31T23:59:59%2B02:00" \
  -H "Authorization: Bearer billy:o:1234567891234567:xxxxxxxxxxxxxxxxx"

Filter by an exact value

Some fields accept a single value. This returns only fulfilled orders:

curl "https://platform.billyapp.live/v1/orders?status=FULFILLED" \
  -H "Authorization: Bearer billy:o:1234567891234567:xxxxxxxxxxxxxxxxx"

The email filter on orders works the same way, matching the customer's email (reported as customer.email) exactly but regardless of case:

curl "https://platform.billyapp.live/v1/orders?email=alice.martin%40example.com" \
  -H "Authorization: Bearer billy:o:1234567891234567:xxxxxxxxxxxxxxxxx"

Filter by multiple values

Multi-value filters scope results to specific resources. This returns tickets belonging to either of two events:

curl "https://platform.billyapp.live/v1/tickets?eventIds=331704d8-50bf-4e99-8d82-95c4974bxxxx,168c36ec-2e28-4312-be93-8893f0ccxxxx" \
  -H "Authorization: Bearer billy:o:1234567891234567:xxxxxxxxxxxxxxxxx"

Filtering by tags

The events endpoint supports filtering by tags, following the multi-value convention described above:

ParameterExampleBehavior
tagstags=sport,footballReturn events having any of the given tags (OR semantics, max 10).

Tag matching is normalization-aware: values are compared case-insensitively, with surrounding and repeated whitespace collapsed, and accents preserved (CaféCafe). tags=Rap%20Music therefore matches events tagged rap music. Matching is scoped to your organization's tags.

curl "https://platform.billyapp.live/v1/events?tags=rap%20music,jazz" \
  -H "Authorization: Bearer billy:o:1234567891234567:xxxxxxxxxxxxxxxxx"

An empty tag value (tags= or a stray comma, e.g. tags=sport,) returns a 400 Bad Request.

🚧 Planned — Negation (tags.ne=sport, see Negation) is not available yet. Once released, both will compose: tags=sport,football&tags.ne=indoor will return sport-or-football events that are not also tagged indoor.

Combining filters

Multiple filters are combined with AND semantics — only results matching every supplied filter are returned. Range, multi-value, and negation filters compose freely with each other and with pagination parameters (page, perPage).

When both bounds of a range are supplied (e.g. updatedAt.gte and updatedAt.lte), the result is the inclusive window between them.

curl "https://platform.billyapp.live/v1/orders?status=FULFILLED&updatedAt.gte=2026-01-01T00:00:00%2B00:00&updatedAt.lte=2026-01-31T23:59:59%2B00:00&page=1&perPage=50" \
  -H "Authorization: Bearer billy:o:1234567891234567:xxxxxxxxxxxxxxxxx"

Validation errors

Invalid filter values return a 400 Bad Request with a JSON body describing the problem:

{
  "detail": "Invalid request parameters",
  "errors": [
    {
      "loc": "query.status",
      "input": "PAID",
      "ctx": "Invalid status. Expected one of ('PENDING', 'FULFILLED', 'CANCELLED')"
    }
  ]
}

Common validation errors include an invalid status value, more than 10 values in a multi-value list (eventIds, sessionIds, qrCodes, tags), an empty tag value, and malformed datetimes.

ℹ️ When a requested page is out of range, the API returns a 204 No Content with an empty body — see Pagination.

On this page