Skip to content

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.

Authorization: Bearer rev_install_8h3k2m...
Accept: application/vnd.revento.v1+json

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:

Accept: application/vnd.revento.v1+json

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 UUID on every request:

X-Revento-Request-Id: 0f8ad6e2-7e1a-4e7e-bc3c-8f5b1c4d2e3f

We echo it back in the response and write it to our logs. When you contact support, hand them this UUID - investigation drops from minutes to seconds.

You can use any UUID format (v4 is fine). It only needs to be unique per request on your side.

Pagination

List endpoints return:

{
  "data":        [ /* array of resources */ ],
  "next_cursor": "opaque-string-or-null",
  "has_more":    true
}

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 cursor is opaque. Don't parse it. Format may change without notice.
  • has_more is the canonical "more pages exist" signal. Don't rely on next_cursor != null - cursors are opaque, and a non-null final cursor is permitted by the contract.
  • limit defaults to 25, max 50. Kept conservative because list responses can carry custom_form_fields per row and may approach the per-response payload cap on rich-form events. If you receive 413 payload_too_large, reduce limit and retry.

Errors

Every error response has the same envelope:

{
  "error":      "string_code",
  "message":    "Human-readable explanation",
  "request_id": "UUID matching 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 UUID echoed}
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:

{
  "start_date": "2026-08-15T16:00:00Z"
}

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}/participants doesn'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.