This article is for the person implementing the PassPass REST API. For an overview and dashboard configuration, see Public API and Webhooks.
Interactive documentation (Swagger): api.passpass.be/api/public/docs
Authentication
Each request carries your API key in the Authorization header:
Authorization: Bearer pk_live_...
The key is linked to your organization. All returned data is automatically filtered to your organization. The secret is only displayed once at creation. If you lose it, rotate it from the dashboard (the old secret stops working immediately).
Validate your configuration with GET /v1/me: it's the only endpoint that requires no scope.
Endpoints
The API is read-only.
Events (scope events:read)
GET /v1/events: list your eventsGET /v1/events/:id: event details
Orders (scope orders:read)
GET /v1/orders: list ordersGET /v1/orders/:id: order details
Attendees (scope attendees:read)
GET /v1/events/:eventId/attendees: attendees of an eventGET /v1/orders/:orderId/attendees: attendees of an order
Analytics (scope events:read): 7 routes exposing the same data as the dashboard Analytics module (KPIs, sales timeline, ticket mix, traffic sources, geography, conversion funnel, audience segments). See the Swagger for route details and responses.
Introspection (no scope required)
GET /v1/me: your API key information
Permissions (scopes)
Scopes control which fields are returned. An unauthorized field is absent, not null.
events:read: events and analytics
orders:read: orders (amount, buyer, billing, line items, status)
orders:read:financial: service_fee, payout_amount, refundable_amount
orders:read:form_answers: order form answers
attendees:read: attendees (minimal data, no personal information)
attendees:read:contact: first_name, last_name, email
attendees:read:financial: ticket_price
attendees:read:form_answers: attendee form answers
attendees:read:full: access_token (automatically includes contact and financial)
Scopes are fixed at key creation. To change them, create a new key. access_token is the secret identifier behind the ticket's QR code. Only request attendees:read:full if necessary.
Conventions
Fields in snake_case (exception: buyer and billing in camelCase)
Amounts in euros (not cents)
Dates in ISO 8601 UTC
Multilingual fields:
{"fr": "...", "en": "...", "nl": "..."}New fields may appear without notice
Pagination
{
"data": [],
"total": 137,
"page": 1,
"limit": 25,
"total_pages": 6
}
Parameters: ?page= (default 1) and ?limit= (default 25, max 100).
Events
GET /v1/events returns all your events (drafts and private included). Each event includes its tickets with the effective VAT rate (vat_rate), sold quantities and capacities.
{
"id": 1535,
"title": {"en": "My event"},
"status": "published",
"visibility": "public",
"sold_count": 128,
"max_capacity": 500,
"start_at": "2026-06-01T18:00:00.000Z",
"end_at": "2026-06-01T23:00:00.000Z",
"timezone": "Europe/Brussels",
"currency": "EUR",
"tickets": [
{
"id": 4525,
"type": "ticket",
"name": {"en": "Standard Entry"},
"price": 25,
"vat_rate": 21,
"max_quantity": 300,
"sold_count": 128,
"visibility": "visible"
}
]
}
Orders
GET /v1/orders returns orders. By default, only paid orders are returned. Pass ?status=all for the complete picture.
Filters: status (paid/pending/cancelled/all), created_after, created_before (ISO-8601).
{
"id": 65817,
"event_id": 1535,
"status": "paid",
"amount_total": 200,
"buyer": {
"firstName": "Marie",
"lastName": "Dupont",
"email": "marie@example.com"
},
"billing": {
"identifierType": "vat",
"companyName": "Demo Corp SRL",
"vat": "BE0123456789",
"vatCountry": "BE",
"addressStreet": "Rue de la Loi 1",
"addressCity": "Bruxelles",
"addressZip": "1000",
"addressCountry": "BE"
},
"line_items": [
{
"type": "ticket",
"ticket_id": 4525,
"name": {"en": "Standard Entry"},
"quantity": 2,
"unit_amount": 100,
"subtotal": 200,
"vat_rate": 21
}
],
"form_answers": null,
"service_fee": 4.6,
"payout_amount": 195.4
}
buyer: checkout identity (camelCase). billing: company data, null if not provided (camelCase). line_items: type ticket (ticket), fee (service fees) or discount (promo, negative amount). vat_rate is the effective VAT rate of the ticket.
Attendees
GET /v1/events/:eventId/attendees returns attendees (one per ticket, active status only).
{
"id": "019fdb0d-...",
"event_id": 1535,
"order_id": 65817,
"status": "active",
"ticket": {
"id": 4525,
"type": "ticket",
"name": {"en": "Standard Entry"}
},
"first_name": "Marie",
"last_name": "Dupont",
"email": "marie@example.com",
"ticket_price": 100,
"access_token": "019fdb0d-...",
"form_answers": [
{
"type": "selection",
"field_id": "abc123...",
"question_title": {"en": "Status"},
"answer": {"en": "Self-employed"}
}
]
}
Fields depend on scopes: contact (first_name, last_name, email), financial (ticket_price), form_answers, full (access_token).
Limits and errors
100 requests per minute per key. Beyond: HTTP 429.
401: missing or invalid key
403: insufficient scope
404: resource not found
400: invalid parameter
429: rate limit exceeded
API or Webhooks?
Real-time (sale, scan) → Webhooks
Accounting export, attendance → API
Custom analytics dashboard → API analytics
Recovery after incident → API
Robust pattern: webhooks + periodic API calls