Maple API
The Maple REST API: base URLs, API keys and scopes, the resources it exposes, pagination, the error envelope, rate limits, and where the OpenAPI specification lives.
The Maple API is the HTTP interface to your Maple organization. It covers dashboards, alert rules and destinations, error issues, scrape targets, ingest and API keys, and read access to traces, logs, metrics, services and session replays. The dashboard uses the same endpoints.
| Base URL (US) | https://api.maple.dev/v2 |
| Base URL (EU) | https://api.eu.maple.dev/v2 |
| Interactive reference | api.maple.dev/v2/docs (EU: api.eu.maple.dev/v2/docs) |
| OpenAPI 3.1 specification | maple.dev/openapi.json (also api.maple.dev/openapi.json) |
| MCP server for AI agents | Maple MCP server |
| Auth | Authorization: Bearer maple_ak_… |
Use the base URL of your organization’s region. A key created in one region does not work in the other.
Authentication
Create an API key in the dashboard under Settings → API Keys, or with POST /v2/api_keys using an existing key. Send it as a Bearer token on every request:
curl https://api.maple.dev/v2/services \
-H "Authorization: Bearer maple_ak_…"
Keys can be scoped at creation. A scope is <family>:read, <family>:write, or *. The family is the first path segment under /v2, listed in the resource index below. write implies read, and a key with no scopes has full access. GET requests need read; POST, PATCH, PUT and DELETE need write, except the search, timeseries, breakdown and preview POSTs, which need only read. A request outside a key’s scopes fails with 403, type: "permission_error" and code: "insufficient_scope".
Keys belong to one organization. Authentication covers every credential Maple accepts, including dashboard session tokens and the x-maple-org-id header.
Resources
Each row is one scope family. The interactive reference documents every operation.
| Family | Endpoints |
|---|---|
api_keys | List, create, get, revoke and roll API keys |
ingest_keys | Read the organization’s public and private ingest keys, and roll either one |
organization | The current organization |
audit_log | The organization’s audit log |
dashboards | Dashboards, templates, version history and restore, public share links, Perses import |
alerts | Alert rules (with test and preview), rule checks, destinations, incidents and deliveries |
error_issues | Error issues and per-service issue counts |
traces | Search traces, time series and breakdowns, one trace, one span |
logs | Search logs, time series and breakdowns, one log record |
metrics | List metrics, time series and breakdowns |
services | Services, one service, and a service overview |
service_map | Service dependency edges |
environments | Deployment environments seen in your data |
session_replays | Search replays, the replays for a trace, one replay’s manifest, events and transcript |
scrape_targets | Prometheus scrape targets, their checks, and a test probe |
attribute_mappings | Attribute mappings |
instrumentation | Instrumentation recommendations, the setup audit, and which signals each service sends |
integrations | Chat connectors and the PlanetScale integration |
Conventions
- Resources are plural nouns under
/v2(/v2/api_keys,/v2/alerts/rules). Actions that are not plain CRUD arePOSTs to a sub-resource (POST /v2/api_keys/{id}/roll). Complex reads arePOST …/search. - Every object carries an
objectfield and a prefixed, opaque public ID (key_…,dash_…,alrt_…). - The wire format is snake_case JSON with ISO-8601 UTC timestamps. Nullable fields are explicit
null. - Updates are JSON
PATCHbodies.
Pagination
List endpoints accept limit (1 to 100, default 20) and an opaque cursor. They return:
{ "object": "list", "data": [], "has_more": true, "next_cursor": "…" }
To read the next page, send the same request with cursor set to next_cursor. Stop when has_more is false. A limit outside 1 to 100 is a 400.
Errors
Every failure, including an unknown route, returns a JSON envelope with the same shape:
{
"error": {
"_tag": "@maple/http/v2/RouteNotFoundError",
"type": "not_found_error",
"code": "route_not_found",
"title": "No such route",
"message": "No route matches GET /v2/typo. The Maple API is documented at https://api.maple.dev/v2/docs; the OpenAPI specification is at https://api.maple.dev/openapi.json.",
"retryable": false,
"recovery": "fix_request"
}
}
| Field | Meaning |
|---|---|
_tag | The exact failure. Branch on this. The OpenAPI spec lists the tags each operation can return |
type | The status family: invalid_request_error (400), authentication_error (401), payment_error (402), permission_error (403), not_found_error (404), conflict_error (409), rate_limit_error (429) or api_error (5xx) |
code | A short category for display |
title, message | Human-readable text, safe to show to users |
retryable | true when the same request can succeed later. The response then also carries Retry-After |
recovery | What the client should do: none, fix_request, reauthenticate, request_access, reconnect, refresh, retry or contact_support |
Stack traces and upstream error messages are never included.
Rate limits
API-key requests share 600 requests per 60 seconds per key across the whole /v2 surface. Over the budget you get 429 with type: "rate_limit_error", code: "rate_limited", and Retry-After: 60. See Limits for the rest.
OpenAPI specification
Every operation in the OpenAPI document has a unique operationId, a summary and description, typed parameters, request and response schemas, and the error _tags it can return. You can import it into Postman, Insomnia, Scalar or openapi-generator, or point an LLM function-calling tool at https://maple.dev/openapi.json. The interactive reference renders the same document.
To connect an AI agent without generating a client, use the MCP server.
Versioning
/v2 is the major version. Changes within it are additive, and error _tag values do not change. The v1 endpoints under /api/… remain available for existing integrations but get no new features.