The
Authorization value can be either an API key (sk_agentmark_...) or a session JWT (used by the Dashboard and agentmark login).
The REST API accepts the
Authorization value with or without the Bearer prefix. The one exception is OpenTelemetry trace ingestion (POST /v1/traces via an OTLP exporter): send the raw key with no Bearer prefix, or the request fails with 401. See OpenTelemetry → Endpoint.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’s only shown once
API key environment scope
When you create a key, the Environment scope choice in the create-key dialog decides which environments the key can reach:- This environment (the default) pins the key to the environment selected in the breadcrumb. Its traces always land in that one environment, and the key can’t reach any other.
- Environment kinds scopes the key to one or more kinds (Development, Preview, and Production) instead of pinning it. A kind-scoped key has no environment pin. Each request names the target environment (by environment name, or by the pull request number whose preview environment it targets), and the gateway authorizes that environment against the key’s allowed kinds before stamping it. The gateway rejects a selection that resolves to a kind the key can’t write to, so those traces stamp no environment rather than crossing kinds.
initTracing({ environment, prNumber }), or through the AGENTMARK_ENVIRONMENT and AGENTMARK_PR_NUMBER variables in CI. See Attributing traces to an environment.
You create kind-scoped keys through the Dashboard’s create-key dialog. The programmatic
POST /v1/api-keys route mints pinned keys only.Endpoint permissions
Every API endpoint requires a specific permission. If your API key lacks the required permission, the request returns403 Forbidden.
Traces and spans
Sessions
Scores
Metrics, datasets, experiments, prompts
Unauthenticated
Making requests
- curl
- TypeScript
- Python
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 returns429 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)
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
Every/v1 error body follows the same shape, { error: { code, message } }:
code and message. Quota errors, for example, spread their context as flat siblings:
400 validation errors are the one case that nests: error.message is a generic summary (Invalid request body / Invalid query parameters / Invalid path parameters), and the error.details map collects the per-field messages keyed by field name: