Skip to main content
A
Docs

API Conventions

Standard patterns for request/response format, pagination, errors, and auth across all Anar APIs.

Overview

All Anar product APIs follow consistent conventions for endpoints, request/response format, authentication, pagination, and error handling. The Gateway (Go) exposes an OpenAI-compatible API; the 13 Python products use FastAPI with auto-generated OpenAPI specs.

Base URLs

Every product API is versioned under /api/v1:

http://localhost:8001/api/v1/conversations
http://localhost:8002/api/v1/policies
http://localhost:8003/api/v1/transcriptions

The Gateway uses OpenAI-compatible paths:

http://localhost:8080/v1/chat/completions
http://localhost:8080/v1/models
http://localhost:8080/health

Request Format

Content Type

All request bodies use application/json unless uploading files:

curl -X POST http://localhost:8002/api/v1/scan \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{"text": "Check this content"}'

File Uploads

File endpoints accept multipart/form-data:

curl -X POST http://localhost:8008/api/v1/docs/process \
  -H "Authorization: Bearer <token>" \
  -F "file=@document.pdf"

Request Size Limits

The shared middleware enforces a default 10MB request body limit. File-heavy products (Docs, Voice, Minutes) may configure higher limits. Requests exceeding the limit receive a 413 response:

{
  "error": "Request body too large. Maximum: 10MB"
}

Response Format

Success Responses

Successful responses return the requested resource directly:

{
  "id": "conv_abc123",
  "title": "Budget Discussion",
  "created_at": "2026-02-16T10:30:00Z",
  "messages": []
}

List endpoints return an array:

[
  {"id": "pol_001", "name": "PII Detection", "enabled": true},
  {"id": "pol_002", "name": "Content Safety", "enabled": true}
]

Paginated Responses

Endpoints returning large collections support offset-based pagination:

ParameterTypeDefaultDescription
skipinteger0Number of records to skip
limitinteger50Maximum records to return
GET /api/v1/conversations?skip=0&limit=20

Response includes the items directly. Use the returned array length to determine if more pages exist.

Timestamps

All timestamps use ISO 8601 format with UTC timezone:

2026-02-16T10:30:45.123456+00:00

IDs

Resource IDs are strings. Some products use UUIDs, others use prefixed IDs:

conv_abc123      # Chat conversation
pol_def456       # Guard policy
wf_ghi789       # Flow workflow

Authentication

Bearer Token

All endpoints (except health checks and OpenAPI docs) require JWT authentication:

Authorization: Bearer eyJhbGciOiJIUzI1NiIs...

Unauthenticated Response

Missing or invalid tokens return 401:

{
  "detail": "Invalid authentication token"
}

Insufficient Permissions

Valid token with wrong role returns 403:

{
  "detail": "Role 'user' not authorized. Requires: admin, manager"
}

Standard Headers

Request Headers

HeaderRequiredDescription
AuthorizationYesBearer <jwt-token>
Content-TypeYesapplication/json or multipart/form-data
X-Request-IDNoClient-provided request ID (auto-generated if absent)

Response Headers

HeaderDescription
X-Request-IDRequest trace identifier (echoed or generated)
X-Response-TimeRequest duration (e.g., 45.23ms)
X-Content-Type-Optionsnosniff
X-Frame-OptionsDENY
Strict-Transport-Securitymax-age=63072000; includeSubDomains

Error Responses

Error Format

All errors return a JSON body with an error field:

{
  "error": "Resource not found"
}

Validation errors include a details array:

{
  "error": "Validation error",
  "details": [
    {
      "loc": ["body", "text"],
      "msg": "field required",
      "type": "value_error.missing"
    }
  ]
}

HTTP Status Codes

CodeMeaningWhen Used
200OKSuccessful GET, PUT, PATCH
201CreatedSuccessful POST creating a resource
204No ContentSuccessful DELETE
400Bad RequestMalformed request body
401UnauthorizedMissing or invalid JWT
403ForbiddenValid JWT but insufficient role
404Not FoundResource does not exist
409ConflictDuplicate resource (e.g., duplicate policy name)
413Payload Too LargeRequest body exceeds size limit
422Unprocessable EntityRequest validation failed
429Too Many RequestsRate limit exceeded
500Internal Server ErrorUnhandled server error
502Bad GatewayUpstream provider error (via Gateway)
503Service UnavailableService is starting up or shutting down

Rate Limiting

The shared middleware applies per-IP rate limits:

Path TypeLimit
Regular endpoints100 requests per minute
Heavy endpoints (LLM calls, exports)10 requests per minute

When rate-limited, the response is:

{
  "error": "Rate limit exceeded. Try again later."
}

Streaming (SSE)

Chat, Agents, and Voice products support Server-Sent Events for streaming responses:

curl -X POST http://localhost:8001/api/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{"messages": [{"role": "user", "content": "Hello"}], "stream": true}'

SSE events follow the OpenAI streaming format:

data: {"choices": [{"delta": {"content": "Hello"}, "index": 0}]}

data: {"choices": [{"delta": {"content": " there"}, "index": 0}]}

data: [DONE]

Health Check Endpoint

Every product exposes an unauthenticated health endpoint:

GET
/health
{
  "status": "healthy",
  "version": "0.1.0",
  "product": "anar-chat",
  "uptime_seconds": 3642.5
}

Some products also expose /api/v1/health with additional details.

OpenAPI Documentation

All FastAPI products serve interactive API documentation:

PathFormat
/docsSwagger UI
/redocReDoc
/openapi.jsonOpenAPI 3.x schema

These endpoints are excluded from authentication and rate limiting.