Contract
- shape
- entity
- authority
- act
- evidence
- none
- subscription
- false
- permission
- any one of: org.admin (carried by the caller's role template in the org `org_id`); account.owner (account role owner or higher in the account of the org `org_id`); a deactivated caller is refused first
- idempotency
- natural
- emits
- security_policy.changed
- MCP tool
- set_ip_allowlist
- decision_set
- approve, reject, escalate
- REST
- POST https://api.containertradehq.com/v1/cap/set_ip_allowlist
Through MCP this call returns an approval request first; see Approvals.
Idempotency: keyed by the contract's own inputs: the same inputs replay the first call's result
Inputs
| name | type | required | validation |
|---|---|---|---|
| org_id | org_id | required | tradehq-org-id; 1 to 20 characters The org whose IP allowlist to set. |
| mode | one_of | required | one of off, monitor, enforce off: no check. monitor: requests from outside the list are recorded and allowed. enforce: they are refused. |
| applies_to | one_of | required | one of members, api_keys, both Who the allowlist checks: members, API keys, or both. |
| entries | network_entries | required | 0 to 100 items The whole list of ranges, each {cidr, label}. A bare address is its /32 (IPv4) or /128 (IPv6). |
Response
org_id· string · The org.current· object · The network section as it now stands, with its version.
Full JSON Schema
{
"type": "object",
"properties": {
"org_id": {
"type": "string",
"minLength": 1,
"maxLength": 20,
"pattern": "^[A-Za-z0-9_-]{1,20}$",
"format": "tradehq-org-id",
"description": "The org.",
"x-data-class": "operational"
},
"current": {
"type": "object",
"properties": {
"section": {
"type": "string",
"enum": [
"sso",
"mfa",
"session",
"network",
"drift"
]
},
"policy": {
"oneOf": [
{
"type": "object",
"properties": {
"domains": {
"type": "array",
"items": {
"type": "object",
"properties": {
"domain": {
"type": "string"
},
"required": {
"type": "boolean"
},
"bypass_until": {
"type": [
"string",
"null"
],
"format": "date-time"
}
},
"required": [
"domain",
"required",
"bypass_until"
],
"additionalProperties": false
}
},
"connections": {
"type": "array",
"items": {
"type": "object",
"properties": {
"connection_id": {
"type": "string"
},
"jit": {
"type": "boolean"
},
"default_role_template": {
"type": [
"string",
"null"
]
},
"idp_mfa_trusted": {
"type": "boolean"
},
"allow_manual_additions": {
"type": "boolean"
}
},
"required": [
"connection_id",
"jit",
"default_role_template",
"idp_mfa_trusted",
"allow_manual_additions"
],
"additionalProperties": false
}
}
},
"required": [
"domains",
"connections"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"mode": {
"type": "string",
"enum": [
"off",
"required",
"required_for_templates"
]
},
"templates": {
"type": "array",
"items": {
"type": "string"
}
},
"grace_days": {
"type": "integer",
"minimum": 0,
"maximum": 30
},
"accept_idp_mfa": {
"type": "boolean"
}
},
"required": [
"mode",
"templates",
"grace_days",
"accept_idp_mfa"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"idle_minutes": {
"type": "integer",
"minimum": 15,
"maximum": 1440
},
"absolute_hours": {
"type": "integer",
"minimum": 1,
"maximum": 168
},
"reauth_on_role_change": {
"type": "boolean"
},
"single_session": {
"type": "boolean"
}
},
"required": [
"idle_minutes",
"absolute_hours",
"reauth_on_role_change",
"single_session"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"mode": {
"type": "string",
"enum": [
"off",
"monitor",
"enforce"
]
},
"entries": {
"type": "array",
"items": {
"type": "object",
"properties": {
"cidr": {
"type": "string"
},
"label": {
"type": "string"
}
},
"required": [
"cidr",
"label"
],
"additionalProperties": false
}
},
"applies_to": {
"type": "string",
"enum": [
"members",
"api_keys",
"both"
]
}
},
"required": [
"mode",
"entries",
"applies_to"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"action": {
"type": "string",
"enum": [
"quarantine",
"alert_only"
]
}
},
"required": [
"action"
],
"additionalProperties": false
}
]
},
"is_default": {
"type": "boolean"
},
"version": {
"type": [
"integer",
"null"
],
"minimum": 1
},
"changed_by": {
"type": [
"string",
"null"
]
},
"changed_at": {
"type": [
"string",
"null"
],
"format": "date-time"
}
},
"required": [
"section",
"policy",
"is_default",
"version",
"changed_by",
"changed_at"
],
"additionalProperties": false,
"description": "The network section as it now stands, with its version.",
"x-data-class": "operational"
}
},
"required": [
"org_id",
"current"
],
"additionalProperties": false
} Refusals
enforce_unavailable· 422 · enforce mode is not available on this deployment until front-door's ingress self-check is true: the origin is reachable through Cloudflare only and Cloudflare's client address is authenticatedcaller_not_allowed· 422 · enforce mode is refused while the caller's own address is outside the list: add it firstnetwork_policy_invalid· 422 · the list is not one the section can hold: a mode other than off names at least one rangesecurity_policy_unenforced· 422 · the stored network section does not parse
The platform refusals apply to every call: version, authentication, authority, validation and rate limits, each in the same envelope.
Surfaces
- MCP: approval required
- Voice: degraded: confirmation
- OneBox: no document originates a change to security settings
- Outbound: crosses to no counterparty
Events
security_policy.changedaudit_only