Skip to Content

REST API

The server’s full API definition is the OpenAPI 3.1 document at /openapi.yaml, with Swagger UI at /docs when MIOT_DASHBOARD_DOCS is on. It also ships in the contract package as @microboxlabs/miot-dashboard-contract/openapi.yaml. This page summarizes it.

Conventions

TopicRule
Base address/tenants/{tenantId}/scopes/{scopeId}, after MIOT_DASHBOARD_BASE_PATH if set
AuthenticationAuthorization: Bearer <JWT>, or the configured ticket header
BodyJSON, at most 1 MiB
SuccessMost answers wrap the result in {"data": ...}
CachingCapability, catalog and credential answers carry Cache-Control: no-store

Dashboards

MethodPathDoesNeeds
GET/dashboardsList the dashboards the caller may see, as {slug, name, order?}Scope member
GET/dashboards/{slug}Load one. data is the document, or null if none. ETag holds the revision.View
PUT/dashboards/{slug}Create or replace. Send If-Match. Answers {revision, updatedAt} and the new ETag.Edit, or create
DELETE/dashboards/{slug}DeleteDelete
GET/dashboards/{slug}/capabilitiesThe caller’s five capability flagsView
GET/dashboards/{slug}/permissions{assignments: [{authorityId, role}]}Manage permissions
PUT/dashboards/{slug}/permissionsReplace every assignmentManage permissions
GET/capabilities{canCreate} for this scopeScope member

A dashboard slug is the address of the dashboard inside its scope.

Queries

MethodPathDoesNeeds
POST/dashboards/{slug}/queries/{queryId}Run a saved query. Body {"filters": {...}}. Answers {"data": {"rows": [...]}}.View. Needs a query executor, otherwise 404.
GET/dashboards/{slug}/query-catalog{connections: [{id, label, operations: [{id, label, schema?}]}]}Edit. Needs a catalog provider, otherwise 404.

Datasources and credentials

Available when the server stores credentials itself.

MethodPathDoes
GET, POST/datasourcesList, or create
GET, PUT, DELETE/datasources/{dataSourceId}Read, create or replace, delete
POST/datasources/testTest values before saving
POST/datasources/{dataSourceId}/testTest a stored datasource
GET/credentialsList credentials as summaries
GET, PUT, DELETE/credentials/{credentialRef}Read a summary, store a secret, delete

With MIOT_DASHBOARD_CREDENTIALS_URL set, the /credentials routes answer 404: credentials are managed where they live.

Server routes

These sit outside the API, before authentication.

PathAnswers
/livez, /health{"status":"ok"}
/readyz{"status":"ready"}
/openapi.yamlThe API definition
/dashboard-config.schema.jsonThe document’s JSON Schema
/docsSwagger UI

Errors

Every error has the same shape:

{ "error": "…", "status": 403, "code": "FORBIDDEN", "reason": "TENANT_SCOPE" }
StatuscodeMeaning
400BAD_REQUESTThe body does not match the contract. error names the field.
401UNAUTHENTICATEDNo credential, or it could not be verified
403FORBIDDENSee reason below
404NOT_FOUNDNo such dashboard, query or datasource, or the feature is not configured
409CONFLICTIf-Match no longer matches the current revision
413PAYLOAD_TOO_LARGEThe body is over 1 MiB
502UPSTREAM_ERRORA query’s data service failed or returned something invalid
500INTERNAL_ERRORA service the server depends on did not answer, such as the directory
reason (403 only)Meaning
TENANT_SCOPENot a member of the organization or the scope, or they do not exist
CAPABILITYA member, but the role does not allow this action
EMBED_SCOPEAn embed token used outside the one dashboard it allows

Error messages never contain upstream bodies, stack traces or credentials.

Example: load and save

# Load curl -i -H "Authorization: Bearer $TOKEN" \ https://dashboards.example.com/tenants/acme/scopes/ops/dashboards/sales # HTTP/1.1 200 OK # etag: "3" # {"data":{"version":2,"name":"Sales",...}} # Save with the revision you loaded curl -X PUT https://dashboards.example.com/tenants/acme/scopes/ops/dashboards/sales \ -H "Authorization: Bearer $TOKEN" -H 'If-Match: "3"' \ -H 'Content-Type: application/json' --data @sales.json # {"data":{"revision":4,"updatedAt":"2026-10-05T12:00:00.000Z"}}
Last updated on