Eternaltwin

Home

/api

Eternaltwin exposes its data over an HTTP+JSON API mounted at /api. Only one version exists today.

  • v1 — the current API.
  • Internal endpoints — routes served by the same process but outside /api: the backend-for-frontend, the OAuth browser flow and the OpenTelemetry collectors.

Conventions

  • Every response body is JSON, encoded as UTF-8.
  • Field names are snake_case, exactly as they are spelled in the Rust types of crates/core. They are not converted to camelCase.
  • Tagged objects carry their own "type" discriminant ("User", "ForumThread", "OauthClient", …).
  • Timestamps are ISO 8601 in UTC with millisecond precision, e.g. "2021-01-15T14:17:14.015Z".
  • Identifiers are UUIDs, serialized as lowercase hyphenated strings.
  • A paginated response is a listing:
{
  "offset": 0,
  "limit": 20,
  "count": 137,
  "items": []
}

count is the total number of matching items, not the length of items.

  • An error response is {"error": "<message>"} with a 4xx or 5xx status. A few endpoints answer with a richer object instead; those say so on their own page.

Authenticating a request

The API accepts three kinds of credentials, checked in this order:

  1. Authorization: Basic <base64(login:password)> — Eternaltwin credentials.
  2. Authorization: Bearer <access_token> — an OAuth access token.
  3. Cookie: sid=<session_id> — the browser session cookie set by PUT /api/v1/auth/self and POST /api/v1/users.

Whatever is used, the request ends up with an auth context: see /api/v1/auth/self for its exact shape. Credentials that cannot be resolved normally degrade to a guest context rather than failing, so a read never breaks on a stale cookie; endpoints that write reject an unresolvable credential with 401 instead.

Some endpoints are reserved for the server itself and require the Etwin-Internal-Auth header rather than a user credential. They are marked as such on their page.