livqenoDocs

API ReferenceConventions

API Conventions

The rules every endpoint follows — base URL, auth, errors, request ids, retries, pagination, and environments.

The REST API is what your backend uses to talk to Livqeno: to create rooms and conversations, mint tokens, and read what happened. The server SDKs (@livqeno/server, livqeno) call it for you. You only call it directly if your backend is in another language, or you're debugging with curl.

These rules apply to every endpoint. Read this page once, and the endpoint pages will make sense.

Base URL

Every endpoint starts with /v1:

https://api.livqeno.com/v1/...

Your backend reads this from LIVQENO_API_URL. If you don't set it, the SDKs use http://localhost:4100. That only works for a local mock or proxy, so always set it.

Authentication

Every request from your backend carries your project API key. Send it as a bearer token:

Terminal
curl "$LIVQENO_API_URL/v1/rooms" \
  -H "Authorization: Bearer $LIVQENO_API_KEY"
  • A key looks like rvk_<env>_<id>.<secret>. <env> is dev, stg, or prod.
  • Each key is tied to one environment on our side. A development key can never reach production data.
  • The <env> part is only a label for you to read.

More: API keys.

Errors

Every error looks like this:

{
  "code": "RAVEN_ROOM_NOT_FOUND",
  "legacyCode": "NOT_FOUND",
  "message": "Room not found",
  "requestId": "req_d4a74eaeb970633fc42414a6",
  "path": "/v1/rooms/2f1b6c3e-8d4a-4b7e-9c21-5a0e7d3f9b10"
}

A validation error (RAVEN_VALIDATION_FAILED, 400) has two extra fields, statusCode and error. Its message can be a list, with one entry per bad field:

{
  "message": ["environment must be one of the following values: DEVELOPMENT, STAGING, PRODUCTION"],
  "error": "Bad Request",
  "statusCode": 400,
  "code": "RAVEN_VALIDATION_FAILED",
  "legacyCode": "VALIDATION_FAILED",
  "requestId": "req_7f9f475ddcab0cb6f554f253",
  "path": "/v1/projects/…/api-keys"
}

How to handle errors:

  • Check code. That's the reliable field.
  • message can be a string or a list of strings (string | string[]).
  • Don't use legacyCode. It is old and will be removed.
  • Some errors add fields. For example, a 429 adds retryAfterSeconds. Ignore fields you don't know.
  • Ids in the URL are UUIDs. A badly formed id gets a 400, not a 404.

Every error code is listed in Errors.

Request ids

When something goes wrong, the request id is how you and Livqeno find the same request in the logs. Every response has an x-request-id header. Error bodies repeat it as requestId. Include it when you report a bug.

You can also send your own id, to follow one request through your logs and ours:

x-request-id: 7c1f9e2a-your-own-correlation-id
  • Your id is used only if it is 1–64 characters of A-Za-z0-9_-.
  • Otherwise we make a new one.
  • Our ids look like req_ plus 24 hex characters.

Safe retries (idempotency)

Networks fail. Say your backend sends "create a message" and the connection drops before the reply arrives. Did it work? If you just retry, you might post the message twice. Idempotency solves this: sending the same request again has the same effect as sending it once.

Endpoints that create a token or a message accept an Idempotency-Key header. If you retry with the same key, you get the first response back. The work is not done twice.

Terminal
curl -X POST .../v1/rooms/$ROOM_ID/rtc-tokens \
  -H "Authorization: Bearer $LIVQENO_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H 'Content-Type: application/json' \
  -d '{"participantIdentity":"user-42","permissions":{"join":true,"subscribe":true}}'

For token creation, the replay window is only 5 minutes. A token can expire in as little as 30 seconds, so a longer window could hand back a dead token.

The endpoint pages show which endpoints support this. More: Idempotency.

Pagination

You'll use this when loading older messages, for example as a user scrolls up in a chat window. Chat message history uses cursors, not page numbers. A cursor is an opaque marker that means "continue from here":

GET /v1/chat/conversations/{room}/messages?limit=50
GET /v1/chat/conversations/{room}/messages?before=<cursor>
  1. Read nextCursor from the response.
  2. Pass it back to get the next page.

Don't build or edit a cursor yourself. A broken cursor returns RAVEN_INVALID_CURSOR. It never quietly restarts at page one. More: Message history.

Environments

  • Endpoints you call with an API key take no environment parameter. The key decides.
  • Dashboard endpoints (with a login session) accept ?environment=. The default is development.

More: Environments.

Rate limits

Some endpoints have a rate limit. The endpoint pages show each limit. Rate limits explains how they are counted and how to handle a 429.

Next steps