Skip to main content

REST API reference

The Listo Sessions API exposes a single endpoint that returns the same screenings Listo published to that tenant's queue, paginated by time. The endpoint is scoped to one tenant per call via the {tenantId} path segment.

The Sessions API returns bare screening objects — the screening payload directly under each items[i], with no CloudEvent envelope wrapper. The Service Bus delivery of the same screenings does carry a CloudEvent envelope; see Differences from the Service Bus payload below.

Placeholder URL

https://api.<environment> is a placeholder. Use the API base URL delivered to you at onboarding.

Base URL

https://api.<environment>

Authentication

All endpoints require an OAuth 2.0 bearer token obtained via the client_credentials grant. See Obtaining tokens.

Authorization: Bearer <access_token>

Calls without a valid token return 401 Unauthorized.

Versioning

The URL prefix /v1 is the API major version. Breaking changes ship under a new prefix (/v2); new optional fields may appear in the response within /v1 without a bump. See Versioning & compatibility.

GET /v1/tenants/{tenantId}/screenings

Returns a page of completed screenings for the tenant in the path whose testTime falls within [from, to).

GET /v1/tenants/{tenantId}/screenings?from={iso8601}&to={iso8601}&pageSize={n} HTTP/1.1
Host: api.<environment>
Authorization: Bearer <token>
Accept: application/json

Path parameters

ParameterTypeRequiredNotes
tenantIdstring (UUID)yesThe tenant whose screenings to return. Must equal the bearer token's tenant_id claim — see Obtaining tokens. Each token is scoped to exactly one tenant; a different {tenantId} returns 403 forbidden.

Query parameters

ParameterTypeRequiredDefaultNotes
fromRFC 3339 date-timeyesInclusive lower bound on testTime. Any RFC 3339 offset is accepted (Z or e.g. +02:00); the server compares on the absolute instant.
toRFC 3339 date-timeyesExclusive upper bound on testTime. Must be ≥ from. Same offset rules as from.
pageSizeintegerno100Range 11000. Values outside the range return 400 page_size_out_of_range.
from_idintegernoInteger id of the last item from a previous page, used as a tie-breaker for screenings sharing the same testTime. When absent, from is inclusive on testTime. When present, the page begins strictly after (from, from_id).

The time range is bounded by testTime (when the screening was performed on the iPad), not by when the screening was persisted or delivered.

The endpoint enforces to >= from. Setting from equal to to is allowed, but always returns an empty items array — to is exclusive, so a zero-width range matches no screenings.

Response

200 OK

HTTP/1.1 200 OK
Content-Type: application/json
Link: <https://api.<environment>/v1/tenants/0d3e2b51-4e7a-44b6-8d5e-1c3a9b2f7c40/screenings?from=2026-05-08T09:30:00Z&from_id=1138291&to=2026-05-08T18:00:00Z&pageSize=100>; rel="next"

{
"items": [
{
"id": 1138291,
"tenantId": "0d3e2b51-4e7a-44b6-8d5e-1c3a9b2f7c40",
"testTime": "2026-05-08T11:25:33+02:00",
"...": "see /events/screening-completed for the full payload"
}
/* … up to pageSize items, ordered by (testTime, id) ascending … */
],
"links": {
"next": "https://api.<environment>/v1/tenants/0d3e2b51-4e7a-44b6-8d5e-1c3a9b2f7c40/screenings?from=2026-05-08T09:30:00Z&from_id=1138291&to=2026-05-08T18:00:00Z&pageSize=100"
}
}

Every screening in items has tenantId equal to the {tenantId} in the request path — the API does not mix tenants on a single response.

Response fields

FieldTypeNotes
itemsarray of screening objectsUp to pageSize screenings. May be empty.
items[i]objectA screening object — see Screening completed and Data schema reference for the full schema. The same fields the Service Bus delivery carries inside its CloudEvent data payload, returned here directly without an envelope wrapper.
items[i].idintegerThe screening's database id — Listo's stable primary key for this session. Use this for application-level idempotency.
linksobjectAlways present, even on the last page.
links.nextstring (URL)Present only when more pages exist. Absent on the final page.

The Link HTTP header is provided in addition to links.next, following RFC 8288. The two carry the same URL and are equivalent — pick whichever is more convenient for your HTTP client.

Link: <https://api.<environment>/v1/tenants/{tenantId}/screenings?from=...&from_id=...&to=...&pageSize=...>; rel="next"

The header is omitted on the final page (just like links.next).

Error responses

HTTPcodeWhen
400invalid_requestMalformed query parameter.
400invalid_time_rangeto < from, or from/to not valid RFC 3339.
400page_size_out_of_rangepageSize outside 1–1000.
401unauthenticatedMissing or invalid bearer token.
403forbiddenToken valid but not authorized for the tenant in the URL path — {tenantId} is not in the token's tenant_id claim.
404not_foundThe tenant in the URL path is not onboarded for the Sessions API.
429rate_limitedRate limit exceeded. The response carries a Retry-After header.
5xxinternal_error / service_unavailableRetry with exponential backoff.

Differences from the Service Bus payload

The Sessions API returns the screening payload directly. Service Bus carries the same payload inside a CloudEvent envelope (see Envelope). The fields and values inside the screening are the same on both transports — same field names, same field values. The difference is only the envelope wrapper, which is present on Service Bus and absent on REST.

Application-level deduplication keys on id (the screening's database id) on both transports. See Delivery semantics for the matching guidance from the queue side.

Ordering

Within a page, items are ordered by testTime ascending (and by id when two share the same testTime). Following links.next to the end returns every screening in your time window exactly once, in that same order. Don't change from/to mid-walk — keep following the URLs we hand you.