Skip to main content

Introduction

The Manifest API provides programmatic access to AI agent observability, analytics, and LLM routing capabilities. The API is built on NestJS and uses RESTful principles with JSON request/response formats.

Base URL

The API base URL depends on your deployment mode:
https://your-domain.com

API Versioning

Most API endpoints use the /api/v1 prefix:
https://your-domain.com/api/v1/{endpoint}
OTLP ingestion endpoints use a separate /otlp/v1 prefix:
https://your-domain.com/otlp/v1/{endpoint}
LLM proxy endpoints follow the OpenAI-compatible format at /v1:
https://your-domain.com/v1/chat/completions

Response Format

All API responses use JSON format. Successful responses return the requested data with appropriate HTTP status codes.

Success Response

A typical success response for analytics data:
{
  "summary": {
    "tokens_today": 125000,
    "cost_today": 0.45,
    "messages": 342,
    "services_hit": {
      "total": 0,
      "healthy": 0,
      "issues": 0
    }
  },
  "token_usage": [...],
  "cost_usage": [...],
  "has_data": true
}

List Response

List endpoints return arrays with metadata:
{
  "data": [
    {
      "id": "agent-123",
      "name": "customer-support",
      "tenant_id": "tenant-456",
      "created_at": "2024-03-15T10:30:00Z"
    }
  ],
  "total": 1
}

Empty Response

Some endpoints return an empty success response with appropriate status codes:
HTTP 202 Accepted
{
  "accepted": 10,
  "rejected": 0
}

Error Handling

The API uses standard HTTP status codes to indicate success or failure. Error responses include a message and optional details.

Error Response Format

{
  "statusCode": 401,
  "message": "X-API-Key header required",
  "error": "Unauthorized"
}

Validation Errors

When request validation fails, the API returns detailed error information:
{
  "statusCode": 400,
  "message": "Bad Request",
  "error": "All events failed validation",
  "details": [
    "Invalid event type: expected 'message' or 'trace'"
  ]
}

HTTP Status Codes

The API uses the following status codes:
200
OK
Request succeeded. Response body contains the requested data.
202
Accepted
Request accepted for processing (used for telemetry ingestion). Processing happens asynchronously.
400
Bad Request
Invalid request parameters or validation errors. Check the error message for details.
401
Unauthorized
Missing or invalid authentication credentials. See Authentication for details.
403
Forbidden
Valid credentials provided, but insufficient permissions to access the resource.
404
Not Found
The requested resource does not exist.
429
Too Many Requests
Rate limit exceeded. Default limits: 100 requests per 60 seconds. The proxy endpoint has separate per-user concurrency limits.
500
Internal Server Error
An unexpected error occurred on the server. If this persists, contact support.

Rate Limiting

The API implements rate limiting to ensure fair usage:
Default Limits
throttle
  • Window: 60 seconds (configurable via THROTTLE_TTL)
  • Max requests: 100 per window (configurable via THROTTLE_LIMIT)
  • Headers: Rate limit information is not currently exposed in response headers
Proxy Limits
special
The LLM proxy endpoint (/v1/chat/completions) has additional per-user concurrency limits to prevent resource exhaustion. Rate limit errors (HTTP 429) are recorded and suppressed with a 60-second cooldown to avoid log spam.
OTLP ingestion endpoints (/otlp/v1/*) skip throttling to ensure telemetry data is never rejected due to rate limits.

CORS Policy

CORS is enabled in development mode only:
  • Development: Enabled for http://localhost:3000 and http://127.0.0.1:3000 (configurable via CORS_ORIGIN)
  • Production: Disabled (API and frontend served from same origin)
  • Credentials: Supported (cookies, authorization headers)

Security Headers

The API enforces strict security policies via Helmet:
// Content Security Policy
defaultSrc: ["'self'"]
scriptSrc: ["'self'"]
styleSrc: ["'self'", "'unsafe-inline'"]
imgSrc: ["'self'", "data:"]
connectSrc: ["'self'", "https://eu.i.posthog.com"]
fontSrc: ["'self'"]
objectSrc: ["'none'"]
frameAncestors: ["'none'"]
External CDN resources are not permitted. All assets must be self-hosted.

Request Examples

Using cURL

Session Authentication
curl -X GET 'https://your-domain.com/api/v1/overview?range=24h' \
  -H 'Cookie: better-auth.session_token=your-session-token' \
  -H 'Content-Type: application/json'
API Key Authentication
curl -X GET 'https://your-domain.com/api/v1/overview?range=24h' \
  -H 'X-API-Key: your-api-key' \
  -H 'Content-Type: application/json'
OTLP Bearer Token
curl -X POST 'https://your-domain.com/otlp/v1/traces' \
  -H 'Authorization: Bearer mnfst_your-agent-key' \
  -H 'Content-Type: application/json' \
  -d '{"resourceSpans": [...]}'

Using JavaScript

Fetch API
const response = await fetch('https://your-domain.com/api/v1/overview?range=24h', {
  method: 'GET',
  headers: {
    'X-API-Key': 'your-api-key',
    'Content-Type': 'application/json'
  }
});

const data = await response.json();
console.log(data);

Using Python

Requests Library
import requests

url = 'https://your-domain.com/api/v1/overview'
headers = {
    'X-API-Key': 'your-api-key',
    'Content-Type': 'application/json'
}
params = {'range': '24h'}

response = requests.get(url, headers=headers, params=params)
data = response.json()
print(data)

Query Parameters

Many analytics endpoints support common query parameters:
range
string
default:"24h"
Time range for analytics queries. Supported values:
  • 1h, 6h, 12h, 24h (hourly granularity)
  • 7d, 30d, 90d (daily granularity)
agent_name
string
Filter results to a specific agent. Omit to see data across all agents.
page
number
default:"1"
Page number for paginated endpoints (e.g., message log).
limit
number
default:"50"
Number of items per page for paginated endpoints.

Multi-Tenancy

The API automatically isolates data by tenant:
  • Session Auth: Data filtered by user.id from the authenticated session
  • API Key Auth: Data filtered by the user_id associated with the API key
  • OTLP Auth: Data scoped to the tenant_id and agent_id from the Bearer token
All analytics queries include automatic tenant filtering via the addTenantFilter() helper. You cannot access data belonging to other users or tenants.

Next Steps

Authentication

Learn about authentication methods and security

Analytics

Query usage metrics and cost analytics

OTLP Ingestion

Send telemetry data via OpenTelemetry

LLM Routing

Configure model routing and use the proxy

Build docs developers (and LLMs) love