Radiator Server Documentation — v10.33.4

RadiatorDB REST API

Read and write RadiatorDB documents through the management API

Table of Contents
  • Access Control
  • Routes
  • List Collections
  • List Documents
  • Get Document
  • Create or Update Document
  • Rename Document
  • Delete Document
  • Invoke Action
  • List Revision History
  • Backup Routes
  • Shared Error Responses
  • Multipart Keys
  • Related Documentation

RadiatorDB exposes document collections through Radiator Management API. Use the REST API when an external tool or service needs to browse, create, update, rename, or delete RadiatorDB documents.

Access Control

RadiatorDB REST API uses management API authentication. A request must authenticate with Basic authentication.

Collection access also depends on the RadiatorDB roles configured for the authenticated user. In the management authentication policy, set user.radiatordb_role to the list of roles that the user has.

These roles are separate from the management API privilege level in user.privilege. Collection document routes do not require a management API privilege level.

After the request is authenticated, collection access requires a matching user.radiatordb_role value. The API matches the user's RadiatorDB roles against the collection roles block.

For example, a user backend query can map a roles array into user.radiatordb_role:

backends {
    jsonfile "MGMT_USERS" {
        query "FIND_USER" {
            mapping {
                user.username = doc | jsonpath("$.users[?(@.username == '%{aaa.identity}')].username");
                user.password = doc | jsonpath("$.users[?(@.username == '%{aaa.identity}')].password");
                user.radiatordb_role = doc | jsonpath("$.users[?(@.username == '%{aaa.identity}')].roles[*]");
            }
        }
    }
}

In the user backend data, store the role names that must match the collection role names:

{
  "users": [
    {
      "username": "alice",
      "password": "{argon2}...",
      "roles": ["support", "ops"]
    }
  ]
}

The collection roles block grants access by matching these user.radiatordb_role values:

  • read roles can list collections, read documents, and read revision history.
  • write roles can create, update, rename, and delete documents. A write role also grants read access.
  • Action allow roles can invoke the matching action when the user can read the collection.
  • Backup export and import require user.privilege write or all. Collection roles do not restrict backup operations.

For example, a user whose user.radiatordb_role contains support can read the DEVICES collection shown above. A user whose user.radiatordb_role contains ops can also write to it.

If the authenticated user does not have a matching collection role, the request returns 403 Forbidden.

Routes

This .radconf example defines a RadiatorDB backend named RADIATORDB and a collection named DEVICES:

backends {
    radiatordb "RADIATORDB" {
        collection "DEVICES" {
            roles {
                read "support";
                write "ops";
            }

            key {
                field {
                    name "Site";
                    type text;
                }

                field {
                    name "Device";
                    type text;
                }
            }
        }
    }
}

In the routes below, this configuration maps placeholders as follows:

Route placeholderValue from the configurationExample value
:db_nameradiatordb "RADIATORDB"RADIATORDB
:collectioncollection "DEVICES"DEVICES
:keyOrdered key fieldshelsinki~edge-1

The example key helsinki~edge-1 represents a document whose Site key part is helsinki and whose Device key part is edge-1.

For example, the configuration above produces these management API routes:

GET /api/v1/backends/radiatordb/RADIATORDB/collections
GET /api/v1/backends/radiatordb/RADIATORDB/collections/DEVICES/documents
GET /api/v1/backends/radiatordb/RADIATORDB/collections/DEVICES/documents/helsinki~edge-1
PUT /api/v1/backends/radiatordb/RADIATORDB/collections/DEVICES/documents/helsinki~edge-1
POST /api/v1/backends/radiatordb/RADIATORDB/collections/DEVICES/documents/helsinki~edge-1/rename
DELETE /api/v1/backends/radiatordb/RADIATORDB/collections/DEVICES/documents/helsinki~edge-1
POST /api/v1/backends/radiatordb/RADIATORDB/collections/DEVICES/documents/helsinki~edge-1/actions/send-coa
GET /api/v1/backends/radiatordb/RADIATORDB/collections/DEVICES/documents/helsinki~edge-1/revisions
POST /api/v1/backends/radiatordb/RADIATORDB/backups/export
POST /api/v1/backends/radiatordb/RADIATORDB/backups/import

List Collections

List collections in a RadiatorDB backend:

GET /api/v1/backends/radiatordb/:db_name/collections

Returns 200 OK with an array of collection summary objects:

FieldTypeDescription
namestringCollection name from the .radconf collection block
displayNamestringDisplay name configured with name, or the collection name
descriptionstring or nullDescription configured with description, or null when omitted
documentCountnumberNumber of active documents currently visible in the collection

Example response:

[
  {
    "name": "DEVICES",
    "displayName": "Devices",
    "description": "Managed network devices",
    "documentCount": 2
  }
]

List Documents

List documents in a collection:

