API overview
The Sessiq API is a JSON-over-HTTPS API. The booking widget, the customer portal and the admin console all use it, and you can call it from your own systems.
This page covers what every endpoint has in common. The per-area pages below go into detail, and the OpenAPI spec is the complete reference.
Base URL
| Environment | Base URL |
|---|---|
| Production | https://api.sessiq.com |
| Local development | http://localhost:3001 |
There is no global path prefix. Each route carries its full path, and nearly all of them start with /api/v1, for example /api/v1/bookings/hold. A few routes sit outside it:
| Path | What it is |
|---|---|
/api/auth/* | Staff login, refresh and logout. See Authentication. |
/webhooks/paytrail/* | Paytrail payment callbacks, called by Paytrail. See Webhooks. |
/payments/stripe/webhook | Older alias of /api/v1/payments/stripe/webhook, called by Stripe. |
/health, /health/ready | Health checks. |
Versioning
The version is part of the path (/api/v1). There is only one version today. Changes inside v1 are additive: new endpoints, new optional request fields and new response fields. Ignore response fields you don't recognise.
Headers
| Header | When |
|---|---|
Authorization | Bearer <token> for staff and customer requests, or Bearer bk_... for an API key. See Authentication. |
x-tenant-id | Your tenant ID. Required on public and customer endpoints. With a staff token or API key, the tenant comes from the credential. |
Content-Type | application/json on requests with a body. |
Errors
Errors use RFC 7807 Problem Details with the content type application/problem+json.
{
"type": "https://api.sessiq.com/.../errors/booking/pricing-changed",
"title": "Pricing Changed",
"status": 409,
"detail": "Pricing has changed since hold was created",
"instance": "https://api.sessiq.com/api/v1/bookings/confirm",
"error": "PRICING_CHANGED",
"expected_hash": "3f9a...",
"current_hash": "b71c..."
}
| Field | Always present | Description |
|---|---|---|
type | Yes | A URI for the kind of error. Its exact form varies by endpoint, so use status and error in code, not this value. |
title | Yes | Short, human-readable summary. |
status | Yes | The HTTP status code. |
detail | Usually | What went wrong, in English. Validation failures list every failing field here. |
instance | Yes | The request URL. |
error | No | A machine-readable code such as SLOT_NOT_AVAILABLE, PRICING_CHANGED or OUTSIDE_WINDOW. |
Some codes add context fields. For example, OUTSIDE_WINDOW adds cancellation_window_hours and time_remaining_hours, and PRICING_CHANGED adds expected_hash and current_hash. The per-area pages list them.
Rate-limit errors (429) use a different body. See Rate limits.
Pagination
Admin list endpoints are paginated. Pass page (1-based, default 1) and limit (default 25, max 100) as query parameters. The response is an envelope:
{
"data": [],
"pagination": {
"page": 1,
"limit": 25,
"total": 150,
"totalPages": 6,
"hasNextPage": true,
"hasPreviousPage": false
}
}
The list is always under data. Detail endpoints return the object itself, without an envelope. Not every list is paginated. The per-area pages say which ones are.
Rate limits
Limits apply per tenant and per client (the signed-in user, or the IP address for anonymous calls).
| Endpoints | Limit |
|---|---|
| Most endpoints | 10 requests per second, 100 per minute |
| Staff and customer login, registration and password reset | 5 per minute, 20 per hour |
| API keys | Each key's own limit (default 1,000 per hour). |
Responses carry X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset. When you go over the limit, you get 429 Too Many Requests with a Retry-After header in seconds. The body (abridged):
{
"statusCode": 429,
"error": "Too Many Requests",
"message": "Rate limit exceeded. You have made more than 100 requests in the last 1 minute. Please wait before retrying.",
"details": { "retryAfter": 60, "limit": 100, "window": "1 minute" }
}
Wait for Retry-After before you retry. Back off further if you get another 429.
API areas
| Area | Covers |
|---|---|
| Authentication | Staff login and refresh, API keys |
| Customer authentication | Customer accounts, login, profile and "my bookings" |
| Authorization | Permissions, roles and role assignments |
| Availability | Open slots, add-ons and site configuration for booking UIs |
| Bookings | Holds, checkout, confirmation, cancellation and rescheduling |
| Booking groups | Several bookings handled as one |
| Event packages | Packaged events such as parties |
| Payments | Payment sessions, refunds and payment status |
| Notifications | Email templates and automation rules |
| Promotions | Promo codes and automatic discounts |
| Gift cards | Selling, checking and redeeming gift cards |
| Waivers | Waiver templates and signatures |
| Resource add-ons | Add-ons tied to resources |
| Webhooks | Outbound webhooks and inbound payment callbacks |
Complete reference
The areas above cover the common integration paths, not every endpoint. The full list, with request and response schemas, is the OpenAPI spec:
- Swagger UI at
/api-docson a development API, for examplehttp://localhost:3001/api-docs. It is turned off in production. apps/api/openapi.jsonin the Sessiq repository, generated from the API source. Import it into Postman, Insomnia or a client generator.
To set up a local API, see Developer setup.