Replace the tenant's policy document
const url = 'https://example.com/v1/policy';const options = { method: 'PUT', headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'}, body: '{"default":"allow","on_error":"allow","rules":[{"action":"allow","match":{"agents":["example"],"tools":["example"],"max_body_bytes":1,"rate_per_min":1}}]}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request PUT \ --url https://example.com/v1/policy \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "default": "allow", "on_error": "allow", "rules": [ { "action": "allow", "match": { "agents": [ "example" ], "tools": [ "example" ], "max_body_bytes": 1, "rate_per_min": 1 } } ] }'A wholesale replace, not a partial patch: every call sets default, on_error, and rules to exactly what is given, including replacing rules with an empty list. The document is validated before it replaces the stored policy; a malformed document is rejected with 400 and never reaches the store (spec 0009).
Authorizations
Section titled “Authorizations”Request Bodyrequired
Section titled “Request Bodyrequired”The PUT /v1/policy request body: a wholesale replacement of the tenant’s policy (spec 0009). default and on_error are both required on every call — there is no partial-patch “leave unchanged” state.
object
Applied when no rule matches. Operator-set, not hardcoded fail-closed.
Applied when the evaluation engine or store errors.
One ordered entry in a policy document’s rule list, evaluated in order (spec 0009).
object
Conditions a rule matches an in-flight call against (spec 0009). Every populated field must match for the rule to apply; an absent/empty field is not a match condition (matches any value). tools is meaningless for protocol=http agents (route-level only).
object
Matches the calling agent’s ID. Absent/empty matches any agent.
Matches the parsed MCP tool name, supporting a single trailing * wildcard (e.g. read_*). Absent/empty matches any tool.
Matches when the request body size is at least this many bytes.
Matches when the caller’s observed rate exceeds this many requests per minute.
Responses
Section titled “Responses”The replaced document’s new version and timestamp.
The PUT /v1/policy response — version and timestamp only, not the full document just written.
object
Examplegenerated
{ "version": 1, "updated_at": "2026-04-15T12:00:00Z"}Malformed request body — unknown action, ill-formed match condition, or missing default/on_error.
The uniform error body for all 4xx responses that carry one.
object
A coarse, caller-safe message. Never contains internal state (invariant
Examplegenerated
{ "error": "example"}Missing or invalid bearer token, or the token’s tenant/user claims are absent. No body.
An unexpected server-side error. No body (internal detail is never returned to callers, invariant