# SecuriThings Developer Center > Complete documentation for Large Language Models --- ## Document: Welcome URL: /welcome # Welcome import { Card, CardHeader, CardTitle, CardDescription } from "zudoku/ui/Card"; import { Link } from "zudoku/components"; The SecuriThings API enables developers and AI agents to access data, execute tasks, automate device workflows, and integrate with third-party systems. ## What you can build - **Monitoring and data retrieval.** Read device, site, and compliance data across your fleet, and feed it into your own tools. - **Automation and tasks.** Execute remediation tasks and automate device workflows programmatically. - **Integrations with third-party systems.** Connect SecuriThings to the platforms and services your team already runs on. ## Start here
Authentication Get credentials and exchange them for a token. API Fundamentals Understand the conventions that apply before you call an endpoint. Use Cases Learn what you can do with the API. API Reference Find every endpoint, parameter, and response in one place.
## Contact For questions and support, speak to our [support team](mailto:cs_engineers@securithings.com). Want to learn more about the SecuriThings solution? Reach out to our [sales team](mailto:info@securithings.com). :::rocket The SecuriThings Developer Center evolves based on your needs. We continuously add new API endpoints, Documentation, and Use Cases driven by customer feedback. ::: --- ## Document: Changelog URL: /changelog # Changelog ## 8 October 2026 - New Compliance Fields and Filters Now Available The SecuriThings API now includes additional compliance fields in the `GET /v1/devices` and `GET /v1/devices/{id}` endpoints, giving you visibility into each device's vulnerability severity level, firmware version suggested by the management platform, replacement model suggested by the vendor, password expiry, and SSL and 802.1X certificate expiry and compliance status. Corresponding query parameters were also added to `GET /v1/devices`, so you can filter devices by these fields. For more details, view the full API Reference. ## 27 September 2026 - Firmware Upgrade Task Type Now Available The SecuriThings API now supports the Firmware Upgrade task type through the `POST /v1/tasks` endpoint, letting you execute firmware upgrades on one or more devices directly through the API. Two new endpoints support it: `GET /v1/devices/{id}/targetFirmware` returns the approved firmware versions a specific device can be upgraded to, and `GET /v1/firmwarePaths` returns all firmware upgrade paths defined in the system and requires Admin permissions. For more details, view the full API Reference. ## 11 August 2026 - New Device Fields and Filters Now Available The SecuriThings API now includes additional fields in the `GET /v1/devices` and `GET /v1/devices/{id}` endpoints, giving you more visibility into each device directly through the API: onboarding date, maintenance mode, last hardened, recording status, storage server, patched firmware version, and orphaned status. Corresponding query parameters were also added to `GET /v1/devices`, so you can filter devices by these fields. For more details, view the full API Reference. ## 29 July 2026 - Onboard Task Type Now Available The SecuriThings API now supports the Onboard task type through the `POST /v1/tasks` endpoint, letting you onboard discovered devices into your managed inventory directly through the API. For more details, view the full API Reference. ## 29 July 2026 - Get Discovered Devices Now Available The SecuriThings API now includes a new `GET /v1/discoveredDevices` endpoint, giving you visibility into all discovered devices and their onboarding status directly through the API. For more details, view the full API Reference. ## 20 July 2026 - Execute Device Tasks Now Available The SecuriThings API now lets you execute device tasks on one or more devices through the new `POST /v1/tasks endpoint`, and track their execution status through the new `GET /v1/tasks/{id}` endpoint, giving you full control over device tasks directly through the API. Three task types are currently supported: Restart, Password Rotation, and SSL Certificate Rotation. Using the `POST /v1/tasks` endpoint requires Admin or Operator permissions. For more details, view the full API Reference. ## 19 May 2026 - Get Device Passwords Metadata Now Available The SecuriThings API now includes a new endpoint under the Devices category - `GET /v1/devices/{id}/passwords`. This endpoint returns password metadata for all users associated with a specific device. Note that actual password values are not included in the response. For more details, view the full API Reference. ## 19 May 2026 - Get Device Certificates Now Available The SecuriThings API now includes a new endpoint under the Devices category - `GET /v1/devices/{id}/certificates`. This endpoint returns full certificate data, including the certificate itself, for all certificate types associated with a specific device, currently SSL and 802.1x, in a single response. For more details, view the full API Reference. ## 30 April 2026 - Site Status Now Available in Get Sites and Get Site By ID The SecuriThings API now includes a new `status` field in the `GET /v1/sites` and `GET /v1/sites/{id}` endpoints, giving you visibility into the connectivity status of each site directly through the API. You can also filter results by status using the new status query parameter. ## 16 Oct 2025 - Filter Devices by Available Task! We’re excited to introduce new query parameters for the GET /v1/devices endpoint that let you filter devices by whether certain tasks are available. This makes it easier to quickly find devices that can perform tasks like password rotation, firmware upgrades, device hardening, rotate SSL certificate and restart device. You can now use the following query parameters in your requests: GET `/v1/devices/?availableTask.passwordRotation=1` This request returns only devices where firmware upgrade is available. ## 8 Sep 2025 - Fetch Device Vulnerabilities with Our New Endpoint We’ve just released a new endpoint that makes it easier to retrieve vulnerability data for any specific device. With GET `/devices/{id}/vulnerabilities` you can fetch all known vulnerabilities tied to a device. This endpoint helps you quickly assess security risks and integrate vulnerability insights into your own monitoring and reporting systems. ## 24 Jun 2025 - New Probe information available! We are excited to announce that the SecuriThings API now provides additional information about probes, enhancing your ability to monitor and manage devices effectively. This update includes the following new fields for probes: - `probe.agent`: Indicates the status of the agent probe. - `probe.deviceSource`: Indicates the status of the device source probe. - `probe.edge`: Indicates the status of the edge probe. - `probe.host`: Indicates the status of the host probe. - `probe.app`: Indicates the status of the app probe. You can also filter devices based on these probe statuses using the `probe.agent`, `probe.deviceSource`, `probe.edge`, `probe.host`, and `probe.app` query parameters. The possible values for these fields are `up`, `down`, `unknown`, or `unmonitored`. These fields provide valuable insights into the connectivity and health of your devices, allowing you to make informed decisions and take proactive measures to ensure optimal performance. --- ## Document: Monitoring URL: /use-cases/monitoring # Monitoring import { Accordion, AccordionContent, AccordionItem, AccordionTrigger, } from "zudoku/ui/Accordion"; API endpoints used in this page - [`GET /v1/devices`](/api/devices) - [`GET /v1/devices/{id}`](/api/devices) - [`GET /v1/sites`](/api/sites) The API exposes the operational state of every device and site, so fleet health can be delivered to the systems your teams already operate, on a schedule you define, and combined with data held outside SecuriThings. ## Scenarios - **NOC dashboards.** Forward device and site state into the dashboards and monitoring stack your NOC already operates. - **Custom alerting.** Evaluate conditions such as offline for longer than a set period, or a single probe down across an entire site, and raise them in your own alerting system. - **CMDB correlation.** Join device state with records held outside SecuriThings, such as asset ownership, maintenance windows, or support contracts. - **SIEM ingestion.** Deliver device state into your SIEM alongside your other security telemetry. - **Availability reporting.** Responses describe current state, so recording them on a schedule produces the availability and trend reporting your organization requires. - **Automated response.** Pair a detection with an [executed task](/use-cases/device-remediation) to remediate without manual intervention. ## Device connectivity `status` reports the connectivity of a device, and `lastSeen` reports the last time the device was not offline, that is, the last time it was `online` or `partial`. Filter server-side rather than retrieving the full inventory: ```bash curl "https://api.securithings.com/v1/devices?status=offline&limit=100" \ -H "Accept: application/json" \ -H "Authorization: Bearer " ``` ```json { "name": "Headquarters camera1", "status": "partial", "lastSeen": "2026-07-09T11:20:00Z", "maintenanceMode": false, "probe": { "agent": "unmonitored", "deviceSource": "down", "edge": "up", "host": "up", "app": "up" } } ``` A `status` of `partial` indicates that some, but not all, of the device's probes are reporting. The `probe` fields identify which component is affected, and each one is also available as a filter. :::info `maintenanceMode` identifies devices under planned work. Exclude them when generating alerts to avoid reporting expected downtime. ::: ## Site connectivity Sites expose their own `status`, so connectivity per location can be retrieved without paging through every device: ```bash curl "https://api.securithings.com/v1/sites?status=offline&limit=100" \ -H "Accept: application/json" \ -H "Authorization: Bearer " ``` --- ## Document: Automating Device Remediation URL: /use-cases/device-remediation # Automating Device Remediation import { Accordion, AccordionContent, AccordionItem, AccordionTrigger, } from "zudoku/ui/Accordion"; API endpoints used in this page - [`GET /v1/devices`](/api/devices) - [`POST /v1/tasks`](/api/tasks) - [`GET /v1/tasks/{id}`](/api/tasks) The API executes remediation tasks across one or more devices and reports the outcome of each, so remediation can be driven from the systems and workflows your teams already operate, or built into new workflows and automations of your own. ## Scenarios - **Scheduled credential rotation.** Rotate device passwords across the fleet on a defined schedule from your orchestration system. - **Ticket-driven remediation.** Execute a task from your ITSM or ticketing tool and post the result back to the ticket. - **Certificate lifecycle automation.** Rotate SSL certificates ahead of expiry as part of your certificate management process. - **Response to monitoring.** Execute remediation automatically from a condition detected through [Monitoring](/use-cases/monitoring). ## Check task availability Not every device supports every task. The `availableTask` object on a device reports which tasks can be executed on it, so filter the target devices before executing: ```json "availableTask": { "hardenDevice": false, "restartDevice": true, "rotate8021xCertificate": false, "rotatePassword": true, "rotateSslCertificate": true, "upgradeFirmware": true } ``` ## Execute a task A single request executes a task across any number of devices, and returns the `taskId` used to track it: ```bash curl -X POST "https://api.securithings.com/v1/tasks" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer " \ -d '{ "taskType": "restartDevice", "devices": [ { "deviceId": "9ff559ee-38b6-11f1-81cb-465864a35d0a" }, { "deviceId": "dc7d4ef1-6bf9-11f1-b083-d27bafcacdf8" } ] }' ``` ```json { "taskId": "23bpozz1mpjjedtr" } ``` Tasks run asynchronously. The execution and polling pattern, the available task types, and the per-task-type payloads are described in [Asynchronous Tasks](/guides/async-tasks). ## Verify the outcome Poll `GET /v1/tasks/{id}` until every device task has a `status` of `completed`, then read the `result` of each device task. Device tasks that did not succeed can be retried independently of the rest. ```bash curl "https://api.securithings.com/v1/tasks/23bpozz1mpjjedtr" \ -H "Accept: application/json" \ -H "Authorization: Bearer " ``` --- ## Document: Manage Device Inventory URL: /use-cases/device-inventory # Manage Device Inventory import { Accordion, AccordionContent, AccordionItem, AccordionTrigger, } from "zudoku/ui/Accordion"; API endpoints used in this page - [`GET /v1/discoveredDevices`](/api/discovered-devices) - [`POST /v1/tasks`](/api/tasks) - [`GET /v1/tasks/{id}`](/api/tasks) - [`GET /v1/devices`](/api/devices) The discovered devices inventory is populated from the device sources connected to SecuriThings, and it is updated continuously as additional devices are discovered. A discovered device must be onboarded before it can be managed through the SecuriThings platform. This guide covers retrieving discovered devices and onboarding them into your managed inventory. ## Managed vs discovered - **Managed devices** (`GET /v1/devices`) are managed through the SecuriThings platform. - **Discovered devices** (`GET /v1/discoveredDevices`) come from the connected device sources and are not managed until they are onboarded. ## Scenarios - **Discovery monitoring.** Track newly reported devices and their onboarding status over time. - **Bulk onboarding.** Onboard every device that is ready to onboard in a single task. - **Onboarding backlog reporting.** Report devices that require enrichment before they can be onboarded. ## List devices ready to onboard Filter discovered devices by `onboardingStatus` to retrieve only the devices that can be onboarded. Omit the filter to retrieve all discovered devices, or filter by `deviceSources.id`, `deviceType`, `vendor`, `discoveredAfter`, or `discoveredBefore`. ```bash curl "https://api.securithings.com/v1/discoveredDevices?onboardingStatus=readyToOnboard&limit=100" \ -H "Accept: application/json" \ -H "Authorization: Bearer " ``` ## Onboard devices Onboarding is an [asynchronous task](/guides/async-tasks). Collect the IDs of devices whose `onboardingStatus` is `readyToOnboard`, then execute an `onboardDevice` task: ```bash curl -X POST "https://api.securithings.com/v1/tasks" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer " \ -d '{ "taskType": "onboardDevice", "devices": [ { "deviceId": "9ff559ee-38b6-11f1-81cb-465864a35d0a" }, { "deviceId": "dc7d4ef1-6bf9-11f1-b083-d27bafcacdf8" } ] }' ``` ## Verify the task succeeded The outcome of the onboarding request is reported by the task. Poll `GET /v1/tasks/{id}` until every device task has a `status` of `completed`, then read the `result` of each device task. A `result` of `succeeded` means the device was onboarded. See [Asynchronous Tasks](/guides/async-tasks). ## Retrieve an onboarded device An onboarded device is part of your device inventory, and can be retrieved from the devices endpoint by its ID: ```bash curl "https://api.securithings.com/v1/devices/9ff559ee-38b6-11f1-81cb-465864a35d0a" \ -H "Accept: application/json" \ -H "Authorization: Bearer " ``` --- ## Document: Postman & Insomnia URL: /resources/postman # Postman & Insomnia import { Button } from "zudoku/ui/Button"; The SecuriThings API Postman Collection includes the authentication setup. To set up Postman or Insomnia to use the SecuriThings API, you can see an example of how to set up the authentication in the following images. ## Postman 1. Open Postman and create a new request. 2. In the Authorization tab, select `OAuth 2.0` and set `Add Authorization Data to` to `Request Headers`. 3. Set the Access Token URL to `https://api.securithings.com/v1/auth/`. 4. Change the Grant Type to `Client Credentials` and fill in the fields with the credentials provided by the SecuriThings team. 5. Change Client Authentication to `Send as Basic Auth header`. An example of the configuration can be seen in the following image: ![Postman 0Auth2 Settings Example](/postman-oauth2-settings.png "Postman 0Auth2 Settings Example") ## Insomnia 1. Open Insomnia and create a new request. 2. In the Authentication tab, select `OAuth 2.0` and set `Grant Type` to `Client Credentials`. 3. Set the Access Token URL to `https://api.securithings.com/v1/auth/`. 4. Fill in the fields with the credentials provided by the SecuriThings team. 5. Under Advanced Options, ensure `Credentials` is set to `As Basic Auth Header`. (should be default) An example of the configuration can be seen in the following image: ![Insomnia 0Auth2 Settings Example](/insomnia-oauth2-settings.png "Insomnia 0Auth2 Settings Example") --- ## Document: Upgrade Firmware URL: /recipes/upgrade-firmware # Upgrade Firmware import { Badge } from "zudoku/ui/Badge";
Automation GET /v1/devices GET /v1/devices/:id/targetFirmware POST /v1/tasks
Upgrade the devices that have an approved firmware upgrade path to the version you're deploying, and track the task to completion. :::tip You can adjust the script to your needs. Change the conditions, variables, and values to produce the output you want. ::: \n new Promise((resolve) => setTimeout(resolve, ms));\n\nconst TARGET_FIRMWARE = "9.80.1";', }, }, { title: "Select candidate devices", body: "`availableTask.upgradeFirmware` reports whether the task can be executed on the device.", code: { python: 'devices = requests.get(\n f"{BASE}/v1/devices",\n params={"status": "online", "limit": 100},\n headers=headers,\n).json()["devices"]\n\ncandidates = [\n device["id"]\n for device in devices\n if device["availableTask"]["upgradeFirmware"]\n]', javascript: 'const query = new URLSearchParams({\n status: "online",\n limit: "100",\n});\nconst devicesResponse = await fetch(\n `${BASE}/v1/devices?${query}`,\n { headers },\n);\nconst { devices } = await devicesResponse.json();\n\nconst candidates = [];\nfor (const device of devices) {\n if (device.availableTask.upgradeFirmware) {\n candidates.push(device.id);\n }\n}', }, }, { title: "Check approved upgrade paths", body: "Only upgrade devices with an approved path to `TARGET_FIRMWARE`; skip the rest.", code: { python: 'targets = []\nfor device_id in candidates:\n paths = requests.get(\n f"{BASE}/v1/devices/{device_id}/targetFirmware",\n headers=headers,\n ).json()["targetFirmware"]\n if TARGET_FIRMWARE in paths:\n targets.append(device_id)', javascript: 'const targets = [];\nfor (const deviceId of candidates) {\n const pathsResponse = await fetch(\n `${BASE}/v1/devices/${deviceId}/targetFirmware`,\n { headers },\n );\n const { targetFirmware } = await pathsResponse.json();\n if (targetFirmware.includes(TARGET_FIRMWARE)) {\n targets.push(deviceId);\n }\n}', }, }, { title: "Execute the task", body: "The payload field for `upgradeFirmware` is documented on the [Execute Task](/api/tasks) endpoint.", code: { python: 'response = requests.post(\n f"{BASE}/v1/tasks",\n json={\n "taskType": "upgradeFirmware",\n "defaultPayload": {"targetFirmware": TARGET_FIRMWARE},\n "devices": [\n {"deviceId": device_id} for device_id in targets\n ],\n },\n headers=headers,\n)\ntask_id = response.json()["taskId"]', javascript: 'const taskResponse = await fetch(`${BASE}/v1/tasks`, {\n method: "POST",\n headers: {\n ...headers,\n "Content-Type": "application/json",\n },\n body: JSON.stringify({\n taskType: "upgradeFirmware",\n defaultPayload: { targetFirmware: TARGET_FIRMWARE },\n devices: targets.map((deviceId) => ({ deviceId })),\n }),\n});\nconst { taskId } = await taskResponse.json();', }, }, { title: "Poll for completion", body: "The task is done once every device task reaches `completed`.", code: { python: 'while True:\n task = requests.get(\n f"{BASE}/v1/tasks/{task_id}",\n headers=headers,\n ).json()\n pending = [\n device_task\n for device_task in task["deviceTasks"]\n if device_task["status"] != "completed"\n ]\n if not pending:\n break\n time.sleep(30)', javascript: 'let task;\nwhile (true) {\n const statusResponse = await fetch(\n `${BASE}/v1/tasks/${taskId}`,\n { headers },\n );\n task = await statusResponse.json();\n const pending = task.deviceTasks.filter(\n (deviceTask) => deviceTask.status !== "completed",\n );\n if (pending.length === 0) break;\n await sleep(30000);\n}', }, }, { title: "Build the result", body: "A device task is `completed` whether or not it succeeded, so read `result`.", code: { python: 'result = {\n "taskId": task_id,\n "succeeded": [\n {\n "deviceId": device_task["deviceId"],\n "deviceName": device_task["deviceName"],\n }\n for device_task in task["deviceTasks"]\n if device_task["result"] == "succeeded"\n ],\n "failed": [\n {\n "deviceId": device_task["deviceId"],\n "deviceName": device_task["deviceName"],\n "result": device_task["result"],\n }\n for device_task in task["deviceTasks"]\n if device_task["result"] != "succeeded"\n ],\n}\n\nprint(json.dumps(result, indent=2))', javascript: 'const succeeded = [];\nconst failed = [];\n\nfor (const deviceTask of task.deviceTasks) {\n const entry = {\n deviceId: deviceTask.deviceId,\n deviceName: deviceTask.deviceName,\n };\n if (deviceTask.result === "succeeded") {\n succeeded.push(entry);\n } else {\n failed.push({\n ...entry,\n result: deviceTask.result,\n });\n }\n}\n\nconst result = { taskId, succeeded, failed };\n\nconsole.log(JSON.stringify(result, null, 2));', }, }, ]} response={`{ "taskId": "19rs171mrlx9j3s", "succeeded": [ { "deviceId": "9ff559ee-38b6-11f1-81cb-465864a35d0a", "deviceName": "192.168.2.53 - Unit" } ], "failed": [ { "deviceId": "dc7d4ef1-6bf9-11f1-b083-d27bafcacdf8", "deviceName": "192.168.2.70 - Unit", "result": "rolledBack" } ] }`} /> --- ## Document: Rotate SSL Certificates URL: /recipes/rotate-ssl-certificates # Rotate SSL Certificates import { Badge } from "zudoku/ui/Badge";
Automation GET /v1/devices POST /v1/tasks
Rotate the SSL certificates on the devices that support the task, and track the task to completion. :::tip You can adjust the script to your needs. Change the conditions, variables, and values to produce the output you want. ::: \n new Promise((resolve) => setTimeout(resolve, ms));', }, }, { title: "Select target devices", body: "`availableTask.rotateSslCertificate` reports whether the task can be executed on the device.", code: { python: 'devices = requests.get(\n f"{BASE}/v1/devices",\n params={"status": "online", "limit": 100},\n headers=headers,\n).json()["devices"]\n\ntargets = [\n device["id"]\n for device in devices\n if device["availableTask"]["rotateSslCertificate"]\n]', javascript: 'const query = new URLSearchParams({\n status: "online",\n limit: "100",\n});\nconst devicesResponse = await fetch(\n `${BASE}/v1/devices?${query}`,\n { headers },\n);\nconst { devices } = await devicesResponse.json();\n\nconst targets = [];\nfor (const device of devices) {\n if (device.availableTask.rotateSslCertificate) {\n targets.push(device.id);\n }\n}', }, }, { title: "Execute the task", body: "The payload fields for `rotateSslCertificate` are documented on the [Execute Task](/api/tasks) endpoint.", code: { python: 'response = requests.post(\n f"{BASE}/v1/tasks",\n json={\n "taskType": "rotateSslCertificate",\n "devices": [\n {"deviceId": device_id}\n for device_id in targets\n ],\n },\n headers=headers,\n)\ntask_id = response.json()["taskId"]', javascript: 'const taskResponse = await fetch(`${BASE}/v1/tasks`, {\n method: "POST",\n headers: {\n ...headers,\n "Content-Type": "application/json",\n },\n body: JSON.stringify({\n taskType: "rotateSslCertificate",\n devices: targets.map((deviceId) => ({\n deviceId,\n })),\n }),\n});\nconst { taskId } = await taskResponse.json();', }, }, { title: "Poll for completion", body: "The task is done once every device task reaches `completed`.", code: { python: 'while True:\n task = requests.get(\n f"{BASE}/v1/tasks/{task_id}",\n headers=headers,\n ).json()\n pending = [\n device_task\n for device_task in task["deviceTasks"]\n if device_task["status"] != "completed"\n ]\n if not pending:\n break\n time.sleep(30)', javascript: 'let task;\nwhile (true) {\n const statusResponse = await fetch(\n `${BASE}/v1/tasks/${taskId}`,\n { headers },\n );\n task = await statusResponse.json();\n const pending = task.deviceTasks.filter(\n (deviceTask) => deviceTask.status !== "completed",\n );\n if (pending.length === 0) break;\n await sleep(30000);\n}', }, }, { title: "Build the result", body: "A device task is `completed` whether or not it succeeded, so read `result`.", code: { python: 'result = {\n "taskId": task_id,\n "succeeded": [\n {\n "deviceId": device_task["deviceId"],\n "deviceName": device_task["deviceName"],\n }\n for device_task in task["deviceTasks"]\n if device_task["result"] == "succeeded"\n ],\n "failed": [\n {\n "deviceId": device_task["deviceId"],\n "deviceName": device_task["deviceName"],\n "result": device_task["result"],\n }\n for device_task in task["deviceTasks"]\n if device_task["result"] != "succeeded"\n ],\n}\n\nprint(json.dumps(result, indent=2))', javascript: 'const succeeded = [];\nconst failed = [];\n\nfor (const deviceTask of task.deviceTasks) {\n const entry = {\n deviceId: deviceTask.deviceId,\n deviceName: deviceTask.deviceName,\n };\n if (deviceTask.result === "succeeded") {\n succeeded.push(entry);\n } else {\n failed.push({\n ...entry,\n result: deviceTask.result,\n });\n }\n}\n\nconst result = { taskId, succeeded, failed };\n\nconsole.log(JSON.stringify(result, null, 2));', }, }, ]} response={`{ "taskId": "19rs171mrlx9j3s", "succeeded": [ { "deviceId": "dccfe2c1-7f92-11f1-a1d3-da3df9dc2a6d", "deviceName": "192.168.2.69 - Unit" } ], "failed": [ { "deviceId": "dc7d4ef1-6bf9-11f1-b083-d27bafcacdf8", "deviceName": "192.168.2.70 - Unit", "result": "rolledBack" } ] }`} /> --- ## Document: Rotate Device Passwords URL: /recipes/rotate-passwords # Rotate Device Passwords import { Badge } from "zudoku/ui/Badge";
Automation GET /v1/devices POST /v1/tasks
Rotate the passwords on the devices that support the task, and track the task to completion. :::tip You can adjust the script to your needs. Change the conditions, variables, and values to produce the output you want. ::: \n new Promise((resolve) => setTimeout(resolve, ms));', }, }, { title: "Select target devices", body: "`availableTask.rotatePassword` reports whether the task can be executed on the device.", code: { python: 'devices = requests.get(\n f"{BASE}/v1/devices",\n params={"status": "online", "limit": 100},\n headers=headers,\n).json()["devices"]\n\ntargets = [\n device["id"]\n for device in devices\n if device["availableTask"]["rotatePassword"]\n]', javascript: 'const query = new URLSearchParams({\n status: "online",\n limit: "100",\n});\nconst devicesResponse = await fetch(\n `${BASE}/v1/devices?${query}`,\n { headers },\n);\nconst { devices } = await devicesResponse.json();\n\nconst targets = [];\nfor (const device of devices) {\n if (device.availableTask.rotatePassword) {\n targets.push(device.id);\n }\n}', }, }, { title: "Build the rotation payload", body: "`defaultPayload` applies the same configuration to every device in the task.", code: { python: 'default_payload = {\n "autoGeneratePassword": True,\n "changePasswordByRole": True,\n "userRoles": ["admin"],\n "passwordExpiryDays": 90,\n "enforceHttps": True,\n "passwordLength": 12,\n "includeUppercase": True,\n "includeLowercase": True,\n "includeNumbers": True,\n "includeSymbols": False,\n}', javascript: 'const defaultPayload = {\n autoGeneratePassword: true,\n changePasswordByRole: true,\n userRoles: ["admin"],\n passwordExpiryDays: 90,\n enforceHttps: true,\n passwordLength: 12,\n includeUppercase: true,\n includeLowercase: true,\n includeNumbers: true,\n includeSymbols: false,\n};', }, }, { title: "Execute the task", body: "One request covers every target device and returns a `taskId`.", code: { python: 'response = requests.post(\n f"{BASE}/v1/tasks",\n json={\n "taskType": "rotatePassword",\n "defaultPayload": default_payload,\n "devices": [\n {"deviceId": device_id}\n for device_id in targets\n ],\n },\n headers=headers,\n)\ntask_id = response.json()["taskId"]', javascript: 'const taskResponse = await fetch(`${BASE}/v1/tasks`, {\n method: "POST",\n headers: {\n ...headers,\n "Content-Type": "application/json",\n },\n body: JSON.stringify({\n taskType: "rotatePassword",\n defaultPayload,\n devices: targets.map((deviceId) => ({\n deviceId,\n })),\n }),\n});\nconst { taskId } = await taskResponse.json();', }, }, { title: "Poll for completion", body: "The task is done once every device task reaches `completed`.", code: { python: 'while True:\n task = requests.get(\n f"{BASE}/v1/tasks/{task_id}",\n headers=headers,\n ).json()\n pending = [\n device_task\n for device_task in task["deviceTasks"]\n if device_task["status"] != "completed"\n ]\n if not pending:\n break\n time.sleep(30)', javascript: 'let task;\nwhile (true) {\n const statusResponse = await fetch(\n `${BASE}/v1/tasks/${taskId}`,\n { headers },\n );\n task = await statusResponse.json();\n const pending = task.deviceTasks.filter(\n (deviceTask) => deviceTask.status !== "completed",\n );\n if (pending.length === 0) break;\n await sleep(30000);\n}', }, }, { title: "Build the result", body: "A device task is `completed` whether or not it succeeded, so read `result`.", code: { python: 'result = {\n "taskId": task_id,\n "succeeded": [\n {\n "deviceId": device_task["deviceId"],\n "deviceName": device_task["deviceName"],\n }\n for device_task in task["deviceTasks"]\n if device_task["result"] == "succeeded"\n ],\n "failed": [\n {\n "deviceId": device_task["deviceId"],\n "deviceName": device_task["deviceName"],\n "result": device_task["result"],\n }\n for device_task in task["deviceTasks"]\n if device_task["result"] != "succeeded"\n ],\n}\n\nprint(json.dumps(result, indent=2))', javascript: 'const succeeded = [];\nconst failed = [];\n\nfor (const deviceTask of task.deviceTasks) {\n const entry = {\n deviceId: deviceTask.deviceId,\n deviceName: deviceTask.deviceName,\n };\n if (deviceTask.result === "succeeded") {\n succeeded.push(entry);\n } else {\n failed.push({\n ...entry,\n result: deviceTask.result,\n });\n }\n}\n\nconst result = { taskId, succeeded, failed };\n\nconsole.log(JSON.stringify(result, null, 2));', }, }, ]} response={`{ "taskId": "23bpozz1mpjjedtr", "succeeded": [ { "deviceId": "9ff559ee-38b6-11f1-81cb-465864a35d0a", "deviceName": "192.168.2.69 - Unit" } ], "failed": [ { "deviceId": "dc7d4ef1-6bf9-11f1-b083-d27bafcacdf8", "deviceName": "192.168.2.70 - Unit", "result": "failed" } ] }`} /> --- ## Document: Retrieve Offline Devices URL: /recipes/retrieve-offline-devices # Retrieve Offline Devices import { Badge } from "zudoku/ui/Badge";
Monitoring GET /v1/devices
Retrieve every device whose `status` is `offline`, paging through the full result set. :::tip You can adjust the script to your needs. Change the conditions, variables, and values to produce the output you want. ::: \n new Promise((resolve) => setTimeout(resolve, ms));', }, }, { title: "Request the first page", body: "Filter on `status` and request the maximum page size.", code: { python: 'params = {\n "status": "offline",\n "limit": 100,\n "offset": 0,\n}\npage = requests.get(\n f"{BASE}/v1/devices",\n params=params,\n headers=headers,\n).json()\ndevices = page["devices"]', javascript: 'const params = {\n status: "offline",\n limit: 100,\n offset: 0,\n};\n\nconst fetchPage = async () => {\n const query = new URLSearchParams(params);\n const response = await fetch(\n `${BASE}/v1/devices?${query}`,\n { headers },\n );\n return response.json();\n};\n\nlet page = await fetchPage();\nconst devices = [...page.devices];', }, }, { title: "Page through the results", body: "Increase `offset` by `limit` until `total` devices have been retrieved.", code: { python: 'while len(devices) < page["total"]:\n params["offset"] += params["limit"]\n time.sleep(1) # 1 request per second\n page = requests.get(\n f"{BASE}/v1/devices",\n params=params,\n headers=headers,\n ).json()\n devices += page["devices"]', javascript: "while (devices.length < page.total) {\n params.offset += params.limit;\n await sleep(1000); // 1 request per second\n page = await fetchPage();\n devices.push(...page.devices);\n}", }, }, { title: "Build the result", body: "`lastSeen` reports the last time each device was not offline.", code: { python: 'result = {\n "total": page["total"],\n "devices": [\n {\n "id": device["id"],\n "name": device["name"],\n "lastSeen": device["lastSeen"],\n }\n for device in devices\n ],\n}\n\nprint(json.dumps(result, indent=2))', javascript: "const result = {\n total: page.total,\n devices: devices.map((device) => ({\n id: device.id,\n name: device.name,\n lastSeen: device.lastSeen,\n })),\n};\n\nconsole.log(JSON.stringify(result, null, 2));", }, }, ]} response={`{ "total": 1, "devices": [ { "id": "9ff559ee-38b6-11f1-81cb-465864a35d0a", "name": "Headquarters camera1", "lastSeen": "2026-07-09T11:20:00Z" } ] }`} /> --- ## Document: Restart Devices URL: /recipes/restart-devices # Restart Devices import { Badge } from "zudoku/ui/Badge";
Automation GET /v1/devices POST /v1/tasks
Restart the devices that support the task, and confirm they return online. :::tip You can adjust the script to your needs. Change the conditions, variables, and values to produce the output you want. ::: \n new Promise((resolve) => setTimeout(resolve, ms));', }, }, { title: "Select target devices", body: "Narrow the fleet with any filter the [devices endpoint](/api/devices) accepts. `availableTask.restartDevice` reports whether the task can be executed on the device.", code: { python: 'devices = requests.get(\n f"{BASE}/v1/devices",\n params={"limit": 100},\n headers=headers,\n).json()["devices"]\n\ntargets = [\n device["id"]\n for device in devices\n if device["availableTask"]["restartDevice"]\n]', javascript: 'const query = new URLSearchParams({ limit: "100" });\nconst devicesResponse = await fetch(\n `${BASE}/v1/devices?${query}`,\n { headers },\n);\nconst { devices } = await devicesResponse.json();\n\nconst targets = [];\nfor (const device of devices) {\n if (device.availableTask.restartDevice) {\n targets.push(device.id);\n }\n}', }, }, { title: "Execute the task", body: "`restartDevice` requires no configuration, so no payload is sent.", code: { python: 'response = requests.post(\n f"{BASE}/v1/tasks",\n json={\n "taskType": "restartDevice",\n "devices": [\n {"deviceId": device_id}\n for device_id in targets\n ],\n },\n headers=headers,\n)\ntask_id = response.json()["taskId"]', javascript: 'const taskResponse = await fetch(`${BASE}/v1/tasks`, {\n method: "POST",\n headers: {\n ...headers,\n "Content-Type": "application/json",\n },\n body: JSON.stringify({\n taskType: "restartDevice",\n devices: targets.map((deviceId) => ({\n deviceId,\n })),\n }),\n});\nconst { taskId } = await taskResponse.json();', }, }, { title: "Poll for completion", body: "The task is done once every device task reaches `completed`.", code: { python: 'while True:\n task = requests.get(\n f"{BASE}/v1/tasks/{task_id}",\n headers=headers,\n ).json()\n pending = [\n device_task\n for device_task in task["deviceTasks"]\n if device_task["status"] != "completed"\n ]\n if not pending:\n break\n time.sleep(30)', javascript: 'let task;\nwhile (true) {\n const statusResponse = await fetch(\n `${BASE}/v1/tasks/${taskId}`,\n { headers },\n );\n task = await statusResponse.json();\n const pending = task.deviceTasks.filter(\n (deviceTask) => deviceTask.status !== "completed",\n );\n if (pending.length === 0) break;\n await sleep(30000);\n}', }, }, { title: "Build the result", body: "Read each device back to check its `status` after the restart.", code: { python: 'result = {"taskId": task_id, "devices": []}\n\nfor device_id in targets:\n device = requests.get(\n f"{BASE}/v1/devices/{device_id}",\n headers=headers,\n ).json()\n result["devices"].append(\n {\n "id": device["id"],\n "name": device["name"],\n "status": device["status"],\n }\n )\n time.sleep(1) # 1 request per second\n\nprint(json.dumps(result, indent=2))', javascript: "const result = { taskId, devices: [] };\n\nfor (const deviceId of targets) {\n const deviceResponse = await fetch(\n `${BASE}/v1/devices/${deviceId}`,\n { headers },\n );\n const device = await deviceResponse.json();\n result.devices.push({\n id: device.id,\n name: device.name,\n status: device.status,\n });\n await sleep(1000); // 1 request per second\n}\n\nconsole.log(JSON.stringify(result, null, 2));", }, }, ]} response={`{ "taskId": "23bpozz1mpjjedtr", "devices": [ { "id": "9ff559ee-38b6-11f1-81cb-465864a35d0a", "name": "192.168.2.69 - Unit", "status": "online" }, { "id": "dc7d4ef1-6bf9-11f1-b083-d27bafcacdf8", "name": "192.168.2.70 - Unit", "status": "offline" } ] }`} /> --- ## Document: Onboard Discovered Devices URL: /recipes/onboard-discovered-devices # Onboard Discovered Devices import { Badge } from "zudoku/ui/Badge";
Inventory GET /v1/discoveredDevices POST /v1/tasks
Onboard the discovered devices that are ready to onboard, and track the task to completion. :::tip You can adjust the script to your needs. Change the conditions, variables, and values to produce the output you want. ::: \n new Promise((resolve) => setTimeout(resolve, ms));', }, }, { title: "Select target devices", body: "Filter discovered devices on `onboardingStatus`.", code: { python: 'discovered = requests.get(\n f"{BASE}/v1/discoveredDevices",\n params={\n "onboardingStatus": "readyToOnboard",\n "limit": 100,\n },\n headers=headers,\n).json()["discoveredDevices"]\n\ntargets = [device["id"] for device in discovered]', javascript: 'const query = new URLSearchParams({\n onboardingStatus: "readyToOnboard",\n limit: "100",\n});\nconst discoveredResponse = await fetch(\n `${BASE}/v1/discoveredDevices?${query}`,\n { headers },\n);\nconst discovered = await discoveredResponse.json();\n\nconst targets = discovered.discoveredDevices.map(\n (device) => device.id,\n);', }, }, { title: "Execute the task", body: "`onboardDevice` requires no configuration, so no payload is sent.", code: { python: 'response = requests.post(\n f"{BASE}/v1/tasks",\n json={\n "taskType": "onboardDevice",\n "devices": [\n {"deviceId": device_id}\n for device_id in targets\n ],\n },\n headers=headers,\n)\ntask_id = response.json()["taskId"]', javascript: 'const taskResponse = await fetch(`${BASE}/v1/tasks`, {\n method: "POST",\n headers: {\n ...headers,\n "Content-Type": "application/json",\n },\n body: JSON.stringify({\n taskType: "onboardDevice",\n devices: targets.map((deviceId) => ({\n deviceId,\n })),\n }),\n});\nconst { taskId } = await taskResponse.json();', }, }, { title: "Poll for completion", body: "The task is done once every device task reaches `completed`.", code: { python: 'while True:\n task = requests.get(\n f"{BASE}/v1/tasks/{task_id}",\n headers=headers,\n ).json()\n pending = [\n device_task\n for device_task in task["deviceTasks"]\n if device_task["status"] != "completed"\n ]\n if not pending:\n break\n time.sleep(30)', javascript: 'let task;\nwhile (true) {\n const statusResponse = await fetch(\n `${BASE}/v1/tasks/${taskId}`,\n { headers },\n );\n task = await statusResponse.json();\n const pending = task.deviceTasks.filter(\n (deviceTask) => deviceTask.status !== "completed",\n );\n if (pending.length === 0) break;\n await sleep(30000);\n}', }, }, { title: "Build the result", body: "A device task is `completed` whether or not it succeeded, so read `result`.", code: { python: 'result = {\n "taskId": task_id,\n "succeeded": [\n {\n "deviceId": device_task["deviceId"],\n "deviceName": device_task["deviceName"],\n }\n for device_task in task["deviceTasks"]\n if device_task["result"] == "succeeded"\n ],\n "failed": [\n {\n "deviceId": device_task["deviceId"],\n "deviceName": device_task["deviceName"],\n "result": device_task["result"],\n }\n for device_task in task["deviceTasks"]\n if device_task["result"] != "succeeded"\n ],\n}\n\nprint(json.dumps(result, indent=2))', javascript: 'const succeeded = [];\nconst failed = [];\n\nfor (const deviceTask of task.deviceTasks) {\n const entry = {\n deviceId: deviceTask.deviceId,\n deviceName: deviceTask.deviceName,\n };\n if (deviceTask.result === "succeeded") {\n succeeded.push(entry);\n } else {\n failed.push({\n ...entry,\n result: deviceTask.result,\n });\n }\n}\n\nconst result = { taskId, succeeded, failed };\n\nconsole.log(JSON.stringify(result, null, 2));', }, }, ]} response={`{ "taskId": "23bpozz1mpjjedtr", "succeeded": [ { "deviceId": "9ff559ee-38b6-11f1-81cb-465864a35d0a", "deviceName": "Lobby camera 12" } ], "failed": [ { "deviceId": "dc7d4ef1-6bf9-11f1-b083-d27bafcacdf8", "deviceName": "Lobby camera 13", "result": "failed" } ] }`} /> --- ## Document: Authenticate URL: /recipes/authentication # Authenticate import { Badge } from "zudoku/ui/Badge";
Getting Started POST /v1/auth/:org
Exchange the client credentials for an access token, and build the request headers every other recipe uses. --- ## Document: Introduction URL: /mcp/introduction # Introduction :::sparkles **Coming soon.** The SecuriThings MCP Server is under active development. ::: Extend SecuriThings into any AI assistant. Ask or act on your device fleet in plain language, or combine SecuriThings with the rest of your MCP ecosystem in one request. --- ## Document: Requests & Responses URL: /guides/requests-and-responses # Requests & Responses :::info The SecuriThings API is a REST API. It uses standard HTTP methods, resource-oriented URLs, and JSON for both requests and responses. ::: ## Base URL All requests go to `https://api.securithings.com`. The API version is part of the path, and all current endpoints are under `/v1`. ## Responses - All responses are returned in `application/json` format. - Successful responses will be 200, 201 or 204 (if there is no resource to return). - Errors are communicated using HTTP status codes. See [Errors](/guides/errors). - All timestamps are in UTC, in ISO 8601 format. ## Collections Endpoints that return a collection of resources return a JSON object with a field named after the resource, containing an array of resource objects. For devices the field is `devices`, for sites it is `sites`, and so on. Alongside it, `total` is the number of resources that match your query, which is not necessarily the number returned in this response. Use it to page through results, as described in [Pagination & Filtering](/guides/pagination-and-filtering). For example, requesting the first two devices out of three that match: ```bash curl "https://api.securithings.com/v1/devices?limit=2" \ -H "Accept: application/json" \ -H "Authorization: Bearer " ``` ```json { "devices": [ { "id": "1", ... }, { "id": "2", ... } ], "total": 3 } ``` The response contains two devices because `limit=2` was requested, while `total` reports that three devices match the query overall. --- ## Document: Rate Limiting URL: /guides/rate-limits # Rate Limiting Our platform remains stable and fair for everyone by subjecting the APIs we provide to rate limiting and throttling. We ask developers to use industry-standard techniques for limiting calls, caching results, and re-trying requests. If you exceed the rate limiting, your requests will be rejected with an error code of `429 Too Many Requests`. ## Limits & Quotas The rate limits are as follows, with each endpoint rate limited separately: | Domain | Rate Limit | | ------------------- | ------------------------------------------------------------- | | Authentication | 5 requests per minute per IP | | All other endpoints | 1 request per second per IP AND 1 request per second per user | :::note If you require a higher rate limit, [contact our support team](mailto:cs_engineers@securithings.com). ::: ## Avoid Rate Limit Errors Designing your application with best practices in mind is the best way to avoid throttling errors. Much of the data returned by the API changes infrequently, so cache responses and only make requests when necessary. --- ## Document: Pagination & Filtering URL: /guides/pagination-and-filtering # Pagination & Filtering :::info All endpoints that return collections of items support pagination, and most also support filtering. ::: ## Pagination The API supports pagination for endpoints returning collections by supplying `limit` and `offset` query parameters. ```shell curl -X GET "https://api.securithings.com/v1/devices?limit=10&offset=0" \ -H "Authorization: Bearer " ``` :::caution By default, if no `limit` and `offset` are provided, the API will return the first 100 items. ::: Every collection response includes a `total` field with the number of items matching the request. Increase `offset` by the value of `limit` until `total` items have been retrieved. ## Filtering Filters are query parameters that restrict a collection to the items matching the specified criteria. Filtering is applied server-side, so filter in the request rather than retrieving the full collection and filtering client-side. ```shell curl -X GET "https://api.securithings.com/v1/devices?status=offline" \ -H "Authorization: Bearer " ``` :::info Each endpoint supports its own set of filters. They are listed under Query Parameters for that endpoint in the [API Reference](/api), together with their accepted values. ::: ### Combining filters Multiple filters can be combined in a single request. An item is returned only if it matches all of them. ```shell curl -X GET "https://api.securithings.com/v1/devices?status=offline&isFirmwareVulnerable=1&lifeCycleStatus=eos" \ -H "Authorization: Bearer " ``` This query returns all offline devices that are End of Support (EOS) and have known firmware vulnerabilities. Filters combine with pagination, so `total` reflects the filtered result set rather than the whole collection. --- ## Document: Errors URL: /guides/errors # Errors Errors are communicated using HTTP status codes. ## Status codes | Code | Description | | ---- | ----------------------------------------------------------- | | 400 | Invalid/bad request | | 401 | Unauthorized, credentials maybe missing, invalid or expired | | 403 | No permissions to access the resource | | 404 | Resource not found or no access to it | | 429 | Rate limit exceeded | | 500 | Internal server error | | 502 | Bad gateway | --- ## Document: Authentication URL: /guides/authentication # Authentication SecuriThings API uses the OAuth 2.0 protocol with JWT for authentication and authorization. Each request made to our API requires a Bearer token in the Authorization header.
This token is a JWT containing information about the user and their permissions. ## Getting credentials for the API Each integration with the SecuriThings API requires a set of credentials. These credentials are used to generate a JWT token that is used to authenticate the user across the API. Credentials are provided manually by the SecuriThings team. To get your credentials, please [contact our support team](https://forms.gle/og4uornuwain2jhSA). Credentials are composed of three parts: - `organization`: The tenant that the client belongs to. - `client_id`: A unique identifier for the client. - `client_secret`: A secret key that is used to generate the JWT token. ## Getting a token Using the credentials provided by the SecuriThings team, you can generate a JWT token by sending a POST request to the `/v1/auth/` endpoint. `client_id` and `client_secret` should be provided using Basic Authentication. :::caution Running these commands will expose your credentials in the terminal history. Make sure to clear the terminal history after running the commands or opt to use an API client. ::: ```bash curl -X POST https://api.securithings.com/v1/auth/ \ -H 'Content-Type: application/json' \ -H 'Authorization : Basic ' # or curl -X POST https://api.securithings.com/v1/auth/ \ -H 'Content-Type: application/json' \ -u ':' ``` A token is valid for one hour by default. Generate a new token after it expires. :::note A `refresh_token` is not provided by default. If you require one, please contact our [support team](mailto:cs_engineers@securithings.com). ::: ## Using Postman or Insomnia Setup instructions for both clients, and a downloadable Postman Collection that includes the authentication setup, are on the [Postman & Insomnia](/resources/postman) page. --- ## Document: Asynchronous Tasks URL: /guides/async-tasks # Asynchronous Tasks import { Stepper } from "zudoku/ui/Stepper"; Beyond reading data, the API can execute tasks on devices. Because tasks take time to complete on physical devices, they run asynchronously. You execute a task, get a `taskId` back immediately, and poll for completion. A single task runs across one or more devices. The work on each individual device is a device task, and the overall task is done once every device task is completed. This page describes the pattern. The per-task-type payload fields are documented in the [API Reference](/api). :::lock `POST /v1/tasks` requires Admin or Operator permissions. To enable it for your account, please [contact our support team](mailto:cs_engineers@securithings.com). ::: ## The lifecycle 1. **Execute the task** Send `POST /v1/tasks` with a `taskType` and the devices to run it on. For tasks that require configuration, use `defaultPayload` to apply the same configuration to every device, or set a `payload` per device. ```json { "taskType": "restartDevice", "devices": [ { "deviceId": "9ff559ee-38b6-11f1-81cb-465864a35d0a" }, { "deviceId": "dc7d4ef1-6bf9-11f1-b083-d27bafcacdf8" } ] } ``` 1. **Take the task ID** The response returns the ID of the created task. ```json { "taskId": "23bpozz1mpjjedtr" } ``` 1. **Poll until every device task is completed** `GET /v1/tasks/{id}` returns one entry per device task. ```json { "userName": "service-account-integrator_1", "deviceTasks": [ { "createDate": "2026-07-15T10:13:14.000Z", "currentStepStatus": "runSucceeded", "deviceHost": "192.168.2.69", "deviceId": "9ff559ee-38b6-11f1-81cb-465864a35d0a", "deviceModel": "P3265-LV", "deviceName": "192.168.2.69 - Unit", "deviceTaskId": "366717", "result": "succeeded", "status": "completed", "taskId": "23bpozz1mpjjedtr", "taskType": "restartDevice" }, { "createDate": "2026-07-15T10:13:14.000Z", "currentStepStatus": "runSucceeded", "deviceHost": "192.168.2.70", "deviceId": "dc7d4ef1-6bf9-11f1-b083-d27bafcacdf8", "deviceModel": "P3265-LV", "deviceName": "192.168.2.70 - Unit", "deviceTaskId": "366718", "result": "succeeded", "status": "completed", "taskId": "23bpozz1mpjjedtr", "taskType": "restartDevice" } ], "total": 2 } ``` :::info `status` tells you whether a device task has finished (`pending`, `running`, `completed`), and `result` tells you how it finished (`succeeded`, `failed`, `rolledBack`, `aborted`). `result` is `null` until the device task completes, so always check both. ::: :::zap Add `includeSteps=true` to `GET /v1/tasks/{id}` to include the per-step breakdown of each device task. Steps increase the response size considerably, so they are not returned by default. Request them only when a device task fails and further information is required to investigate it. ::: ## Check availability first Not every device supports every task. Device objects expose an `availableTask` map, so check it before executing: ```json "availableTask": { "hardenDevice": false, "restartDevice": true, "rotate8021xCertificate": false, "rotatePassword": true, "rotateSslCertificate": true, "upgradeFirmware": true } ``` --- ## Document: Recipes URL: /recipes # Recipes import { Card, CardHeader, CardTitle, CardDescription, CardContent, } from "zudoku/ui/Card"; import { Badge } from "zudoku/ui/Badge"; import { Link } from "zudoku/components"; export const recipes = [ { title: "Authenticate", category: "Getting Started", description: "Exchange the client credentials for an access token.", endpoints: ["POST /v1/auth/:org"], href: "/recipes/authentication", }, { title: "Retrieve Offline Devices", category: "Monitoring", description: "Retrieve every device whose status is offline, paging through the full result set.", endpoints: ["GET /v1/devices"], href: "/recipes/retrieve-offline-devices", }, { title: "Onboard Discovered Devices", category: "Inventory", description: "Onboard the discovered devices that are ready to onboard, and track the task to completion.", endpoints: ["GET /v1/discoveredDevices", "POST /v1/tasks"], href: "/recipes/onboard-discovered-devices", }, { title: "Restart Devices", category: "Automation", description: "Restart the devices that support the task, and confirm they return online.", endpoints: ["GET /v1/devices", "POST /v1/tasks"], href: "/recipes/restart-devices", }, { title: "Rotate Device Passwords", category: "Automation", description: "Rotate the passwords on the devices that support the task, and track the task to completion.", endpoints: ["GET /v1/devices", "POST /v1/tasks"], href: "/recipes/rotate-passwords", }, { title: "Rotate SSL Certificates", category: "Automation", description: "Rotate the SSL certificates on the devices that support the task, and track the task to completion.", endpoints: ["GET /v1/devices", "POST /v1/tasks"], href: "/recipes/rotate-ssl-certificates", }, { title: "Upgrade Firmware", category: "Automation", description: "Upgrade the devices that have an approved firmware path, and track the task to completion.", endpoints: [ "GET /v1/devices", "GET /v1/devices/:id/targetFirmware", "POST /v1/tasks", ], href: "/recipes/upgrade-firmware", }, ]; Recipes are runnable examples of common jobs. Each one combines several steps, and often several endpoints, into a single script.
{recipes.map((recipe) => (
{recipe.category}
{recipe.title} {recipe.description}
{recipe.endpoints.map((endpoint) => ( {endpoint} ))}
))}