Skip to content
FreeTicketDocs
Esc
↑↓navigate↵open⌘Jpreview

Create the ticket reservation (step 1 of the headless purchase)

Requires the X-Customer-Session header. The enterprise service API key is OPTIONAL: with a key, the date and the ticket type must belong to the workspace pinned to it (anything else is 404); without a key, it is enough for the ticket type to exist and be on sale (same eligibility as the first-party checkout). Reserves inventory and creates the PENDING sale with the SAME rules as the first-party checkout (stock under lock, seats validated against seats.io, per-buyer limit, presale, memberships and virtual queue turn). The buyer email comes from the session, never from the body. Rejections carry a stable reason in error.details.reason (sold_out, queue_turn_required, seats_not_held, …). With pending_sale_in_progress the inventory is taken by a half-paid purchase FROM THE SAME buyer: error.details.pendingSaleId and pendingReference identify it, and the right step is to reopen its payment with POST /customer/orders/{pendingSaleId}/payment (idempotent) instead of reserving again. If free is true the sale is already confirmed and /payment must NOT be called. Next step: POST /customer/orders/{id}/payment.

POST/customer/orders
Authorization
AuthorizationAPI key · headerrequired

API key prefixed with Bearer . Alternative: the x-api-key header with the raw key. Available scopes: read and write (see /.well-known/oauth-protected-resource).

or
x-api-keyAPI key · headerrequired

Raw API key (without Bearer ), alternative to Authorization.

Header parameters
X-Workspace-Idstring

Active workspace to operate on. Optional: when omitted, the default workspace of the user who owns the key is used (pickActiveOrg).

X-Purchase-Sessionstring

Purchase session id (POST /customer/purchase-sessions). Required when the event's workspace enforces a single purchase session; if present, it is always validated. The requirement is decided by the EVENT, not the API key: it applies if the owning workspace, a linked artist or a catalog seller of the show has the flag, with or without a key. Rejections (409; uppercase error.code and the slug in error.details.reason): PURCHASE_SESSION_REQUIRED (missing, or belongs to another buyer or another event date), PURCHASE_SESSION_SUPERSEDED (another tab or device replaced it), PURCHASE_SESSION_EXPIRED (the map clock ran out before the order was created), PURCHASE_SESSION_BUSY (an order is already in flight with this session) and, on POST /customer/orders with seats, HOLD_TOKEN_MISMATCH (the holdToken is not the session's, or belongs to a replaced session or another buyer even if the header is absent). Payment POSTs accept the buyer's live session or the session that created THAT order, as long as no other session has been opened since. Rejecting a new payment NEVER affects a payment already in flight.

Request body
requiredapplication/json
eventDateIdstringrequired
min length 1
itemsCustomerOrderItem[]required
min items 1 · max items 1
Show properties
Array of CustomerOrderItem
ticketTypeIdstringrequired
min length 1
quantityintegerrequired
min 1 · max 30
seatsstring[]

seats.io labels. Only for seated events.

max items 30
holdTokenstring

Hold token of the seats.io map session. Required if seats are sent.

max length 120
discountCodestring
max length 40
buyerobjectrequired
Show properties
namestringrequired
min length 2 · max length 120
phonestringrequired
max length 40
idTypestringrequired
Allowed:CCCENITPPTIPEP
idNumberstringrequired
min length 5 · max length 20
nitDigitstring

Check digit. Required if idType is NIT.

max length 1
returnUrlstringrequired

Absolute URL of the landing page the buyer returns to. Validated against the enterprise domain allowlist and the workspace that owns the event; if it fails validation it is ignored and the purchase proceeds as usual.

max length 2048
Responses
201

OK

dataCustomerOrderCreateResultrequired
Show properties
freebooleanrequired

true = the purchase was CONFIRMED without a payment gateway (100% discount). In that case do NOT call /payment: there is nothing to charge and the other fields are null.

referencestringrequired

Sale reference (FT-…). Always identifies the purchase.

saleIdstring | nullrequired

Sale id. null when free is true.

Show properties
Any of:
string
string
null
null
totalnumber | nullrequired

Amount to charge. null when free is true.

Show properties
Any of:
number
number
null
null
currencystring | nullrequired
Show properties
Any of:
string
string
null
null
expiresAtstring | nullrequired

Instant (ISO 8601 UTC) at which the inventory reservation expires. After that, the purchase must be started over.

Show properties
Any of:
string
string
null
null
401

Missing or invalid credential.

errorobjectrequired
Show properties
codestringrequired
messagestringrequired
retryablebooleanrequired
detailsany
403

Insufficient role or resource not accessible.

errorobjectrequired
Show properties
codestringrequired
messagestringrequired
retryablebooleanrequired
detailsany
404

Resource does not exist or is out of scope.

errorobjectrequired
Show properties
codestringrequired
messagestringrequired
retryablebooleanrequired
detailsany
409

Conflict: the resource does not allow this operation in its current state.

errorobjectrequired
Show properties
codestringrequired
messagestringrequired
retryablebooleanrequired
detailsany
422

Request body/parameter validation failed.

errorobjectrequired
Show properties
codestringrequired
messagestringrequired
retryablebooleanrequired
detailsany
429

Too many requests: rate limit exceeded.

errorobjectrequired
Show properties
codestringrequired
messagestringrequired
retryablebooleanrequired
detailsany
503

Service unavailable: an external dependency is down or initialization failed.

errorobjectrequired
Show properties
codestringrequired
messagestringrequired
retryablebooleanrequired
detailsany
Try it
Server
Authorization
Parameters
Bodyapplication/json
Request
curl -X POST 'https://admin.appfreeticket.com/api/v1/customer/orders' \
  -H 'Authorization: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
  "eventDateId": "string",
  "items": [
    {
      "ticketTypeId": "string",
      "quantity": 1,
      "seats": [
        "string"
      ]
    }
  ],
  "holdToken": "string",
  "discountCode": "string",
  "buyer": {
    "name": "string",
    "phone": "string",
    "idType": "CC",
    "idNumber": "string",
    "nitDigit": "s"
  },
  "returnUrl": "string"
}'
Response
{
  "data": {
    "free": true,
    "reference": "string",
    "saleId": "string",
    "total": 0,
    "currency": "string",
    "expiresAt": "string"
  }
}