Read API overview¶
The full per-endpoint reference is on Endpoints. This page covers the cross-cutting concerns: authentication, versioning, pagination, correlation IDs, errors. Read this once and the per-endpoint pages become a quick lookup.
Base URL¶
| Environment | Base |
|---|---|
| All usage | https://api.revento.app/api/v1 |
Use this base URL for all API requests. To test your integration, connect it to an event you control through the standard OAuth flow; the base URL stays the same.
URLs in Endpoints are written relative to the base.
Authentication¶
Every API request requires a Bearer header with an installation token (event-scoped) or user token (participant-scoped). Token type matters per endpoint - see the table on each endpoint page.
Wrong token type for an endpoint returns 403 user_token_required or 403 installation_token_required. See Errors.
API versioning¶
Pin a version with the Accept header. Today there's only v1:
If you omit the Accept header, you get the current default version. Fine for development, risky for production - pin the header so a version transition can't silently change your response shape.
Versioning commitment: any previous version is supported for at least 6 months after the next version is announced, with the deprecation surfaced in the changelog and in Revento's integration-management notices.
Correlation IDs¶
Send a correlation id on every request. Any unique-per-request value works; a v4 UUID is the recommended shape, not a requirement:
We echo your value back, in the X-Revento-Request-Id response header and in the request_id field of any error body, so your logs and ours join on one string.
A value we cannot use is replaced, never rejected: if the header is missing, or the value is not 8-64 characters of letters, digits, ., _ or -, the response carries an id we generated instead. You keep the response - a correlation id is a debugging aid and losing the join is not worth failing the call - but you will not see your own value, so a mismatch means the header was malformed rather than dropped.
When you contact support, hand them the request_id from the response rather than the value you sent - they are the same string whenever we could use yours, and only the response carries the one we logged. Investigation drops from minutes to seconds.
Pagination¶
Every list endpoint paginates, including the short-looking ones: /participants, /activities, /threads, /locations, /registration-waves, /roles and /program. All of them return the same envelope:
To fetch the next page, pass next_cursor as the cursor query parameter:
GET /events/{event_id}/participants?limit=25
GET /events/{event_id}/participants?limit=25&cursor=eyJjIjogIjI...
Rules:
- The array is
items. There is nodatakey and nohas_morefield. - The cursor is opaque. Don't parse it. Format may change without notice.
- Stop when a page comes back with an empty
itemsarray. Do not treat a non-nullnext_cursoras proof that more rows exist: a final page may still carry a cursor, so a loop keyed on the cursor alone can run an iteration longer than the data. limitdefaults to 25. A value above 50 is silently clamped to 50, and a value below 1 is silently raised to 1: you get200with a page size you did not ask for. Read the length ofitemsinstead of assuming yourlimitwas honoured. A non-numericlimitfalls back to 25.
A request that omits limit and cursor returns at most 25 rows, on every one of those endpoints. An event with 52 locations answers /locations with 25 of them plus a cursor, and nothing else in the payload says the remainder exists. Paginate every list endpoint, not only the ones you expect to be long.
A cursor the server cannot resolve - malformed, expired, or taken from a different collection - answers 400 validation_error with field: "cursor". It is a client-side error, so retrying the same request cannot help; start the walk again without a cursor.
Errors¶
Every error response has the same envelope:
{
"error": "string_code",
"message": "Human-readable explanation",
"request_id": "correlation string echoing X-Revento-Request-Id"
}
The error code is the machine-readable identifier. Branch on this in your code. The message is for humans (logs, dashboards, operator notes); it may evolve.
Full error catalog is in Errors. The codes you'll see most often:
| Code | Meaning |
|---|---|
token_expired |
Refresh and retry |
token_revoked |
Permanent - re-consent required |
insufficient_scope |
Token doesn't grant this endpoint |
event_not_authorized |
Token is for a different event |
rate_limit_exceeded |
Back off (Retry-After header has duration) |
Idempotency¶
All current endpoints are read-only GETs, so no idempotency keys are required. Repeating a request gives the same response (modulo data changes between calls).
Headers we always send¶
Every API response includes:
X-RateLimit-Limit: 500
X-RateLimit-Remaining: 487
X-RateLimit-Reset: 1747000000
X-Revento-Request-Id: {your correlation id, or ours}
Content-Type: application/vnd.revento.v1+json; charset=utf-8
See Rate limits for header semantics.
Time format¶
All timestamps in request and response bodies are ISO 8601 in UTC:
We never return local times. Convert to local at your display layer using whatever your stack provides (Intl in browsers, pytz / zoneinfo in Python, etc.). Same convention applies to webhook payloads.
Cursor stability¶
If you're storing cursors (e.g. for resumable sync), be aware:
- Cursors remain valid for at least 24 hours.
- Cursors are tied to the (endpoint, query, token) tuple - a cursor from
/events/{a}/participantsdoesn't work on/events/{b}/participants. - Within a single page response, the result set is point-in-time consistent.
- Across pages fetched at different times, rows may appear, disappear, or shift because the underlying data changed. A newly-created row may appear on a later page even if it would have sorted onto an earlier one; a deleted row may simply be absent.
- Cursors remain safe to reuse even when the underlying data changes. They advance the walk; they do not promise a mutation-free snapshot across the entire pagination session.
- After 24 hours we make no guarantee. If you need long-running paginated reads, complete them within a session.
If you need strict change tracking while paginating, treat webhooks as the source of truth for mutations and use pagination for baseline syncs, not for change notification.
Integration management¶
Revento provides integration-management tools for reviewing metadata, rotating secrets, testing webhooks, and inspecting delivery history.