Device Agent Authentication
Exchange a one-time enrollment token for a device API key, authenticate subsequent requests with a bearer token, and handle 401 responses safely.
The Device Agent API uses two credentials with different purposes:
| Credential | Purpose | Sent as |
|---|---|---|
| Enrollment token | One-time exchange for a device API key | token in the /enroll body |
| Device API key | Heartbeat, posture, and unenrollment requests | Authorization: Bearer <api-key> |
Both credentials are 96-character hexadecimal strings. Probo stores only their SHA-256 hashes.
Enrollment tokens
Section titled “Enrollment tokens”An enrollment token belongs to one device record. It is single-use and expires after seven days by default. Self-hosted deployments can configure a different validity period.
Create the device and obtain its token before calling the Device Agent API:
- In the Probo console, use the device enrollment flow.
- Through the console GraphQL API, use
createDeviceorenrollDevice. - Through MCP, use the
createDevicetool. - Through the CLI, use
prb device create. - Through n8n, use the device create operation.
Those interfaces return the Probo server URL alongside the token. Device
creation is not part of /api/agent/v1.
Exchange a token
Section titled “Exchange a token”Send the token once to the server URL supplied with the enrollment:
curl --request POST \ --url https://us.probo.com/api/agent/v1/enroll \ --header 'Accept: application/json' \ --header 'Content-Type: application/json' \ --data '{"token":"<enrollment-token>"}'curl --request POST \ --url https://eu.probo.com/api/agent/v1/enroll \ --header 'Accept: application/json' \ --header 'Content-Type: application/json' \ --data '{"token":"<enrollment-token>"}'curl --request POST \ --url https://probo.example.com/api/agent/v1/enroll \ --header 'Accept: application/json' \ --header 'Content-Type: application/json' \ --data '{"token":"<enrollment-token>"}'A successful exchange returns:
{ "api_key": "<device-api-key>"}The server deletes the enrollment token after the exchange. Reusing it, using
an expired token, or using an unknown token returns 401 Unauthorized.
Persist the API key before starting the service. The official agent stores it in its state directory with access restricted to the service account. A custom agent can use the operating system’s secret store instead.
Authenticate device requests
Section titled “Authenticate device requests”Send the device API key as a bearer token on every endpoint except /enroll:
Authorization: Bearer <device-api-key>For example:
curl --request POST \ --url https://us.probo.com/api/agent/v1/heartbeat \ --header 'Accept: application/json' \ --header 'Authorization: Bearer <device-api-key>' \ --header 'Content-Type: application/json' \ --data '{ "hardware_uuid": "example-hardware-id", "hostname": "example-device", "platform": "LINUX", "os_version": "Example Linux 1.0", "agent_version": "1.0.0" }'The API key remains valid until the device is revoked by an administrator or unenrolled by the agent. Probo displays the plaintext key only in the enrollment response.
Handle unauthorized responses
Section titled “Handle unauthorized responses”Treat any 401 Unauthorized response from an authenticated endpoint as a dead
credential:
- Stop heartbeat and posture uploads.
- Delete the API key and queued posture data from local storage.
- Require a new device enrollment and enrollment token.
Do not retry a rejected API key indefinitely.
One important exception during bring-up: /postures also returns 401 when the
device is still PENDING because no successful heartbeat has activated it yet.
Activate with /heartbeat before the first posture upload so a valid key is not
cleared as revoked.
Desktop enrollment links
Section titled “Desktop enrollment links”The official desktop flow can pass enrollment input through this custom URI:
probo://enroll?server=https%3A%2F%2Fus.probo.com&token=<enrollment-token>If your agent implements this flow, register the probo scheme securely,
validate that server is an HTTPS origin, reject unexpected parameters, and
avoid logging the URI. A custom URI is optional; command-line and managed
installation flows can pass the server and token separately.
Next step
Section titled “Next step”See Endpoints for request and response schemas.