GET /api/v1/backends/radiatordb/:db_name/collections/:collection/documents

The list endpoint accepts these query parameters:

ParameterDescription
cursorContinue from a cursor returned in nextCursor
limitLimit the number of returned documents. Default: 50, maximum: 200
searchSearch documents for matching text
includeDocSet to false to return metadata without document payloads
stateSelect active, deleted, or all documents. Default: active

Returns 200 OK with a paginated document list:

FieldTypeDescription
documentsobject[]Returned documents for the current page
nextCursorstring or nullCursor for the next page, or null when no page remains
totalnumberTotal number of documents matching the request

When includeDoc=false, each returned document has doc set to null.

Example response:

{
  "documents": [
    {
      "key": ["helsinki", "edge-1"],
      "collection": "DEVICES",
      "doc": {
        "hostname": "edge-1",
        "enabled": true
      },
      "createdAt": "2026-06-12T10:00:00Z",
      "updatedAt": "2026-06-12T10:15:00Z",
      "updatedBy": "alice",
      "rev": "00000000-0000-0000-0000-000000000000",
      "deleted": false
    }
  ],
  "nextCursor": null,
  "total": 1
}

Get Document

Get one document:

GET /api/v1/backends/radiatordb/:db_name/collections/:collection/documents/:key

The get endpoint accepts the state query parameter with the same values as the list endpoint.

Returns 200 OK with a document object:

FieldTypeDescription
keystring[]Ordered key parts for the document
collectionstringCollection name
docobject or nullJSON document payload. Tombstones and metadata-only reads use null
createdAtstringCreation time in RFC 3339 format
updatedAtstringLast update time in RFC 3339 format
updatedBystring or nullAuthenticated management user that last updated the document
revstringDocument revision identifier
deletedbooleanWhether this response represents a deleted document

Example response:

{
  "key": ["helsinki", "edge-1"],
  "collection": "DEVICES",
  "doc": {
    "hostname": "edge-1",
    "enabled": true
  },
  "createdAt": "2026-06-12T10:00:00Z",
  "updatedAt": "2026-06-12T10:15:00Z",
  "updatedBy": "alice",
  "rev": "00000000-0000-0000-0000-000000000000",
  "deleted": false
}

Create or Update Document

Create or update one document:

PUT /api/v1/backends/radiatordb/:db_name/collections/:collection/documents/:key
Content-Type: application/json

{
  "doc": {
    "hostname": "edge-1",
    "enabled": true
  }
}

The doc value must be a JSON object. When a collection defines fields, the request must match the collection schema.

Returns 201 Created when the API creates a new document. Returns 200 OK when the API updates an existing document. The response body is a document object with the same fields as the get endpoint.

Rename Document

Rename one active document:

POST /api/v1/backends/radiatordb/:db_name/collections/:collection/documents/:key/rename
Content-Type: application/json

{
  "newKey": "helsinki~edge-2",
  "rev": "00000000-0000-0000-0000-000000000000"
}

Use the current document rev from a previous read. The API rejects stale rename requests when the document changed before the rename.

Returns 200 OK with a document object for the renamed document. The key field contains the new key parts.

Delete Document

Delete one document:

DELETE /api/v1/backends/radiatordb/:db_name/collections/:collection/documents/:key

Delete is a soft delete. You can read deleted documents by using state=deleted or state=all.

Returns 200 OK with a status message:

FieldTypeDescription
codenumberHTTP status code
messagestringOperation result text

Example response:

{
  "code": 200,
  "message": "RadiatorDB document deleted"
}

Invoke Action

Invoke a configured action for one active or soft-deleted document:

POST /api/v1/backends/radiatordb/:db_name/collections/:collection/documents/:key/actions/:action_id
Content-Type: application/json

{
  "input": {
    "reason": "operator request"
  }
}

The authenticated user must have collection read access and one of the action's roles allow roles. Hidden actions return 404 Not Found.

The request body has these fields:

FieldTypeDescription
inputobjectValues for the action input fields. Use {} when the action has no inputs.
targetobject or nullNested list target. Omit or set to null for top-level actions.

For nested list actions, include a target object:

{
  "input": {
    "reason": "stale session"
  },
  "target": {
    "path": [
      {
        "fieldName": "sessions",
        "parentItemIndex": null
      }
    ],
    "itemIndex": 0
  }
}

path identifies the nested list field path. itemIndex identifies the list item for the action. For deeper nested lists, each path segment includes the list field name and the parent list item index.

The API validates input against the action input fields. Unknown fields, missing required fields, and invalid values return 400 Bad Request.

The server fetches the document and nested item by key, path, and item index. Do not send document payloads in the request body. For deleted documents, the action pipeline receives deleted as true and doc as the latest non-tombstone payload when one exists.

Returns 200 OK when the action pipeline accepts:

