Repository navigation
API
The OCS endpoints described here are introduced by PR #609. They require a version of Analytics that includes that change; older installations can continue using the existing APIs documented below.
OCS is a REST API using Nextcloud's standard response envelope. Existing non-OCS API URLs and response formats remain unchanged.
Authenticate with a Nextcloud username and an application password from Personal settings → Security. Send OCS-APIRequest: true and request JSON with Accept: application/json. POST requests also use Content-Type: application/json.
All paths in the table below are relative to:
https://cloud.example/ocs/v2.php/apps/analytics/api/v1
If Nextcloud is installed in a subdirectory, include it before /ocs/v2.php.
| Method | Path | Purpose |
|---|---|---|
| GET | /reports |
List accessible reports |
| GET | /reports/{reportId} |
Read report metadata and saved options |
| GET | /reports/{reportId}/data |
Read report data with saved filters |
| GET | /datasets |
List owned datasets |
| POST | /datasets/{datasetId}/data/add |
Add or update dataset rows |
| POST | /datasets/{datasetId}/data/delete |
Delete rows matching a filter |
curl --user 'user:app-password' \
--header 'OCS-APIRequest: true' \
--header 'Accept: application/json' \
'https://cloud.example/ocs/v2.php/apps/analytics/api/v1/reports'Report summaries contain only id, name, and dataset:
{
"ocs": {
"meta": {"status": "ok", "statuscode": 200, "message": "OK"},
"data": [{"id": 27, "name": "Sales", "dataset": 2}]
}
}The list includes owned reports and reports shared with the user, their groups, or through shared report folders. Folders themselves are excluded. Public-link-only and panorama-only access do not grant standalone report access through these endpoints.
Use the report id with /reports/{reportId} for metadata and saved visualization/filter options, or /reports/{reportId}/data for the viewer's backend data payload.
Report data uses the same backend processing as the viewer, including saved filters, dynamic filter variables, sorting, and transformations. Both internal and external datasources are supported. Temporary filter overrides are not accepted. The response can include header, data, options, filterApplied, thresholds, and datasource-specific fields. Browser-side formatting and pivot output are not rendered by this API.
Connection settings and share secrets are excluded from metadata. Missing or inaccessible report IDs return HTTP 404; unauthenticated requests return HTTP 401. Datasource errors retain the viewer payload's error field.
GET /datasets returns owned datasets. Each item contains only the dataset ID, name, and column labels:
{
"ocs": {
"meta": {"status": "ok", "statuscode": 200, "message": "OK"},
"data": [
{"id": 22, "name": "iobroker", "dimension1": "Object", "dimension2": "Date", "value": "Value"}
]
}
}Navigation, scheduling, and storage metadata are omitted. Shared report access does not grant dataset write access.
OCS writes reuse the existing v4 behavior described below. They require ownership of a legacy Internal Database dataset. Flexible datasets must use the stable-column record API. The dataset ID in the URL takes precedence over body parameters.
Add/update example:
curl --user 'user:app-password' \
--header 'OCS-APIRequest: true' \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--data '{"data":[{"dimension1":"2026-10-15","dimension2":"server-a","value":"42"}]}' \
'https://cloud.example/ocs/v2.php/apps/analytics/api/v1/datasets/22/data/add'Delete example:
curl --user 'user:app-password' \
--header 'OCS-APIRequest: true' \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--data '{"filter":{"dimension1":{"option":"EQ","value":"2026-10-15"},"dimension2":{"option":"EQ","value":"server-a"}}}' \
'https://cloud.example/ocs/v2.php/apps/analytics/api/v1/datasets/22/data/delete'Successful writes return success: true and a message inside ocs.data; deletion also includes the delete row count. Application errors preserve v4 semantics: HTTP 200 with ocs.data.success: false and ocs.data.error.code/message. Check success, not only HTTP status or ocs.meta.
Error codes are 9001 (unknown), 9002 (invalid input), 9003 (missing or unauthorized dataset), and 9004 (unsupported storage mode). Authentication failures return HTTP 401.
The machine-readable contract is in openapi.json.
The REST API is for Internal Database datasets. Authenticate as the dataset owner. For scripts and integrations, use an application password from Personal settings → Security rather than the account password.
All examples use Basic authentication and JSON:
curl --user 'user:app-password' \
--header 'Content-Type: application/json' \
--data '{"data":[{"dimension1":"2026-08-25","dimension2":"server-a","value":"42"}]}' \
'https://cloud.example/apps/analytics/api/4.0/data/10/add'POST /nextcloud/apps/analytics/api/4.0/data/{datasetId}/add
Pass a data array. Every record needs dimension1, dimension2, and value, either by those technical names or by the matching dataset column labels.
{
"data": [
{"dimension1": "%currentDate%", "dimension2": "server-a", "value": "42"},
{"Date": "2026-08-25", "Host": "server-b", "Load": "38"}
]
}In v4, %currentDate% uses the ISO Y-m-d format. The endpoint creates or updates matching records.
POST /nextcloud/apps/analytics/api/4.0/data/{datasetId}/delete
Use a non-empty filter object to delete matching rows from an Internal Database dataset. A filter key may be dimension1 or dimension2, or the matching dataset column label. Every filter condition contains an option and a string value; multiple conditions are combined with AND.
{
"filter": {
"Date": {"option": "LT", "value": "%last 5 days%"},
"Host": {"option": "EQ", "value": "server-a"}
}
}Supported options are EQ, GT, LT, IN, LIKE, NOTLIKE, and BETWEEN. Dynamic date variables, including %last 5 days%, are resolved when the request is processed. Unknown columns and an empty filter are rejected, so the endpoint cannot delete every row accidentally.
curl --user 'user:app-password' \
--header 'Content-Type: application/json' \
--data '{"filter":{"dimension1":{"option":"LT","value":"%last 5 days%"},"dimension2":{"option":"EQ","value":"server-a"}}}' \
'https://cloud.example/apps/analytics/api/4.0/data/10/delete'A successful response includes the number of deleted rows:
{"success": true, "message": "Data deleted", "delete": 12}These endpoints remain available:
| Purpose | Endpoint |
|---|---|
| Add data | POST /api/3.0/data/{datasetId}/add |
| Delete data | POST /api/3.0/data/{datasetId}/delete |
| Read report data | GET /api/3.0/data/{reportId} |
| List datasets | GET /api/3.0/datasets |
| List reports | GET /api/3.0/reports |
| Read report metadata | GET /api/3.0/report/{reportId} |
Delete requests use a delete array. * is a wildcard:
{"delete":[{"dimension1":"2026-08-*","dimension2":"server-a"}]}Use v4 for new integrations. v1 and v2 are retained for compatibility only.
-
POST /api/1.0/adddata/{datasetId}accepts one top-level record withdimension1,dimension2, anddimension3. -
POST /api/2.0/adddata/{datasetId}andPOST /api/2.0/deletedata/{datasetId}use the v3dataanddeletepayload shapes. - v3 uses localized
%currentDate%; migrate date-sensitive writers to v4.
Errors use the standard response form with codes 9001 (unknown), 9002 (missing parameter), 9003 (not found or unauthorized), and 9004 (not allowed).