RDFM Server API Reference

API Authentication

By default, the RDFM server expects all API requests to be authenticated. Depending on the type of the API, this can be either:

  • Device Token

  • Management Token

In either case, the server expects the token to be passed as part of the request, in the HTTP Authorization header. An example authenticated request is shown below:

GET /api/v1/groups HTTP/1.1
Host: rdfm-server:5000
User-Agent: python-requests/2.31.0
Accept-Encoding: gzip, deflate
Accept: */*
Connection: keep-alive
Authorization: Bearer token=eyJhbGciOiJSUzI1NiIsInR5cC<...truncated...>RpPonb7-IAsk89YpGayxg

Any request that was not successfully authenticated (because of a missing or otherwise invalid token) will return the 401 Unauthorized status code. Additionally, in the case of management tokens, if the given token does not provide sufficient access to the requested resource, the request will be rejected with a 403 Forbidden status code. This can happen if the token does not claim all scopes required by the target endpoint (for example: trying to upload a package using a read-only token).

Error Handling

Should an error occur during the handling of an API request, either because of incorrect request data or other endpoint-specific scenarios, the server will return an error structure containing a user-friendly description of the error. An example error response is shown below:

{
   "error": "delete failed, the package is assigned to at least one group"
}

Packages API

GET /api/v1/packages

Fetch a list of packages uploaded to the server

Status Codes:
  • 200 OK – no error

  • 401 Unauthorized – user did not provide authorization data, or the authorization has expired

Response JSON Array of Objects:
  • id (integer) – package identifier

  • created (string) – UTC creation date (RFC822)

  • sha256 (string) – sha256 of the uploaded package

  • driver (string) – storage driver used to store the package

  • metadata (dict[str, str]) – package metadata (key/value pairs)

Example Request

GET /api/v1/packages HTTP/1.1
Accept: application/json, text/javascript

Example Response

HTTP/1.1 200 OK
Content-Type: application/json

[
    {
        "created": "Thu, 17 Aug 2023 10:41:08 GMT",
        "id": 1,
        "metadata": {
            "rdfm.hardware.devtype": "dummydevice",
            "rdfm.software.version": "v10",
            "rdfm.storage.local.length": 4194304,
            "rdfm.storage.local.uuid": "6f7483ac-5cde-467f-acf7-39e4b397e313"
        },
        "driver": "local",
        "sha256": "4e415854e6d0cf9855b2290c02638e8651537989b8862ff9c9cb91b8d956ea06"
    }
]

Warning

Accessing this endpoint requires providing a management token with read-only scope rdfm_admin_ro or administrative scope rdfm_admin_rw.

POST /api/v1/packages

Upload an update package.

Uploads an update package to the server. Remaining key/value pairs in the form request are used as metadata for the artifact.

If required, an additional storage directory can be specified that indicates the directory within server-side storage that the package is placed in.

Form Parameters:
  • file – binary contents of the package

  • rdfm.software.version – required: software version of the package

  • rdfm.hardware.devtype – required: compatible device type

  • rdfm.storage.directory – optional: storage directory specific to the current storage driver

  • ... – remaining package metadata

Status Codes:
  • 200 OK – no error, package was uploaded

  • 400 Bad Request – provided metadata contains keys reserved by RDFM or a file was not provided

  • 401 Unauthorized – user did not provide authorization data, or the authorization has expired

  • 403 Forbidden – user was authorized, but did not have permission to upload packages

Example Request

POST /api/v1/packages HTTP/1.1
Accept: */*
Content-Length: 4194738
Content-Type: multipart/form-data; boundary=------------------------0f8f9642db3a513e

--------------------------0f8f9642db3a513e
Content-Disposition: form-data; name="rdfm.software.version"

v10
--------------------------0f8f9642db3a513e
Content-Disposition: form-data; name="rdfm.hardware.devtype"

dummydevice
--------------------------0f8f9642db3a513e
Content-Disposition: form-data; name="file"; filename="file.img"
Content-Type: application/octet-stream

<file contents>
--------------------------0f8f9642db3a513e--

Example Response

HTTP/1.1 200 OK
Content-Type: application/json

Warning

Accessing this endpoint requires providing a management token with read-write scope rdfm_admin_rw.

DELETE /api/v1/packages/(int: identifier)

Delete the specified package

Deletes the specified package from the server and from the underlying storage. The package can only be deleted if it’s not assigned to any group.

Parameters:
  • identifier – package identifier

