> For the complete documentation index, see [llms.txt](https://developer.celigo.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developer.celigo.com/api/api-reference/account-and-admin/network-policies.md).

# Network Policies

Network policies are named IP allow and deny lists that control where API tokens, MCP servers, and users may connect from. A policy takes effect only once it is assigned — through `_networkPolicyId` on an API token or MCP server, or in account settings for workspace-user and end-user sign-in — and each environment (production or sandbox) keeps its own library of policies. Network policies must be enabled for the account, and only the account owner and administrators can manage them.

Every policy that applies to a call must admit the caller. An API token's policy is checked when the token authenticates, before the request runs; an MCP server's policy is checked on every request to it, so a call to an MCP server passes both its token's policy and the server's. A personal access token has no policy of its own: it is checked against the workspace-user sign-in policy of the environment it belongs to. Sign-in policies are checked when a workspace user signs in or switches account or environment, and when an end user signs in to an MCP server.

A refused call gets HTTP 403 with `{"errors": [{"code": "access_denied", "message": "Access denied."}]}` and nothing that names the policy or the address. An MCP server endpoint speaks JSON-RPC, so its 403 carries the MCP server's access-denied error (`-32006`) in a JSON-RPC envelope instead — `{"jsonrpc": "2.0", "error": {"code": -32006, "message": "Access denied."}, "id": <request id>}`, with `id` echoed when the request had one — and the server's request log records the call as blocked.

### Network policy schema

## The NetworkPolicy object

```json
{"openapi":"3.2.0","info":{"title":"Network Policies","version":"1.0.0"},"components":{"schemas":{"NetworkPolicy":{"type":"object","description":"Network policy as returned by the API.","required":["_id","_userId","name","ipAllowList","ipDenyList","createdAt","lastModified"],"properties":{"_id":{"type":"string","format":"objectId","readOnly":true,"description":"Unique identifier for the network policy."},"_userId":{"type":"string","format":"objectId","readOnly":true,"description":"Environment that owns the policy — the account user for production, or the\nsandbox user for a policy created there. A policy is visible and assignable\nonly within its own environment."},"name":{"type":"string","maxLength":150,"description":"Display name shown wherever a policy is picked or listed. Unique among the\nenvironment's policies that are not in the recycle bin; on create, a name that\ndiffers only in case from a live policy's is accepted."},"description":{"type":"string","maxLength":500,"description":"Explains what the policy is for. Absent when the policy has no description."},"ipAllowList":{"type":"array","maxItems":200,"description":"Source addresses permitted to connect, each an IPv4 or IPv6 address or CIDR\nrange in stored form (bare addresses carry `/32` or `/128`). An empty list\npermits every address that `ipDenyList` does not block.","items":{"type":"string"}},"ipDenyList":{"type":"array","maxItems":200,"description":"Source addresses refused even when `ipAllowList` permits them. Same entry\nformat and stored form as `ipAllowList`; deny always wins over allow.","items":{"type":"string"}},"createdAt":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp when the policy was created."},"lastModified":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp when the policy was last modified. Updated on every PUT and PATCH that changes a field."}}}}}}
```

## List network policies

> Returns the policies of the caller's environment, most recently modified first.\
> Policies in the recycle bin are not included. The \`include\` and \`exclude\`\
> projection parameters used by other list endpoints are not supported here.

```json
{"openapi":"3.2.0","info":{"title":"Network Policies","version":"1.0.0"},"tags":[{"name":"Network Policies","description":"Network policies are named IP allow and deny lists that control where API tokens, MCP servers, and users may connect from. A policy takes effect only once it is assigned — through `_networkPolicyId` on an API token or MCP server, or in account settings for workspace-user and end-user sign-in — and each environment (production or sandbox) keeps its own library of policies. Network policies must be enabled for the account, and only the account owner and administrators can manage them.\n\nEvery policy that applies to a call must admit the caller. An API token's policy is checked when the token authenticates, before the request runs; an MCP server's policy is checked on every request to it, so a call to an MCP server passes both its token's policy and the server's. A personal access token has no policy of its own: it is checked against the workspace-user sign-in policy of the environment it belongs to. Sign-in policies are checked when a workspace user signs in or switches account or environment, and when an end user signs in to an MCP server.\n\nA refused call gets HTTP 403 with `{\"errors\": [{\"code\": \"access_denied\", \"message\": \"Access denied.\"}]}` and nothing that names the policy or the address. An MCP server endpoint speaks JSON-RPC, so its 403 carries the MCP server's access-denied error (`-32006`) in a JSON-RPC envelope instead — `{\"jsonrpc\": \"2.0\", \"error\": {\"code\": -32006, \"message\": \"Access denied.\"}, \"id\": <request id>}`, with `id` echoed when the request had one — and the server's request log records the call as blocked.\n\n## Network policy schema\n\n{% openapi-schemas spec=\"networkpolicy\" schemas=\"NetworkPolicy\" grouped=\"true\" %}"}],"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"},{"url":"https://api.au.integrator.io","description":"Production (AU region)"},{"url":"https://api.ca.integrator.io","description":"Production (CA region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"parameters":{"After":{"name":"after","in":"query","required":false,"description":"Opaque cursor for forward pagination. Pass the value from the `Link`\nresponse header (`rel=\"next\"`) to fetch the next page.","schema":{"type":"string"}}},"schemas":{"NetworkPolicy":{"type":"object","description":"Network policy as returned by the API.","required":["_id","_userId","name","ipAllowList","ipDenyList","createdAt","lastModified"],"properties":{"_id":{"type":"string","format":"objectId","readOnly":true,"description":"Unique identifier for the network policy."},"_userId":{"type":"string","format":"objectId","readOnly":true,"description":"Environment that owns the policy — the account user for production, or the\nsandbox user for a policy created there. A policy is visible and assignable\nonly within its own environment."},"name":{"type":"string","maxLength":150,"description":"Display name shown wherever a policy is picked or listed. Unique among the\nenvironment's policies that are not in the recycle bin; on create, a name that\ndiffers only in case from a live policy's is accepted."},"description":{"type":"string","maxLength":500,"description":"Explains what the policy is for. Absent when the policy has no description."},"ipAllowList":{"type":"array","maxItems":200,"description":"Source addresses permitted to connect, each an IPv4 or IPv6 address or CIDR\nrange in stored form (bare addresses carry `/32` or `/128`). An empty list\npermits every address that `ipDenyList` does not block.","items":{"type":"string"}},"ipDenyList":{"type":"array","maxItems":200,"description":"Source addresses refused even when `ipAllowList` permits them. Same entry\nformat and stored form as `ipAllowList`; deny always wins over allow.","items":{"type":"string"}},"createdAt":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp when the policy was created."},"lastModified":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp when the policy was last modified. Updated on every PUT and PATCH that changes a field."}}},"Error":{"type":"object","description":"Standard error response envelope returned by integrator.io APIs.","properties":{"errors":{"type":"array","description":"List of errors that occurred while processing the request.","items":{"type":"object","properties":{"code":{"oneOf":[{"type":"string"},{"type":"integer"}],"description":"Machine-readable error code. Usually a string like\n`invalid_ref`, `missing_required_field`, or `unauthorized`;\nmay be an **integer** when the error mirrors an upstream HTTP\nstatus (e.g. `500`) — most commonly returned by connection-ping\nand adaptor-proxy responses."},"message":{"type":"string","description":"Human-readable description of the error."},"field":{"type":"string","description":"Optional pointer to the document field that caused the error.\nUsed by structural validation errors (`missing_required_field`,\n`invalid_ref`) to indicate which field is at fault\n(e.g. `_id`, `type`, `http.baseURI`)."},"source":{"type":"string","description":"Optional origin layer for the error — e.g. `application` when\nthe error came from the remote system the adaptor called,\n`connector` when the adaptor itself rejected the request."}},"required":["message"]}}},"required":["errors"]}},"responses":{"400-bad-request":{"description":"Bad request. The server could not understand the request because of malformed syntax or invalid parameters.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401-unauthorized":{"description":"Unauthorized. The request lacks a valid bearer token, or the provided token\nfailed to authenticate.\n\nNote: the 401 response is produced by the auth middleware **before** the\nrequest reaches the endpoint handler, so it does **not** follow the\nstandard `{errors: [...]}` envelope. Instead the body is a bare\n`{message: string}` object with no `code`, no `errors` array. Callers\nhandling 401s should key off the HTTP status and the `message` string,\nnot try to destructure an `errors[]`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable description of the auth failure. Known values:\n- `\"Unauthorized\"` — no `Authorization` header on the request.\n- `\"Bearer Authentication Failed\"` — header present but token\n  is invalid, revoked, or expired."}},"required":["message"]}}}},"422-unprocessable-entity":{"description":"Unprocessable entity. The request was well-formed but was unable to be followed due to semantic errors.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/networkpolicies":{"get":{"summary":"List network policies","description":"Returns the policies of the caller's environment, most recently modified first.\nPolicies in the recycle bin are not included. The `include` and `exclude`\nprojection parameters used by other list endpoints are not supported here.","operationId":"listNetworkPolicies","tags":["Network Policies"],"parameters":[{"name":"limit","in":"query","required":false,"description":"Maximum number of policies to return per page.","schema":{"type":"integer","minimum":1,"maximum":1000}},{"name":"sort_by","in":"query","required":false,"description":"Field to order the page by. `lastModified` lists the most recently changed\npolicy first; `name` lists alphabetically.","schema":{"type":"string","enum":["lastModified","name"]}},{"$ref":"#/components/parameters/After"}],"responses":{"200":{"description":"Array of network policies.","headers":{"Link":{"description":"RFC 5988 pagination links. When more pages remain, includes a\n`<...>; rel=\"next\"` entry with an `after` cursor; absent on the\nfinal page.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/NetworkPolicy"}}}}},"204":{"description":"No network policies exist in this environment."},"400":{"$ref":"#/components/responses/400-bad-request"},"401":{"$ref":"#/components/responses/401-unauthorized"},"422":{"$ref":"#/components/responses/422-unprocessable-entity"}}}}}}
```

## Create a network policy

> Creates a policy in the caller's environment. Entries in both lists are\
> validated and stored in normalized form — a bare address becomes \`/32\` or\
> \`/128\`, IPv6 is compressed — and the response shows the stored values. The new\
> policy restricts nothing until it is assigned to an API token, an MCP server,\
> or account sign-in.

```json
{"openapi":"3.2.0","info":{"title":"Network Policies","version":"1.0.0"},"tags":[{"name":"Network Policies","description":"Network policies are named IP allow and deny lists that control where API tokens, MCP servers, and users may connect from. A policy takes effect only once it is assigned — through `_networkPolicyId` on an API token or MCP server, or in account settings for workspace-user and end-user sign-in — and each environment (production or sandbox) keeps its own library of policies. Network policies must be enabled for the account, and only the account owner and administrators can manage them.\n\nEvery policy that applies to a call must admit the caller. An API token's policy is checked when the token authenticates, before the request runs; an MCP server's policy is checked on every request to it, so a call to an MCP server passes both its token's policy and the server's. A personal access token has no policy of its own: it is checked against the workspace-user sign-in policy of the environment it belongs to. Sign-in policies are checked when a workspace user signs in or switches account or environment, and when an end user signs in to an MCP server.\n\nA refused call gets HTTP 403 with `{\"errors\": [{\"code\": \"access_denied\", \"message\": \"Access denied.\"}]}` and nothing that names the policy or the address. An MCP server endpoint speaks JSON-RPC, so its 403 carries the MCP server's access-denied error (`-32006`) in a JSON-RPC envelope instead — `{\"jsonrpc\": \"2.0\", \"error\": {\"code\": -32006, \"message\": \"Access denied.\"}, \"id\": <request id>}`, with `id` echoed when the request had one — and the server's request log records the call as blocked.\n\n## Network policy schema\n\n{% openapi-schemas spec=\"networkpolicy\" schemas=\"NetworkPolicy\" grouped=\"true\" %}"}],"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"},{"url":"https://api.au.integrator.io","description":"Production (AU region)"},{"url":"https://api.ca.integrator.io","description":"Production (CA region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{"Request":{"type":"object","description":"Request body for creating or replacing a network policy.","required":["name"],"properties":{"name":{"type":"string","maxLength":150,"description":"Display name shown wherever a policy is picked or listed. Unique among the\nenvironment's policies that are not in the recycle bin; on create, a name that\ndiffers only in case from a live policy's is accepted."},"description":{"type":"string","maxLength":500,"description":"Explains what the policy is for and where its ranges come from. Omit on PUT to clear it."},"ipAllowList":{"type":"array","maxItems":200,"description":"Source addresses permitted to connect. Each entry is an IPv4 or IPv6 address\nor CIDR range; bare addresses are stored as `/32` or `/128`. Leave empty to\npermit every address that `ipDenyList` does not block. Omitting the field on\nPUT empties the list.","items":{"type":"string"}},"ipDenyList":{"type":"array","maxItems":200,"description":"Source addresses refused even when `ipAllowList` permits them. Same entry\nformat as `ipAllowList`; deny always wins over allow. Omitting the field on\nPUT empties the list.","items":{"type":"string"}}}},"NetworkPolicy":{"type":"object","description":"Network policy as returned by the API.","required":["_id","_userId","name","ipAllowList","ipDenyList","createdAt","lastModified"],"properties":{"_id":{"type":"string","format":"objectId","readOnly":true,"description":"Unique identifier for the network policy."},"_userId":{"type":"string","format":"objectId","readOnly":true,"description":"Environment that owns the policy — the account user for production, or the\nsandbox user for a policy created there. A policy is visible and assignable\nonly within its own environment."},"name":{"type":"string","maxLength":150,"description":"Display name shown wherever a policy is picked or listed. Unique among the\nenvironment's policies that are not in the recycle bin; on create, a name that\ndiffers only in case from a live policy's is accepted."},"description":{"type":"string","maxLength":500,"description":"Explains what the policy is for. Absent when the policy has no description."},"ipAllowList":{"type":"array","maxItems":200,"description":"Source addresses permitted to connect, each an IPv4 or IPv6 address or CIDR\nrange in stored form (bare addresses carry `/32` or `/128`). An empty list\npermits every address that `ipDenyList` does not block.","items":{"type":"string"}},"ipDenyList":{"type":"array","maxItems":200,"description":"Source addresses refused even when `ipAllowList` permits them. Same entry\nformat and stored form as `ipAllowList`; deny always wins over allow.","items":{"type":"string"}},"createdAt":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp when the policy was created."},"lastModified":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp when the policy was last modified. Updated on every PUT and PATCH that changes a field."}}},"Error":{"type":"object","description":"Standard error response envelope returned by integrator.io APIs.","properties":{"errors":{"type":"array","description":"List of errors that occurred while processing the request.","items":{"type":"object","properties":{"code":{"oneOf":[{"type":"string"},{"type":"integer"}],"description":"Machine-readable error code. Usually a string like\n`invalid_ref`, `missing_required_field`, or `unauthorized`;\nmay be an **integer** when the error mirrors an upstream HTTP\nstatus (e.g. `500`) — most commonly returned by connection-ping\nand adaptor-proxy responses."},"message":{"type":"string","description":"Human-readable description of the error."},"field":{"type":"string","description":"Optional pointer to the document field that caused the error.\nUsed by structural validation errors (`missing_required_field`,\n`invalid_ref`) to indicate which field is at fault\n(e.g. `_id`, `type`, `http.baseURI`)."},"source":{"type":"string","description":"Optional origin layer for the error — e.g. `application` when\nthe error came from the remote system the adaptor called,\n`connector` when the adaptor itself rejected the request."}},"required":["message"]}}},"required":["errors"]}},"responses":{"400-bad-request":{"description":"Bad request. The server could not understand the request because of malformed syntax or invalid parameters.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401-unauthorized":{"description":"Unauthorized. The request lacks a valid bearer token, or the provided token\nfailed to authenticate.\n\nNote: the 401 response is produced by the auth middleware **before** the\nrequest reaches the endpoint handler, so it does **not** follow the\nstandard `{errors: [...]}` envelope. Instead the body is a bare\n`{message: string}` object with no `code`, no `errors` array. Callers\nhandling 401s should key off the HTTP status and the `message` string,\nnot try to destructure an `errors[]`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable description of the auth failure. Known values:\n- `\"Unauthorized\"` — no `Authorization` header on the request.\n- `\"Bearer Authentication Failed\"` — header present but token\n  is invalid, revoked, or expired."}},"required":["message"]}}}},"409-name-conflict":{"description":"Conflict. Another policy in this environment that is not in the recycle bin\nalready uses the requested `name`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422-unprocessable-entity":{"description":"Unprocessable entity. The request was well-formed but was unable to be followed due to semantic errors.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/networkpolicies":{"post":{"summary":"Create a network policy","description":"Creates a policy in the caller's environment. Entries in both lists are\nvalidated and stored in normalized form — a bare address becomes `/32` or\n`/128`, IPv6 is compressed — and the response shows the stored values. The new\npolicy restricts nothing until it is assigned to an API token, an MCP server,\nor account sign-in.","operationId":"createNetworkPolicy","tags":["Network Policies"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Request"}}}},"responses":{"201":{"description":"Created network policy, with entries in stored form.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NetworkPolicy"}}}},"400":{"$ref":"#/components/responses/400-bad-request"},"401":{"$ref":"#/components/responses/401-unauthorized"},"409":{"$ref":"#/components/responses/409-name-conflict"},"422":{"$ref":"#/components/responses/422-unprocessable-entity"}}}}}}
```

## Get a network policy

> Returns a single policy from the caller's environment. A policy that has been\
> moved to the recycle bin, or that belongs to another environment, returns 404.

```json
{"openapi":"3.2.0","info":{"title":"Network Policies","version":"1.0.0"},"tags":[{"name":"Network Policies","description":"Network policies are named IP allow and deny lists that control where API tokens, MCP servers, and users may connect from. A policy takes effect only once it is assigned — through `_networkPolicyId` on an API token or MCP server, or in account settings for workspace-user and end-user sign-in — and each environment (production or sandbox) keeps its own library of policies. Network policies must be enabled for the account, and only the account owner and administrators can manage them.\n\nEvery policy that applies to a call must admit the caller. An API token's policy is checked when the token authenticates, before the request runs; an MCP server's policy is checked on every request to it, so a call to an MCP server passes both its token's policy and the server's. A personal access token has no policy of its own: it is checked against the workspace-user sign-in policy of the environment it belongs to. Sign-in policies are checked when a workspace user signs in or switches account or environment, and when an end user signs in to an MCP server.\n\nA refused call gets HTTP 403 with `{\"errors\": [{\"code\": \"access_denied\", \"message\": \"Access denied.\"}]}` and nothing that names the policy or the address. An MCP server endpoint speaks JSON-RPC, so its 403 carries the MCP server's access-denied error (`-32006`) in a JSON-RPC envelope instead — `{\"jsonrpc\": \"2.0\", \"error\": {\"code\": -32006, \"message\": \"Access denied.\"}, \"id\": <request id>}`, with `id` echoed when the request had one — and the server's request log records the call as blocked.\n\n## Network policy schema\n\n{% openapi-schemas spec=\"networkpolicy\" schemas=\"NetworkPolicy\" grouped=\"true\" %}"}],"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"},{"url":"https://api.au.integrator.io","description":"Production (AU region)"},{"url":"https://api.ca.integrator.io","description":"Production (CA region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{"NetworkPolicy":{"type":"object","description":"Network policy as returned by the API.","required":["_id","_userId","name","ipAllowList","ipDenyList","createdAt","lastModified"],"properties":{"_id":{"type":"string","format":"objectId","readOnly":true,"description":"Unique identifier for the network policy."},"_userId":{"type":"string","format":"objectId","readOnly":true,"description":"Environment that owns the policy — the account user for production, or the\nsandbox user for a policy created there. A policy is visible and assignable\nonly within its own environment."},"name":{"type":"string","maxLength":150,"description":"Display name shown wherever a policy is picked or listed. Unique among the\nenvironment's policies that are not in the recycle bin; on create, a name that\ndiffers only in case from a live policy's is accepted."},"description":{"type":"string","maxLength":500,"description":"Explains what the policy is for. Absent when the policy has no description."},"ipAllowList":{"type":"array","maxItems":200,"description":"Source addresses permitted to connect, each an IPv4 or IPv6 address or CIDR\nrange in stored form (bare addresses carry `/32` or `/128`). An empty list\npermits every address that `ipDenyList` does not block.","items":{"type":"string"}},"ipDenyList":{"type":"array","maxItems":200,"description":"Source addresses refused even when `ipAllowList` permits them. Same entry\nformat and stored form as `ipAllowList`; deny always wins over allow.","items":{"type":"string"}},"createdAt":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp when the policy was created."},"lastModified":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp when the policy was last modified. Updated on every PUT and PATCH that changes a field."}}},"Error":{"type":"object","description":"Standard error response envelope returned by integrator.io APIs.","properties":{"errors":{"type":"array","description":"List of errors that occurred while processing the request.","items":{"type":"object","properties":{"code":{"oneOf":[{"type":"string"},{"type":"integer"}],"description":"Machine-readable error code. Usually a string like\n`invalid_ref`, `missing_required_field`, or `unauthorized`;\nmay be an **integer** when the error mirrors an upstream HTTP\nstatus (e.g. `500`) — most commonly returned by connection-ping\nand adaptor-proxy responses."},"message":{"type":"string","description":"Human-readable description of the error."},"field":{"type":"string","description":"Optional pointer to the document field that caused the error.\nUsed by structural validation errors (`missing_required_field`,\n`invalid_ref`) to indicate which field is at fault\n(e.g. `_id`, `type`, `http.baseURI`)."},"source":{"type":"string","description":"Optional origin layer for the error — e.g. `application` when\nthe error came from the remote system the adaptor called,\n`connector` when the adaptor itself rejected the request."}},"required":["message"]}}},"required":["errors"]}},"responses":{"401-unauthorized":{"description":"Unauthorized. The request lacks a valid bearer token, or the provided token\nfailed to authenticate.\n\nNote: the 401 response is produced by the auth middleware **before** the\nrequest reaches the endpoint handler, so it does **not** follow the\nstandard `{errors: [...]}` envelope. Instead the body is a bare\n`{message: string}` object with no `code`, no `errors` array. Callers\nhandling 401s should key off the HTTP status and the `message` string,\nnot try to destructure an `errors[]`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable description of the auth failure. Known values:\n- `\"Unauthorized\"` — no `Authorization` header on the request.\n- `\"Bearer Authentication Failed\"` — header present but token\n  is invalid, revoked, or expired."}},"required":["message"]}}}},"404-not-found":{"description":"Not found. The requested resource does not exist or is not visible to the caller.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/networkpolicies/{_id}":{"get":{"summary":"Get a network policy","description":"Returns a single policy from the caller's environment. A policy that has been\nmoved to the recycle bin, or that belongs to another environment, returns 404.","operationId":"getNetworkPolicyById","tags":["Network Policies"],"parameters":[{"name":"_id","in":"path","required":true,"description":"Network policy ID.","schema":{"type":"string","format":"objectId"}}],"responses":{"200":{"description":"Network policy.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NetworkPolicy"}}}},"401":{"$ref":"#/components/responses/401-unauthorized"},"404":{"$ref":"#/components/responses/404-not-found"}}}}}}
```

## Replace a network policy

> Replaces the policy with the request body. Fields left out are cleared: an\
> omitted \`description\` is removed and an omitted \`ipAllowList\` or \`ipDenyList\`\
> becomes empty, which lifts every restriction that list imposed. Entries are\
> validated and normalized exactly as on create. The change applies to every\
> token, MCP server, and sign-in setting the policy is assigned to.

```json
{"openapi":"3.2.0","info":{"title":"Network Policies","version":"1.0.0"},"tags":[{"name":"Network Policies","description":"Network policies are named IP allow and deny lists that control where API tokens, MCP servers, and users may connect from. A policy takes effect only once it is assigned — through `_networkPolicyId` on an API token or MCP server, or in account settings for workspace-user and end-user sign-in — and each environment (production or sandbox) keeps its own library of policies. Network policies must be enabled for the account, and only the account owner and administrators can manage them.\n\nEvery policy that applies to a call must admit the caller. An API token's policy is checked when the token authenticates, before the request runs; an MCP server's policy is checked on every request to it, so a call to an MCP server passes both its token's policy and the server's. A personal access token has no policy of its own: it is checked against the workspace-user sign-in policy of the environment it belongs to. Sign-in policies are checked when a workspace user signs in or switches account or environment, and when an end user signs in to an MCP server.\n\nA refused call gets HTTP 403 with `{\"errors\": [{\"code\": \"access_denied\", \"message\": \"Access denied.\"}]}` and nothing that names the policy or the address. An MCP server endpoint speaks JSON-RPC, so its 403 carries the MCP server's access-denied error (`-32006`) in a JSON-RPC envelope instead — `{\"jsonrpc\": \"2.0\", \"error\": {\"code\": -32006, \"message\": \"Access denied.\"}, \"id\": <request id>}`, with `id` echoed when the request had one — and the server's request log records the call as blocked.\n\n## Network policy schema\n\n{% openapi-schemas spec=\"networkpolicy\" schemas=\"NetworkPolicy\" grouped=\"true\" %}"}],"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"},{"url":"https://api.au.integrator.io","description":"Production (AU region)"},{"url":"https://api.ca.integrator.io","description":"Production (CA region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{"Request":{"type":"object","description":"Request body for creating or replacing a network policy.","required":["name"],"properties":{"name":{"type":"string","maxLength":150,"description":"Display name shown wherever a policy is picked or listed. Unique among the\nenvironment's policies that are not in the recycle bin; on create, a name that\ndiffers only in case from a live policy's is accepted."},"description":{"type":"string","maxLength":500,"description":"Explains what the policy is for and where its ranges come from. Omit on PUT to clear it."},"ipAllowList":{"type":"array","maxItems":200,"description":"Source addresses permitted to connect. Each entry is an IPv4 or IPv6 address\nor CIDR range; bare addresses are stored as `/32` or `/128`. Leave empty to\npermit every address that `ipDenyList` does not block. Omitting the field on\nPUT empties the list.","items":{"type":"string"}},"ipDenyList":{"type":"array","maxItems":200,"description":"Source addresses refused even when `ipAllowList` permits them. Same entry\nformat as `ipAllowList`; deny always wins over allow. Omitting the field on\nPUT empties the list.","items":{"type":"string"}}}},"NetworkPolicy":{"type":"object","description":"Network policy as returned by the API.","required":["_id","_userId","name","ipAllowList","ipDenyList","createdAt","lastModified"],"properties":{"_id":{"type":"string","format":"objectId","readOnly":true,"description":"Unique identifier for the network policy."},"_userId":{"type":"string","format":"objectId","readOnly":true,"description":"Environment that owns the policy — the account user for production, or the\nsandbox user for a policy created there. A policy is visible and assignable\nonly within its own environment."},"name":{"type":"string","maxLength":150,"description":"Display name shown wherever a policy is picked or listed. Unique among the\nenvironment's policies that are not in the recycle bin; on create, a name that\ndiffers only in case from a live policy's is accepted."},"description":{"type":"string","maxLength":500,"description":"Explains what the policy is for. Absent when the policy has no description."},"ipAllowList":{"type":"array","maxItems":200,"description":"Source addresses permitted to connect, each an IPv4 or IPv6 address or CIDR\nrange in stored form (bare addresses carry `/32` or `/128`). An empty list\npermits every address that `ipDenyList` does not block.","items":{"type":"string"}},"ipDenyList":{"type":"array","maxItems":200,"description":"Source addresses refused even when `ipAllowList` permits them. Same entry\nformat and stored form as `ipAllowList`; deny always wins over allow.","items":{"type":"string"}},"createdAt":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp when the policy was created."},"lastModified":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp when the policy was last modified. Updated on every PUT and PATCH that changes a field."}}},"Error":{"type":"object","description":"Standard error response envelope returned by integrator.io APIs.","properties":{"errors":{"type":"array","description":"List of errors that occurred while processing the request.","items":{"type":"object","properties":{"code":{"oneOf":[{"type":"string"},{"type":"integer"}],"description":"Machine-readable error code. Usually a string like\n`invalid_ref`, `missing_required_field`, or `unauthorized`;\nmay be an **integer** when the error mirrors an upstream HTTP\nstatus (e.g. `500`) — most commonly returned by connection-ping\nand adaptor-proxy responses."},"message":{"type":"string","description":"Human-readable description of the error."},"field":{"type":"string","description":"Optional pointer to the document field that caused the error.\nUsed by structural validation errors (`missing_required_field`,\n`invalid_ref`) to indicate which field is at fault\n(e.g. `_id`, `type`, `http.baseURI`)."},"source":{"type":"string","description":"Optional origin layer for the error — e.g. `application` when\nthe error came from the remote system the adaptor called,\n`connector` when the adaptor itself rejected the request."}},"required":["message"]}}},"required":["errors"]}},"responses":{"400-bad-request":{"description":"Bad request. The server could not understand the request because of malformed syntax or invalid parameters.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401-unauthorized":{"description":"Unauthorized. The request lacks a valid bearer token, or the provided token\nfailed to authenticate.\n\nNote: the 401 response is produced by the auth middleware **before** the\nrequest reaches the endpoint handler, so it does **not** follow the\nstandard `{errors: [...]}` envelope. Instead the body is a bare\n`{message: string}` object with no `code`, no `errors` array. Callers\nhandling 401s should key off the HTTP status and the `message` string,\nnot try to destructure an `errors[]`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable description of the auth failure. Known values:\n- `\"Unauthorized\"` — no `Authorization` header on the request.\n- `\"Bearer Authentication Failed\"` — header present but token\n  is invalid, revoked, or expired."}},"required":["message"]}}}},"404-not-found":{"description":"Not found. The requested resource does not exist or is not visible to the caller.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409-name-conflict":{"description":"Conflict. Another policy in this environment that is not in the recycle bin\nalready uses the requested `name`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422-unprocessable-entity":{"description":"Unprocessable entity. The request was well-formed but was unable to be followed due to semantic errors.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/networkpolicies/{_id}":{"put":{"summary":"Replace a network policy","description":"Replaces the policy with the request body. Fields left out are cleared: an\nomitted `description` is removed and an omitted `ipAllowList` or `ipDenyList`\nbecomes empty, which lifts every restriction that list imposed. Entries are\nvalidated and normalized exactly as on create. The change applies to every\ntoken, MCP server, and sign-in setting the policy is assigned to.","operationId":"updateNetworkPolicy","tags":["Network Policies"],"parameters":[{"name":"_id","in":"path","required":true,"description":"Network policy ID.","schema":{"type":"string","format":"objectId"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Request"}}}},"responses":{"200":{"description":"Updated network policy, with entries in stored form.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NetworkPolicy"}}}},"400":{"$ref":"#/components/responses/400-bad-request"},"401":{"$ref":"#/components/responses/401-unauthorized"},"404":{"$ref":"#/components/responses/404-not-found"},"409":{"$ref":"#/components/responses/409-name-conflict"},"422":{"$ref":"#/components/responses/422-unprocessable-entity"}}}}}}
```

## Delete a network policy

> Moves the policy to the recycle bin, where it is retained for 30 days and can\
> be restored. A policy that is still assigned to an API token, MCP server, or\
> account sign-in setting is not deleted: the request fails with 409\
> \`network\_policy\_in\_use\` and \`info\` lists every assignment. Repeat with\
> \`force=true\` to clear those assignments and delete the policy — every principal\
> it was assigned to loses the restriction. Use \`GET /v1/networkpolicies/{\_id}/dependencies\`\
> to review the assignments first.

```json
{"openapi":"3.2.0","info":{"title":"Network Policies","version":"1.0.0"},"tags":[{"name":"Network Policies","description":"Network policies are named IP allow and deny lists that control where API tokens, MCP servers, and users may connect from. A policy takes effect only once it is assigned — through `_networkPolicyId` on an API token or MCP server, or in account settings for workspace-user and end-user sign-in — and each environment (production or sandbox) keeps its own library of policies. Network policies must be enabled for the account, and only the account owner and administrators can manage them.\n\nEvery policy that applies to a call must admit the caller. An API token's policy is checked when the token authenticates, before the request runs; an MCP server's policy is checked on every request to it, so a call to an MCP server passes both its token's policy and the server's. A personal access token has no policy of its own: it is checked against the workspace-user sign-in policy of the environment it belongs to. Sign-in policies are checked when a workspace user signs in or switches account or environment, and when an end user signs in to an MCP server.\n\nA refused call gets HTTP 403 with `{\"errors\": [{\"code\": \"access_denied\", \"message\": \"Access denied.\"}]}` and nothing that names the policy or the address. An MCP server endpoint speaks JSON-RPC, so its 403 carries the MCP server's access-denied error (`-32006`) in a JSON-RPC envelope instead — `{\"jsonrpc\": \"2.0\", \"error\": {\"code\": -32006, \"message\": \"Access denied.\"}, \"id\": <request id>}`, with `id` echoed when the request had one — and the server's request log records the call as blocked.\n\n## Network policy schema\n\n{% openapi-schemas spec=\"networkpolicy\" schemas=\"NetworkPolicy\" grouped=\"true\" %}"}],"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"},{"url":"https://api.au.integrator.io","description":"Production (AU region)"},{"url":"https://api.ca.integrator.io","description":"Production (CA region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"responses":{"401-unauthorized":{"description":"Unauthorized. The request lacks a valid bearer token, or the provided token\nfailed to authenticate.\n\nNote: the 401 response is produced by the auth middleware **before** the\nrequest reaches the endpoint handler, so it does **not** follow the\nstandard `{errors: [...]}` envelope. Instead the body is a bare\n`{message: string}` object with no `code`, no `errors` array. Callers\nhandling 401s should key off the HTTP status and the `message` string,\nnot try to destructure an `errors[]`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable description of the auth failure. Known values:\n- `\"Unauthorized\"` — no `Authorization` header on the request.\n- `\"Bearer Authentication Failed\"` — header present but token\n  is invalid, revoked, or expired."}},"required":["message"]}}}},"404-not-found":{"description":"Not found. The requested resource does not exist or is not visible to the caller.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409-in-use":{"description":"Conflict. The policy is still assigned to at least one API token, MCP server, or\naccount sign-in setting, so it was not deleted. `info` lists every assignment;\nrepeat the request with `force=true` to clear them and delete the policy.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"info":{"$ref":"#/components/schemas/NetworkPolicyDependencies"}}}]}}}}},"schemas":{"Error":{"type":"object","description":"Standard error response envelope returned by integrator.io APIs.","properties":{"errors":{"type":"array","description":"List of errors that occurred while processing the request.","items":{"type":"object","properties":{"code":{"oneOf":[{"type":"string"},{"type":"integer"}],"description":"Machine-readable error code. Usually a string like\n`invalid_ref`, `missing_required_field`, or `unauthorized`;\nmay be an **integer** when the error mirrors an upstream HTTP\nstatus (e.g. `500`) — most commonly returned by connection-ping\nand adaptor-proxy responses."},"message":{"type":"string","description":"Human-readable description of the error."},"field":{"type":"string","description":"Optional pointer to the document field that caused the error.\nUsed by structural validation errors (`missing_required_field`,\n`invalid_ref`) to indicate which field is at fault\n(e.g. `_id`, `type`, `http.baseURI`)."},"source":{"type":"string","description":"Optional origin layer for the error — e.g. `application` when\nthe error came from the remote system the adaptor called,\n`connector` when the adaptor itself rejected the request."}},"required":["message"]}}},"required":["errors"]},"NetworkPolicyDependencies":{"type":"object","description":"Every place a network policy is assigned within its own environment. All four\nkeys are always present; an unassigned policy returns empty arrays and `false`\nflags.","required":["mcpservers","accesstokens","account"],"properties":{"mcpservers":{"type":"array","description":"MCP servers whose `_networkPolicyId` is this policy.","items":{"$ref":"#/components/schemas/NetworkPolicyDependencyRef"}},"accesstokens":{"type":"array","description":"API tokens whose `_networkPolicyId` is this policy. Personal access tokens never appear here; they inherit the account's workspace-user policy instead.","items":{"$ref":"#/components/schemas/NetworkPolicyDependencyRef"}},"account":{"type":"object","description":"Account sign-in assignments of this policy, resolved per environment.","required":["workspaceUsers","workspaceUserEnvironments","endUsers","endUserEnvironments"],"properties":{"workspaceUsers":{"type":"boolean","description":"When true, the policy restricts workspace-user sign-in in at least one environment listed in `workspaceUserEnvironments`."},"workspaceUserEnvironments":{"type":"array","description":"Environments whose workspace-user sign-in this policy restricts. Empty when `workspaceUsers` is false.","items":{"$ref":"#/components/schemas/NetworkPolicyEnvironmentRef"}},"endUsers":{"type":"boolean","description":"When true, the policy restricts end-user sign-in in at least one environment listed in `endUserEnvironments`."},"endUserEnvironments":{"type":"array","description":"Environments whose end-user sign-in this policy restricts. Empty when `endUsers` is false.","items":{"$ref":"#/components/schemas/NetworkPolicyEnvironmentRef"}}}}}},"NetworkPolicyDependencyRef":{"type":"object","description":"A resource the policy is assigned to.","required":["_id","name"],"properties":{"_id":{"type":"string","format":"objectId","description":"Identifier of the assigned resource; use it with the resource's own `GET /v1/<type>/{_id}` endpoint."},"name":{"type":"string","description":"Display name of the assigned resource at the time of the request."}}},"NetworkPolicyEnvironmentRef":{"type":"object","description":"An environment whose sign-in the policy restricts.","required":["_envUserId","name"],"properties":{"_envUserId":{"type":"string","format":"objectId","description":"Account user that represents the environment holding the assignment."},"name":{"type":["string","null"],"description":"Environment name. Null when the environment has no name record, in which case identify it by `_envUserId`."}}}}},"paths":{"/v1/networkpolicies/{_id}":{"delete":{"summary":"Delete a network policy","description":"Moves the policy to the recycle bin, where it is retained for 30 days and can\nbe restored. A policy that is still assigned to an API token, MCP server, or\naccount sign-in setting is not deleted: the request fails with 409\n`network_policy_in_use` and `info` lists every assignment. Repeat with\n`force=true` to clear those assignments and delete the policy — every principal\nit was assigned to loses the restriction. Use `GET /v1/networkpolicies/{_id}/dependencies`\nto review the assignments first.","operationId":"deleteNetworkPolicy","tags":["Network Policies"],"parameters":[{"name":"_id","in":"path","required":true,"description":"Network policy ID.","schema":{"type":"string","format":"objectId"}},{"name":"force","in":"query","required":false,"description":"When true, clears the policy from every API token, MCP server, and account\nsign-in setting it is assigned to, then deletes it. Without it, an assigned\npolicy returns 409 and nothing changes.","schema":{"type":"boolean","default":false}}],"responses":{"204":{"description":"Network policy moved to the recycle bin."},"401":{"$ref":"#/components/responses/401-unauthorized"},"404":{"$ref":"#/components/responses/404-not-found"},"409":{"$ref":"#/components/responses/409-in-use"}}}}}}
```

## Patch a network policy

> Partially updates a policy with a JSON Patch document (RFC 6902). Fields the\
> document does not touch are preserved, unlike PUT. Whitelisted paths:\
> \
> \| Path | Operations |\
> \|------|------------|\
> \| \`/name\` | \`add\`, \`replace\` |\
> \| \`/description\` | \`add\`, \`replace\`, \`remove\` |\
> \| \`/ipAllowList\`, \`/ipDenyList\` | \`replace\` the whole list |\
> \| \`/ipAllowList/-\`, \`/ipDenyList/-\` | \`add\` one entry at the end |\
> \| \`/ipAllowList/{index}\`, \`/ipDenyList/{index}\` | \`add\` or \`replace\` one entry |\
> \
> Entries are validated and normalized exactly as on create. \`move\`, \`copy\`, and\
> \`test\` on \`/name\` or either list return 400 \`invalid\_patch\_operation\`; removing\
> a single list entry by index is not supported (422) — \`replace\` the whole list\
> instead. Any other path returns 422.

```json
{"openapi":"3.2.0","info":{"title":"Network Policies","version":"1.0.0"},"tags":[{"name":"Network Policies","description":"Network policies are named IP allow and deny lists that control where API tokens, MCP servers, and users may connect from. A policy takes effect only once it is assigned — through `_networkPolicyId` on an API token or MCP server, or in account settings for workspace-user and end-user sign-in — and each environment (production or sandbox) keeps its own library of policies. Network policies must be enabled for the account, and only the account owner and administrators can manage them.\n\nEvery policy that applies to a call must admit the caller. An API token's policy is checked when the token authenticates, before the request runs; an MCP server's policy is checked on every request to it, so a call to an MCP server passes both its token's policy and the server's. A personal access token has no policy of its own: it is checked against the workspace-user sign-in policy of the environment it belongs to. Sign-in policies are checked when a workspace user signs in or switches account or environment, and when an end user signs in to an MCP server.\n\nA refused call gets HTTP 403 with `{\"errors\": [{\"code\": \"access_denied\", \"message\": \"Access denied.\"}]}` and nothing that names the policy or the address. An MCP server endpoint speaks JSON-RPC, so its 403 carries the MCP server's access-denied error (`-32006`) in a JSON-RPC envelope instead — `{\"jsonrpc\": \"2.0\", \"error\": {\"code\": -32006, \"message\": \"Access denied.\"}, \"id\": <request id>}`, with `id` echoed when the request had one — and the server's request log records the call as blocked.\n\n## Network policy schema\n\n{% openapi-schemas spec=\"networkpolicy\" schemas=\"NetworkPolicy\" grouped=\"true\" %}"}],"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"},{"url":"https://api.au.integrator.io","description":"Production (AU region)"},{"url":"https://api.ca.integrator.io","description":"Production (CA region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{"JsonPatchRequest":{"type":"array","description":"A JSON Patch document (RFC 6902). Send an array of patch\noperations on whitelisted fields — all other paths are rejected\nwith 422.","minItems":1,"items":{"$ref":"#/components/schemas/JsonPatchOperation"}},"JsonPatchOperation":{"type":"object","description":"A single JSON Patch operation (RFC 6902).","required":["op","path"],"properties":{"op":{"type":"string","enum":["replace","add","remove"],"description":"The operation to perform."},"path":{"type":"string","description":"JSON Pointer (RFC 6901) to the field to patch. Only\nwhitelisted paths are accepted — unlisted paths return\n`422` with `\"<path> is not a whitelisted property\"`."},"value":{"description":"The new value to set. Required for `replace` and `add`, omit for `remove`."}}},"Error":{"type":"object","description":"Standard error response envelope returned by integrator.io APIs.","properties":{"errors":{"type":"array","description":"List of errors that occurred while processing the request.","items":{"type":"object","properties":{"code":{"oneOf":[{"type":"string"},{"type":"integer"}],"description":"Machine-readable error code. Usually a string like\n`invalid_ref`, `missing_required_field`, or `unauthorized`;\nmay be an **integer** when the error mirrors an upstream HTTP\nstatus (e.g. `500`) — most commonly returned by connection-ping\nand adaptor-proxy responses."},"message":{"type":"string","description":"Human-readable description of the error."},"field":{"type":"string","description":"Optional pointer to the document field that caused the error.\nUsed by structural validation errors (`missing_required_field`,\n`invalid_ref`) to indicate which field is at fault\n(e.g. `_id`, `type`, `http.baseURI`)."},"source":{"type":"string","description":"Optional origin layer for the error — e.g. `application` when\nthe error came from the remote system the adaptor called,\n`connector` when the adaptor itself rejected the request."}},"required":["message"]}}},"required":["errors"]}},"responses":{"400-bad-request":{"description":"Bad request. The server could not understand the request because of malformed syntax or invalid parameters.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401-unauthorized":{"description":"Unauthorized. The request lacks a valid bearer token, or the provided token\nfailed to authenticate.\n\nNote: the 401 response is produced by the auth middleware **before** the\nrequest reaches the endpoint handler, so it does **not** follow the\nstandard `{errors: [...]}` envelope. Instead the body is a bare\n`{message: string}` object with no `code`, no `errors` array. Callers\nhandling 401s should key off the HTTP status and the `message` string,\nnot try to destructure an `errors[]`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable description of the auth failure. Known values:\n- `\"Unauthorized\"` — no `Authorization` header on the request.\n- `\"Bearer Authentication Failed\"` — header present but token\n  is invalid, revoked, or expired."}},"required":["message"]}}}},"404-not-found":{"description":"Not found. The requested resource does not exist or is not visible to the caller.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409-name-conflict":{"description":"Conflict. Another policy in this environment that is not in the recycle bin\nalready uses the requested `name`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422-unprocessable-entity":{"description":"Unprocessable entity. The request was well-formed but was unable to be followed due to semantic errors.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/networkpolicies/{_id}":{"patch":{"summary":"Patch a network policy","description":"Partially updates a policy with a JSON Patch document (RFC 6902). Fields the\ndocument does not touch are preserved, unlike PUT. Whitelisted paths:\n\n| Path | Operations |\n|------|------------|\n| `/name` | `add`, `replace` |\n| `/description` | `add`, `replace`, `remove` |\n| `/ipAllowList`, `/ipDenyList` | `replace` the whole list |\n| `/ipAllowList/-`, `/ipDenyList/-` | `add` one entry at the end |\n| `/ipAllowList/{index}`, `/ipDenyList/{index}` | `add` or `replace` one entry |\n\nEntries are validated and normalized exactly as on create. `move`, `copy`, and\n`test` on `/name` or either list return 400 `invalid_patch_operation`; removing\na single list entry by index is not supported (422) — `replace` the whole list\ninstead. Any other path returns 422.","operationId":"patchNetworkPolicy","tags":["Network Policies"],"parameters":[{"name":"_id","in":"path","required":true,"description":"Network policy ID.","schema":{"type":"string","format":"objectId"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonPatchRequest"}}}},"responses":{"204":{"description":"Network policy patched."},"400":{"$ref":"#/components/responses/400-bad-request"},"401":{"$ref":"#/components/responses/401-unauthorized"},"404":{"$ref":"#/components/responses/404-not-found"},"409":{"$ref":"#/components/responses/409-name-conflict"},"422":{"$ref":"#/components/responses/422-unprocessable-entity"}}}}}}
```

## List assignments of a network policy

> Returns every API token, MCP server, and account sign-in setting the policy is\
> assigned to within its own environment. Call it before \`DELETE\` to see what a\
> \`force=true\` delete would clear. Unlike other \`/dependencies\` endpoints, the\
> response is a fixed object rather than a map keyed by resource type.

```json
{"openapi":"3.2.0","info":{"title":"Network Policies","version":"1.0.0"},"tags":[{"name":"Network Policies","description":"Network policies are named IP allow and deny lists that control where API tokens, MCP servers, and users may connect from. A policy takes effect only once it is assigned — through `_networkPolicyId` on an API token or MCP server, or in account settings for workspace-user and end-user sign-in — and each environment (production or sandbox) keeps its own library of policies. Network policies must be enabled for the account, and only the account owner and administrators can manage them.\n\nEvery policy that applies to a call must admit the caller. An API token's policy is checked when the token authenticates, before the request runs; an MCP server's policy is checked on every request to it, so a call to an MCP server passes both its token's policy and the server's. A personal access token has no policy of its own: it is checked against the workspace-user sign-in policy of the environment it belongs to. Sign-in policies are checked when a workspace user signs in or switches account or environment, and when an end user signs in to an MCP server.\n\nA refused call gets HTTP 403 with `{\"errors\": [{\"code\": \"access_denied\", \"message\": \"Access denied.\"}]}` and nothing that names the policy or the address. An MCP server endpoint speaks JSON-RPC, so its 403 carries the MCP server's access-denied error (`-32006`) in a JSON-RPC envelope instead — `{\"jsonrpc\": \"2.0\", \"error\": {\"code\": -32006, \"message\": \"Access denied.\"}, \"id\": <request id>}`, with `id` echoed when the request had one — and the server's request log records the call as blocked.\n\n## Network policy schema\n\n{% openapi-schemas spec=\"networkpolicy\" schemas=\"NetworkPolicy\" grouped=\"true\" %}"}],"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"},{"url":"https://api.au.integrator.io","description":"Production (AU region)"},{"url":"https://api.ca.integrator.io","description":"Production (CA region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{"NetworkPolicyDependencies":{"type":"object","description":"Every place a network policy is assigned within its own environment. All four\nkeys are always present; an unassigned policy returns empty arrays and `false`\nflags.","required":["mcpservers","accesstokens","account"],"properties":{"mcpservers":{"type":"array","description":"MCP servers whose `_networkPolicyId` is this policy.","items":{"$ref":"#/components/schemas/NetworkPolicyDependencyRef"}},"accesstokens":{"type":"array","description":"API tokens whose `_networkPolicyId` is this policy. Personal access tokens never appear here; they inherit the account's workspace-user policy instead.","items":{"$ref":"#/components/schemas/NetworkPolicyDependencyRef"}},"account":{"type":"object","description":"Account sign-in assignments of this policy, resolved per environment.","required":["workspaceUsers","workspaceUserEnvironments","endUsers","endUserEnvironments"],"properties":{"workspaceUsers":{"type":"boolean","description":"When true, the policy restricts workspace-user sign-in in at least one environment listed in `workspaceUserEnvironments`."},"workspaceUserEnvironments":{"type":"array","description":"Environments whose workspace-user sign-in this policy restricts. Empty when `workspaceUsers` is false.","items":{"$ref":"#/components/schemas/NetworkPolicyEnvironmentRef"}},"endUsers":{"type":"boolean","description":"When true, the policy restricts end-user sign-in in at least one environment listed in `endUserEnvironments`."},"endUserEnvironments":{"type":"array","description":"Environments whose end-user sign-in this policy restricts. Empty when `endUsers` is false.","items":{"$ref":"#/components/schemas/NetworkPolicyEnvironmentRef"}}}}}},"NetworkPolicyDependencyRef":{"type":"object","description":"A resource the policy is assigned to.","required":["_id","name"],"properties":{"_id":{"type":"string","format":"objectId","description":"Identifier of the assigned resource; use it with the resource's own `GET /v1/<type>/{_id}` endpoint."},"name":{"type":"string","description":"Display name of the assigned resource at the time of the request."}}},"NetworkPolicyEnvironmentRef":{"type":"object","description":"An environment whose sign-in the policy restricts.","required":["_envUserId","name"],"properties":{"_envUserId":{"type":"string","format":"objectId","description":"Account user that represents the environment holding the assignment."},"name":{"type":["string","null"],"description":"Environment name. Null when the environment has no name record, in which case identify it by `_envUserId`."}}},"Error":{"type":"object","description":"Standard error response envelope returned by integrator.io APIs.","properties":{"errors":{"type":"array","description":"List of errors that occurred while processing the request.","items":{"type":"object","properties":{"code":{"oneOf":[{"type":"string"},{"type":"integer"}],"description":"Machine-readable error code. Usually a string like\n`invalid_ref`, `missing_required_field`, or `unauthorized`;\nmay be an **integer** when the error mirrors an upstream HTTP\nstatus (e.g. `500`) — most commonly returned by connection-ping\nand adaptor-proxy responses."},"message":{"type":"string","description":"Human-readable description of the error."},"field":{"type":"string","description":"Optional pointer to the document field that caused the error.\nUsed by structural validation errors (`missing_required_field`,\n`invalid_ref`) to indicate which field is at fault\n(e.g. `_id`, `type`, `http.baseURI`)."},"source":{"type":"string","description":"Optional origin layer for the error — e.g. `application` when\nthe error came from the remote system the adaptor called,\n`connector` when the adaptor itself rejected the request."}},"required":["message"]}}},"required":["errors"]}},"responses":{"401-unauthorized":{"description":"Unauthorized. The request lacks a valid bearer token, or the provided token\nfailed to authenticate.\n\nNote: the 401 response is produced by the auth middleware **before** the\nrequest reaches the endpoint handler, so it does **not** follow the\nstandard `{errors: [...]}` envelope. Instead the body is a bare\n`{message: string}` object with no `code`, no `errors` array. Callers\nhandling 401s should key off the HTTP status and the `message` string,\nnot try to destructure an `errors[]`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable description of the auth failure. Known values:\n- `\"Unauthorized\"` — no `Authorization` header on the request.\n- `\"Bearer Authentication Failed\"` — header present but token\n  is invalid, revoked, or expired."}},"required":["message"]}}}},"404-not-found":{"description":"Not found. The requested resource does not exist or is not visible to the caller.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/networkpolicies/{_id}/dependencies":{"get":{"operationId":"listNetworkPolicyDependencies","tags":["Network Policies"],"summary":"List assignments of a network policy","description":"Returns every API token, MCP server, and account sign-in setting the policy is\nassigned to within its own environment. Call it before `DELETE` to see what a\n`force=true` delete would clear. Unlike other `/dependencies` endpoints, the\nresponse is a fixed object rather than a map keyed by resource type.","parameters":[{"name":"_id","in":"path","required":true,"description":"Network policy ID.","schema":{"type":"string","format":"objectId"}}],"responses":{"200":{"description":"Assignments of the policy. All keys are present even when the policy is unassigned.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NetworkPolicyDependencies"}}}},"401":{"$ref":"#/components/responses/401-unauthorized"},"404":{"$ref":"#/components/responses/404-not-found"}}}}}}
```

## Get audit log for a network policy

> Returns the change history for a network policy, newest first. Each entry\
> records one event with who made the change, when, and which fields were\
> affected. Entries survive the policy's deletion and purge, but the route\
> itself returns 404 as soon as the policy is deleted, so use\
> \`GET /v1/audit?resourceType=networkpolicy\` to read the history of a\
> deleted policy.

```json
{"openapi":"3.2.0","info":{"title":"Network Policies","version":"1.0.0"},"tags":[{"name":"Network Policies","description":"Network policies are named IP allow and deny lists that control where API tokens, MCP servers, and users may connect from. A policy takes effect only once it is assigned — through `_networkPolicyId` on an API token or MCP server, or in account settings for workspace-user and end-user sign-in — and each environment (production or sandbox) keeps its own library of policies. Network policies must be enabled for the account, and only the account owner and administrators can manage them.\n\nEvery policy that applies to a call must admit the caller. An API token's policy is checked when the token authenticates, before the request runs; an MCP server's policy is checked on every request to it, so a call to an MCP server passes both its token's policy and the server's. A personal access token has no policy of its own: it is checked against the workspace-user sign-in policy of the environment it belongs to. Sign-in policies are checked when a workspace user signs in or switches account or environment, and when an end user signs in to an MCP server.\n\nA refused call gets HTTP 403 with `{\"errors\": [{\"code\": \"access_denied\", \"message\": \"Access denied.\"}]}` and nothing that names the policy or the address. An MCP server endpoint speaks JSON-RPC, so its 403 carries the MCP server's access-denied error (`-32006`) in a JSON-RPC envelope instead — `{\"jsonrpc\": \"2.0\", \"error\": {\"code\": -32006, \"message\": \"Access denied.\"}, \"id\": <request id>}`, with `id` echoed when the request had one — and the server's request log records the call as blocked.\n\n## Network policy schema\n\n{% openapi-schemas spec=\"networkpolicy\" schemas=\"NetworkPolicy\" grouped=\"true\" %}"}],"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"},{"url":"https://api.au.integrator.io","description":"Production (AU region)"},{"url":"https://api.ca.integrator.io","description":"Production (CA region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"responses":{"400-bad-request":{"description":"Bad request. The server could not understand the request because of malformed syntax or invalid parameters.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401-unauthorized":{"description":"Unauthorized. The request lacks a valid bearer token, or the provided token\nfailed to authenticate.\n\nNote: the 401 response is produced by the auth middleware **before** the\nrequest reaches the endpoint handler, so it does **not** follow the\nstandard `{errors: [...]}` envelope. Instead the body is a bare\n`{message: string}` object with no `code`, no `errors` array. Callers\nhandling 401s should key off the HTTP status and the `message` string,\nnot try to destructure an `errors[]`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable description of the auth failure. Known values:\n- `\"Unauthorized\"` — no `Authorization` header on the request.\n- `\"Bearer Authentication Failed\"` — header present but token\n  is invalid, revoked, or expired."}},"required":["message"]}}}},"404-not-found":{"description":"Not found. The requested resource does not exist or is not visible to the caller.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422-unprocessable-entity":{"description":"Unprocessable entity. The request was well-formed but was unable to be followed due to semantic errors.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"Error":{"type":"object","description":"Standard error response envelope returned by integrator.io APIs.","properties":{"errors":{"type":"array","description":"List of errors that occurred while processing the request.","items":{"type":"object","properties":{"code":{"oneOf":[{"type":"string"},{"type":"integer"}],"description":"Machine-readable error code. Usually a string like\n`invalid_ref`, `missing_required_field`, or `unauthorized`;\nmay be an **integer** when the error mirrors an upstream HTTP\nstatus (e.g. `500`) — most commonly returned by connection-ping\nand adaptor-proxy responses."},"message":{"type":"string","description":"Human-readable description of the error."},"field":{"type":"string","description":"Optional pointer to the document field that caused the error.\nUsed by structural validation errors (`missing_required_field`,\n`invalid_ref`) to indicate which field is at fault\n(e.g. `_id`, `type`, `http.baseURI`)."},"source":{"type":"string","description":"Optional origin layer for the error — e.g. `application` when\nthe error came from the remote system the adaptor called,\n`connector` when the adaptor itself rejected the request."}},"required":["message"]}}},"required":["errors"]}}},"paths":{"/v1/networkpolicies/{_id}/audit":{"get":{"summary":"Get audit log for a network policy","description":"Returns the change history for a network policy, newest first. Each entry\nrecords one event with who made the change, when, and which fields were\naffected. Entries survive the policy's deletion and purge, but the route\nitself returns 404 as soon as the policy is deleted, so use\n`GET /v1/audit?resourceType=networkpolicy` to read the history of a\ndeleted policy.","tags":["Network Policies"],"operationId":"getNetworkPolicyAudit","parameters":[{"name":"_id","in":"path","description":"Network policy ID.","required":true,"schema":{"type":"string","format":"objectId"}},{"name":"limit","in":"query","description":"Maximum number of audit entries to return per page.","required":false,"schema":{"type":"integer","minimum":1,"maximum":1000,"default":1000}},{"name":"after","in":"query","required":false,"description":"Opaque pagination cursor for the next page. Take it from the `after` value in the `Link`\nresponse header's `rel=\"next\"` URL rather than constructing it.","schema":{"type":"string"}},{"name":"from","in":"query","required":false,"description":"Only return entries at or after this timestamp.","schema":{"type":"string","format":"date-time"}},{"name":"to","in":"query","required":false,"description":"Only return entries at or before this timestamp.","schema":{"type":"string","format":"date-time"}},{"name":"action","in":"query","required":false,"description":"Filter by the change type. Maps to the `event` field on each entry.","schema":{"type":"string","enum":["create","update","delete","view","restore","purge","signin","signout","purgelogs"]}},{"name":"source","in":"query","required":false,"description":"Filter by how the change was initiated.","schema":{"type":"string","enum":["ui","api","system","connector","script","sso"]}},{"name":"_byUserId","in":"query","required":false,"description":"Filter to changes performed by a single user.","schema":{"type":"string","format":"objectId"}}],"responses":{"200":{"description":"Array of audit entries, newest first.","headers":{"Link":{"description":"RFC 5988 pagination link. Includes `<...>; rel=\"next\"` with an\n`after` cursor when more entries exist; absent on the final page.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"_id":{"type":"string","format":"objectId","description":"Unique identifier for this audit entry."},"resourceType":{"type":"string","description":"Always `networkpolicy` for this endpoint."},"_resourceId":{"type":"string","format":"objectId","description":"ID of the network policy this entry belongs to."},"event":{"type":"string","description":"Type of change that occurred. A policy's history runs `create`, then any\nnumber of `update`, then `delete`; a deleted policy either gains a\n`restore` and continues, or ends with `purge`.","enum":["create","update","delete","restore","purge"]},"source":{"type":"string","description":"How the change was initiated. Restores from the recycle bin are recorded as `system`.","enum":["api","ui","system"]},"time":{"type":"string","format":"date-time","description":"When the change occurred."},"byUser":{"type":"object","description":"User who made the change.","properties":{"_id":{"type":"string","format":"objectId","description":"User ID."},"email":{"type":"string","format":"email","description":"User email address."},"name":{"type":"string","description":"User display name."}}},"fieldChanges":{"type":"array","description":"Fields that were modified. Empty on `create`, `delete`, `restore`, and `purge` events.","items":{"type":"object","properties":{"fieldPath":{"type":"string","description":"Dot-notation path of the changed field."},"oldValue":{"description":"Previous value (absent when the field was newly set)."},"newValue":{"description":"New value (absent when the field was removed)."}}}},"deletedInfo":{"type":"object","description":"Metadata about the deleted policy. Present on `delete` and `purge` events.","properties":{"name":{"type":"string","description":"Name of the policy at the time of deletion."}}}}}}}}},"204":{"description":"No audit entries exist for this network policy."},"400":{"$ref":"#/components/responses/400-bad-request"},"401":{"$ref":"#/components/responses/401-unauthorized"},"404":{"$ref":"#/components/responses/404-not-found"},"422":{"$ref":"#/components/responses/422-unprocessable-entity"}}}}}}
```
