List offers
Retrieves a paginated list of the offers belonging to your Billy organization, in creation order, with their pricings and their stock lines. An offer is a `TICKET`, a `PRODUCT` or a `BUNDLE` of other offers; `type` discriminates the three shapes. The `offerId` and `pricingId` returned here are exactly the ones carried by `GET /tickets`, which is what makes a ticket resolvable against this catalog. **`?resaleEnabled=` returns a partial view.** It selects offers *and* prunes their `pricing[]`: a matching offer comes back carrying only the pricings that matched, so the same `offerId` has different contents depending on the query. Do not cache a filtered response as the offer's pricing list — a consumer that does will conclude the student pricing does not exist. `GET /catalog/offers/{offerId}` takes no filter and is the complete view. **Options.** A `TICKET` offer lists in `optionOffers` the offers proposed as options with its tickets, each with the pricing it is sold at there. That pricing is an ordinary entry of the option offer's `pricing[]`, but it is sold only under that base ticket, on the base ticket's session — never on its own. An offer whose own pricings (`bundleOfferId: null`) are all cited is therefore sold only as an option. The rule reads one way only: an own pricing no pair cites is not proof of a standalone price, since the option pricing of an offer that is, for now, no base ticket's option is cited by no pair either. The pairs sit on the base tickets, so read the whole event (`?eventId=`) to know whether a pricing is cited.
Preview release
preview release target — send Billy-API-Version: preview to reach it. Preview has no stability promise: its routes and payloads can change without notice, so pin a dated release before you depend on one.Retrieves a paginated list of the offers belonging to your Billy organization, in creation order, with their pricings and their stock lines. An offer is a TICKET, a PRODUCT or a BUNDLE of other offers; type discriminates the three shapes. The offerId and pricingId returned here are exactly the ones carried by GET /tickets, which is what makes a ticket resolvable against this catalog.
?resaleEnabled= returns a partial view. It selects offers and prunes their pricing[]: a matching offer comes back carrying only the pricings that matched, so the same offerId has different contents depending on the query. Do not cache a filtered response as the offer's pricing list — a consumer that does will conclude the student pricing does not exist. GET /catalog/offers/{offerId} takes no filter and is the complete view.
Options. A TICKET offer lists in optionOffers the offers proposed as options with its tickets, each with the pricing it is sold at there. That pricing is an ordinary entry of the option offer's pricing[], but it is sold only under that base ticket, on the base ticket's session — never on its own. An offer whose own pricings (bundleOfferId: null) are all cited is therefore sold only as an option. The rule reads one way only: an own pricing no pair cites is not proof of a standalone price, since the option pricing of an offer that is, for now, no base ticket's option is cited by no pair either. The pairs sit on the base tickets, so read the whole event (?eventId=) to know whether a pricing is cited.
Authorization
HTTPBearer API key authentication. Format: Bearer billy:o:<organization_id>:<api_key>
Example: Bearer billy:o:yyyyyyyyyyyyyyyy:xxxxxxxxxxxxxxxxx
In: header
Query Parameters
Page index (1-based, e.g., 1 for first page, 2 for second page)
1 <= value1Maximum number of records to return
Return results where createdAt is at or after this value. For datetime fields, use ISO 8601 format with timezone offset (e.g. 2026-03-01T00:00:00+02:00).
Return results where createdAt is at or before this value. For datetime fields, use ISO 8601 format with timezone offset (e.g. 2026-03-01T00:00:00+02:00).
Return only the offers of this event — tickets, and the products and bundles the event currently holds. Only a TICKET reports the eventId back, so a filtered PRODUCT or BUNDLE cannot be checked against this value from its payload; that is deliberate, since their event scoping is a storage fact today rather than a promise.
Narrow inventory[] on ticket offers to this session. Does not remove offers from the list.
Return only offers of this type. type=BUNDLE is the bundles-only list.
Select offers and prune their pricing[]: an offer is returned when at least one of its pricings matches, carrying only those pricings. Since resaleEnabled exists only on the pricings of a TICKET offer, this filter never returns a PRODUCT or a BUNDLE, whatever value is passed.
Header Parameters
Requested API version. Current context: preview.
"preview"Response Body
application/json
application/json
application/json
application/json
application/json
curl -X GET "https://example.com/v1/catalog/offers" \ -H "Billy-API-Version: preview"{ "items": [ { "offerId": "331704d8-50bf-4e99-8d82-95c4974b1a2b", "type": "TICKET", "name": "Pass 2 jours", "description": "<p>Accès aux deux journées</p>", "eventId": "168c36ec-2e28-4312-be93-8893f0cc4d5e", "currency": "EUR", "images": [], "tags": [ "pass" ], "minQuantityPerOrder": 1, "maxQuantityPerOrder": 10, "compareAtPrice": 55, "createdAt": "2026-08-01T10:00:00+00:00", "vatRate": 0.2, "defaultMaximumCapacity": 500, "attendeeFormId": "5d6e7f80-9a0b-4c1d-8e2f-3a4b5c6d7e8f", "pricing": [ { "pricingId": "9f2c1b44-77aa-4f10-9c3e-0d1b2e3f4a5b", "name": "Tarif plein", "price": 45, "bundleOfferId": null, "resaleEnabled": true }, { "pricingId": "b3e7d901-1c22-4a55-8f6d-7e8f9a0b1c2d", "name": "Tarif étudiant", "price": 32, "bundleOfferId": null, "resaleEnabled": false }, { "pricingId": "c4f8ea12-2d33-4b66-9a7e-8f9a0b1c2d3e", "name": "Pass festival 3 dates", "price": 36, "bundleOfferId": "7a1b2c3d-4e5f-4061-8172-93a4b5c6d7e8", "resaleEnabled": true } ], "optionOffers": [ { "offerId": "4c5d6e7f-8091-4a2b-b3c4-d5e6f7a8b9c0", "pricingId": "5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9" } ], "inventory": [ { "inventoryId": "e1f2a3b4-c5d6-4e7f-8091-a2b3c4d5e6f7", "sessionId": "11223344-5566-4778-899a-bbccddeeff00", "totalStock": 500, "availableStock": 412 } ] }, { "offerId": "2b3c4d5e-6f70-4812-9345-56789abcdef0", "type": "PRODUCT", "name": "T-shirt officiel", "description": "Coton bio, sérigraphie", "currency": "EUR", "images": [ "https://cdn.billyapp.live/tshirt.png" ], "tags": [ "merch" ], "minQuantityPerOrder": 1, "maxQuantityPerOrder": 5, "compareAtPrice": null, "createdAt": "2026-08-02T08:00:00+00:00", "vatRate": 0.2, "defaultQuantity": 100, "variantOptionLabels": { "option1": "Taille", "option2": "Couleur", "option3": null }, "pricing": [ { "pricingId": "8c9d0e1f-2a3b-4c5d-8e6f-7a8b9c0d1e2f", "name": "Prix boutique", "price": 25, "bundleOfferId": null } ], "inventory": [ { "inventoryId": "3d4e5f60-7182-4939-a4b5-c6d7e8f90a1b", "option1": "M", "option2": "Noir", "option3": null, "totalStock": 100, "availableStock": 73, "weightInGrams": 180 } ] }, { "offerId": "7a1b2c3d-4e5f-4061-8172-93a4b5c6d7e8", "type": "BUNDLE", "name": "Pass festival 3 dates", "description": null, "currency": "EUR", "images": [], "tags": [], "minQuantityPerOrder": 1, "maxQuantityPerOrder": 4, "compareAtPrice": 135, "createdAt": "2026-08-02T09:12:00+00:00", "pricingId": "c4f8ea12-2d33-4b66-9a7e-8f9a0b1c2d3e", "price": 108, "contains": [ { "offerId": "331704d8-50bf-4e99-8d82-95c4974b1a2b", "quantity": 3, "price": 36 } ] }, { "offerId": "4c5d6e7f-8091-4a2b-b3c4-d5e6f7a8b9c0", "type": "TICKET", "name": "Place accompagnant", "description": null, "eventId": "168c36ec-2e28-4312-be93-8893f0cc4d5e", "currency": "EUR", "images": [], "tags": [], "minQuantityPerOrder": 0, "maxQuantityPerOrder": 4, "compareAtPrice": null, "createdAt": "2026-08-02T10:30:00+00:00", "vatRate": 0.2, "defaultMaximumCapacity": 50, "attendeeFormId": null, "pricing": [ { "pricingId": "5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9", "name": "Tarif accompagnant", "price": 6, "bundleOfferId": null, "resaleEnabled": false } ], "optionOffers": [], "inventory": [ { "inventoryId": "6f7a8b9c-0d1e-4f2a-b3c4-d5e6f7a8b9c0", "sessionId": "11223344-5566-4778-899a-bbccddeeff00", "totalStock": 50, "availableStock": 38 } ] } ], "page": 1, "perPage": 100, "totalPages": 1, "hasMore": false, "nextPage": null}