Status Codes:
  • 200 OK – no error

  • 401 Unauthorized – user did not provide authorization data, or the authorization has expired

  • 403 Forbidden – user was authorized, but did not have permission to delete packages

  • 404 Not Found – specified package does not exist

  • 409 Conflict – package is assigned to a group and cannot be deleted

Example Request

DELETE /api/v1/packages/1 HTTP/1.1

Example Response

HTTP/1.1 200 OK

Warning

Accessing this endpoint requires providing a management token with read-write scope rdfm_admin_rw.

GET /api/v1/packages/(int: identifier)

Fetch information about a single package given by the specified ID

Parameters:
  • identifier – package identifier

Status Codes:
Response JSON Object:
  • id (integer) – package identifier

  • created (string) – UTC creation date (RFC822)

  • sha256 (string) – sha256 of the uploaded package

  • driver (string) – storage driver used to store the package

  • metadata (dict[str, str]) – package metadata (simple key/value pairs)

Example Request

GET /api/v1/packages/1 HTTP/1.1
Accept: application/json, text/javascript

Example Response

HTTP/1.1 200 OK
Content-Type: application/json

{
    "created": "Thu, 17 Aug 2023 10:41:08 GMT",
    "id": 1,
    "metadata": {
        "rdfm.hardware.devtype": "dummydevice",
        "rdfm.software.version": "v10",
        "rdfm.storage.local.length": 4194304,
        "rdfm.storage.local.uuid": "6f7483ac-5cde-467f-acf7-39e4b397e313"
    },
    "driver": "local",
    "sha256": "4e415854e6d0cf9855b2290c02638e8651537989b8862ff9c9cb91b8d956ea06"
}

Warning

Accessing this endpoint requires providing a management token with read-only scope rdfm_admin_ro or administrative scope rdfm_admin_rw.

GET /local_storage/(path: name)

Endpoint for exposing local package storage.

WARNING: Local storage should not be used in production deployment, only for local testing! This will be disabled in the future for non-prod configurations.

Parameters:
  • name – identifier (UUID) of the package object in local storage

Status Codes:

Note

This is a public API route; no authorization is required to access it.

Group API

POST /api/v1/groups

Create a new group

Status Codes:
Request JSON Object:
  • key (any) – metadata value

Example request

POST /api/v1/groups/1 HTTP/1.1
Content-Type: application/json
Accept: application/json, text/javascript

{
    "description": "A test group",
}

Example Response

HTTP/1.1 200 OK
Content-Type: application/json

{
    "created": "Mon, 14 Aug 2023 11:50:40 GMT",
    "devices": [],
    "id": 2,
    "packages": [],
    "metadata": {
        "description": "A test group",
    },
    "policy": "no_update,"
}

Warning

Accessing this endpoint requires providing a management token with read-write scope rdfm_admin_rw.

GET /api/v1/groups

Fetch all groups

Status Codes:
  • 200 OK – no error

  • 401 Unauthorized – user did not provide authorization data, or the authorization has expired

Response JSON Array of Objects:
  • id (integer) – group identifier

  • created (string) – UTC creation date (RFC822)

  • packages (array[integer]) – currently assigned package identifiers

  • devices (array[integer]) – currently assigned device identifiers

  • metadata (dict[str, str]) – group metadata

  • policy (str) – group update policy

Example Request

GET /api/v1/groups HTTP/1.1
Accept: application/json, text/javascript

Example Response

HTTP/1.1 200 OK
Content-Type: application/json

[
    {
        "created": "Mon, 14 Aug 2023 11:00:56 GMT",
        "devices": [],
        "id": 1,
        "packages": [],
        "metadata": {},
        "policy": "no_update,"
    }
]

Warning

Accessing this endpoint requires providing a management token with read-only scope rdfm_admin_ro or administrative scope rdfm_admin_rw.

DELETE /api/v1/groups/(int: identifier)

Delete a group

The group being deleted must NOT be assigned to any devices.

Parameters:
  • identifier – group identifier

Status Codes:
  • 200 OK – no error

  • 401 Unauthorized – user did not provide authorization data, or the authorization has expired

  • 403 Forbidden – user was authorized, but did not have permission to delete groups

  • 404 Not Found – group does not exist

  • 409 Conflict – at least one device is still assigned to the group

Example Request

DELETE /api/v1/groups/1 HTTP/1.1

Example Response

HTTP/1.1 200 OK

Warning

Accessing this endpoint requires providing a management token with read-write scope rdfm_admin_rw.

GET /api/v1/groups/(int: identifier)

Fetch information about a group

Parameters:
  • identifier – group identifier

