> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.loreos.app/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.loreos.app/_mcp/server.

# Core concepts

## Response envelope

Every successful response has the same shape:

```json
{
  "schema_version": "...",
  "data": { "...": "the actual result" },
  "next_actions": [ { "command": "...", "description": "..." } ]
}
```

* **`data`** holds the result — read your fields from here.
* **`next_actions`** is a hint about what to call next (handy for agents and for chaining
  calls without re-reading the docs).

## Errors

Failures return a machine-readable error nested under `detail` (the FastAPI envelope):

```json
{ "detail": { "code": "...", "message": "human-readable", "fix": "how to resolve it" } }
```

Read `body.detail.code` (not a top-level `code`). Common HTTP statuses:

* **`401`** — missing API key (no `Authorization: Bearer`).
* **`403`** — invalid, revoked, or expired key.
* **`402`** — you've hit a budget cap (see Usage & limits); returned before any model call.
* **`404`** — not found, or not owned by your app (cross-tenant resources look absent).
* **`422`** — request validation failed (bad/missing fields).

## Replies are asynchronous

Sending a message starts a **run** — the character's reply is produced in the background.
You don't get the reply in the `POST .../messages` response. Instead:

* **Poll** `GET /v1/sessions/{session_id}/events` until the reply event appears, or
* **Stream** `GET /v1/sessions/{session_id}/events/stream` (Server-Sent Events) for push.

`GET /v1/sessions/{session_id}/runs` shows the status of in-flight and past runs.

## End-users

Your end-users are **bring-your-own**: you pass an opaque `external_user_ref` (your id for
the user) when starting a session. LoreOS tracks each end-user's relationship and usage
under that ref, scoped to your app — it never authenticates your user. Manage them under
**End-users**:

* `GET /v1/external-users` lists the app's end-users for dashboards, with usage,
  limits, session count, last activity, and `next_cursor` pagination.
* `GET /v1/external-users/{external_user_ref}` reads one user record and usage summary.
* `GET /v1/external-users/{external_user_ref}/sessions` lists that user's sessions.
* `POST /v1/external-users/{external_user_ref}/budget-policy` sets the enforced
  per-user hard cap.

To inspect conversation events, list the user's sessions first, then read
`GET /v1/sessions/{session_id}/events?since=0`. The user list endpoint is a
CRM/metering summary, not a transcript export.

## Usage & limits

Calls are metered. You can set an app-wide budget and per-end-user caps; once a cap is
reached, requests return **`402`** before any model call runs (no surprise spend). Check
`GET /v1/usage` for app usage and `GET /v1/rates` for the rate card.

## Character readiness

A bare character (just a slug + name) will chat, but a great one needs a persona, voice,
and — for selfies — an identity image. Before you launch, check
`GET /v1/characters/{slug}/readiness` (per-area readiness + score) and
`GET /v1/characters/{slug}/runtime-preview` (what the engine will actually use).

## Stateful runtime

LoreOS compiles character behavior from ledgers: persona, memory, character facts,
relationship state, world context, visual readiness, and recent session events. That
compiled runtime state is separate from private plans and internal candidates.

This separation matters:

* model-generated candidates do not automatically become facts;
* committed state does not automatically become visible;
* runtime chat only receives safe context;
* each app and external user stays isolated.

Read the platform overview in [Architecture](https://docs.loreos.app/platform/architecture) and
[Character state](https://docs.loreos.app/platform/character-state).

## For coding agents

* `GET https://api.loreos.app/v1/llms.txt` — an agent-friendly integration guide.
* The docs site serves `/llms.txt` and `/.well-known/api-catalog`; append `.md` to a docs
  page URL when an agent needs that page as Markdown.