Guides

Use these guides with the OpenAPI reference to integrate queries and backup operations with your tenant. Reference descriptions follow the contract; the original is available for download.

Getting started

Have your tenant’s HTTPS hostname and a credential with the required permissions. The base URL is https://{tenant_host}/api/v1: replace tenant_host with your environment’s hostname. This documentation website is not the tenant API origin.

To query inventory, use GET /devices with devices:read. Reference paths are relative to the /api/v1 base URL. Use IDs returned by the API when reading devices, runs and files; do not infer IDs from names.

For collections, read data.items and reuse meta.next_cursor unchanged until it is null. Keep the same token, filters and limit between pages. Cursors expire after 30 minutes; permission or parameter changes require restarting pagination.

Filters apply before pagination. Inclusion has a time cutoff, but current access, group membership and deletions are checked on every page. Collections provide neither a global count nor a transactional snapshot across requests.

Authentication and permissions

Send the credential only in the Authorization: Bearer header. Browser cookies do not authenticate the API. The credential is opaque, not a JWT, and this scheme is not OAuth. The header example shows syntax only and contains no real token.

Permissions are independent: authorizing one operation does not authorize others. Check the table below and x-required-scope in the reference. For example, backups:run does not grant runs:read, backups:metadata:read or backups:download.

Access combines individually selected devices with the current members of selected groups. Tenant, resources, permissions, expiration and revocation are checked again on every call.

Revocation blocks new calls without cancelling accepted work. Rotation immediately invalidates the old credential. Keep credentials out of URLs, shared examples and diagnostic logs.

Authorization: Bearer <token>

Run and follow backups

To start, send POST /devices/{identifier}/runs with backups:run, Content-Type: application/json, body {} and Idempotency-Key. A 202 response means acceptance for asynchronous processing, not backup completion. Read run_href with runs:read to follow the run.

Idempotency-Key accepts 1–200 printable ASCII characters without whitespace. Reuse the same key and body when repeating the same request. The key is stored for 24 hours and bound to tenant, token, route and normalized JSON body. A divergent body returns 409.

An active run is reused. New external requests share a 60-second cooldown per tenant/device. Billing, tenant lifecycle and SSH trust continue to govern the operation.

Metadata and download permissions are separate. Only success runs with an artifact and valid or legacy_unverified validation are eligible. Legacy status does not prove a consolidated protection assessment.

GET /backups/{identifier}/download returns the file without redirecting to external storage. A failure after transfer starts closes the connection without inserting JSON into the file. Server completion does not prove client receipt. HEAD preserves authorization and returns attachment headers without retrieving the file, starting a transfer or sending body-dependent Content-Length; GET confirms storage existence.

Errors and retries

Use error.code for handling decisions rather than the translated message. Keep correlation_id or X-Correlation-ID for diagnostics; they are not credentials. See the reference for each operation’s specific codes.

401 means a missing, invalid, expired, rotated or revoked credential. 403 means a missing required permission; backup execution may also be restricted by billing. 404 may mean a missing resource, unknown tenant, resource outside scope or missing artifact.

409 distinguishes conflicts by code: cursor_invalid requires restarting pagination; idempotency_conflict means the repeated request differs. tenant_read_only and host_key_required restrictions also apply to execution. 410 means an inactive tenant or an environment being closed.

400 means a malformed request or JSON. For 405, read Allow for the resource’s accepted methods, including HEAD and OPTIONS where applicable.

422 means invalid parameters, body or idempotency key. 413 indicates an exceeded size limit; 415 requires application/json for execution. 503 means service, storage or audit persistence is unavailable: the operation fails closed.

For 429, honor Retry-After in seconds. Preserve Idempotency-Key and body when retrying the same run creation. Errors before a download starts are JSON; after transfer starts, also verify file integrity and receipt.

Limits and pagination

Default shared limits per fixed one-minute window are 30 attempts per origin/tenant before authentication, including valid calls; 120 requests per token; and 600 per tenant. Backend configuration may change these values. Use the contract for your deployed version.

limit accepts 1–100 items and defaults to 50. Unknown, duplicate or invalid filters are rejected. Run and backup filters from and to use UTC ending in Z; numeric offsets are not accepted, and to must not precede from.

Run requests accept only {} and are limited to 16 KiB. Downloads are subject to configured size and timeout limits; this guide does not declare a universal maximum download size.

Permissions by operation

Tenant operationIndependent permission
GET /device-groupsdevices:read
GET /devicesdevices:read
GET /devices/{identifier}devices:read
POST /devices/{identifier}/runsbackups:run
GET /runsruns:read
GET /runs/{identifier}runs:read
GET /backupsbackups:metadata:read
GET /backups/{identifier}backups:metadata:read
GET /backups/{identifier}/downloadbackups:download