Conventions and permissions
In shortThe 10xGraph REST API response envelope, HTTP and WebSocket authentication, the endpoint permission table, WebSocket close codes and HTTP status codes.
- 5 min read
- 5 sections
- Updated
- v0.10.0
- Markdown
Every route in the 10xGraph REST API lives under /v1/ (except /ping), returns the same JSON envelope, authenticates with a Bearer token, and is guarded by a resource and action permission pair. This page lists those shared rules, the full permission table, the WebSocket close codes and the HTTP status codes.
Base URL and response envelope
Successful responses wrap the payload in data and add a metadata object with request_id, timestamp and message. Errors raised by the application return error instead, with the same metadata. The details list is empty unless the error carries extra context (validation errors, for example).
{
"data": {},
"metadata": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-05-23T10:00:00",
"message": "OK"
}
}{
"error": {
"code": "EXPIRED_TOKEN",
"message": "Token has expired, please login again",
"details": []
},
"metadata": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-05-23T10:00:00",
"message": "Token has expired, please login again"
}
}Errors from HTTPException (permission denied, not found, empty upload) use the code HTTPException. Request validation failures use VALIDATION_ERROR. Three responses come from middleware and do not use this exact shape: 409, 413 and 429 (see HTTP status codes).
Authentication
When auth is configured in 10xgraph.json, every endpoint except /ping (and the public eval routes) needs a Bearer token. Send it as an Authorization header on HTTP routes. WebSocket clients that cannot set headers have two fallbacks, listed here in order of preference.
Authorization: Bearer <token>// Preferred for browsers: the token rides in a request header, not the URL
new WebSocket("ws://host/v1/graph/ws", ["10xgraph-bearer", token]);# Last-resort fallback (WebSocket only): the token lands in URLs and access logs
/v1/graph/ws?token=<token>The server echoes the 10xgraph-bearer sentinel back on accept, which browsers require to complete the handshake. The older agentflow-bearer sentinel is accepted until 2.0. The ?token= query parameter is read only on WebSocket connections.
If auth is not configured ("auth": null), credentials are not required. Missing, invalid or expired credentials return HTTP 401. A permission failure returns 403. On WebSocket routes both become close code 1008. See authentication for setup.
Permission model
Each endpoint declares one (resource, action) pair. On every request the server calls authorize(user, resource, action) on the configured AuthorizationBackend. The built-in DefaultAuthorizationBackend allows any request whose user has a user_id, so write your own backend for real access control.
Permission reference
The table lists every (resource, action) pair the server enforces. POST /v1/ag-ui exists only when ag_ui.enabled is true in 10xgraph.json. The /v1/evals/* routes are mounted only when MODE is not production.
| Endpoint | Resource | Action |
|---|---|---|
POST /v1/graph/invoke |
graph |
invoke |
POST /v1/graph/stream |
graph |
stream |
POST /v1/ag-ui |
graph |
stream |
WebSocket /v1/graph/ws |
graph |
stream |
WebSocket /v1/graph/live |
graph |
stream |
GET /v1/graph |
graph |
read |
GET /v1/graph/tools |
graph |
read |
GET /v1/observability/{thread_id} |
graph |
read |
GET /v1/graph:StateSchema |
graph |
read |
POST /v1/graph/stop |
graph |
stop |
POST /v1/graph/fix |
graph |
fix |
GET /v1/threads/{id}/state |
checkpointer |
read |
PUT /v1/threads/{id}/state |
checkpointer |
write |
DELETE /v1/threads/{id}/state |
checkpointer |
delete |
GET /v1/threads/{id}/messages |
checkpointer |
read |
GET /v1/threads/{id}/messages/{msg} |
checkpointer |
read |
POST /v1/threads/{id}/messages |
checkpointer |
write |
DELETE /v1/threads/{id}/messages/{msg} |
checkpointer |
delete |
GET /v1/threads |
checkpointer |
read |
GET /v1/threads/{id} |
checkpointer |
read |
DELETE /v1/threads/{id} |
checkpointer |
delete |
POST /v1/store/memories |
store |
write |
POST /v1/store/search |
store |
read |
POST /v1/store/memories/{id} |
store |
read |
POST /v1/store/memories/list |
store |
read |
PUT /v1/store/memories/{id} |
store |
write |
DELETE /v1/store/memories/{id} |
store |
delete |
POST /v1/store/memories/forget |
store |
delete |
POST /v1/files/upload |
files |
upload |
GET /v1/files/{id} |
files |
read |
GET /v1/files/{id}/info |
files |
read |
GET /v1/files/{id}/url |
files |
read |
GET /v1/config/multimodal |
config |
read |
GET /ping |
(none) | (none) |
GET /v1/evals/runs |
(none) | (none) |
GET /v1/evals/runs/{run_id} |
(none) | (none) |
The last three rows are the complete public allowlist. Every other route must carry a RequirePermission guard, and the server refuses to start if one does not.
WebSocket close codes
WebSocket routes report failures with close codes instead of HTTP statuses. 1008 also covers a graph that is on the wrong socket: a realtime graph on /v1/graph/ws, or a turn-based graph on /v1/graph/live.
| Code | Name | When |
|---|---|---|
1000 |
Normal closure | The client disconnected cleanly |
1008 |
Policy violation | Authentication or authorization failed, or the graph type does not match the route |
1011 |
Server error | Unexpected server error |
1013 |
Try again later | Rate limit or connection cap exceeded at the handshake |
HTTP status codes
These are the status codes the server returns. Routes document their own specific causes on their pages.
| Code | When |
|---|---|
200 |
Success |
400 |
Empty file upload, missing filename, or malformed Content-Length |
401 |
Missing, invalid or expired credentials |
403 |
Insufficient permissions, or access to a thread you do not own |
404 |
File, thread, message or eval run not found |
409 |
Another run updated the thread while yours was in flight. Body is {"error": "state_conflict", "detail": "...", "thread_id": ...}. Reload the thread and retry |
413 |
Request body over MAX_REQUEST_SIZE (default 10 MB), or upload over MEDIA_MAX_SIZE_MB (default 25) |
415 |
Uploaded content type not allowed |
422 |
Request validation error (malformed body or invalid parameter) |
429 |
Rate limit exceeded. Body has error.code RATE_LIMIT_EXCEEDED; the Retry-After and X-RateLimit-* headers say when to retry |
500 |
Unexpected server error |
503 |
Checkpointer or storage temporarily unavailable |