Endpoints
The Analytics and Usage API endpoints, their parameters, and response shapes
Every endpoint is GET, authenticated with a mesh_sk_ Bearer key, and wrapped in the standard { data, meta, next_cursor } envelope. All accept the shared start / end timeframe params; if omitted, they default to the last 90 days. meta.start / meta.end always reflect the window actually queried. The four /analytics/* endpoints need the analytics:read scope; /usage needs usage:read.
GET /users
Per-user analytics rows, one per user in your workspace. Cursor-paginated — follow next_cursor until it is null.
Query parameters
| Param | Type | Default | Description |
|---|---|---|---|
start | ISO date | last 90 days | Start of the timeframe. |
end | ISO date | last 90 days | End of the timeframe. |
cursor | string | — | Opaque cursor from a previous next_cursor. |
limit | integer (1–200) | 50 | Max rows per page. |
Example response
{
"data": [
{
"userId": "9c1f…",
"email": "[email protected]",
"name": "Ada Lovelace",
"segment": "active",
"firstLoginDate": "2026-03-02T09:14:00.000Z",
"lastActivityDate": "2026-05-24T17:41:00.000Z",
"firstTaskDate": "2026-03-02T10:01:00.000Z",
"totalCreditsUsed": 412.5,
"inputTokens": 1840221,
"outputTokens": 290114,
"agentCount": 7,
"taskCount": 31,
"uniqueTaskTypes": 4,
"connectionCount": 2,
"role": "member",
"joinedAt": "2026-03-01T00:00:00.000Z"
}
],
"meta": { "start": "2026-03-01", "end": "2026-05-25", "has_more": true },
"next_cursor": "MjAyNi0wMy0wMXw5YzFm"
}segment is one of active, lapsed, or inactive. name, firstLoginDate, lastActivityDate, firstTaskDate, and role may be null.
GET /overview
Workspace totals, the user-segment distribution, and the onboarding funnel for the timeframe.
Query parameters
| Param | Type | Default | Description |
|---|---|---|---|
start | ISO date | last 90 days | Start of the timeframe. |
end | ISO date | last 90 days | End of the timeframe. |
Example response
{
"data": {
"summary": {
"totalUsers": 48,
"activeUsers": 31,
"lapsedUsers": 9,
"inactiveUsers": 8,
"totalCreditsUsed": 12840.75,
"avgCreditsPerUser": 267.52,
"avgAgentsPerUser": 5.4,
"avgTasksPerUser": 22.1
},
"segmentDistribution": [
{ "segment": "active", "count": 31, "percentage": 65 },
{ "segment": "lapsed", "count": 9, "percentage": 19 },
{ "segment": "inactive", "count": 8, "percentage": 17 }
],
"funnel": [
{ "stage": "total", "label": "Total Users", "count": 48, "percentage": 100 },
{ "stage": "tier-0", "label": "1+ tasks", "count": 40, "percentage": 83 },
{ "stage": "tier-1", "label": "5+ tasks", "count": 28, "percentage": 58 },
{ "stage": "tier-2", "label": "10+ tasks", "count": 19, "percentage": 40 },
{ "stage": "tier-3", "label": "25+ tasks", "count": 9, "percentage": 19 },
{ "stage": "tier-4", "label": "50+ tasks", "count": 3, "percentage": 6 }
]
},
"meta": { "start": "2026-03-01", "end": "2026-05-25" },
"next_cursor": null
}segment is one of active, lapsed, or inactive. segmentDistribution[].percentage and funnel[].percentage are integers (rounded). Funnel stages are total (Total Users) followed by task-count tiers tier-0 (1+ tasks), tier-1 (5+), tier-2 (10+), tier-3 (25+), tier-4 (50+), and tier-5 (100+); only stages with a non-zero count are included.
GET /credits
Credit-burn timeseries plus a per-user credit leaderboard.
Query parameters
| Param | Type | Default | Description |
|---|---|---|---|
start | ISO date | last 90 days | Start of the timeframe. |
end | ISO date | last 90 days | End of the timeframe. |
granularity | day | week | month | day | Bucket size for the burn timeseries. |
Example response
{
"data": {
"granularity": "day",
"creditBurn": [
{ "period": "2026-05-23", "totalCredits": 218.4, "userCount": 12 },
{ "period": "2026-05-24", "totalCredits": 301.9, "userCount": 15 }
],
"leaderboard": [
{ "userId": "9c1f…", "email": "[email protected]", "name": "Ada Lovelace", "totalCredits": 412.5 },
{ "userId": "3b7d…", "email": "[email protected]", "name": null, "totalCredits": 388.0 }
]
},
"meta": { "start": "2026-03-01", "end": "2026-05-25" },
"next_cursor": null
}leaderboard[].name may be null.
GET /engagement
Daily/weekly active-user counts, weekly cohort retention, and the weekly user-segment trend (active / lapsed / inactive).
Query parameters
| Param | Type | Default | Description |
|---|---|---|---|
start | ISO date | last 90 days | Start of the timeframe. |
end | ISO date | last 90 days | End of the timeframe. |
The dauWau series respects start/end. cohortRetention and segmentTrend are always computed over all-time data — they are not windowed by start/end.
Example response
{
"data": {
"dauWau": [
{ "date": "2026-05-23", "dau": 12, "wau": 28 },
{ "date": "2026-05-24", "dau": 15, "wau": 29 }
],
"cohortRetention": [
{ "cohortWeek": "2026-03-02", "cohortSize": 11, "retention": [100, 82, 64, 55] },
{ "cohortWeek": "2026-03-09", "cohortSize": 8, "retention": [100, 75, 50] }
],
"segmentTrend": [
{ "week": "2026-05-04", "active": 18, "lapsed": 4, "inactive": 2 },
{ "week": "2026-05-11", "active": 21, "lapsed": 3, "inactive": 2 }
]
},
"meta": { "start": "2026-03-01", "end": "2026-05-25" },
"next_cursor": null
}In cohortRetention, retention is a percentage array indexed by weeks since signup — index 0 is the signup week (always 100).
In segmentTrend, each week classifies every member who had joined by then: active (used the product that week), lapsed (active in an earlier week but not this one), or inactive (never active up to that week).
GET /usage
Raw per-call usage records for your workspace — one row per metered LLM call, including token counts, provider cost, and credits charged. Tenant-wide: rows for every user are returned, each tagged with userId / email. Cursor-paginated by (createdAt, id) — follow next_cursor until it is null.
This endpoint requires a key with the usage:read scope — separate from analytics:read, because it exposes per-call provider cost. Grant it when you mint the key.
Query parameters
| Param | Type | Default | Description |
|---|---|---|---|
start | ISO date | last 90 days | Start of the timeframe. |
end | ISO date | last 90 days | End of the timeframe. |
userId | string | — | Narrow to one user. Filtering only, not a permission. |
model | string | — | Narrow to one model. |
provider | string | — | Narrow to one provider. |
cursor | string | — | Opaque cursor from a previous next_cursor. |
limit | integer (1–200) | 50 | Max rows per page. |
Example response
{
"data": [
{
"tenantId": "org_9f…",
"tenantName": "Acme Inc",
"userId": "9c1f…",
"email": "[email protected]",
"model": "claude-opus-4-8",
"provider": "anthropic",
"promptTokens": 1840,
"completionTokens": 290,
"totalTokens": 2130,
"cacheCreationInputTokens": 512,
"cacheReadInputTokens": 1024,
"providerCostUsd": "0.04821500",
"creditsActual": "6.450000",
"taskId": "22a1…",
"createdAt": "2026-05-24T17:41:03.221Z"
}
],
"meta": { "start": "2026-03-01", "end": "2026-05-25", "has_more": true },
"next_cursor": "MjAyNi0wNS0yNFQxNzo0MTowMy4yMjFafDIyYTE"
}providerCostUsd and creditsActual are decimal strings (not numbers) to preserve full precision — parse them with a decimal library if you compute on them. taskId may be null for non-task calls.
The four Analytics endpoints above report consumption only — credits and tokens, never cost or markup. Per-call provider cost is available solely through GET /usage, which requires the usage:read scope.