Set an approval policy override
The approval_policies.overrides.set operation: PUT /api/v1/approval_policy/overrides in the REST API and the approval_policies_overrides_set tool in the MCP server.
/api/v1/approval_policy/overridesCreates or changes the approval policy override for one legal entity (entityId), one agent (agentId)
or one app (clientId, its OAuth client). Send exactly one of them.
An override has the same parts as the organization's policy: tiers (each tier you send replaces the
current one; null removes it), twoPersonFor and amountLimits (each list you send replaces the current
one). The strictest applicable rule wins: a call is checked against the organization's policy and every
override for its entity, its agent and its app, so an override can only tighten what the organization
allows, never loosen it.
Agents and apps are referenced by ID; the entity must belong to the organization. Returns the whole approval policy. Owners and admins only, with a sign-in in the last 15 minutes.
At a glance
- REST:
PUT /api/v1/approval_policy/overrides - MCP tool:
approval_policies_overrides_set - Operation ID:
approval_policies.overrides.set - Scope: Organization
- Permission:
approvals:admin - Risk tier:
security - Dry run: Supported (send
Ownrecord-Dry-Run: true) - Idempotency:
Idempotency-Keyoptional - Modes: Test and live
- Authentication: API key with the
approvals:adminscope - Fresh sign-in: In the console, a sign-in within the last 15 minutes
- Since: M10
Request
Body
A JSON object (Content-Type: application/json):
| Field | Type | Required | Description |
|---|---|---|---|
entityId | ent_… ID | No | |
agentId | agt_… ID | No | |
clientId | ocl_… ID | No | |
tiers | object | No | |
tiers.write | one of allow, require_approval, deny or null | No | |
tiers.financial | one of allow, require_approval, deny or null | No | |
tiers.compliance | one of allow, require_approval, deny or null | No | |
tiers.security | one of allow, require_approval, deny or null | No | |
twoPersonFor | array of string | No | |
amountLimits | array of object | No | |
amountLimits[].operationId | string | Yes | |
amountLimits[].perCall | money | Yes | |
version | integer (at least 0) | No |
Response
200 OK with a JSON object:
| Field | Type | Description |
|---|---|---|
object | "approval_policy" | |
id | apol_… ID or null | |
orgId | org_… ID | |
tiers | object | |
tiers.write | one of allow, require_approval, deny | |
tiers.financial | one of allow, require_approval, deny | |
tiers.compliance | one of allow, require_approval, deny | |
tiers.security | one of allow, require_approval, deny | |
twoPersonFor | array of string | |
amountLimits | array of object | |
amountLimits[].operationId | string | |
amountLimits[].perCall | money | |
version | integer (at least 0) | |
updatedAt | date-time or null | |
overrides | array of object | |
overrides[].id | apol_… ID | |
overrides[].object | "approval_policy_override" | |
overrides[].entityId | ent_… ID or null | |
overrides[].agentId | agt_… ID or null | |
overrides[].clientId | ocl_… ID or null | |
overrides[].tiers | object | |
overrides[].tiers.write | one of allow, require_approval, deny or null | |
overrides[].tiers.financial | one of allow, require_approval, deny or null | |
overrides[].tiers.compliance | one of allow, require_approval, deny or null | |
overrides[].tiers.security | one of allow, require_approval, deny or null | |
overrides[].twoPersonFor | array of string | |
overrides[].amountLimits | array of object | |
overrides[].amountLimits[].operationId | string | |
overrides[].amountLimits[].perCall | money | |
overrides[].version | integer (at least 1) | |
overrides[].updatedAt | date-time | |
availableOperations | array of object | |
availableOperations[].id | string | |
availableOperations[].summary | string | |
availableOperations[].riskTier | one of write, financial, compliance, security | |
availableOperations[].scope | one of org, entity, brand | |
availableOperations[].amounts | boolean |
Examples
One agent may not move money
PUT /api/v1/approval_policy/overrides
Authorization: Bearer or_test_…
Content-Type: application/json
{
"agentId": "agt_01m4ttwd3veh9apbewxheq5xhc",
"tiers": {
"financial": "deny"
}
}
Response (200):
{
"object": "approval_policy",
"id": "apol_01m4ttwd3veh9apbewxheq5xh9",
"orgId": "org_01m4ttwd3veh9apbewxheq5xh3",
"tiers": {
"write": "allow",
"financial": "allow",
"compliance": "require_approval",
"security": "require_approval"
},
"twoPersonFor": ["brands.update"],
"amountLimits": [],
"version": 2,
"updatedAt": "2026-10-13T14:30:00.000Z",
"overrides": [
{
"id": "apol_01m4ttwd3veh9apbewxheq5xhb",
"object": "approval_policy_override",
"entityId": null,
"agentId": "agt_01m4ttwd3veh9apbewxheq5xhc",
"clientId": null,
"tiers": {
"write": null,
"financial": "deny",
"compliance": null,
"security": null
},
"twoPersonFor": [],
"amountLimits": [],
"version": 1,
"updatedAt": "2026-10-13T14:30:00.000Z"
}
],
"availableOperations": [
{
"id": "brands.update",
"summary": "Update a brand",
"riskTier": "write",
"scope": "brand",
"amounts": false
},
{
"id": "members.remove",
"summary": "Remove a member",
"riskTier": "security",
"scope": "org",
"amounts": false
}
]
}
Refunds at one legal entity need a person above EUR 200
PUT /api/v1/approval_policy/overrides
Authorization: Bearer or_test_…
Content-Type: application/json
{
"entityId": "ent_01m4ttwd3veh9apbewxheq5xh4",
"amountLimits": [
{
"operationId": "refunds.create",
"perCall": {
"amount": "200000000",
"currency": "EUR"
}
}
]
}
Response (200):
{
"object": "approval_policy",
"id": "apol_01m4ttwd3veh9apbewxheq5xh9",
"orgId": "org_01m4ttwd3veh9apbewxheq5xh3",
"tiers": {
"write": "allow",
"financial": "allow",
"compliance": "require_approval",
"security": "require_approval"
},
"twoPersonFor": ["brands.update"],
"amountLimits": [],
"version": 2,
"updatedAt": "2026-10-13T14:30:00.000Z",
"overrides": [
{
"id": "apol_01m4ttwd3veh9apbewxheq5xhb",
"object": "approval_policy_override",
"entityId": "ent_01m4ttwd3veh9apbewxheq5xh4",
"agentId": null,
"clientId": null,
"tiers": {
"write": null,
"financial": null,
"compliance": null,
"security": null
},
"twoPersonFor": [],
"amountLimits": [
{
"operationId": "refunds.create",
"perCall": {
"amount": "200000000",
"currency": "EUR"
}
}
],
"version": 1,
"updatedAt": "2026-10-13T14:30:00.000Z"
}
],
"availableOperations": [
{
"id": "brands.update",
"summary": "Update a brand",
"riskTier": "write",
"scope": "brand",
"amounts": false
},
{
"id": "members.remove",
"summary": "Remove a member",
"riskTier": "security",
"scope": "org",
"amounts": false
}
]
}
Errors
| Code | HTTP status | When | What to do |
|---|---|---|---|
validation_failed | 400 | The override names no subject or several, an unknown or ineligible operation, compliance or security set to allow, or amount limits that don't fit (details.issues). | Fix the fields listed in details.issues and send the request again. |
resource_not_found | 404 | No legal entity with this ID exists in the organization. | Check the ID and that your credentials are scoped to the right organization, entity, brand and mode. |
approval_policy_override_limit_reached | 409 | The organization already has 100 overrides. | Delete an override you no longer need (details.limit is the maximum), or set the rule in the organization's policy instead. |
version_conflict | 409 | The override changed since you read it (version); read it again. | Fetch the object again and retry the change. |
fresh_auth_required | 403 | You last signed in more than 15 minutes ago. | Sign in again, then repeat the action within 15 minutes. |
permission_denied | 403 | Only owners and admins change the approval policy. | Ask an organization owner or admin for a role or scope that allows this action. |
It can also return these common errors: api_version_unsupported, invalid_json, unsupported_media_type, authentication_required, api_key_invalid, idempotency_key_reused, idempotency_in_progress, approval_required, approval_rejected, approval_expired, stale_approval, approval_policy_denied, rate_limited, internal_error.