FieldTypeDescription
actionIdstringInvoked action identifier
messagestringOptional public message from aaa.message

Example response:

{
  "actionId": "send-coa",
  "message": "Disconnect queued."
}

If the pipeline accepts without setting aaa.message, the response contains only actionId. The API does not return aaa.reason or pipeline errors to the caller because those values can contain sensitive operational details.

If the action pipeline rejects or ignores the request, the API returns 400 Bad Request.

List Revision History

List revision history for one document key:

GET /api/v1/backends/radiatordb/:db_name/collections/:collection/documents/:key/revisions

The revision endpoint accepts these query parameters:

ParameterDescription
cursorContinue from a cursor returned in nextCursor
limitLimit the number of returned revisions

Returns 200 OK with a paginated revision history:

FieldTypeDescription
historyobject[]Revision history entries for the requested document key
nextCursorstring or nullCursor for the next page, or null when no page remains

Each revision history entry has these fields:

FieldTypeDescription
revstringRevision identifier
kindstringdocument for content revisions, or rename for rename events
keystring[]Ordered key parts for this revision
previousKeystring[] or nullPrevious key parts for rename events, or null otherwise
updatedAtstringRevision update time in RFC 3339 format
updatedBystring or nullAuthenticated management user that made the change
docobject or nullJSON payload stored for this revision
deletedbooleanWhether this revision is a delete tombstone

Example response:

{
  "history": [
    {
      "rev": "00000000-0000-0000-0000-000000000000",
      "kind": "document",
      "key": ["helsinki", "edge-1"],
      "previousKey": null,
      "updatedAt": "2026-06-12T10:15:00Z",
      "updatedBy": "alice",
      "doc": {
        "hostname": "edge-1",
        "enabled": true
      },
      "deleted": false
    }
  ],
  "nextCursor": null
}

Backup Routes

RadiatorDB backup export and import use these routes:

POST /api/v1/backends/radiatordb/:db_name/backups/export
POST /api/v1/backends/radiatordb/:db_name/backups/import

Backup export and import require user.privilege write or all. Backup streams can use raw JSON Lines or gzip-compressed JSON Lines. Import accepts importRevisions, strategy, batchSize, and validateFields query parameters. For request fields, response fields, strategy behavior, curl examples, and the backup file format, see RadiatorDB Backup.

Shared Error Responses

Error responses use a JSON status message body:

FieldTypeDescription
codenumberHTTP status code
messagestringHuman-readable error

Common status codes are:

StatusMeaning
400Invalid request body, key, cursor, revision, or schema
401Missing or invalid management API authentication
403Authenticated user lacks the required RadiatorDB role or privilege
404Database, collection, document, or visible action was not found
409Rename conflict or stale rename revision

Multipart Keys

Multipart keys allow hierarchical document organization. Key parts are separated by ~ in management API URLs. Escape a literal ~ inside a key part as ~~.

For example, a document stored with two key parts helsinki and edge-1 has the composite key helsinki~edge-1 and is accessible through the management API at:

GET /api/v1/backends/radiatordb/:db_name/collections/:collection/documents/helsinki~edge-1

Multipart keys enable partial key matching through at and contains filters in RadiatorDB backend queries. This allows lookups by any subset of key parts without knowing the full key.

Navigation
  • About Radiator software development security

  • Architecture Overview

  • Backend Load Balancing

  • Basic Installation

  • Built-in Environment Variables

  • Byte Size Units

  • Certificate Revocation Lists

  • Comparison Operators

  • Configuration Editor

  • Configuration Import and Export

  • Containers

  • Cron and interval timers

  • Data Types

  • Duration Units

  • Environment Variables

  • Execution Context

  • Execution Pipelines

  • Filters

  • Getting a Radiator License

  • Health check /live and /ready

  • High Availability and Load Balancing

  • High availability identifiers

  • HTTP Basic Authentication

  • Introduction

  • Linux systemd support

  • Local AAA Backends

  • Log storage and formatting

  • Management API privilege levels

  • Namespaces

  • Password Hashing

  • Password Rehashing During Login

  • Probabilistic Sampling

  • Prometheus scraping

  • PROXY Protocol Support

  • Radiator server health and boot up logic

  • Radiator sizing

  • Radiator software releases

  • RadiatorDB

  • RadiatorDB Backup

  • RadiatorDB CLI

  • RadiatorDB Installation

  • RadiatorDB REST API

  • Rate Limiting

  • Rate Limiting Algorithms

  • Reverse Dynamic Authorization

  • Service Level Objective

  • TACACS+ Authentication, Authorization, and Accounting

  • Template Rendering CLI

  • Timestamp Format

  • Timestamps

  • Tools radiator-client

  • TOTP/HOTP Authentication

  • What is Radiator?

  • YubiKey Authentication

  • YubiKey Context Variables