For AI Agents
Everything an autonomous agent needs to read Sealmetrics analytics, in one place. If you are wiring an LLM to this API, start here.
At a glance
| Base URL | https://my.sealmetrics.com/api/v1 |
| OpenAPI 3.1 spec | /openapi.json · /openapi.yaml |
| Hosted MCP server | https://mcp.sealmetrics.com/mcp (Streamable HTTP) — setup |
| Auth | API key (X-API-Key), JWT bearer, or OAuth 2.1 + PKCE |
| Headless account creation | POST /provision |
| Batch | Up to 50 queries per request with dependency ordering |
| Long-running work | Async export jobs + completion webhooks |
| Error format | One envelope, stable error.code — catalogue |
| Rate limits | X-RateLimit-* on every response, Retry-After on 429 — details |
| Docs for LLMs | /llms.txt · /llms-full.txt |
The fastest path: use the MCP server
If your agent runtime speaks the Model Context Protocol, you do not need to write HTTP code at all. Point the client at the hosted server and the analytics surface arrives as tools:
claude mcp add --transport http sealmetrics https://mcp.sealmetrics.com/mcp
The server exposes read-only analytics tools covering traffic, conversions and microconversions (including raw event-level data), campaigns, landing pages, content groups, countries, devices, browsers, operating systems, channels, funnels, custom properties, segments, alerts, webhooks and bot detection — plus setup tools that can create a free account and verify the pixel from the chat.
Append ?discovery=progressive to the URL to load tool definitions on demand instead of all at once, which keeps context usage low on clients with tight limits.
Full client-by-client setup (Claude, ChatGPT, Cursor, Codex, VS Code): MCP Server. To create an account from the chat with no dashboard login: AI Agentic Package.
Using the REST API directly
1. Read the spec first
The complete machine-readable contract lives at https://docs.sealmetrics.com/openapi.json (OpenAPI 3.1, also available as YAML). Every operation carries an operationId, tags, parameter schemas, response schemas and the error responses described below. Generate a client from it rather than hand-rolling one:
curl -sO https://docs.sealmetrics.com/openapi.json
npx @redocly/cli lint openapi.json # validate
npx @openapitools/openapi-generator-cli generate -i openapi.json -g python -o ./sm-client
Where a page in these docs and the OpenAPI spec disagree about a field's type, the spec is correct. In particular, monetary fields backed by decimals (revenue, average_order_value on the overview and aggregate reports) are serialized as JSON strings — "12450.00", not 12450.00 — so no precision is lost in transit. Parse them with a decimal type. A few endpoints still return revenue as a JSON number; check the field's type in the spec before parsing.
2. Authenticate
Three options, in increasing order of setup cost:
| Method | Header | Use it when |
|---|---|---|
| API key | X-API-Key: sm_… | The agent runs on behalf of one account you control. Read-only, scoped, revocable — see API Tokens. |
| JWT bearer | Authorization: Bearer … | You already hold a dashboard session and need write access. See Authentication. |
| OAuth 2.1 | Authorization: Bearer … | Your product connects to other people's Sealmetrics accounts. PKCE, dynamic client registration, refresh tokens. See OAuth 2.1. |
API keys are read-only by design (stats:read, sites:read, accounts:read). That is the right default for an analytics agent: it cannot mutate anything.
3. Ask for a lot in one request
Two features exist specifically so an agent does not have to fan out dozens of HTTP calls:
Batch — up to 50 analytics queries in one round trip, with depends_on to express ordering, parallel_limit to cap concurrency, and POST /batch/validate to dry-run the plan before spending the request:
/batch
{
"queries": [
{"id": "overview", "endpoint": "/stats/overview", "params": {"account_id": "my-site", "period": "30d"}},
{"id": "pages", "endpoint": "/stats/pages", "params": {"account_id": "my-site", "period": "30d", "page_size": 10}}
],
"options": {"parallel_limit": 5, "include_timing": true}
}
Each query resolves its dates in its own account's timezone, so a multi-site batch does not need you to pre-resolve 30d per site.
Multi-dimensional query — POST /stats/query takes dimensions, metrics, filters, granularity and comparison in one body, instead of stitching together several report endpoints.
4. Hand off long work instead of blocking
Bulk exports are a proper asynchronous job, not a long HTTP request:
- POST
/exportscreates a job and returns immediately. - The job moves through
pending→estimating→generating→completed(orfailed/expired). - You do not have to poll. Subscribe a webhook to
export.completedandexport.failedand the API pushes the result to you. - Fetch the file with the download token, or
DELETEthe job to cancel it.
For small datasets, POST /exports/stream streams the rows back directly in one call.
Full lifecycle, filters and formats: Exports.
5. Page through results
List endpoints use page / page_size and return total, has_next and has_prev:
{"data": [], "total": 156, "page": 1, "page_size": 50, "has_next": true, "has_prev": false}
Read has_next rather than computing it from total, and hold page_size constant across a run. See Pagination, Sorting & Filters.
Analytics data keeps arriving while you page. If rows shift between requests you can see a row twice or miss one. For a complete, consistent snapshot of a large report, use an export job instead of paging.
6. Respect the rate limiter
Every response carries the current state — you never have to guess:
| Header | Meaning |
|---|---|
X-RateLimit-Limit | Requests allowed per minute on this account's plan |
X-RateLimit-Remaining | Requests left in the current window |
X-RateLimit-Reset | Unix timestamp when the window resets |
Retry-After | On 429 and 503: seconds to wait |
All four are exposed via CORS, so a browser-side agent can read them too. There is no burst allowance and no soft-throttling phase: you are either under the limit or you get a 429. Back off on Retry-After plus jitter. Limits per plan tier: Rate Limits.
7. Branch on error.code, never on the message
Every non-2xx response uses the same envelope:
{
"error": {
"code": "rate_limit_exceeded",
"message": "Too many requests. Please retry after 15 seconds."
},
"request_id": "ae817c5b-82df-430f-83e6-10c937e4e5e4"
}
code is stable and safe to switch on. message is for humans and may change. request_id also arrives in the X-Request-ID response header — log it, and quote it if you open a support ticket.
The full list, with which codes are retryable, is in the Error codes catalogue.
Retry policy that works
| Status | Retry? | How |
|---|---|---|
429 | Yes | Wait Retry-After seconds + jitter |
503 | Yes | Wait Retry-After seconds (the API sends 30 on database unavailability) |
500, 502, 504 | Yes | Exponential backoff, cap the attempts |
408 timeouts | Yes | Backoff; consider narrowing the date range |
400, 422 | No | Fix the request — the detail array names the offending field |
401, 403 | No | Re-authenticate or widen the token's scopes |
404, 409 | No | Resolve the conflict in your own logic |
The API does not currently accept an Idempotency-Key header. Retrying a failed POST may create a duplicate resource (a second export job, a second segment). Until that lands, retry writes only when you can confirm the first attempt did not take effect — for exports, list the account's jobs before retrying.
Health and readiness
Three unauthenticated probes, excluded from rate limiting:
GET/health · GET/livez · GET/readyz
These live at the host root, not under /api/v1 — for example https://my.sealmetrics.com/livez.
What is not available
Stated plainly so you do not build around something that does not exist:
- No SSE or WebSocket streaming. Real-time updates come from webhooks, not a persistent stream. Export downloads are chunked HTTP, which is not the same thing.
- No idempotency keys on writes (see the caution above).
- No cursor pagination — offset only.
- No sandbox or demo dataset. The closest thing is
POST /provision, which creates a real free-tier account headlessly. - No burst allowance on the rate limiter.
Related
- API Overview — the full endpoint map
- Quick Start — first call in five minutes
- Error codes
- OAuth 2.1
- Provisioning
- MCP Server · AI Agentic Package
- Web analytics prompts — ready-made prompts for agents driving the MCP tools