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.
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.
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 } ], "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 } ] } ], "page": 1, "perPage": 100, "totalPages": 1, "hasMore": false, "nextPage": null}