Status Codes:
Response JSON Object:
  • id (integer) – group identifier

  • created (string) – UTC creation date (RFC822)

  • packages (array[integer]) – currently assigned package identifiers

  • devices (array[integer]) – currently assigned device identifiers

  • metadata (dict[str, str]) – group metadata

  • policy (str) – group update policy

Example Request

GET /api/v1/groups/1 HTTP/1.1
Accept: application/json, text/javascript

Example Response

HTTP/1.1 200 OK
Content-Type: application/json

{
    "created": "Mon, 14 Aug 2023 11:00:56 GMT",
    "devices": [],
    "id": 1,
    "packages": [],
    "metadata": {},
    "policy": "no_update,"
}

Warning

Accessing this endpoint requires providing a management token with read-only scope rdfm_admin_ro or administrative scope rdfm_admin_rw.

PATCH /api/v1/groups/(int: identifier)/devices

Modify the list of devices assigned to a group

This endpoint allows modifying the list of devices assigned to the group, as described by two arrays containing device identifiers of devices that will be added/removed from the group.

This operation is atomic - if at any point an invalid device identifier is encountered, the entire operation is aborted. This covers:

  • Any device identifier which does not match a registered device

  • Any device identifier in additions which already has an assigned group (even if the group is the as specified by identifier)

  • Any device identifier in removals which is not currently assigned to the specified package

Additions are evaluated first, followed by the removals.

Parameters:
  • identifier – group identifier

Status Codes:
  • 200 OK – no error

  • 401 Unauthorized – user did not provide authorization data, or the authorization has expired

  • 403 Forbidden – user was authorized, but did not have permission to delete groups

  • 404 Not Found – group does not exist

  • 409 Conflict – one of the conflict situations described above has occurred

Request JSON Object:
  • add (array[string]) – identifiers of devices that should be assigned to the group

  • remove (array[string]) – identifiers of devices that should be removed from the group

Example request

PATCH /api/v1/groups/1/devices HTTP/1.1
Accept: application/json, text/javascript

{
    "add": [
        1,
        2,
        5,
    ]
    "remove": [
        3,
    ]
}

Example Response

HTTP/1.1 200 OK

Warning

Accessing this endpoint requires providing a management token with read-write scope rdfm_admin_rw.

POST /api/v1/groups/(int: identifier)/package

Assign a package to a specific group

Parameters:
  • identifier – group identifier

Status Codes:
  • 200 OK – no error

  • 400 Bad Request – invalid request schema

  • 401 Unauthorized – user did not provide authorization data, or the authorization has expired

  • 403 Forbidden – user was authorized, but did not have permission to assign packages

  • 404 Not Found – the specified package or group does not exist

  • 409 Conflict – the package/group was modified or deleted during the operation

Request JSON Object:
  • packages (array[integer]) – identifiers of the packages to assign, or empty array

Example request

POST /api/v1/groups/1/package HTTP/1.1
Content-Type: application/json
Accept: application/json, text/javascript

{
    "packages": [1],
}

Example Response

HTTP/1.1 200 OK

Warning

Accessing this endpoint requires providing a management token with read-write scope rdfm_admin_rw.

POST /api/v1/groups/(int: identifier)/policy

Change the update policy of the group

The update policy defines the target versions that each device within the group should be receiving. For information about group policies, consult the OTA manual.

Parameters:
  • identifier – group identifier

Status Codes:
  • 200 OK – no error

  • 400 Bad Request – invalid request schema, or an invalid policy schema was requested

  • 401 Unauthorized – user did not provide authorization data, or the authorization has expired

  • 403 Forbidden – user was authorized, but did not have permission to modify groups

  • 404 Not Found – the specified group does not exist

Request JSON Object:
  • policy (string) – new group policy string to set

Example Request

POST /api/v1/groups/1/policy HTTP/1.1
Content-Type: application/json
Accept: application/json, text/javascript

{
    "policy": "exact_match,v1",
}

Example Response

HTTP/1.1 200 OK

Warning

Accessing this endpoint requires providing a management token with read-write scope rdfm_admin_rw.

Update API

POST /api/v1/update/check

Check for available updates

Device clients must call this endpoint with their associated metadata. At minimum, the rdfm.software.version, rdfm.hardware.devtype and rdfm.hardware.macaddr pairs must be present. Based on this metadata, the device’s currently assigned group (if any) and package, an update package is picked from the available ones.

Status Codes:
  • 200 OK – an update is available

  • 204 No Content – no updates are available

  • 400 Bad Request – device metadata is missing device type, software version, and/or MAC address

  • 401 Unauthorized – device did not provide authorization data, or the authorization has expired

