Device commands

Four POST endpoints send a command to one managed device. They need an API key with the DEVICES_COMMAND permission.

Overview

Each call acts on exactly one device, identified by its assetId, which is the pathName returned by GET /assets. There is no bulk endpoint. To command several devices, make one call per device within the rate limit. The endpoints do the same thing as the MCP command tools.

The key needs DEVICES_COMMAND and DEVICES_READ. Send it in the X-API-Key header. The REST API does not accept an Authorization header.

The device must be enrolled (status ACTIVE, INACTIVE or SYNCHRONIZING). Lock and lost mode work only on Android Management (Google-managed) devices. A message is a push notification to the Nomid agent and needs a registered push token.

Endpoints

MethodEndpointDescription
POST/assets/{assetId}/commands/lockLock the device screen immediately. No request body.
POST/assets/{assetId}/commands/lost-modeLock the device and show a message, with optional contact details, on its lock screen.
POST/assets/{assetId}/commands/foundEnd lost mode. Nothing happens, and no error is returned, if the device was not in lost mode. No request body.
POST/assets/{assetId}/commands/messageShow a plain-text push notification on the device.

Send Content-Type: application/json with the lost-mode and message endpoints. The lock and found endpoints take no body. Unknown fields are rejected, and required text fields cannot be blank.

Request bodies

Lost mode request body

FieldRequiredDescription
messageYesText shown on the lock screen. Up to 4096 characters.
phoneNumberNoContact phone number shown on the lock screen. Up to 4096 characters.
emailNoContact email address shown on the lock screen. Must be a valid email address, up to 320 characters.
streetAddressNoContact street address shown on the lock screen. Up to 4096 characters.
organizationNoOrganization name shown on the lock screen. Up to 4096 characters.

Message request body

FieldRequiredDescription
titleYesNotification title. Up to 60 characters.
bodyYesNotification text. Up to 500 characters.

Example: send a message

Replace the asset id with a pathName from GET /assets, and keep the key in an environment variable.

curl -X POST "https://api.nomid.tech/emm/api/v1/assets/k3x9m2pa/commands/message" \
  -H "X-API-Key: $NOMID_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"title": "Please return this device", "body": "Bring it to the IT desk by 5 pm."}'
{
  "assetId": "k3x9m2pa",
  "type": "NOTIFICATION_MESSAGE",
  "status": "SUCCESS",
  "createdAt": "2026-10-06T14:30:00Z"
}

A 200 response means the command was created. The status field is the state of the command when the request returned. For a message, SUCCESS means the push was accepted for delivery, not that the user has seen it. Follow up with GET /assets/ASSET_ID/commands.

Example: lock a device

curl -X POST "https://api.nomid.tech/emm/api/v1/assets/k3x9m2pa/commands/lock" \
  -H "X-API-Key: $NOMID_API_KEY"
{
  "assetId": "k3x9m2pa",
  "type": "LOCK",
  "status": "IN_PROGRESS",
  "createdAt": "2026-10-06T14:30:00Z"
}

Lock and lost mode return IN_PROGRESS while the device has not yet confirmed the command. The command history shows SUCCESS once it does. The lock endpoint takes no body.

Responses and what to do

The retry rules matter. Retrying a command whose outcome is unknown can deliver it twice.

StatusMeaningWhat to do
200The command was created and queued.Read the status field. For lock and lost mode it is IN_PROGRESS until the device confirms, so check the command history for SUCCESS.
202UNCONFIRMED. Nomid cannot tell whether the command reached the device, for example because the provider timed out or failed on its side. The body is the normal result object with status UNCONFIRMED and guidance in detail.Do not resend. Check the device's command history first, and ask the user before sending again. For a message, the history may show ERROR even if the notification was shown. The command may only appear once the device acknowledges it.
400The request body failed validation, or a parameter is invalid.Fix the fields listed in the errors array or in detail. No command was sent.
401The API key is missing, invalid or expired.Send a valid key in the X-API-Key header.
403The key does not have the DEVICES_COMMAND permission.Use a key that was created with DEVICES_COMMAND and DEVICES_READ.
404No asset with this id exists in the key's company. The body is empty. An asset from another company also returns 404.Check the id against GET /assets.
409The device cannot take this command: it has no managed device, an ineligible status or an unsupported device type, or, for a message, no valid push token. Also returned when the provider reports that the device is no longer managed. Nomid then marks the device as deleted.Retrying fails the same way until the device's state changes. Do not retry in a loop.
422The provider evaluated the request and refused it for this device or message, or reported that the command already failed.Do not retry with the same arguments.
429The command rate limit was exceeded. A Retry-After header gives the seconds until the window resets.Wait for the Retry-After time, then try again.
502Android Management rejected the command for a reason that is not about this device. The retryable member says whether to try again. Messages never return 502.If retryable is true (the provider is throttling or reported a temporary conflict), retry after a short delay. If it is false, the company's Android Management setup has a problem: do not retry and contact support.
503Not sent. The request failed inside Nomid before anything was dispatched. retryable is always true.Safe to retry. Nothing was delivered, so a retry cannot duplicate the command.

Error bodies

Errors from the command endpoints use application/problem+json (RFC 9457). The exceptions are 401 and 429, which return a small JSON object with error, message and status, and 404, which has no body. The 502 and 503 responses add a boolean retryable member. A 202 response is not an error: it carries the normal result object.

Example 202 response

HTTP/1.1 202 Accepted

{
  "assetId": "k3x9m2pa",
  "type": "LOCK",
  "status": "UNCONFIRMED",
  "detail": "The command's outcome is unknown. Check the device's command history (list_device_commands or GET /api/v1/assets/{assetId}/commands) before retrying; it may only appear once the device acknowledges it."
}

Example 503 response

HTTP/1.1 503 Service Unavailable
Content-Type: application/problem+json

{
  "type": "about:blank",
  "title": "Service Unavailable",
  "status": 503,
  "detail": "Command was not sent; it is safe to retry.",
  "instance": "/emm/api/v1/assets/k3x9m2pa/commands/message",
  "retryable": true
}

Rate limit

Commands are limited to 10 per minute per API key. The same budget is shared with the MCP command tools. Over REST, requests over the limit get HTTP 429 with a Retry-After header.

Only keys with DEVICES_COMMAND spend this budget. A request with an invalid body or an unknown asset id still counts, because the limit is applied before the request is validated.

Audit trail

Every command is recorded in the device's command history in the Nomid portal and attributed to the API key that sent it, not to a person. The entry shows api-key, the key id and the key prefix. The history returned by GET /assets/ASSET_ID/commands and by the MCP list_device_commands tool contains only type, status, createdAt, feedbackAt and outcome, not who sent the command.

Choose Your Time

Loading...
Open booking calendar