EN
For organizers
For organizers

Organizer API

Pull your events, orders and attendees into your own system; verify entries with your own turnstile or scanner.

Base URL: https://tixvio.com/api/v1/ext

Authentication

Every request carries an API key in the Authorization: Bearer txk_… header. The account owner creates keys on the Developers page of the panel; a key is shown only once and Tixvio stores only its hash.

A key belongs to one organizer and sees only the events that organizer hosts. A Tixvio Pro session doesn’t work on these endpoints, and an API key doesn’t work on the panel or Pro endpoints.

Validity is 30, 90 or 365 days, or no expiry. Up to 10 keys can be active at a time. Revoke keys you don’t use; revoking takes effect immediately.

curl https://tixvio.com/api/v1/ext/events?status=upcoming \
  -H "Authorization: Bearer txk_…"

Scopes

Pick only the scopes you need when creating a key. A request to an endpoint outside the key’s scopes gets 403 insufficient_scope.

ScopeMeaning
events:readEvent list and detail: ticket types, price, quota, sold, entry counts.
orders:readPaid and refunded orders: buyer name and email, total, discount, coupon, line items.
attendees:readTickets and entry codes: name, type, status, order code, check-in time.
checkinDoor: the offline door list (with QR keys), check-in sync and online QR validation.

Limits and paging

  • 120 requests per minute per key; above that you get 429 rate_limited with Retry-After: 60.
  • Lists come in pages of 100 rows: ?page=1, 2, … If more is true in the response, there is a next page.
  • Orders and attendees accept ?since=<ISO date> and return only what changed after that moment (payment, refund, new ticket, check-in); store the time of your last run when syncing.
  • Amounts are integers in minor units (25000 = 250.00); the currency is in the currency field. Times are ISO 8601 (UTC).

Endpoints

All paths are under the base URL. Responses are JSON and never cached.

MethodPathScopeMeaning
GET/me—The key’s name, prefix, scopes, expiry and organizer.
GET/eventsevents:readEvents. ?status=upcoming (default) | past | all.
GET/events/{id}events:readOne event: ticket types, sold, capacity, entry counts.
GET/events/{id}/ordersorders:readOrders (primary sales; resale excluded). ?since, ?page.
GET/events/{id}/attendeesattendees:readTickets / entry codes (sold, guest, multi-event pass). ?since, ?page.
GET/events/{id}/doorcheckinOffline door list: per ticket the code, status, name, type, scan window and QR key. Only during door time (12 hours before the start → end; without an end, start + 12 hours), at most 3 times per 2 minutes; every download is written to the audit log.
POST/events/{id}/checkinscheckinCheck-in sync: { items: [{ code, at, mode }] } (up to 500). First in wins; if another device or key admitted the ticket first, you get ALREADY.
POST/scancheckinOnline QR validation: { eventId, payload } → OK, USED, INVALID, EXPIRED, WRONG_EVENT, OUT_OF_WINDOW, REFUNDED, LISTED, CANCELLED.
{
  "events": [{
    "id": "clx…", "slug": "gece-…", "title": "…",
    "status": "PUBLISHED", "startsAt": "2026-11-21T19:00:00.000Z",
    "currency": "TRY", "sold": 412, "capacity": 600,
    "ticketTypes": [{ "id": "clt…", "name": "Genel", "price": 45000, "quantity": 500, "sold": 380 }]
  }],
  "page": 1, "more": false
}
POST https://tixvio.com/api/v1/ext/events/{id}/checkins
{ "items": [{ "code": "K7Q2…", "at": "2026-11-21T22:14:05Z", "mode": "scan" }] }

Error codes

Error responses look like { "error": "<code>" }.

CodeHTTPMeaning
invalid_key401The key is missing, unknown, revoked or expired, or the organizer account isn’t approved.
insufficient_scope403The key lacks this endpoint’s scope (scope in the response).
not_found404The event doesn’t exist or doesn’t belong to this organizer.
door_window403The door list is only available during door time (opensAt, closesAt in the response).
invalid_since400since isn’t a valid ISO date.
empty400The body contains no check-ins or QR payload.
rate_limited429Rate limit exceeded; wait Retry-After seconds.

Offline QR verification (TX2)

The QR on a Tixvio ticket changes every 30 seconds, so a screenshot soon becomes invalid. Format: TX2.<ticketCode>.<window>.<signature>.

window = floor(unix milliseconds / 30000). signature = the first 16 characters of the base64url text of HMAC-SHA256(key, ticketCode + "." + window). key is the row’s key field from the door list (as text, UTF-8).

Device clocks drift, so ±2 windows (about ±1 minute) are accepted. A row with an empty key (used, refunded, listed for resale) must not be admitted. The row’s win field is the [start, end] scan window; outside it, treat the ticket as OUT_OF_WINDOW.

Send entries made offline to the checkins endpoint once you’re online, so Tixvio Pro and the other doors won’t admit the same ticket twice.

// Node.js · list = GET /events/{id}/door
import crypto from 'node:crypto';
const rows = new Map(list.tickets.map((t) => [t.code, t]));

function verify(payload, now = Date.now()) {
  const [ver, code, w, sig] = String(payload).split('.');
  const row = rows.get(code);
  if (ver !== 'TX2' || !row || !row.key) return false;
  const win = Math.floor(now / 30000);
  if (Math.abs(Number(w) - win) > 2) return false; // EXPIRED
  const expected = crypto.createHmac('sha256', row.key)
    .update(`${code}.${w}`).digest('base64url').slice(0, 16);
  return expected === sig; // + row.win [from, to]
}

Entry-code CSV

Downloaded per event from the Developers page of the panel (owners and managers). Columns: code, name, type, status, order, checked in. UTF-8 (BOM) with ; as separator, so Excel opens it correctly; cells starting with formula characters are neutralised.

Static barcode import

Importing static barcodes sold elsewhere into the Tixvio door isn’t available yet: a static code can be shared as a screenshot, which defeats the dynamic QR protection. If you need it, write to us via live support.