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:
| Parameter | Type | Default | Description |
|---|---|---|---|
skip | integer | 0 | Number of records to skip |
limit | integer | 50 | Maximum 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
| Header | Required | Description |
|---|---|---|
Authorization | Yes | Bearer <jwt-token> |
Content-Type | Yes | application/json or multipart/form-data |
X-Request-ID | No | Client-provided request ID (auto-generated if absent) |
Response Headers
| Header | Description |
|---|---|
X-Request-ID | Request trace identifier (echoed or generated) |
X-Response-Time | Request duration (e.g., 45.23ms) |
X-Content-Type-Options | nosniff |
X-Frame-Options | DENY |
Strict-Transport-Security | max-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
| Code | Meaning | When Used |
|---|---|---|
| 200 | OK | Successful GET, PUT, PATCH |
| 201 | Created | Successful POST creating a resource |
| 204 | No Content | Successful DELETE |
| 400 | Bad Request | Malformed request body |
| 401 | Unauthorized | Missing or invalid JWT |
| 403 | Forbidden | Valid JWT but insufficient role |
| 404 | Not Found | Resource does not exist |
| 409 | Conflict | Duplicate resource (e.g., duplicate policy name) |
| 413 | Payload Too Large | Request body exceeds size limit |
| 422 | Unprocessable Entity | Request validation failed |
| 429 | Too Many Requests | Rate limit exceeded |
| 500 | Internal Server Error | Unhandled server error |
| 502 | Bad Gateway | Upstream provider error (via Gateway) |
| 503 | Service Unavailable | Service is starting up or shutting down |
Rate Limiting
The shared middleware applies per-IP rate limits:
| Path Type | Limit |
|---|---|
| Regular endpoints | 100 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:
/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:
| Path | Format |
|---|---|
/docs | Swagger UI |
/redoc | ReDoc |
/openapi.json | OpenAPI 3.x schema |
These endpoints are excluded from authentication and rate limiting.