Guides
Device-initiated enrollment
A device can request to join an organization. The request sits in pending
until an administrator approves or rejects it. After approval the device polls
and receives its dev_ credential once.
This is the second enrollment path. The first path (a registration token) is documented in device-registration.md.
Flow
- An administrator creates an API key under Fleet → API keys.
- The device is configured (
meteorcli config --domain … --api-key …) and runsmeteorcli request-token. POST /api/v1/agent/enroll/request(Bearerkey_…) creates a pending request and returns a one-timeclaim_secret(clm_…).- The administrator reviews the request on Fleet → API keys and approves or rejects it.
- The device polls
POST /api/v1/agent/enroll/pollwithrequest_idandclaim_secretfor a limited time (meteorcli request-tokendefaults to 5 minutes, at most once every 10 seconds). On first poll after approval the server issues adev_credential, creates/updates the device (same identity matching as token registration), and returns the token once. - If approval happens later, the same stored claim secret is used by
meteorcli claim— it does not submit a new enrollment request.
Device endpoints
GET /api/v1/agent/enroll/check
Authorization: Bearer key_...
Returns the organization and key label if the key is valid. Used by
meteorcli test. Does not create an enrollment request.
POST /api/v1/agent/enroll/request
Authorization: Bearer key_...
Request body is inventory (all fields optional). Response:
{
"request_id": "…",
"claim_secret": "clm_…",
"status": "pending",
"poll_interval_seconds": 10,
"expires_at": "…"
}
POST /api/v1/agent/enroll/poll
{
"request_id": "…",
"claim_secret": "clm_…"
}
Statuses: pending, approved, rejected, expired. device_token is
present only on the first successful claim after approval.
Admin endpoints
| Method | Path |
|---|---|
GET | /api/v1/organizations/{org}/enrollment-requests?status=pending |
POST | /api/v1/organizations/{org}/enrollment-requests/{id}/approve |
POST | /api/v1/organizations/{org}/enrollment-requests/{id}/reject |
Approve body (all optional): { "name", "device_type_id", "device_group_id" }.
Reject body (optional): { "reason" }. Mutation requires owner or admin.
Rate limiting and security
- Submit: fixed-window limiter keyed by source IP + API key (default 5 / 60s).
- Poll: fixed-window limiter keyed by source IP (default 30 / 60s).
- Claim secrets are hashed (SHA-256); plaintext is never listed.
- A wrong
claim_secretreturns401 invalid_enrollment_request. - Duplicate identity matching matches token registration (same org upsert,
cross-org
409 device_registered_elsewhere). - Pending requests expire after
ENROLLMENT_REQUEST_TTL_SECONDS(default 3600). - HTTP is allowed but warned;
REGISTRATION_REQUIRE_HTTPS=truerejects it.
Using meteorcli
meteorcli config --domain meteorxx.com --api-key key_...
meteorcli test
meteorcli request-token --name edge-01
# if still pending, later:
meteorcli claim
meteorcli run