Skip to content
Rello edited this page Oct 15, 2026 · 26 revisions

OCS 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.

Authentication and base URL

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

List reports

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.

Report metadata and data

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.

List datasets

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.

Add and delete data

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.


REST API

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'

Current API: v4

Add data

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.

Delete data with filters

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}

v3 read and delete endpoints

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"}]}

Legacy v1 and v2

Use v4 for new integrations. v1 and v2 are retained for compatibility only.

  • POST /api/1.0/adddata/{datasetId} accepts one top-level record with dimension1, dimension2, and dimension3.
  • POST /api/2.0/adddata/{datasetId} and POST /api/2.0/deletedata/{datasetId} use the v3 data and delete payload 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).

Clone this wiki locally