Provisioning QR codes

Create a QR code that enrolls a new or factory-reset Android device into your company with a given policy.

How it works

Each request creates a new enrollment token for the policy and returns a QR code that carries it. The code stops working 24 hours after it is created; the response gives the exact time in expiresAt. Create a code when someone is about to set up devices, and create a new one instead of reusing an older one.

To use the code, tap the welcome screen of the device's setup wizard six times, connect to Wi-Fi if asked, and scan it. A device can only be enrolled this way when it is new or has been factory reset.

VR-only policies cannot be provisioned with a QR code: their devices are provisioned with Nomid Ops over USB.

Requirements

  • An API key with the PROVISIONING permission, combined with POLICIES_READ. Only a portal user who is allowed to provision devices and has access to all policies can create a key with PROVISIONING.
  • The company must have finished its Android Enterprise enrollment.
  • MCP clients that connect with Sign in with Nomid instead of an API key need the mcp:provisioning scope, and the company's provisioning setting under AI agent access in the portal must be turned on.

Endpoint

The path is relative to the API base URL and needs the X-API-Key header. A successful request returns 201 Created.

MethodEndpointDescription
POST/policies/{policyId}/provisioning-qr-codesCreate a provisioning QR code for a policy, with a new enrollment token

Request body

Every field is optional: send an empty JSON object for a code without Wi-Fi and with the default personal usage. An unknown field returns 400.

FieldValuesDescription
personalUsageUNSPECIFIED, ALLOWED, DISALLOWED, USERLESSHow the device is used: ALLOWED for a work profile on a personally owned device, DISALLOWED for a fully managed company-owned device, USERLESS for a dedicated device without a user account. UNSPECIFIED is the default when omitted.
wifiSsidA Wi-Fi network the device joins during setup. Up to 32 bytes in UTF-8. Spaces around it are kept as part of the name.
wifiPasswordThe password of wifiSsid, up to 63 bytes in UTF-8. A WPA password has at least 8 bytes. A WEP key is 5 or 13 ASCII characters, or 10 or 26 hexadecimal digits. Never returned.
wifiSecurityNONE, WPA, WEPThe security of wifiSsid. Defaults to WPA when a password is given and NONE otherwise. NONE takes no password, and WPA and WEP need one.
wifiHiddenWhether wifiSsid is a hidden network. Defaults to false.

wifiPassword, wifiSecurity and wifiHidden need wifiSsid.

Response

FieldDescription
policyIdThe policy's path name, the policyId devices enroll with.
policyNameThe policy's display name.
personalUsageThe personal usage mode of the enrollment token.
expiresAtWhen the QR code stops enrolling devices.
wifiSsidThe Wi-Fi network the device joins during setup. Omitted when none was given.
imageThe QR code image: mimeType (image/png) and data, the image bytes in base64.
portalUrlA link to the policy in the Nomid portal.

Example

Create a code for a fully managed device that joins a WPA network during setup. jq builds the body from an environment variable, so the password is escaped correctly and does not end up in your shell history.

curl -X POST "https://api.nomid.tech/emm/api/v1/policies/p7k2m9qa4xz/provisioning-qr-codes" \
  -H "X-API-Key: $NOMID_API_KEY" \
  -H "Content-Type: application/json" \
  -d "$(jq -n --arg password "$WIFI_PASSWORD" \
    '{personalUsage: "DISALLOWED", wifiSsid: "Warehouse", wifiPassword: $password}')"
HTTP/1.1 201 Created

{
  "policyId": "p7k2m9qa4xz",
  "policyName": "Warehouse scanners",
  "personalUsage": "DISALLOWED",
  "expiresAt": "2026-10-11T14:30:00Z",
  "wifiSsid": "Warehouse",
  "image": {
    "mimeType": "image/png",
    "data": "iVBORw0KGgoAAAANSUhEUgAA..."
  },
  "portalUrl": "https://portal.nomid.tech/#/acme/acme/policy/p7k2m9qa4xz"
}

Decode data from base64 to get the PNG. The image data is shortened here.

Error: VR-only policy

HTTP/1.1 409 Conflict
Content-Type: application/problem+json

{
  "type": "about:blank",
  "title": "Conflict",
  "status": 409,
  "detail": "Policy q4vr8headset is a VR-only policy: its devices are provisioned with Nomid Ops over USB, not with a QR code.",
  "instance": "/emm/api/v1/policies/q4vr8headset/provisioning-qr-codes",
  "code": "unsupported",
  "retryable": false
}

Errors

Once the API key is authenticated, errors use application/problem+json with two extra fields: code, a stable identifier to branch on, and retryable, which says whether the same request can be sent again. A body that cannot be read is the exception, described in the 400 row. A missing or invalid key gets the shared 401 response, a small JSON object with error, message and status. The MCP tool returns the same code and message as a tool error.

StatusCodeMeaning
400invalid_argumentsAn option is invalid: an unknown personalUsage or wifiSecurity value, a Wi-Fi field without wifiSsid, or a Wi-Fi name, password or security that does not fit the rules above. The detail says which. A body that is not valid JSON, or that has an unknown field, also returns 400, as problem details without code or retryable.
401-The API key is missing, invalid, expired or revoked.
403forbiddenThe key lacks PROVISIONING or POLICIES_READ.
404not_foundNo policy with this policyId in the key's company.
409unsupportedThe policy cannot provision devices with a QR code: it is a VR-only policy, or the company has not finished its Android Enterprise enrollment.
422refusedThe policy was deleted.
429rate_limitedToo many write requests for this key. The Retry-After header and the detail give the seconds to wait. retryable is true.
502provider_errorGoogle did not create the enrollment token. No QR code was created. retryable is true: try again in a moment.

Rate limits

Each request counts toward the write limit of 10 requests per minute per key, shared with the device command and policy change endpoints and the MCP write tools. A Sign in with Nomid connection that calls create_provisioning_qr_code spends the same limit, counted per connection. Requests that fail the permission checks or argument validation do not count.

MCP tool

The MCP tool create_provisioning_qr_code takes the same options, with policyId as an argument. It returns the QR code as an MCP image block, so the assistant can show it to the user without reading it.

MCP server

Choose Your Time

Loading...
Open booking calendar