Device Lifecycle API
Introduction
The Device Lifecycle API provides you with an Application Program Interface (API) to request permanent device deletion of your enrolled managed devices. Main purpose of this API is to allow automation of device lifecycle management and provide an alternative to manual device lifecycle management in Radar portal UI.
The API is RESTful and HTTP-based. This means that the communication is made through normal HTTP requests.
If at any point you require any further assistance, please reach out to your Jamf support representative.
Getting Started
- From RADAR portal generate an API key and get your Application ID and Secret. Get your customer ID from RADAR URL address parameter
customerId
. - Authenticate with the following terminal command replacing
<Application ID>
and<Application Secret>
with the ones retrieved on the previous step:curl -X POST -u '<Application ID>:<Application Secret>' <https://api.wandera.com/v1/login>
- Copy the JWT value from the token field in the response without double quotations.
- Request permanent device deletion by running a command in terminal replacing
<JWT>
placeholder by value obtained in previous step. Replace<CUSTOMER_ID>
with customer ID obtained in step 1 and finally, replace<EXTERNAL_ID>
with externalId identifier (or comma-separated double-quoted identifiers) of a device or devices you wish to delete.curl -X POST -H 'Content-Type: application/json; charset=utf-8' \ -H 'Authorization: Bearer <JWT>' \ -d '{"externalIds": ["<EXTERNAL_ID>"]}' \ https://api.wandera.com/device-lifecycle/v1/<CUSTOMER_ID>/devices/purge/async/external
Authentication
Authentication is needed in order to use the Device Lifecycle API
The authentication used is in the form of a JSON Web Token (JWT). Each request to the API needs to contain a Bearer type Authorization header containing a valid JWT. A JWT can be obtained by calling the /v1/login endpoint via POST request using a valid Application ID and Application secret as HTTP Basic Authorization credentials. These credentials can be created in the Security Integrations part of RADAR Settings. Each JWT has a limited validity of 15 minutes, during which it can be used.
You can find out more about JWT and decode a token on https://jwt.io/.
Examples
Using curl
Once you have your Application ID and secret from RADAR you can add them into the following in a terminal or console:
$ curl \
-X POST \
-u '<Application ID>:<Application secret>' \
https://api.wandera.com/v1/login
This returns the encoded JWT, which has the following format:
{"token":"<JWT header (base 64)>.<JWT payload (base 64)>.<JWT signature>"}
Using jwt.io link above you can decode the payload of this particular JWT:
{
"customer_id": "4744defa-1042-4a85-9fff-763ae00c7584",
"iat": 1734456531,
"exp": 1734457431,
"aud": "DEVICE_LIFECYCLE_API",
"client_id": "df3e7a9a-585e-475a-87d5-aa1e83c0cbf1"
}
Note the iat and exp fields in the decoded token where you can check when a JWT was issued and when it expires.
Rate Limiting
The Device Lifecycle API has rate limits to avoid applications degrading the user experience. There are individual limits for requests obtaining JWTs and for permanent device deletion requests.
The current values of the limits are the same for both types – 5 per second and 10,000 per day. Requests are counted for each application integration individually so one application won't block other applications integrated into the same account.
When a request is blocked, the body is empty and time (in milliseconds) until the next possible non-limited request is returned via X-Rate-Limit-Retry-After-Milliseconds
response header field. Blocked requests count up to the limits too.
Example of headers of a blocked request:
$ curl \
-D - \
-X POST \
-H 'Authorization: Bearer <JWT token>' \
-H 'Content-Type: application/json; charset=utf-8' \
-d '{"externalIds": ["010fc047-df30-4851-bff8-a26390cf01a6", "020fc047-df30-4851-bff8-a26390cf01a6", "030fc047-df30-4851-bff8-a26390cf01a6"]}' \
https://api.wandera.com/device-lifecycle/v1/4744defa-1042-4a85-9fff-763ae00c7584/devices/purge/async/external
HTTP/2 429
referrer-policy: no-referrer
strict-transport-security: max-age=315360000
vary: Accept-Encoding
x-rate-limit-retry-after-milliseconds: 40298409
content-length: 0
date: Mon, 06 Jan 2020 13:48:21 GMT
Error Messages
When an error occurs during an API call, the user is notified about it with a well-defined error response.
Error codes
Error responses contain machine-parseable error codes. While the error messages may change in the future, the error codes stay the same all the time.
Error | StatusCode | Message |
---|---|---|
UNKNOWN_URI_PATH | 404 | The requested URI does not exist. |
Forbidden | 403 | Access Denied |
TOO_MANY_REQUESTS | 429 | Too Many Requests. |
The error response is structured in the following format.
{
"timestamp":"2024-11-17T17:20:15.471+00:00",
"path":"/device-lifecycle/v1/4744defa-1042-4a85-9fff-763ae00c7584/devices/purge/async/external",
"status":403,
"error":"Forbidden"
}
Field name | Data type | Description |
---|---|---|
logref | String | Logging reference |
message | String | Human-readable error description |
error | String | Fixed error code |
statusCode | Integer | HTTP status code |
Unauthorized Errors
An unauthorized error might occur during using the API, which could be like the following:
{
"timestamp": "2020-01-06T15:11:17.882+0000",
"status": 403,
"error": "Forbidden",
"message": "Access Denied",
"path": "/v1/tokens"
}
Where the timestamp and path fields may differ for this error.
Updated 3 days ago