Reporting Manager API · analytics
The dashboard's analytics strip over the last 7
GET /analytics/summary
The dashboard's analytics strip over the last 7, 30 or 90 days (period, 30d by default) against the same length of time just before it: total sales (integer cents, net of discounts and of tax), orders placed, units sold and average order value, each as current and previous; the window day by day (every day present, for the sparklines) and the previous window likewise; and up to three movers, the SKUs whose units sold grew most.
Read from the reporting star's order-line facts, so an order counts on the day it was placed, and asOf carries the fold's watermarks so a consumer can tell zero from not-yet-folded. A management view on either accounting basis, not the books: the general ledger recognises revenue at invoice or at payment.
Access
Requires reports:read or financials:read.
Any one of these scopes is enough.
How scopes come from roles: Scopes and roles. Getting a token: Authentication and app tokens.
AI agent tool
Agents call this as reporting_get_analytics_summary (Reporting: Get analytics summary), in the reporting toolset. It only reads.
Connecting an agent: AI agents.
Example
curl -X GET 'https://reporting.getmanifold.io/analytics/summary?period=7d' \
-H "Authorization: Bearer $MANIFOLD_TOKEN"const response = await fetch("https://reporting.getmanifold.io/analytics/summary?period=7d", {
method: "GET",
headers: { Authorization: `Bearer ${process.env.MANIFOLD_TOKEN}` },
});
if (!response.ok) throw new Error(`${response.status}: ${await response.text()}`);
const answer = await response.json();{
"period": {
"firstDay": "2026-10-14",
"lastDay": "2026-10-20"
},
"comparePeriod": {
"firstDay": "2026-10-07",
"lastDay": "2026-10-13"
},
"currency": "AUD",
"salesCents": {
"current": 296100,
"previous": 255600
},
"orders": {
"current": 24,
"previous": 21
},
"units": {
"current": 57,
"previous": 53
},
"averageOrderCents": {
"current": 12338,
"previous": 12171
},
"daily": [
{
"day": "2026-10-14",
"salesCents": 48200,
"orders": 4,
"units": 9
},
{
"day": "2026-10-15",
"salesCents": 61500,
"orders": 5,
"units": 12
},
{
"day": "2026-10-16",
"salesCents": 0,
"orders": 0,
"units": 0
},
{
"day": "2026-10-17",
"salesCents": 35800,
"orders": 3,
"units": 7
},
{
"day": "2026-10-18",
"salesCents": 72900,
"orders": 6,
"units": 14
},
{
"day": "2026-10-19",
"salesCents": 54300,
"orders": 4,
"units": 10
},
{
"day": "2026-10-20",
"salesCents": 23400,
"orders": 2,
"units": 5
}
],
"previousDaily": [
{
"day": "2026-10-07",
"salesCents": 39100,
"orders": 3,
"units": 8
},
{
"day": "2026-10-08",
"salesCents": 44800,
"orders": 4,
"units": 9
},
{
"day": "2026-10-09",
"salesCents": 51200,
"orders": 4,
"units": 11
},
{
"day": "2026-10-10",
"salesCents": 0,
"orders": 0,
"units": 0
},
{
"day": "2026-10-11",
"salesCents": 28700,
"orders": 2,
"units": 6
},
{
"day": "2026-10-12",
"salesCents": 60300,
"orders": 5,
"units": 13
},
{
"day": "2026-10-13",
"salesCents": 31500,
"orders": 3,
"units": 6
}
],
"movers": [
{
"sku": "WIDGET-BLUE",
"name": "Blue widget, 40mm",
"units": 22,
"previousUnits": 14,
"salesCents": 54780,
"daily": [
3,
5,
0,
2,
6,
4,
2
],
"previousDaily": [
2,
2,
3,
0,
1,
4,
2
]
}
],
"includesHistory": false,
"unconvertedLines": 0,
"asOf": [
{
"source": "inventory",
"tenants": 1,
"maxFoldedSequence": 128,
"lastRun": {
"at": "2026-10-20T08:59:58.000Z",
"outcome": "folded",
"folded": 3,
"skipped": 0,
"durationMs": 41
}
},
{
"source": "fulfillment",
"tenants": 1,
"maxFoldedSequence": 77,
"lastRun": {
"at": "2026-10-20T08:59:58.000Z",
"outcome": "empty",
"folded": 0,
"skipped": 0,
"durationMs": 6
}
}
]
}The panel writes this call in other languages. It does not send it: Manifold's APIs do not take calls from a web
page on another site, so run the call from your own code or terminal. The whole API as OpenAPI: reporting-manager.openapi.json. Base URL https://reporting.getmanifold.io.
Errors
Every refusal is a status and a JSON body whose _tag names it. A refused call changes nothing.
401
| Refusal | What it means | What to do |
|---|---|---|
Unauthorized reason | The token is missing, expired or not one Manifold issued. | Get a fresh token and send the call again. |
TokenAlreadyUsed tokenId | A single-use app token was already spent. | Mint a new token for this call. |
402
| Refusal | What it means | What to do |
|---|---|---|
SubscriptionRequired status | The organization's subscription has lapsed, so writes are refused. | An owner settles billing. Reads still work meanwhile. |
403
| Refusal | What it means | What to do |
|---|---|---|
TenantRequired userId | The token names no organization. | Choose the organization, then get a new token. |
ScopeRequired required | The token's roles do not grant the scope this call needs. | Ask an owner or admin for a role that grants it. |
409
| Refusal | What it means | What to do |
|---|---|---|
MirroredFromSource source | This area is fed by your source system until the organization goes live. | Make the change in the source system, or go live first. |
503
| Refusal | What it means | What to do |
|---|---|---|
RequestLogUnavailable tokenId, reason | The service could not record the request, so it did nothing. | Try again shortly. |
How refusals work everywhere: Errors.
Used in
- Read the dashboard and tidy it, step 1: The analytics strip