Skip to content

API Reference ​

Base URL: https://api.echomode.io/v1

All endpoints return JSON unless noted (e.g. POST /chats/{chat_id}/messages/stream uses Server-Sent Events).

POST /chats/{chat_id}/messages/stream emits meta, then delta events carrying reply text, then one done
event. The done event includes context, describing how much of the model's window the
request used:

{"type": "done", "context": {"used": 2088, "limit": 128000, "compacted": true}}

used is the prompt tokens the provider counted, limit is the model's context window,
and compacted is true once older turns in the chat have been folded into a summary.
limit is null when the window is unknown, and clients must then hide any usage
indicator rather than assume a size. An error event carries the same detail and code
pair as a JSON error response. Authenticated endpoints require a Bearer token in the Authorization header.

Authentication

EchoMode uses JWT bearer tokens with refresh-token rotation. Obtain tokens via login or SSO, then pass the access token on every request:

Authorization: Bearer <access_token>

When the access token expires, exchange the refresh token for a new pair via POST /auth/refresh.

Versioning

The API is versioned in the path. Every endpoint below is reachable at
https://api.echomode.io/v1/<path> — the base URL above already includes it,
so paths in this reference are written relative to it.

Build clients to tolerate additions: new endpoints, new optional request fields,
and new response fields can appear under v1. Ignore response fields you do not
recognize rather than failing on them.

One surface sits outside the version prefix:

Path Why
/hooks/workflows/* Webhook ingress — the URLs are stored in your systems

Error format

Errors carry a detail field. For everything except 422 it is a string you can
surface directly:

{
  "detail": "Human-readable error message"
}

Some errors also carry a machine-readable code. Switch on it rather than matching the
prose, which is free to change:

{
  "detail": "this message does not fit the model's context window. Remove an attached file or narrow the Knowledge Base selection, then send again",
  "code": "context_overflow"
}
code Returned by Meaning
context_overflow POST /chats/{chat_id}/messages, POST /chats/{chat_id}/messages/stream The request still exceeds the model's context window after older turns were summarised. Remove an attachment or narrow the Knowledge Base selection.
Status Meaning
400 Validation or domain error
401 Missing or expired token
403 Insufficient permissions
404 Resource not found
409 Conflict (duplicate email, etc.)
413 Payload too large (avatar > 5 MB), or a chat request that does not fit the model's context window (code: "context_overflow")
422 Request body failed schema validation — detail is a list, see below
429 Rate limited

Unknown fields in a request

Request bodies reject fields they do not declare. A misspelled key is refused with
422 rather than accepted and ignored, so a mistyped field surfaces as an error
instead of a silent no-op.

On a 422 the detail field is a list of problems, one entry per field.
loc locates the field, and type is extra_forbidden for an undeclared one:

{
  "detail": [
    {
      "type": "extra_forbidden",
      "loc": ["body", "visibilty"],
      "msg": "Extra inputs are not permitted",
      "input": "personal"
    }
  ]
}

Read loc last-element-first to find the offending key — here visibilty, a
misspelling of visibility. The same list carries ordinary validation failures
(missing required fields, wrong types), so handling it once covers both.

Responses work the opposite way: ignore response fields you do not recognize — new
ones can appear (see Versioning above).

Pagination

List endpoints use two pagination styles:

Keyset pagination (chats, logs): pass the next_cursor value from the response as the cursor query parameter.

Offset pagination (documents, job audit): use limit/offset query parameters.

Enums & constants

Accepted values for each enum field appear on that field in the reference below.
The ones here need more than a list: what the values mean, and how they move.

Visibility

Controls who can access a resource (agents, chats, documents, folders).

Value Scope
personal Only the creator can access
team_level Accessible to members of the specified teams (requires team_ids)
org_level Accessible to all organization members
universal Read-only built-in resources (cannot be created via API)

Echo state

The alignment state machine that tracks whether conversations stay on-topic.

Value Meaning
stable Conversation is on-topic
mildDrift Slight topic drift detected
moderateDrift Significant topic drift
severeDrift Conversation has drifted far off-topic
assistantRefusal The assistant refused to respond

Transitions flow: stable → mildDrift → moderateDrift → severeDrift. On-topic messages move the state back toward stable. assistantRefusal is set independently when a refusal is detected.

Organization tier

Value Description
free Free tier (default for new self-serve organizations)
pro Pro tier
max Max tier

Transition reason

Returned inside Echo events arrays to explain why the alignment state changed.

Value Meaning
no change Score stayed within current state bounds
scored below bound of stable Score dropped below the stable threshold
scored below bound of mild drift Score dropped below the mild-drift threshold
scored below bound of moderate drift Score dropped below the moderate-drift threshold
scored above bound of mild drift Score rose above the mild-drift threshold (recovering)
scored above bound of moderate drift Score rose above the moderate-drift threshold (recovering)
scored above bound of severe drift Score rose above the severe-drift threshold (recovering)
user exceeded off topic streak Consecutive off-topic rounds hit the streak threshold
user exceeded on topic streak Consecutive on-topic rounds hit the recovery threshold
assistant refusal detected The assistant refused to respond
assistant refusal cleared A normal response followed a prior refusal