Request JSON Array of Objects:
  • rdfm.software.version (string) – required: running software version

  • rdfm.hardware.devtype (string) – required: device type

  • rdfm.hardware.macaddr (string) – required: MAC address (used as ID)

  • ... (string) – other device metadata

Response JSON Object:
  • id (integer) – package identifier

  • created (string) – UTC creation date (RFC822)

  • sha256 (string) – sha256 of the uploaded package

  • uri (string) – generated URI for downloading the package

Example Request

POST /api/v1/update/check HTTP/1.1
Accept: application/json, text/javascript
Content-Type: application/json

{
    "rdfm.software.version": "v0.0.1",
    "rdfm.hardware.macaddr": "00:11:22:33:44:55",
    "rdfm.hardware.devtype": "example"
}

Example Responses

HTTP/1.1 204 No Content
HTTP/1.1 200 OK
Content-Type: application/json

{
  "created": "Mon, 14 Aug 2023 13:03:27 GMT",
  "id": 1,
  "sha256": "4e415854e6d0cf9855b2290c02638e8651537989b8862ff9c9cb91b8d956ea06",
  "uri": "http://127.0.0.1:5000/local_storage/12a83ff3-2de2-4a95-8f3f-c7a884e426e5"
}

Warning

Accessing this endpoint requires providing a device token.

Device Management API

GET /api/v1/devices

Fetch a list of devices registered on the server

Status Codes:
  • 200 OK – no error

  • 401 Unauthorized – user did not provide authorization data, or the authorization has expired

Response JSON Array of Objects:
  • id (integer) – device identifier

  • last_access (string) – UTC datetime of last access to the server (RFC822)

  • name (string) – device-reported user friendly name

  • mac_addr (string) – device-reported MAC address

  • group (optional[integer]) – group identifier of assigned group

  • metadata (dict[str, str]) – device metadata (key/value pairs)

  • capabilities (dict[str, bool]) – device RDFM client capabilities

Example Request

GET /api/v1/devices HTTP/1.1
Accept: application/json, text/javascript

Example Response

HTTP/1.1 200 OK
Content-Type: application/json

[
  {
    "capabilities": {
      "exec_cmds": false,
      "file_transfer": true,
      "shell_connect": true
    },
    "group": 1,
    "id": 1,
    "last_access": null,
    "mac_address": "loopback",
    "metadata": {},
    "name": "dummy_device"
  }
]

Warning

Accessing this endpoint requires providing a management token with read-only scope rdfm_admin_ro or administrative scope rdfm_admin_rw.

GET /api/v1/devices/(int: identifier)

Fetch information about a single device given by the identifier

Status Codes:
  • 200 OK – no error

  • 401 Unauthorized – user did not provide authorization data, or the authorization has expired

  • 404 Not Found – device with the specified identifier does not exist

Response JSON Object:
  • id (integer) – device identifier

  • last_access (string) – UTC datetime of last access to the server (RFC822)

  • name (string) – device-reported user friendly name

  • mac_addr (string) – device-reported MAC address

  • group (optional[integer]) – group identifier of assigned group

  • metadata (dict[str, str]) – device metadata (key/value pairs)

  • capabilities (dict[str, bool]) – device RDFM client capabilities

Example Request

GET /api/v1/devices/1 HTTP/1.1
Accept: application/json, text/javascript

Example Response

HTTP/1.1 200 OK
Content-Type: application/json

{
  "capabilities": {
    "exec_cmds": false,
    "file_transfer": true,
    "shell_connect": true
  },
  "group": 1,
  "id": 1,
  "last_access": null,
  "mac_address": "loopback",
  "metadata": {},
  "name": "dummy_device"
}

Warning

Accessing this endpoint requires providing a management token with read-only scope rdfm_admin_ro or administrative scope rdfm_admin_rw.

Device Authorization API

POST /api/v1/auth/device

Device authorization endpoint

All device clients must first authorize with the RDFM server via this endpoint.

Status Codes:
Request JSON Object:
  • metadata (dict[str, str]) – device metadata

  • public_key (str) – the device’s RSA public key, in PEM format, with newline characters escaped

  • timestamp (int) – POSIX timestamp at the time of making the request

Example Request

POST /api/v1/auth/device HTTP/1.1
Accept: application/json, text/javascript
Content-Type: application/json
X-RDFM-Device-Signature: FGACvvZ4CFC0np9Z8QNeuF8jnaE7y8v532FNtwMjkWKyT6sHj0hTIgggxfgaC1mOmY/9xmnwv2aQLgUxbzCJs0yf1/PyxG3Gyf8Mt47+aXbT4/Mj8j++8EB2QxbB9TKwZiCGa+lkevXsZwOrD6l4WNWUeQFA/jgWzTLoYxsIdz0=

