Seller API

Manage your inventory on the Ticketero marketplace. Publish tickets, fulfill orders, track payments and receive signed webhooks.

The Seller API gives partners programmatic access to manage their inventory in real time on the Ticketero marketplace: list events from our catalog, publish and update tickets, fulfill orders, track payments, and receive signed webhook notifications for every relevant change. Whether you are building a sync engine, an internal dashboard or fully automated workflows, it gives you everything required to operate at scale.

All endpoints are authenticated with a Bearer token and protected by per-route rate limits.

This is a separate surface from the Buyer API. Explore every endpoint live in the Seller API Reference.

Base URL & authentication

https://production.ticketero.co/api      # production
https://sandbox.ticketero.co/api         # sandbox

Seller endpoints live under /broker. Every request needs the Bearer token Ticketero issued you:

curl https://production.ticketero.co/api/broker/profile \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Accept: application/json"

Tokens do not expire automatically, keep yours secret. If it is compromised, contact Ticketero to rotate it.

Typical integration flow

The endpoints chain together: the id you get from one call feeds into the next.

  1. Find the event in our catalog: GET /broker/events?q=..., each result has an id. If the event does not exist yet, submit it with POST /broker/events (returns an id plus approval_status: "pending"). Wait for the event.approved webhook before posting tickets.
  2. List your inventory for that event: GET /broker/tickets?event_id={id}.
  3. Create a ticket: POST /broker/tickets with event_id from step 1. The response gives you a ticket_id, persist it; every later call references the ticket by it. Send your own external_id to make retries safe (a repeat POST returns 409 with the existing ticket).
  4. Update inventory: PUT /broker/tickets/{ticket_id} (full update), or the shortcuts PATCH /broker/tickets/{ticket_id}/stock, /price, /status. A ticket held by a checkout in progress is locked and rejects writes with 409, see Locked tickets.
  5. Receive orders: when a customer buys, you get an order.created webhook. Then GET /broker/orders/{id} to read it, and POST /broker/orders/{id}/deliver to upload the tickets and mark it delivered (pending-delivery → delivered).
  6. Payments: once Ticketero settles the order you receive a payment.confirmed webhook; query history via GET /broker/payments.

Identifiers cheat-sheet

Returned by Use as
id from GET /events (or POST /events) event_id in POST /tickets; event_id query of GET /tickets
id from GET /venues venue.id in POST /events
ticket_id from POST /tickets path param of GET/PUT/PATCH/DELETE /tickets/{ticket_id}
external_id you choose external_id in POST /tickets; external_id query of GET /tickets
id from the order.created webhook (data.id) path param of GET/POST /orders/{id}/...

Webhooks

Register HTTPS URLs with POST /broker/webhooks and Ticketero sends signed POSTs whenever events occur. Each delivery carries an X-Ticketero-Signature header (HMAC-SHA256 over the raw request body, using the secret returned at registration).

The secret is returned once, at registration. Copy it then, verify every delivery server-side, and reject unsigned or mismatched requests.

Events

Subscribe to any subset of these on POST /broker/webhooks:

Event Fired when data shape
order.created A customer buys one of your tickets order object + recipient
order.updated An order you own changes order object
order.delivered You deliver an order (POST /orders/{id}/deliver) order object + booking, delivery_method, delivered_at
order.cancelled Ticketero cancels an order you own order object (status: "cancelled")
payment.confirmed Ticketero records a payment for your delivered orders payment object
ticket.disabled One of your tickets is deactivated ticket_id, external_id, event_id, reason, disabled_at
event.approved An event you submitted is approved event_id, title, date, time, approved_at

Payload shape

Every delivery is the same envelope: event, created_at, and an event-specific data:

{ "event": "order.created", "created_at": "2026-04-22T19:14:00+00:00", "data": { } }

Order events

For order.created, order.updated, order.delivered and order.cancelled, data is the same order object as GET /orders/{id}, so you can act on the webhook without a follow-up GET. data.id is the order id (there is no order_id), and Ticketero’s markup is never included.

{
  "event": "order.created",
  "created_at": "2026-06-05T17:58:01-06:00",
  "data": {
    "id": 245243,
    "order": "A1B2C3",
    "quantity": 1,
    "price": 3,
    "total": 3,
    "currency": "USD",
    "status": "pending-delivery",
    "recipient": { "name": "Carlos Smeke", "email": "[email protected]", "phone": "+1 3055550100" },
    "ticket": {
      "id": "211451505",
      "external_id": "BRK-INV-0001",
      "section": "Testing Sales 2",
      "row": "Last",
      "low_seat": "1000",
      "high_seat": "1014",
      "price": 3,
      "currency": "USD",
      "delivery_date": "2026-03-10T06:00:00.000000Z",
      "delivery_method": "e-ticket",
      "notes": ""
    },
    "event": {
      "name": "Ahab The Ticket Whaler Presents Safe Ticket Whaling",
      "date": "2026-12-25",
      "time": "03:03 PM",
      "datetext": "Friday, December 25, 2026",
      "datetime": "2026-12-25 15:03",
      "venue_name": "Webster Theater",
      "country": "United States of America",
      "state": "Connecticut",
      "city": "Hartford"
    },
    "payment_date": null,
    "payment_status": "unpaid",
    "delivery_data": "Delivery details will appear here once you deliver the tickets via POST /orders/{id}/deliver."
  }
}

