Transfer a ticket
Hands a ticket to whoever bought it on a resale marketplace. The ticket keeps its `ticketId` — nothing is voided and nothing is re-issued — but its `qrCode` is regenerated, so the seller's code stops opening the door the moment this returns. Billy sends no email: the response carries the new code, and delivering it to the new holder is yours to do. `attendee` is optional. Sent, it also changes the holder — whether or not the offer collects attendee details of its own; left out, only the code rotates. The response carries the holder as the ticket now has them. `attendee` carries the person's own details only — no `additionalFields`, and unknown keys are rejected with a 400. A resale marketplace knows who bought the ticket; it has no way to have asked the organizer's own questions, and an answer it invented would reach the attendance list as though the buyer had given it. Those questions stay unanswered until the buyer answers them, and the details sent here are accepted as the partial picture they are — there is no form here for them to fail. **This endpoint is not idempotent, and there is no `Idempotency-Key`.** Every call rotates the code afresh, so calling it twice retires the code the first call returned. Retry a request whose response you never saw — a timeout, a dropped connection — and the code you already delivered to the new holder stops scanning, silently, with nothing to tell you until they are refused at the door. Treat a transfer whose outcome you are unsure of as a read: fetch the ticket and compare its `qrCode` before sending anything.
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. The playground below sends a real POST request to the live API with your own key, and will create or modify actual data.Hands a ticket to whoever bought it on a resale marketplace. The ticket keeps its ticketId — nothing is voided and nothing is re-issued — but its qrCode is regenerated, so the seller's code stops opening the door the moment this returns. Billy sends no email: the response carries the new code, and delivering it to the new holder is yours to do.
attendee is optional. Sent, it also changes the holder — whether or not the offer collects attendee details of its own; left out, only the code rotates. The response carries the holder as the ticket now has them.
attendee carries the person's own details only — no additionalFields, and unknown keys are rejected with a 400. A resale marketplace knows who bought the ticket; it has no way to have asked the organizer's own questions, and an answer it invented would reach the attendance list as though the buyer had given it. Those questions stay unanswered until the buyer answers them, and the details sent here are accepted as the partial picture they are — there is no form here for them to fail.
This endpoint is not idempotent, and there is no Idempotency-Key. Every call rotates the code afresh, so calling it twice retires the code the first call returned. Retry a request whose response you never saw — a timeout, a dropped connection — and the code you already delivered to the new holder stops scanning, silently, with nothing to tell you until they are refused at the door. Treat a transfer whose outcome you are unsure of as a read: fetch the ticket and compare its qrCode before sending anything.
Authorization
HTTPBearer API key authentication. Format: Bearer billy:o:<organization_id>:<api_key>
Example: Bearer billy:o:yyyyyyyyyyyyyyyy:xxxxxxxxxxxxxxxxx
In: header
Path Parameters
Header Parameters
Requested API version. Current context: preview.
"preview"Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Request body for POST /v1/tickets/{ticket_id}/transfer.
attendee is optional: left out, the transfer rotates the code and leaves the holder as they
were. The body itself may therefore be {}.
Response Body
application/json
application/json
application/json
curl -X POST "https://example.com/v1/tickets/string/transfer" \ -H "Billy-API-Version: preview" \ -H "Content-Type: application/json" \ -d '{}'{ "ticketId": "a385b297-a4d0-47fd-ab18-dd5bb56eebc3", "eventId": "34280fd9-3f2f-4831-90ec-d76ac0cb7c8b", "invoiceReference": "FR12345678901", "status": "FULFILLED", "offerId": "a9e51970-77db-4439-b1d8-7432203e04a2", "offerName": "VIP", "issuedAt": "2025-02-10T14:22:05.000Z", "updatedAt": "2025-02-10T14:22:05.000Z", "cancelledAt": null, "eventSessionId": "6095dfdb-aa90-4d18-b0cb-3f9ef4b82238", "eventSessionStartAt": "2025-03-21T19:30:00.000Z", "seatingInfo": { "blocName": "Bloc A", "seatRow": "B", "seatNumber": "12" }, "qrCode": "TCKT-9F2K-77QX", "issuanceChannel": "ONLINE_EVENT_SHOP", "salesChannelName": "Default online store", "salesChannelId": "5ad8d09e-c789-49e6-a8f8-1434f880beeb", "orderId": "b2c8c0d4-1f2e-4a3b-9c6d-2e7f1a8b3c4d", "orderNumber": "QASQTFGU", "priceLabel": "PLEIN TARIF", "listPrice": 120, "finalPaidPrice": 100, "vat": 20, "currency": "EUR", "transferable": true, "customer": { "customerId": "eecedea0-e9ed-44d9-9fbf-6cc24a2b2bf4", "firstName": "Claire", "lastName": "Dupont", "email": "claire.dupont@email.com", "phone": "+33612345678", "birthDate": "1990-05-17", "address": { "companyName": null, "addressLine1": "12 rue de la Paix", "addressLine2": null, "city": "Paris", "postalCode": "75001", "countryCode": "FR" }, "additionalFields": [ { "name": "tshirt-size", "type": "SINGLE_SELECT", "value": "L" }, { "name": "dietary", "type": "MULTI_SELECT", "value": [ "vegetarian" ] } ] }, "attendeeForm": { "formId": "frm_01BCDEFGHIJKLMNO", "formVersion": 4, "submittedAt": "2025-02-11T09:03:12.000Z" }, "customerForm": { "formId": "frm_01ABCDEFGHIJKLMN", "formVersion": 2, "submittedAt": "2025-02-10T14:22:05.000Z" }, "attendee": { "firstName": "Alice", "lastName": "Martin", "email": "alice.martin@email.com", "phone": null, "birthDate": null, "address": null, "additionalFields": [] }}