Analytics API
Read-only HTTP API for your workspace's usage analytics
The Analytics API is a read-only HTTP API that exposes usage analytics for your workspace — the same per-user activity, credit, and engagement data the console dashboard shows. Every request is scoped to the tenant the API key belongs to; there is no way to read another workspace's data.
Aggregated endpoints live under https://gateway.meshmesh.io/api/v1/public/analytics, and the raw per-call feed under https://gateway.meshmesh.io/api/v1/public/usage. All respond with JSON.
Creating a key
API keys are created in the console:
- Go to Workspace Admin → API Keys.
- Click Create key, give it a name, and confirm.
- Copy the key — it is shown once and never again. Store it somewhere secure (a secrets manager, not source control).
If you lose a key you cannot recover it. Create a new one and revoke the old one. Revoking a key takes effect within ~60 seconds.
Keys are minted by workspace admins and carry one or more scopes: analytics:read for the aggregated /analytics/* endpoints, and usage:read for the raw /usage feed (which includes per-call provider cost). Pick the scopes when you create the key.
Authentication
Pass the key as a Bearer token. API keys are prefixed mesh_sk_.
Authorization: Bearer mesh_sk_…Requests with a missing, invalid, revoked, or expired key get a generic 401. A key that is valid but lacks the scope an endpoint requires (e.g. usage:read for /usage) gets a 403.
curl https://gateway.meshmesh.io/api/v1/public/analytics/overview \
-H "Authorization: Bearer mesh_sk_your_key_here"const res = await fetch(
'https://gateway.meshmesh.io/api/v1/public/analytics/overview',
{ headers: { Authorization: `Bearer ${process.env.MESH_ANALYTICS_KEY}` } },
);
const { data, meta, next_cursor } = await res.json();Timeframe
Every endpoint accepts an optional timeframe via two query params:
| Param | Type | Description |
|---|---|---|
start | ISO date (UTC) | Start of the window. If omitted, defaults to the last 90 days. |
end | ISO date (UTC) | End of the window. If omitted, defaults to the last 90 days. |
When start/end are omitted, all four endpoints default to the last 90 days. meta.start and meta.end in the response always reflect the window actually queried (as ISO dates), whether you specified it or got the default.
curl "https://gateway.meshmesh.io/api/v1/public/analytics/credits?start=2026-03-01&end=2026-05-25" \
-H "Authorization: Bearer mesh_sk_…"If start is after end, or either value isn't a valid ISO date, you get a 400.
Analytics data is available from approximately 2026-03-01. Requesting an earlier window returns partial or empty results rather than an error.
Response envelope
Every endpoint returns the same envelope:
{
"data": { "...": "endpoint-specific payload" },
"meta": { "start": "2026-03-01", "end": "2026-05-25" },
"next_cursor": null
}data— the endpoint-specific payload (an array or object; see each endpoint).meta.start/meta.end— the window actually queried, echoed back as ISO dates. When you omitstart/end, these reflect the default last-90-days window.next_cursor— an opaque pagination cursor, ornullwhen there are no more pages.
Cursor pagination
Only GET /users is paginated. When more rows are available, next_cursor is a non-null string and meta.has_more is true. Pass the value back as the cursor query param to fetch the next page; keep going until next_cursor is null.
let cursor = null;
const rows = [];
do {
const url = new URL('https://gateway.meshmesh.io/api/v1/public/analytics/users');
url.searchParams.set('limit', '200');
if (cursor) url.searchParams.set('cursor', cursor);
const res = await fetch(url, {
headers: { Authorization: `Bearer ${process.env.MESH_ANALYTICS_KEY}` },
});
const body = await res.json();
rows.push(...body.data);
cursor = body.next_cursor;
} while (cursor);limit accepts 1–200 and defaults to 50.
Rate limits
Each key is limited to 120 requests/minute and 10,000 requests/day by default. When you exceed a limit you get a 429 with these headers:
| Header | Meaning |
|---|---|
Retry-After | Seconds to wait before retrying. |
RateLimit-Limit | Request quota for the current window. |
RateLimit-Remaining | Requests remaining in the window. |
RateLimit-Reset | Seconds until the window resets. |
Back off and retry after Retry-After seconds.
Errors
Errors use RFC 9457 problem documents with the application/problem+json content type:
{
"type": "https://docs.meshmesh.io/errors/invalid-request",
"title": "Invalid request parameters",
"status": 400,
"detail": "`start` is not a valid ISO date."
}| Status | When |
|---|---|
400 | Malformed query params (bad date, start after end). |
401 | Unauthorized — API key is missing, invalid, revoked, or expired. |
403 | Insufficient scope — the key lacks the required analytics:read scope. |
429 | Rate limit exceeded (see above). |
Endpoints
See the Endpoints reference for all available endpoints and their response shapes.