{
    "metadata": {
        "rdfm.software.version": "v0",
        "rdfm.hardware.devtype": "dummy",
        "rdfm.hardware.macaddr": "00:00:00:00:00:00"
    },
    "public_key": "-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVqdgCAfyXUqLfOpHYwHFv4OQL\n2p3LwHm5ag9XMY2ylvqU2r9eGNWkdXTtEnL81S6u+4CDFNmbUuimoeDMazqSKYED\n3FtOU4+FrqaHf7T3oMkng5mNHcAqbyq6WAXs/HrXfvj7lR38qLJXgslgR3Js3M0k\nB91oGfFwUa7I67BZYwIDAQAB\n-----END PUBLIC KEY-----",
    "timestamp": 1694414456
}

Example Response

Unauthorized device:

HTTP/1.1 401 Unauthorized
Content-Type: application/json

Authorized device:

HTTP/1.1 200 OK
Content-Type: application/json

{
    "expires": 300,
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJkZXZpY2VfaWQiOiIwMDowMDowMDowMDowMDowMCIsImNyZWF0ZWQiOjE2OTQ0MTQ0NTYsImV4cGlyZXMiOjMwMH0.cG37RTA1niB8NhokqI0ryvDKZj_0eRpWWEeqawu4IYE"
}

Note

This is a public API route; no authorization is required to access it.

GET /api/v1/auth/pending

Fetch all pending registrations

This endpoint returns device registrations requests that have not been accepted by an administrator yet.

Status Codes:
  • 200 OK – no error

  • 401 Unauthorized – user did not provide authorization data, or the authorization has expired

Response JSON Array of Objects:
  • metadata (dict[str, str]) – device metadata

  • public_key (str) – the device’s RSA public key, in PEM format, with newline characters escaped

  • mac_address (str) – the device’s MAC address

  • last_appeared (str) – datetime (RFC822) of the last registration request made by the device

Example Request

GET /api/v1/auth/registrations HTTP/1.1
Accept: application/json, text/javascript

Example Response

HTTP/1.1 200 OK
Content-Type: application/json

[
  {
    "last_appeared": "Wed, 13 Sep 2023 10:40:49 GMT",
    "mac_address": "00:00:00:00:00:00",
    "metadata": {
      "rdfm.hardware.devtype": "dummy",
      "rdfm.hardware.macaddr": "00:00:00:00:00:00",
      "rdfm.software.version": "v0"
    },
    "public_key": "-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCdBgmI/FGkb17Bcxr99lEF1Nof\njwQaPcipnBWW+S3N6c937rGkINH0vkHMjcS3HRF2ku6/Knjj4uXrZtbwUbPoP4bP\nbK+HrYVw9Di6hTHr042W7FxIzU3howCF68QQnUMG/5XmqwdsucH1gMRv8cuU21Vz\nQazvf08UWZCUeQjw5QIDAQAB\n-----END PUBLIC KEY-----"
  }
]

Warning

Accessing this endpoint requires providing a management token with read-only scope rdfm_admin_ro or administrative scope rdfm_admin_rw.

POST /api/v1/auth/register

Accept registration request

Accepts an incoming device registration request. As a result, the device will be allowed access to the RDFM server on next registration attempt.

Status Codes:
  • 200 OK – no error

  • 401 Unauthorized – user did not provide authorization data, or the authorization has expired

  • 403 Forbidden – user was authorized, but did not have permission to change device registration status

  • 404 Not Found – the specified registration request does not exist

Request JSON Object:
  • public_key (str) – RSA public key used in the registration request

  • mac_address (str) – MAC address used in the registration request

Example Request

POST /api/v1/auth/registrations HTTP/1.1
Accept: application/json, text/javascript
Content-Type: application/json

{
    "mac_address": "00:00:00:00:00:00",
    "public_key": "-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCdBgmI/FGkb17Bcxr99lEF1Nof\njwQaPcipnBWW+S3N6c937rGkINH0vkHMjcS3HRF2ku6/Knjj4uXrZtbwUbPoP4bP\nbK+HrYVw9Di6hTHr042W7FxIzU3howCF68QQnUMG/5XmqwdsucH1gMRv8cuU21Vz\nQazvf08UWZCUeQjw5QIDAQAB\n-----END PUBLIC KEY-----"
}

Example Response

HTTP/1.1 200 OK

Warning

Accessing this endpoint requires providing a management token with read-write scope rdfm_admin_rw.


Last update: 2024-05-15