API Endpoints
Both endpoints are GET calls that need a bearer token, see Authentication. The base address follows the environment you pick here.
https://api.statistics-v2.metaforce.net
1. GET /analytics
Returns the events of your company as counts per hour, one page at a time. Each row is the number of events in one hour for one combination of event, system, template, source, distribution, environment, area and event detail.
Query Parameters
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
| pageNumber | integer | No | 1 | Page number, 1 or higher |
| pageSize | integer | No | 500 | Rows per page, 1 to 1000 |
| startDate | datetime | No | none | Start of the range, UTC, inclusive. Always send it. |
| toDate | datetime | No | none | End of the range, UTC, inclusive. Leave it out to read up to now. |
Dates are UTC, for example 2026-09-01T00:00:00Z. If you leave out startDate, the call has no lower limit and reads from the oldest event, which makes the response large. Send both dates and keep the range short, see Best Practices.
Example
curl "https://api.statistics-v2.metaforce.net/analytics?pageNumber=1&pageSize=50&startDate=2026-09-01T00:00:00Z&toDate=2026-09-07T23:59:59Z" \
-H "Authorization: Bearer <access_token>"
Success Response
{
"pageNumber": 1,
"pageSize": 50,
"totalRecords": 235,
"totalPages": 5,
"data": [
{
"event": "Create",
"system": "Smartforms",
"date": "2026-09-01",
"hour": "08",
"template": "Customer onboarding",
"source": "SmartForms",
"distribution": null,
"environment": "Production",
"area": null,
"count": 12,
"eventDetail": "form-created"
}
]
}The row above says that SmartForms recorded 12 Create events with the detail form-created for the form Customer onboarding, in the Production environment, between 08:00 and 09:00 UTC on 1 September. The form name is an example. Your response holds the events your own Doc Gen applications recorded. See Data Models for every field and the values you will see.
The rows come in no fixed order. Read every page, then sort the rows yourself. A range without events returns 200 with totalRecords set to 0 and an empty data.
totalPages is totalRecords divided by pageSize, rounded up. A range without events gives totalPages 0, so there is nothing to read after the first call.
Read every page
This JavaScript example reads a whole range, one page of 1000 rows at a time, and sorts the rows at the end. It assumes you already have a token, see Authentication.
async function readRange(token, startDate, toDate) {
const rows = [];
let pageNumber = 1;
let totalPages = 1;
while (pageNumber <= totalPages) {
const url = "https://api.statistics-v2.metaforce.net/analytics"
+ "?pageNumber=" + pageNumber
+ "&pageSize=1000"
+ "&startDate=" + encodeURIComponent(startDate)
+ "&toDate=" + encodeURIComponent(toDate);
const response = await fetch(url, {
headers: { Authorization: "Bearer " + token },
});
if (response.status === 404) return rows; // no data at all
if (!response.ok) throw new Error("Statistics returned " + response.status);
const page = await response.json();
rows.push(...page.data);
totalPages = page.totalPages;
pageNumber++;
}
// The rows come in no fixed order.
return rows.sort((a, b) =>
(a.date + a.hour).localeCompare(b.date + b.hour));
}
// readRange(token, "2026-09-01T00:00:00Z", "2026-09-07T23:59:59Z")
2. GET /analytics/prometheus
Returns the same events as counts in the Prometheus text format, for a monitoring system to scrape. The response is not paged and has no date or hour: it is one total per combination for the whole range.
Query Parameters
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
| startDate | datetime | No | Today at 00:00 UTC | Start of the range, UTC, inclusive |
| toDate | datetime | No | none | End of the range, UTC, inclusive |
Example
curl "https://api.statistics-v2.metaforce.net/analytics/prometheus?startDate=2026-09-01T00:00:00Z&toDate=2026-09-07T23:59:59Z" \
-H "Authorization: Bearer <access_token>"
Response (text format)
create_event_count{system="Smartforms", template="Customer onboarding", source="SmartForms", distribution="", environment="Production", area="", eventdetail="form-created"} 42- The metric name is the event name in lower case followed by
_event_count. - The value is the number of events.
- The labels are
system,template,source,distribution,environment,areaandeventdetail, written in lower case. A field without a value is an empty label. - If nothing was recorded in the range, the body is empty.
- The response has no
Content-Typeheader. Prometheus 3 needs a setting for that, see BI Integration.
Errors
| Status | When | Body |
|---|---|---|
| 400 | pageNumber or pageSize is outside its limits, or a date cannot be read | The validation problems, as JSON |
| 401 | No token, an expired token, or a token for a different API | none |
| 403 | /analytics only: the token is not tied to a company. /analytics/prometheus answers this case with 500 | none |
| 404 | Your company has no statistics data at all, for example because it has never had a Statistics licence | {"Message":"Customer does not have any data"} |
| 500 | Unexpected error | {"Message":"Internal server error"} |
Treat 404 as an empty result, not as a fault. See How the Data Is Collected for when events are stored.