curl --request POST \
--url https://api.letsdothis.com/v0/bookings/import \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"bookings": [
{
"externalBookingId": "<string>",
"ticketId": "<string>",
"participants": [
{
"fields": [
{
"fieldId": "<string>",
"value": "<string>",
"values": [
{
"value": "<string>",
"id": "<string>"
}
]
}
],
"status": {
"type": "CONFIRMED"
}
}
],
"idempotencyKey": "<string>",
"externalOrderId": "<string>",
"bookingFormId": "<string>",
"bookedAt": "2026-05-08T11:30:00.000Z",
"bookerFields": [
{
"fieldId": "<string>",
"value": "<string>",
"values": [
{
"value": "<string>",
"id": "<string>"
}
]
}
],
"status": {
"type": "CONFIRMED"
}
}
]
}
'const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
bookings: [
{
externalBookingId: '<string>',
ticketId: '<string>',
participants: [
{
fields: [
{
fieldId: '<string>',
value: '<string>',
values: [{value: '<string>', id: '<string>'}]
}
],
status: {type: 'CONFIRMED'}
}
],
idempotencyKey: '<string>',
externalOrderId: '<string>',
bookingFormId: '<string>',
bookedAt: '2026-05-08T11:30:00.000Z',
bookerFields: [
{
fieldId: '<string>',
value: '<string>',
values: [{value: '<string>', id: '<string>'}]
}
],
status: {type: 'CONFIRMED'}
}
]
})
};
fetch('https://api.letsdothis.com/v0/bookings/import', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.letsdothis.com/v0/bookings/import"
payload = { "bookings": [
{
"externalBookingId": "<string>",
"ticketId": "<string>",
"participants": [
{
"fields": [
{
"fieldId": "<string>",
"value": "<string>",
"values": [
{
"value": "<string>",
"id": "<string>"
}
]
}
],
"status": { "type": "CONFIRMED" }
}
],
"idempotencyKey": "<string>",
"externalOrderId": "<string>",
"bookingFormId": "<string>",
"bookedAt": "2026-05-08T11:30:00.000Z",
"bookerFields": [
{
"fieldId": "<string>",
"value": "<string>",
"values": [
{
"value": "<string>",
"id": "<string>"
}
]
}
],
"status": { "type": "CONFIRMED" }
}
] }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text){
"jobId": "65d4e5f60718293a4b5c6d7e",
"status": "queued"
}{
"statusCode": 400,
"error": "<string>",
"message": "<string>"
}{
"statusCode": 409,
"error": "<string>",
"message": "<string>"
}{
"statusCode": 413,
"error": "<string>",
"message": "<string>"
}{
"error": "validation_failed",
"message": "<string>",
"totalRows": 123,
"rowsWithErrors": 123,
"errorCount": 123,
"summary": [
{
"code": "<string>",
"count": 123,
"message": "<string>",
"examples": [
{
"rowIndex": 123,
"externalBookingId": "<string>",
"participantIndex": 123,
"value": "<string>"
}
],
"fieldId": "<string>"
}
],
"errors": [
{
"rowIndex": 123,
"errors": [
{
"code": "<string>",
"message": "<string>",
"fieldId": "<string>",
"participantIndex": 123
}
],
"externalBookingId": "<string>"
}
],
"truncated": true
}{
"statusCode": 429,
"error": "<string>",
"message": "<string>"
}Import bookings
Asynchronously imports a batch of bookings. The whole batch is validated synchronously against each ticket’s booking form — use the booking form fields endpoints to discover the import contract — and either every row is accepted (202 with a job to poll) or nothing is imported (422 with every problem, aggregated by error class).
externalBookingId is the row’s idempotency key: imports are create-once, so re-importing one returns the original booking (reported as alreadyImported) rather than creating a second — supply a fresh row idempotencyKey to import corrected data for the same id. Send an Idempotency-Key header to make the submission replayable: retrying the same key and body returns the original job; reusing a key with a different body is rejected (409).
A row may pin the booking form it validates against via bookingFormId; the pin is required (AMBIGUOUS_BOOKING_FORM) when the ticket has more than one live form, and a supplied pin must be a live form of the row’s ticket (UNKNOWN_BOOKING_FORM).
Rows sharing an externalOrderId are given one bookingReference, so a purchase that produced several bookings stays one order; the reference is derived from the id, so rows split across batches or retried later still join it. externalOrderId is deliberately not an idempotency key — reusing one is how an order gains bookings, and rows carrying it still dedup individually on externalBookingId. It groups bookings, not payments: the financial records stay one per booking.
A row may carry a status for backfilling history: withdrawn, deferred and canceled bookings, and bookings flagged as due to be transferred, are created in that state rather than created and then changed, so importing them sends no withdrawal or deferral emails to participants. Omit it for a confirmed booking. A completed transfer is not importable, because its meaning lives in the link between two bookings, which this API gives you no way to express; nor is a refund, or a refund taken as credit, because both imply payment or credit records an import does not create.
curl --request POST \
--url https://api.letsdothis.com/v0/bookings/import \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"bookings": [
{
"externalBookingId": "<string>",
"ticketId": "<string>",
"participants": [
{
"fields": [
{
"fieldId": "<string>",
"value": "<string>",
"values": [
{
"value": "<string>",
"id": "<string>"
}
]
}
],
"status": {
"type": "CONFIRMED"
}
}
],
"idempotencyKey": "<string>",
"externalOrderId": "<string>",
"bookingFormId": "<string>",
"bookedAt": "2026-05-08T11:30:00.000Z",
"bookerFields": [
{
"fieldId": "<string>",
"value": "<string>",
"values": [
{
"value": "<string>",
"id": "<string>"
}
]
}
],
"status": {
"type": "CONFIRMED"
}
}
]
}
'const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
bookings: [
{
externalBookingId: '<string>',
ticketId: '<string>',
participants: [
{
fields: [
{
fieldId: '<string>',
value: '<string>',
values: [{value: '<string>', id: '<string>'}]
}
],
status: {type: 'CONFIRMED'}
}
],
idempotencyKey: '<string>',
externalOrderId: '<string>',
bookingFormId: '<string>',
bookedAt: '2026-05-08T11:30:00.000Z',
bookerFields: [
{
fieldId: '<string>',
value: '<string>',
values: [{value: '<string>', id: '<string>'}]
}
],
status: {type: 'CONFIRMED'}
}
]
})
};
fetch('https://api.letsdothis.com/v0/bookings/import', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.letsdothis.com/v0/bookings/import"
payload = { "bookings": [
{
"externalBookingId": "<string>",
"ticketId": "<string>",
"participants": [
{
"fields": [
{
"fieldId": "<string>",
"value": "<string>",
"values": [
{
"value": "<string>",
"id": "<string>"
}
]
}
],
"status": { "type": "CONFIRMED" }
}
],
"idempotencyKey": "<string>",
"externalOrderId": "<string>",
"bookingFormId": "<string>",
"bookedAt": "2026-05-08T11:30:00.000Z",
"bookerFields": [
{
"fieldId": "<string>",
"value": "<string>",
"values": [
{
"value": "<string>",
"id": "<string>"
}
]
}
],
"status": { "type": "CONFIRMED" }
}
] }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text){
"jobId": "65d4e5f60718293a4b5c6d7e",
"status": "queued"
}{
"statusCode": 400,
"error": "<string>",
"message": "<string>"
}{
"statusCode": 409,
"error": "<string>",
"message": "<string>"
}{
"statusCode": 413,
"error": "<string>",
"message": "<string>"
}{
"error": "validation_failed",
"message": "<string>",
"totalRows": 123,
"rowsWithErrors": 123,
"errorCount": 123,
"summary": [
{
"code": "<string>",
"count": 123,
"message": "<string>",
"examples": [
{
"rowIndex": 123,
"externalBookingId": "<string>",
"participantIndex": 123,
"value": "<string>"
}
],
"fieldId": "<string>"
}
],
"errors": [
{
"rowIndex": 123,
"errors": [
{
"code": "<string>",
"message": "<string>",
"fieldId": "<string>",
"participantIndex": 123
}
],
"externalBookingId": "<string>"
}
],
"truncated": true
}{
"statusCode": 429,
"error": "<string>",
"message": "<string>"
}403. Contact your Let’s Do This representative if you’d like access.Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your auth token.
Body
An asynchronous booking import request: the whole batch imports or none of it.
The bookings to import.
1 - 1000 elementsShow child attributes
Show child attributes
Was this page helpful?

