Documentation Index
Fetch the complete documentation index at: https://docs.agentmark.co/llms.txt
Use this file to discover all available pages before exploring further.
All API endpoints (except health checks and capabilities) require two headers:
| Header | Description |
|---|
Authorization | Your API key — Bearer sk_agentmark_... |
X-Agentmark-App-Id | Your application ID — app_... |
The gateway also accepts the legacy X-Puzzlet-App-Id header (per verify-api-key.ts:12), but new integrations should use X-Agentmark-App-Id.
Creating an API key
- Open the AgentMark Dashboard
- Switch to the app you want to scope the key to (shown in the breadcrumb)
- Navigate to the app’s Settings → API keys page (app-level, not org-level)
- Click Create API key
- Select a role (SDK, Read-Only, or Full Access) or choose Custom to toggle individual permissions
- Copy the key — it is only shown once
API keys enforce per-endpoint permissions. A key with SDK access can ingest traces and read templates but cannot delete anything. See Users and access control for the permission catalog and role presets.
Endpoint permissions
Every API endpoint requires a specific permission. If your API key lacks the required permission, the request returns 403 Forbidden.
Traces and spans
| Endpoint | Permission |
|---|
POST /v1/traces | trace.write |
GET /v1/traces | trace.read |
GET /v1/traces/{traceId} | trace.read |
GET /v1/traces/{traceId}/graph | trace.read |
GET /v1/traces/{traceId}/spans | span.read |
GET /v1/traces/{traceId}/spans/{spanId} | span.read |
GET /v1/spans | span.read |
Sessions
| Endpoint | Permission |
|---|
GET /v1/sessions | session.read |
GET /v1/sessions/{sessionId}/traces | session.read |
Scores
| Endpoint | Permission |
|---|
POST /v1/scores | score.write |
POST /v1/scores/batch | score.write |
GET /v1/scores | score.read |
GET /v1/scores/{scoreId} | score.read |
GET /v1/scores/aggregations | score.read |
GET /v1/scores/names | score.read |
DELETE /v1/scores/{scoreId} | score.delete |
Metrics, datasets, experiments, prompts
| Endpoint | Permission |
|---|
GET /v1/metrics | trace.read |
GET /v1/config | template.read |
GET /v1/datasets | dataset.read |
POST /v1/datasets/{datasetName}/rows | dataset.write |
POST /v1/datasets/{datasetName}/rows/from-traces | dataset.write |
POST /v1/datasets/{datasetName}/rows/from-spans | dataset.write |
GET /v1/experiments | experiment.read |
GET /v1/experiments/{experimentId} | experiment.read |
GET /v1/prompts | template.read |
GET /v1/runs/{runId}/traces | trace.read |
GET /v1/templates/{templatePath} | template.read |
Annotation queues
| Endpoint | Permission |
|---|
GET /v1/annotation-queues | annotation_queue.read |
POST /v1/annotation-queues | annotation_queue.write |
GET /v1/annotation-queues/{queueId} | annotation_queue.read |
PATCH /v1/annotation-queues/{queueId} | annotation_queue.write |
DELETE /v1/annotation-queues/{queueId} | annotation_queue.delete |
GET /v1/annotation-queues/{queueId}/items | annotation_queue.read |
POST /v1/annotation-queues/{queueId}/items | annotation_queue.write |
GET /v1/annotation-queues/{queueId}/items/{itemId} | annotation_queue.read |
PATCH /v1/annotation-queues/{queueId}/items/{itemId} | annotation_queue.write |
DELETE /v1/annotation-queues/{queueId}/items/{itemId} | annotation_queue.delete |
POST /v1/annotation-queues/{queueId}/items/{itemId}/reviews | annotation_queue.review |
Unauthenticated
| Endpoint | Notes |
|---|
GET /v1/capabilities | No auth required |
GET /health | No auth required |
GET /v1/health/ingestion | No auth required |
GET /v1/health/files | No auth required |
Making requests
curl https://api.agentmark.co/v1/traces \
-H "Authorization: Bearer sk_agentmark_your_key_here" \
-H "X-Agentmark-App-Id: app_your_app_id_here"
const response = await fetch("https://api.agentmark.co/v1/traces", {
headers: {
"Authorization": `Bearer ${process.env.AGENTMARK_API_KEY}`,
"X-Agentmark-App-Id": process.env.AGENTMARK_APP_ID!,
},
});
const data = await response.json();
import os
import requests
response = requests.get(
"https://api.agentmark.co/v1/traces",
headers={
"Authorization": f"Bearer {os.environ['AGENTMARK_API_KEY']}",
"X-Agentmark-App-Id": os.environ["AGENTMARK_APP_ID"],
},
)
data = response.json()
Rate limiting
API requests are rate-limited per tenant. Limits vary by plan — see Billing and usage. When you exceed your rate limit, the API returns 429 Too Many Requests with a Retry-After header indicating how long to wait before retrying.
Span and storage limits
Trace ingestion (POST /v1/traces) enforces monthly quotas depending on your plan:
- Span limit — maximum number of spans per month (Hobby/Growth tiers)
- Storage cap — maximum storage used (certain plans only)
When exceeded, the API returns 429 with a span_limit_exceeded or storage_cap_exceeded error code and a Retry-After header. Upgrade your plan at Settings → Billing.
Error responses
Error bodies follow this shape:
{
"error": {
"message": "Not authorized"
}
}
Some errors include a machine-readable code and additional details:
{
"error": {
"code": "span_limit_exceeded",
"message": "Monthly unit limit exceeded. Upgrade your plan for unlimited units.",
"details": {
"currentCount": 20000,
"limit": 20000,
"upgradeUrl": "https://app.agentmark.co/settings/billing"
}
}
}
| Status | Meaning |
|---|
400 | Invalid request — check the details array for field-level errors |
401 | Missing or invalid Authorization / X-Agentmark-App-Id header |
403 | API key is valid but does not have the required permission for this endpoint |
429 | Rate limited or plan quota exceeded |
503 | Service temporarily overloaded — retry after the interval in the Retry-After header |