Per-event extras on top of the order object:

  • data.ticket.id is the same ticket_id you got from POST /tickets and data.ticket.external_id is the id you supplied; use either to reconcile the sale against your inventory.
  • data.order is a short 6-character code identifying the buyer’s checkout. Orders bought together in one checkout share the same order code, so you can group a multi-ticket purchase. Returned on every order object (GET /orders, GET /orders/{id} and the order.* webhooks); may be null.
  • order.created carries data.recipient ({name, email, phone}): who you must deliver to.
  • order.delivered carries booking, delivery_method, delivered_at, and data.delivery_data becomes the object you submitted ({ "files": [{ "url", "name", "source" }] }) instead of the placeholder string.
  • order.cancelled sets status: "cancelled"; delivery_data stays a placeholder string.

ticket.disabled

Fired when one of your tickets is deactivated (e.g. PATCH /tickets/{id}/status → inactive). reason is null unless a reason was supplied.

{
  "event": "ticket.disabled",
  "created_at": "2026-06-08T12:50:45-06:00",
  "data": {
    "ticket_id": "219561517",
    "external_id": "BRK-INV-0001",
    "event_id": 168126800,
    "reason": null,
    "disabled_at": "2026-06-08T12:50:45-06:00"
  }
}

event.approved

Dispatched only to the broker that originally submitted the event, once it’s approved.

{
  "event": "event.approved",
  "created_at": "2026-04-22T19:14:00+00:00",
  "data": {
    "event_id": 169133082,
    "title": "Ahab The Ticket Whaler Presents Safe Ticket Whaling",
    "date": "2026-12-25",
    "time": "20:00:00",
    "approved_at": "2026-04-22T19:14:00+00:00"
  }
}

payment.confirmed

Sent when Ticketero records a settlement against one or more of your delivered orders. The data object uses the same field names as the payment resource from GET /broker/payments, so one parser works on both. orders is the list of orders_broker ids the payment covers (same shape as the REST list endpoint); payment_reference and voucher may be null.

{
  "event": "payment.confirmed",
  "created_at": "2026-06-08T12:00:00-06:00",
  "data": {
    "id": 85,
    "payment_method": "bank_transfer",
    "payment_reference": "WIRE-2026-0042",
    "amount": 181.01,
    "currency": "USD",
    "voucher": null,
    "orders": [245241, 245242],
    "created_at": "2026-06-08T12:00:00-06:00"
  }
}

Sandbox/test deliveries set data.test: true: ignore them. POST /webhooks/{id}/test fires a full synthetic order.created (a complete order shape with fake values like id: 0, order: "TEST01" and 2099 dates) so you can validate your parser end-to-end before going live.

Locked tickets

While a buyer is checking out one of your listings, Ticketero holds it and the ticket becomes locked. A locked ticket cannot be modified: PUT /tickets/{ticket_id}, PATCH /tickets/{ticket_id}/price, /stock, /status and DELETE /tickets/{ticket_id} all return 409:

{
  "message": "Ticket is locked by an in-progress sale and cannot be modified. Try again later.",
  "locked": true
}

The lock is temporary and clears on its own once the sale completes or the checkout expires. It exists so a price or stock change cannot land mid-sale and break a purchase already in flight.

Every ticket payload carries a locked boolean (GET /tickets, GET /tickets/{ticket_id}), so a sync job can skip locked listings up front instead of retrying blindly:

const { data } = await get("/broker/tickets?event_id=" + eventId);
const syncable = data.filter((t) => !t.locked);   // locked ones retry on the next pass

If you do hit a 409, do not loop on it. Queue the change and retry on your next sync cycle; a checkout hold is short-lived.

Sandbox accounts

If your account is provisioned for sandbox testing:

  • GET /events always returns a single dedicated test event.
  • POST /tickets and POST /tickets/bulk only accept the test event id, any other event_id is rejected with 422.
  • POST /events is disabled (403).
  • Every other endpoint behaves like production.

Rate limits

Bucket Limit
broker-read 240 req/min
broker-write 60 req/min
broker-bulk (only POST /tickets/bulk) 10 req/min

Where to next