Skip to content

Update the approval policy

The approval_policies.update operation: PATCH /api/v1/approval_policy in the REST API and the approval_policies_update tool in the MCP server.

PATCH/api/v1/approval_policy

Changes the organization's approval policy. Each part you send replaces the current one; leave one out to keep it.

  • tiers: what agents, apps and MCP clients may do per risk tier: allow, require_approval or deny (a denied call fails with approval_policy_denied). Compliance and security are require_approval or deny, never allow: those calls always need a person.
  • twoPersonFor: operations that need a second person's approval, whoever calls. For a call by an agent or app, two people approve.
  • amountLimits: for operations that carry an amount, the amount per currency at or below which a call runs at once (micros as a string). Above it, in a currency without a limit, or without an amount, an agent's or app's call needs approval; for people the limits apply to the operations in twoPersonFor.

Only changes inside the organization that support dry runs can be named (availableOperations in approval_policies.get), never the approvals operations themselves. Overrides for single entities, agents and apps are set with approval_policies.overrides.set. Requests already waiting for approval keep their requirement. Owners and admins only, with a sign-in in the last 15 minutes.

At a glance

  • REST: PATCH /api/v1/approval_policy
  • MCP tool: approval_policies_update
  • Operation ID: approval_policies.update
  • Scope: Organization
  • Permission: approvals:admin
  • Risk tier: security
  • Dry run: Supported (send Ownrecord-Dry-Run: true)
  • Idempotency: Idempotency-Key optional
  • Modes: Test and live
  • Authentication: API key with the approvals:admin scope
  • Fresh sign-in: In the console, a sign-in within the last 15 minutes
  • Since: M2

Request

Body

A JSON object (Content-Type: application/json):

FieldTypeRequiredDescription
tiersobjectNo
tiers.writeone of allow, require_approval, denyNo
tiers.financialone of allow, require_approval, denyNo
tiers.complianceone of allow, require_approval, denyNo
tiers.securityone of allow, require_approval, denyNo
twoPersonForarray of stringNo
amountLimitsarray of objectNo
amountLimits[].operationIdstringYes
amountLimits[].perCallmoneyYes
versioninteger (at least 0)No

Response

200 OK with a JSON object:

FieldTypeDescription
object"approval_policy"
idapol_… ID or null
orgIdorg_… ID
tiersobject
tiers.writeone of allow, require_approval, deny
tiers.financialone of allow, require_approval, deny
tiers.complianceone of allow, require_approval, deny
tiers.securityone of allow, require_approval, deny
twoPersonForarray of string
amountLimitsarray of object
amountLimits[].operationIdstring
amountLimits[].perCallmoney
versioninteger (at least 0)
updatedAtdate-time or null
overridesarray of object
overrides[].idapol_… ID
overrides[].object"approval_policy_override"
overrides[].entityIdent_… ID or null
overrides[].agentIdagt_… ID or null
overrides[].clientIdocl_… ID or null
overrides[].tiersobject
overrides[].tiers.writeone of allow, require_approval, deny or null
overrides[].tiers.financialone of allow, require_approval, deny or null
overrides[].tiers.complianceone of allow, require_approval, deny or null
overrides[].tiers.securityone of allow, require_approval, deny or null
overrides[].twoPersonForarray of string
overrides[].amountLimitsarray of object
overrides[].amountLimits[].operationIdstring
overrides[].amountLimits[].perCallmoney
overrides[].versioninteger (at least 1)
overrides[].updatedAtdate-time
availableOperationsarray of object
availableOperations[].idstring
availableOperations[].summarystring
availableOperations[].riskTierone of write, financial, compliance, security
availableOperations[].scopeone of org, entity, brand
availableOperations[].amountsboolean

Examples

Require a second person for brand changes

HTTP
PATCH /api/v1/approval_policy
Authorization: Bearer or_test_…
Content-Type: application/json

{
  "twoPersonFor": [
    "brands.update"
  ],
  "version": 1
}

Response (200):

JSON
{
  "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": [],
  "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
    }
  ]
}

Agents and apps may not change anything without approval

HTTP
PATCH /api/v1/approval_policy
Authorization: Bearer or_test_…
Content-Type: application/json

{
  "tiers": {
    "write": "require_approval",
    "financial": "require_approval"
  },
  "version": 2
}

Response (200):

JSON
{
  "object": "approval_policy",
  "id": "apol_01m4ttwd3veh9apbewxheq5xh9",
  "orgId": "org_01m4ttwd3veh9apbewxheq5xh3",
  "tiers": {
    "write": "require_approval",
    "financial": "require_approval",
    "compliance": "require_approval",
    "security": "require_approval"
  },
  "twoPersonFor": ["brands.update"],
  "amountLimits": [],
  "version": 3,
  "updatedAt": "2026-10-13T14:30:00.000Z",
  "overrides": [],
  "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
    }
  ]
}

Turn the two-person rule off

HTTP
PATCH /api/v1/approval_policy
Authorization: Bearer or_test_…
Content-Type: application/json

{
  "twoPersonFor": [],
  "amountLimits": [],
  "version": 2
}

Response (200):

JSON
{
  "object": "approval_policy",
  "id": "apol_01m4ttwd3veh9apbewxheq5xh9",
  "orgId": "org_01m4ttwd3veh9apbewxheq5xh3",
  "tiers": {
    "write": "allow",
    "financial": "allow",
    "compliance": "require_approval",
    "security": "require_approval"
  },
  "twoPersonFor": [],
  "amountLimits": [],
  "version": 3,
  "updatedAt": "2026-10-13T14:30:00.000Z",
  "overrides": [],
  "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

CodeHTTP statusWhenWhat to do
validation_failed400The policy names an unknown or ineligible operation, sets compliance or security to allow, or its amount limits don't fit (details.issues).Fix the fields listed in details.issues and send the request again.
version_conflict409The policy changed since you read it (version); read it again.Fetch the object again and retry the change.
fresh_auth_required403You last signed in more than 15 minutes ago.Sign in again, then repeat the action within 15 minutes.
permission_denied403Only 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, resource_not_found, idempotency_key_reused, idempotency_in_progress, approval_required, approval_rejected, approval_expired, stale_approval, approval_policy_denied, rate_limited, internal_error.