Enroll and Status
Two commands, one enrollment record
After reading the Service's Inspect document, an Agent can call Enroll if the Service advertises it and accepts the Agent's identity method. The Service uses that request to make an initial enrollment decision. The decision may be immediate, or it may depend on claim verification or action by the Agent's Owner.
Status does not submit another enrollment. It reads the Service's current state for the authenticated Agent identity. If the Service advertises Status, an Agent uses it after a pending response and whenever it needs to know whether an existing enrollment remains usable. Both commands return lifecycle representations on success; an error about a blocked operation is a different response.
Send Enroll
The Agent sends POST to the advertised Enroll path, built from http.endpoint_base. It presents a fresh baseline client assertion with op set to enroll and sends a non-empty Idempotency-Key header. The example uses /aep/ as the endpoint base and a Service that requested contact.email in Inspect.
POST /aep/enroll HTTP/1.1
Host: api.example.com
Content-Type: application/aep+json
Authorization: AEP <jwt>
Idempotency-Key: 9f8a4d2e-1c3b-4f5e-8b7a-000000000000
{
"agent_did": "did:web:agent.example.com:agents:123",
"claims": {"contact.email": "ops@example.com"}
}agent_did must identify the same Agent as the assertion's iss, sub, and DID portion of kid. The identity method must be one the Service advertised. The optional claims object carries values requested in Inspect; submitting a value does not mean the Service has verified it. The request body may also carry idempotency_key; when it does, it must equal the header value.
Interpret the Enroll result
A successful Enroll response uses 200 OK. For a new enrollment, active means the Service recognizes the Agent and it can continue; pending means the decision is not complete; rejected means the initial decision did not approve enrollment. An immediate approval needs only a status field with the value active.
When verification or Owner action is outstanding, the response may instead look like this. It tells the Agent to check Status later; it does not provide a verified claim value or grant access to a protected resource.
{
"owner_action_required": "true",
"status": "pending",
"verification_pending": ["contact.email"]
}If this Agent DID already has an enrollment record, Enroll returns its current lifecycle representation. That can include unavailable, suspended, or terminated as well as the three initial-decision states. It is not a renewal or replacement request: the Service does not rerun enrollment policy, reset timestamps, or replace the record.
Check Status
Status is a bodyless GET for the Agent identity authenticated on that request. Its path uses the same advertised endpoint base as Enroll. Its baseline client assertion uses op equal to status. A concrete session-credential type may additionally allow its credential on Status, but every exposed Status endpoint accepts the baseline assertion.
GET /aep/status HTTP/1.1 Host: api.example.com Authorization: AEP <jwt>
A successful Status response uses 200 OK and reports one of six states. When present, since is the time of the last state transition, not the original enrollment time.
{
"since": "2026-05-28T12:00:00Z",
"status": "active"
}- active: Enrolled and operational.
- pending: Waiting for asynchronous verification.
- unavailable: Temporarily unavailable for a Service-defined, non-punitive reason.
- suspended: Temporarily disabled by Service action.
- terminated: Permanently de-registered.
- rejected: Asynchronous verification failed.
The status field describes enrollment state. It is not an HTTP status or a promise that the application will authorize every request from an active Agent.
Understand what remains unfinished
verification_pending names submitted claims the Service has not finished verifying. requirements_pending names requirements the Agent still needs to satisfy. They are not interchangeable: a submitted email awaiting verification is different from a missing requirement. Both fields can appear in either Enroll or Status; an omitted field means its set is empty, and empty arrays are not emitted. Neither array contains claim values.
owner_action_required is independent of those two lists. Its value is a JSON string: true means the Agent's Owner must complete an out-of-band action before enrollment can become or remain active. Canonical responses omit the field unless it is true; consumers also accept an explicit false. The Agent should use these details to decide whether to wait, request information, or ask its Owner to act.
Retry Enroll without changing the request
A network failure can leave the Agent unsure whether Enroll succeeded. Retry with the same authenticated Agent, command, request body, and Idempotency-Key. The Service retains the response for that key for at least one hour and returns the cached response or an equivalent successful response. Reusing the key with a different command or body produces 409 idempotency_conflict. A missing or empty key produces 400 invalid_request.
The retry uses a fresh client assertion and jti; the idempotency key stays the same because the operation being retried has not changed. Calling Enroll with a new key after a record exists is a different case: the Service returns the record's current lifecycle state without replacing it. See Errors and idempotency for general retry and error rules.
Next steps
- Accept enrollment and status: Implement the Service's enrollment decisions and lifecycle responses.
- Enroll an Agent: Prepare and submit an enrollment request as an Agent.
- Check status: Read the current enrollment state and decide what to do next.