Protocol

Grant and Revoke

Grant lets an enrolled Agent obtain an optional session credential. Revoke invalidates credentials the Service issued to that Agent. Both commands use the Agent's baseline client assertion.

Check whether the commands are available

The Agent reads Inspect before calling either command. commands.supported must name the command, and commands.grant_types must contain the requested credential type. If the grant-type list is absent or empty, the Service cannot advertise Grant or Revoke. The Agent must not infer command support from an authentication method advertised for protected resources.

Grant also requires an existing enrollment recognized by the Service. When the Agent does not know its current state, it should call Status before starting credential issuance. The Service must reject Grant for an unrecognized Agent with not_recognized; Grant never creates an enrollment as a side effect.

Issue a credential with Grant

The Agent sends POST to the Grant path under the Service's advertised http.endpoint_base. It signs a fresh baseline assertion with op=grant, sends a non-empty Idempotency-Key, and names an advertised grant_type in the JSON body. This illustrative Service uses /aep/ as its endpoint base and offers api-key:

POST /aep/grant HTTP/1.1
Host: api.example.com
Content-Type: application/aep+json
Authorization: AEP <jwt>
Idempotency-Key: 7e2bdbd7-165e-4c35-9f11-9376e314e617

{"grant_type":"api-key"}

The selected grant-type specification may require additional request fields and defines the successful response's usable secret, expiry, and presentation rules. Every successful response is a JSON object containing that credential material and a stable Service-issued credential_id. The identifier is unique across all credentials issued by that Service, including different Agents and grant types, and is never reassigned. Its logical identity is the Service DID paired with credential_id. It is a management identifier, not the secret presented to a protected resource.

Choose what Revoke invalidates

Revoke uses POST under the same advertised endpoint base, but its baseline assertion has op=revoke. This request invalidates all API-key credentials issued to the authenticated Agent, not credentials issued to other Agents:

POST /aep/revoke HTTP/1.1
Host: api.example.com
Content-Type: application/aep+json
Authorization: AEP <jwt>
Idempotency-Key: 156572f4-2cfb-40e6-8f3d-4db4f588b42b

{"grant_type":"api-key"}

The request body selects one of three scopes. The all_grant_types value is the JSON string "true", not a JSON boolean. It cannot be combined with either of the other fields.

TargetRequest fields and support
One grant typegrant_type alone revokes every matching credential issued to this Agent.
One credentialgrant_type plus credential_id is permitted only when commands.grant_types_config advertises supports_per_credential_revoke as "true" for that type.
Every grant type"all_grant_types":"true" revokes every session credential issued to this Agent. Every Service supporting Revoke supports this scope.

A successful Revoke returns 200 OK with an empty JSON object, {}, even if no matching credential existed. The Agent should remove the targeted credential from local storage after success. The Revoke credentials guide helps an Agent choose the appropriate scope.

Authenticate and retry safely

Grant and Revoke always use the baseline Authorization: AEP <jwt> form with the operation appropriate to the command. A session credential cannot authenticate either command. The Service verifies the assertion independently on each request, including a retry; a retry needs a fresh assertion and replay identifier, while its idempotency key stays the same.

Both state-changing commands require a non-empty Idempotency-Key header. The Service retains the result for the authenticated Agent and key for at least one hour, bound to the command and request body. Retrying the same command and body with that key returns the cached response or an equivalent success; using it for another command or body returns 409 idempotency_conflict. A missing or empty key returns 400 invalid_request. Use a new key for a new operation.

Interpret failure without guessing

401 not_recognized covers an unrecognized Agent and other failed assertion checks without disclosing which check failed. 400 unsupported_grant_type means the requested type was not advertised. 400 invalid_request covers malformed field combinations, including an all_grant_types request mixed with grant_type or credential_id. Do not retry the same rejected request without correcting its cause.

For the full Problem Details and retry contract, see Errors and idempotency. For the concrete credential fields, continue with API key, Basic, or OAuth Bearer.