Skip to content

Suggested searches

    Search all documentation ↑↓ to navigate Enter to open Esc to close

    Device Agent Endpoints

    Request and response reference for the four Device Agent API routes — /enroll, /heartbeat, /postures, and /unenroll — plus their error codes.

    Markdown

    All Device Agent API routes use POST and are relative to {probo-origin}/api/agent/v1.

    EndpointAuthenticationSuccess response
    /enrollEnrollment token in body200 JSON
    /heartbeatDevice API key200 JSON
    /posturesDevice API key204
    /unenrollDevice API key204

    Send these headers with every request:

    Accept: application/json
    Content-Type: application/json
    User-Agent: my-probo-agent/1.0.0

    For every route except /enroll, also send:

    Authorization: Bearer <device-api-key>

    User-Agent is recommended for troubleshooting and is not used for authentication.

    Exchanges a one-shot enrollment token for a device API key.

    POST /api/agent/v1/enroll

    The request body is limited to 16 KiB.

    {
    "token": "<enrollment-token>"
    }
    FieldTypeRequiredDescription
    tokenstringYesOne-shot enrollment token

    200 OK

    {
    "api_key": "<device-api-key>"
    }

    Store the key securely before starting the service. The enrollment token is deleted after a successful exchange and cannot be reused.

    Reports the device identity and retrieves its reporting schedule. The first successful heartbeat changes a PENDING device to ACTIVE. Heartbeat and posture intervals are independent; update each local timer from the response.

    POST /api/agent/v1/heartbeat
    Authorization: Bearer <device-api-key>

    The request body is limited to 16 KiB.

    {
    "hardware_uuid": "example-hardware-id",
    "serial_number": "example-serial-number",
    "hostname": "example-device",
    "platform": "LINUX",
    "os_version": "Example Linux 1.0",
    "agent_version": "1.0.0"
    }
    FieldTypeRequiredDescription
    hardware_uuidstringYesStable hardware identifier
    serial_numberstringNoHardware serial number
    hostnamestringYesCurrent device hostname
    platformstringYesOne of the supported platform values below
    os_versionstringYesHuman-readable operating-system version
    agent_versionstringYesVersion of the reporting agent implementation

    Valid platform values are:

    ValuePlatform
    DARWINmacOS
    LINUXLinux
    FREEBSDFreeBSD
    WINDOWSWindows

    The hardware UUID must be stable across restarts. Probo rejects activation if another device in the organization already uses it.

    200 OK

    {
    "device_id": "<device-id>",
    "heartbeat_interval_seconds": 300,
    "posture_interval_seconds": 3600,
    "server_time": "2026-08-05T14:00:00Z"
    }
    FieldTypeDescription
    device_idstringProbo identifier for the enrolled device
    heartbeat_interval_secondsintegerDelay between heartbeat requests
    posture_interval_secondsintegerDelay between posture collection cycles
    server_timestringCurrent server time in RFC 3339 UTC format

    The current defaults are 300 seconds for heartbeats and 3,600 seconds for posture collection. Treat the response as authoritative: update each local timer after every successful heartbeat instead of hard-coding these values or assuming the schedules stay in lockstep.

    Pushes a batch of locally evaluated posture checks. The device must have sent a successful heartbeat before reporting posture. A posture request while the device is still PENDING returns 401 Unauthorized—the same status used for revocation—so activate with /heartbeat first.

    POST /api/agent/v1/postures
    Authorization: Bearer <device-api-key>

    The request body is limited to 1 MiB and can contain at most 100 results.

    {
    "results": [
    {
    "check_key": "FIREWALL_ENABLED",
    "status": "PASS",
    "evidence": {
    "backend": "ufw",
    "raw": "Status: active"
    },
    "observed_at": "2026-08-05T14:00:00Z"
    }
    ]
    }
    FieldTypeRequiredDescription
    resultsarrayYesUp to 100 posture results
    check_keystringYesStable identifier for the check
    statusstringYesResult status
    evidenceJSON objectNoDetails supporting the result
    observed_atstringYesObservation time in RFC 3339 format
    correlation_idstringNoProbo posture-report ID used to group related result sets

    An empty results array is accepted as a no-op. A successful request returns 204 No Content.

    ValueMeaning
    PASSThe check passed
    FAILThe check failed
    UNKNOWNThe agent could not determine the result
    NOT_APPLICABLEThe check does not apply to this device

    Use the official keys when your check has the same meaning. This allows Probo to interpret and display the evidence consistently.

    Check keyWhat it evaluates
    DISK_ENCRYPTIONFull-disk encryption
    SCREEN_LOCKScreen or idle-lock configuration
    FIREWALL_ENABLEDHost firewall
    TIME_SYNCSystem clock synchronization
    OS_VERSIONOperating-system version
    AUTO_UPDATEAutomatic operating-system updates
    PASSWORD_POLICYLocal password policy
    REMOTE_LOGINRemote-login exposure
    MALWARE_PROTECTIONBuilt-in malware protection

    The API accepts other non-empty check keys, but Probo might display their evidence as unknown. Use a stable uppercase identifier and keep its semantics consistent across agent versions.

    Evidence is free-form JSON. Prefer an object with concise machine-readable fields. Do not include secrets, full configuration files, or command output that might contain personal or sensitive data.

    The official agent’s evidence schemas are the best reference when implementing a canonical check. See the checks package.

    Results from one collection cycle should belong to one posture report. If correlation_id is omitted, Probo creates one ID and applies it to every result in the request.

    Only provide a correlation ID when you already have a valid Probo device-posture-report ID for the same tenant. Invalid IDs, IDs for another entity type, and IDs from another tenant return 400 Bad Request.

    Revokes the current device API key.

    POST /api/agent/v1/unenroll
    Authorization: Bearer <device-api-key>

    No request fields are required. A successful request returns 204 No Content. Delete local credentials whether or not this best-effort request succeeds during uninstall.

    StatusMeaning
    400Invalid JSON, missing fields, invalid enum, or oversized batch
    401Invalid enrollment token, missing/invalid API key, revocation, or posture before activation
    405The route was called with a method other than POST
    500Unexpected server error

    Do not depend on the exact error message. Log the status and safe request context without logging credentials or posture evidence. Retry temporary network failures and 5xx responses with bounded exponential backoff. Do not retry 400 responses without changing the request, and clear credentials after 401 except during bring-up when a posture request precedes the first successful heartbeat.