Endpoints
Every surface each party exposes, who may call it, and what it answers.
Grouped by the party that operates them. Authorization column says who may call.
The owner's authorization server
Public
| Endpoint | Auth | Answers |
|---|---|---|
GET /.well-known/uma4agents-configuration |
none | Issuer, endpoints, jwks_uri, accepted claim formats |
GET /jwks |
none | Signing keys for RPTs, receipts and PATs |
GET /terms |
none | The owner's terms roster |
GET /terms/{template_id} |
none | A proffered terms document, every version dereferenceable |
GET /terms/{template_id} serves three representations at one URI: JSON by
default, plain-language HTML on Accept: text/html, and JSON-LD with ODRL
permissions and prohibitions on ?format=jsonld.
Its metadata also names where the parties beside her reach it:
rs_registration_endpoint (/rs/register), org_notice_endpoint
(/org/notice), org_admin_endpoint (/org/admin), joint_quote_endpoint
(/joint/quote) and joint_verdict_endpoint (/joint/verdict). Each message on
those paths is specified in
Multi-Party Authorization §4.
Token endpoint
| Grant type | Caller | Answers |
|---|---|---|
urn:ietf:params:oauth:grant-type:uma-ticket |
the agent | The four-beat loop |
client_credentials, scope=uma_protection |
an owner-authorized resource server | A PAT |
The PAT is an ordinary access token this authority issues: signed, expiring, carrying the owner as subject and the resource server as authorized party. The owner can revoke a resource server, which kills issuance and verification at once.
A resource server holds one PAT per owner it serves, so client_credentials
takes the owner it is asking about — there is no default. It authenticates
with a client secret where the pair was provisioned together, and otherwise
with an RFC 9421 signature over the request from a key its own origin
publishes. Which of the two applies follows from the stored record, so a
resource server that registered by signature cannot fall back to guessing a
secret. While the owner has not yet authorized it, the answer is 403
authorization_pending rather than a refusal.
Establishment
| Endpoint | Auth | Answers |
|---|---|---|
POST /rs/register |
an RFC 9421 signature from a key published at the origin of the resource being claimed | 202 with status: pending. The body names owner, resource_uri and optionally name |
POST /token, grant_type=client_credentials |
the registration's secret or origin signature | A PAT for the owner named in owner |
How a resource server introduces itself to an authority nobody configured it against. The authority fetches the RFC 9728 document at the claimed resource and the JWKS it names, and requires that the document claim this resource, name this authority, and be same-origin with its keys. Nothing is provisioned in advance and no secret is transmitted.
Success settles who is asking and nothing else: the registration waits in the owner's registry until she answers. See many owners, one resource server.
Protection API
Resource servers only, PAT-authorized. FedAuthz shape.
| Endpoint | Answers |
|---|---|
POST /perm |
Registers attempted permissions, returns a ticket. Rejects unregistered resources (invalid_resource_id) and excess scopes (invalid_scope) |
POST /introspect |
RPT introspection with the permissions array. Never consumes; an inactive answer carries a reason |
POST /consume |
Burns a single-use RPT. The atomic last step of enforcement |
POST /audit/access |
The enforcement point reports an allowed call, grounding the ledger's "touched" column |
There is no /rreg on this line. Registration is declarative — the authority
reads what the resource server publishes. Classic push registration remains
conformant and is preserved on the legacy/rreg-baseline branch.
Owner API
Takes a credential that is hers. Two are defined and a deployment may accept both: an OIDC access token validated against her realm's published keys, or an RFC 9421 signature from a key she enrolled. No static owner credential exists either way. See put the authority on her device.
| Endpoint | Answers |
|---|---|
GET /owner/pending |
Requests in awaiting-owner state |
POST /owner/pending/{family}/decision |
Approve or deny |
GET /owner/policies |
Tier policy |
POST /owner/policies |
Add a tier of her own, over resources that are registered and not already governed |
PUT /owner/policies/{tier_id} |
Edit a tier's terms, its ask-me flag, or its rules |
DELETE /owner/policies/{tier_id} |
Remove a tier. Its resources become ungoverned, and ungoverned is denied |
GET /owner/policy-vocabulary |
The conditions a rule may use, and which of them may relax one |
GET /owner/resources |
Registered resources joined with tiers |
GET /owner/resource-servers |
Resource servers holding her protection access, each pending, active or revoked |
POST /owner/resource-servers/decision |
Approve one that introduced itself, or withdraw one. Takes the client_id in the body, because a self-registered resource server is identified by an https URL |
POST /owner/resource-servers/{id}/revoke |
The same withdrawal by path, for relationships whose ids are plain names |
GET /owner/connections |
Standing agent relationships |
POST /owner/connections/revoke |
Revoke a connection and its live RPTs. The handle travels in the body: an identified agent's carries its issuer, path and all |
GET /owner/operators |
The operators behind those connections, and whether any are blocked |
POST /owner/operators/block |
Shut out every agent one operator runs, revoking what is connected in the same step |
POST /owner/operators/unblock |
Restores the right to negotiate, not the access that was withdrawn |
GET /owner/ledger |
The activity ledger |
GET /owner/events |
Server-sent event stream for portal notification |
The organization above her, if she has joined one
Only present where an organization owns resources shared with this owner — see shared ownership.
| Endpoint | Answers |
|---|---|
GET /owner/organization |
Whether she administers resources for anyone, what it shares with her, what its ceiling does to each of her tiers, and any invitation waiting on her |
POST /owner/organization/preview |
What a code would commit her to, and exactly what it would change about terms she has already written. Nothing happens |
POST /owner/organization |
Join. Refused without an explicit agreed, because joining hands another party standing authority over her agents |
POST /owner/organization/decline |
Refuse an invitation, recorded as an answer rather than a silence |
DELETE /owner/organization |
Leave. Takes back the access; leaves every narrowing in place |
POST /org/notice |
A signed notice from her organization — the charter moved, her role changed, the glass was broken. Verified against the keys that organization publishes, never a shared secret |
GET/POST /org/admin/{owner}/… |
An administrator acting on the agents that touch the organization's resources: pending, connections, operators, ledger. Scoped by the charter's claims before anything is answered, and everything written into her record under his name |
Health
| Endpoint | Purpose |
|---|---|
GET /health |
Local liveness. Deliberately independent of the registry pull |
GET /health/registry |
Has the pull landed. For waits and dashboards — never a readiness probe |
The asymmetry is the point: the pull dereferences this server's own public hostname, which routes back to it. Gating readiness on the pull deadlocks.
The resource server's enforcement point
| Endpoint | Auth | Answers |
|---|---|---|
GET /.well-known/oauth-protected-resource[/mcp] |
none | RFC 9728 metadata, OAuth+DPoP binding |
GET /jwks |
none | The resource's signing keys |
GET /owner-resources |
RFC 9421-signed query by the owner's authority | Owner-bound resource instances |
/check{path} |
the gateway | The external authorization decision |
The public document is structural only. Which instances sit behind the resource — whose positions, whose vault — is served only to a querier that proves possession of the owner's authority's signing key. Publishing that at an unauthenticated URI would be a privacy leak.
RFC 9728 members
Standard: resource, authorization_servers, scopes_supported, jwks_uri,
signed_metadata.
Extension members: tool_surfaces (tool names and scopes, structural only) and
owner_resources_endpoint (the protected instance layer).
signed_metadata carries the same claims as a JWT under the resource's key, so
a relayed copy stays attributable.
The organization's authority
A party of its own, not a table inside anyone's authorization server.
| Endpoint | Answers |
|---|---|
GET /.well-known/u4a-organization |
Discovery: issuer, JWKS, and every endpoint below that a member's authority or an enforcement point calls, each under its own member name |
GET /jwks |
Its signing keys. Members verify notices against these; enforcement points verify the grants it signs itself |
POST /member/preview |
The charter in sentences, before anybody has joined |
POST /member/join |
Enrol, by an invitation addressed to one person, by the organization's identity provider vouching for her, or by a shared code where one is configured. Names the charter version she agreed to, and is refused without it. Returns a membership token her authority holds |
GET /member/envelope |
The ceiling, and what her role shares with her. Polled, not pushed — a push that failed would be silent on both sides |
POST /decision |
The organization's answer about one request: allow, ask or refuse, and never anything that widens |
POST /member/compliance |
Her authority reporting that the ceiling was applied and which of its fields bit. Never what her terms say |
GET /member/invitation |
Whether this organization has asked for a named person |
GET /member/clearance |
What this organization will attest about her, signed and audienced at her authority. Fetched by her authorization server, never by an agent. 404 when it holds nothing, which her authority reads as unmet rather than as an error |
GET /membership/{owner} |
For an enforcement point: whether this owner is governed here, what is shared with her, and the ceiling to check grants against |
POST /break-glass |
An agent redeeming a window, signing with the key the grant will bind to |
POST /introspect, /consume |
RFC 7662 over the grants this service signed, shaped exactly like a member authority's answers, and spending one. An enforcement point authenticates with the credential this organization provisioned for it |
/admin/… |
The console's backend: charter versions, members and their groups, invitations, break-glass windows, activity |
Groups are charter data, so the four endpoints that manage them publish a charter version rather than editing the one in force:
| Endpoint | Answers |
|---|---|
GET /admin/roles |
The groups this charter defines, which one joiners land in, and who is in each. Membership is state this service holds, not something the engine is asked |
PUT /admin/roles/{id} |
Create a group or change what it reaches. Refused if it grants anything the charter does not claim |
DELETE /admin/roles/{id} |
Remove a group. Refused while anybody is in it — deleting one fails closed for its members, which is an access change nobody would see happen |
POST /admin/roles/default |
Which group somebody lands in when they join. null is valid: joining grants nothing until an administrator says what this person is |
POST /admin/members/{owner}/role |
Move one member. With PUT /admin/roles/{id}, the way this console widens what somebody reaches |
PUT /admin/members/{owner}/clearance |
What this organization is prepared to attest about one member. An empty object withdraws it, and access stops within the attestation's lifetime |
The tally, for a resource held jointly
A party of its own, and the only one here that owns nothing and decides
nothing. It speaks an ordinary authorization-server surface — /perm,
/token, /introspect, /consume — so an unmodified agent and an ordinary
enforcement point both work against it unchanged. What is listed below is only
what is not an ordinary authorization server.
| Endpoint | Answers |
|---|---|
GET /.well-known/uma4agents-configuration |
Discovery, carrying u4a_tally: true — a relying party finding this field is being told the party at this endpoint decides nothing |
GET /mandate/{account} |
Who is entitled to be counted, at what weight, and how many it takes. Public: a holder reads it before she agrees, and anyone verifying a grant needs it to re-run the count |
GET /terms/{template_id} |
The folded terms document an agent signed — every holder's terms intersected into one |
GET /jwks |
Its signing keys. Note what they are not good for: no relying party accepts a signature from here as a verdict |
And on each holder's own authorization server:
| Endpoint | Answers |
|---|---|
POST /owner/joint/preview |
What a mandate would commit her to, and what her co-owners' terms would narrow about hers. Nothing happens |
POST /owner/joint |
Agree to a mandate. Refused without an explicit agreed — it gives other people a say over a resource she administers |
GET /owner/joint |
The accounts she holds jointly, who holds them with her, and the rule |
DELETE /owner/joint/{account} |
Stop being a holder. Her terms stay exactly as they were |
POST /joint/quote |
Her terms over one jointly held resource, for the fold. That resource only |
POST /joint/verdict |
Her authority's answer about one request — signed, or pending while she is asked. Answered only for a mandate she agreed to, and only to the tally that mandate names |
The requesting party's operator
| Endpoint | Answers |
|---|---|
| CIMD document | The firm's public client identity metadata |
| Web Bot Auth key directory | Keys for the Signature-Agent header |
Neither becomes an authorization input. The verifying key is always the RPT's
cnf, and the connection handle is unchanged by either.
Registration flow
The resource server publishes; it never registers.
- The authority fetches the public RFC 9728 document.
- It verifies
signed_metadataagainst the resource'sjwks_uri. - It queries the advertised
owner_resources_endpointwith an RFC 9421-signed request. - It materializes its registry from the response.
One fetch replaces N registration calls, and there is one registry with one
writer. Staleness is the price, and repairing it is the authority's job: an
unknown resource_id at /perm triggers a re-pull.