APIZDocs

APIZ guide

Filter API Access By IP And Geo

Use verified Request Origin when an agent should call an API only from trusted networks or geographic locations. APIZ provides two complementary controls:

NeedConfigure it inEnforcement point
Accept only known IPv4/IPv6 networksAPI Instance Request Origin AccessBefore Policy, credential release, or upstream contact
Allow or deny countries, continents, regions, cities, timezones, or private-network contextStructured or Scripted PolicyAfter origin verification and the API Instance IP filter

The IP restriction is commonly called an IP whitelist or IP allowlist. Geo is Policy context, not a second API Instance allowlist. Both use APIZ's canonical verified origin and never trust a caller-supplied forwarding header by itself.

edge trust -> verified IP + Geo -> API Instance CIDR filter -> Policy -> upstream
                                      deny stops here        deny stops here

This restriction applies to every Client Binding for the API Instance, including intentionally public bindings. A Policy may narrow access further, but cannot override an IP denial.

Before You Configure It

  • Identify the stable egress addresses of the agent runtime, sandbox platform, NAT gateway, or corporate network that will call APIZ.
  • Express individual IPv4 addresses as /32 and individual IPv6 addresses as /128. Use a broader CIDR only when the complete network is trusted.
  • Confirm that the APIZ deployment has a healthy Edge Trust Profile. APIZ uses only the caller IP established by that trust boundary; it never trusts a caller-supplied forwarding header by itself.
  • For Geo rules, confirm that the deployment exposes available Geo context. Geo may come from a verified Cloudflare edge or the operator's bounded MMDB provider. It is approximate authorization context, not proof of a person's physical location.
  • Keep a second authorized management session available while changing a production allowlist.

The addresses below are reserved documentation examples. Replace them with your real trusted networks:

203.0.113.10/32
2001:db8:1234::/48

Configure The IP Filter In The Web Console

  1. Open API Instances and create an instance, or open an existing instance and choose Edit.
  2. Expand Advanced Settings, then Request Origin Access.
  3. Enable Restrict trusted source IPs.
  4. Add one to 64 IPv4 or IPv6 CIDRs under Allowed source CIDRs.
  5. Review the complete list and save the API Instance.

APIZ canonicalizes network addresses, sorts the list, and removes duplicates. For example, 203.0.113.99/24 is stored as 203.0.113.0/24. A bare address without a prefix is rejected rather than guessed.

Connection tests validate APIZ-to-upstream connectivity and do not apply the caller allowlist. Verify the restriction with a real Data Plane request after saving.

Configure The IP Filter With The CLI

Add the allowlist while creating any adapter-backed API Instance by repeating --allow-source-cidr:

apiz api create \
  --adapter github \
  --name restricted-github \
  --config-json '{}' \
  --test-config-json '{"preset":"get_user_info"}' \
  --allow-source-cidr 203.0.113.10/32 \
  --allow-source-cidr 2001:db8:1234::/48 \
  --credential-stdin

Replace the complete allowlist on an existing instance:

apiz api update <api-instance-id> \
  --allow-source-cidr 203.0.113.10/32 \
  --allow-source-cidr 2001:db8:1234::/48

The update command replaces the list atomically; it does not append to the previous value. Disable filtering and clear every CIDR explicitly:

apiz api update <api-instance-id> --clear-source-cidrs

Do not combine --clear-source-cidrs with --allow-source-cidr.

Add A Geo Rule With Structured Policy

The following Policy allows requests only when verified Geo is available and the country code is US or SG. Replace those synthetic choices with the countries required by your own risk model.

Web Console

  1. Open Policies → Create Policy and choose Structured.
  2. Select the adapter scope for the API you are protecting, or leave it unscoped only when the same gate should apply across adapters.
  3. Add Geo · Available with operator equals and value true.
  4. Add Geo · Country code with operator in and values US, SG.
  5. Set THEN to allow with reason geo_allowed.
  6. Set OTHERWISE to deny with reason geo_not_allowed.
  7. Save and publish the Policy. Review the current testing boundary below before attaching it to traffic.

You can use the same editor for continent, region, city, timezone, Geo provider, or private-network context. Prefer country or continent rules when possible; city-level Geo is less stable and may be unavailable.

CLI

Use this as the definition in a Structured Policy Project:

{
  "type": "structured",
  "when": {
    "conditions": [
      {"field": "request_origin.geo.available", "op": "equals", "value": true},
      {"field": "request_origin.geo.country_code", "op": "in", "value": ["US", "SG"]}
    ]
  },
  "then": {"decision": "allow", "reason": "geo_allowed"},
  "otherwise": {"decision": "deny", "reason": "geo_not_allowed"}
}

Publish it using the lifecycle in the Structured Policy tutorial:

apiz -o json policy publish --project ./geo-access > policy-review.json
POLICY_ID=$(jq -r '.candidate.policy_id' policy-review.json)
DRAFT_REVISION=$(jq -r '.candidate.draft_revision' policy-review.json)
POLICY_REVISION=$(jq -r '.candidate.current_published_revision' policy-review.json)
jq '{candidate, changes, evidence, traffic_effect}' policy-review.json
apiz policy publish "$POLICY_ID" --project ./geo-access \
  --expected-draft-revision "$DRAFT_REVISION" \
  --expected-policy-revision "$POLICY_REVISION" --confirm
apiz policy enable "$POLICY_ID"

Current Testing Boundary

The current public Policy Fixture API does not accept synthetic request_origin or Geo context; it permits only bounded Client and API Instance tag overrides. A Geo-dependent fixture therefore fails closed with policy_context_unavailable instead of establishing readiness. Do not claim a passing Geo suite or substitute caller-controlled headers.

This implemented limitation conflicts with the active Request Origin contract, which requires synthetic origin and Geo fixture context. Until that gap is resolved, validate Geo Policies on a non-production API Instance. Test evidence is advisory; attaching does not require an override:

apiz api policy add <api-instance-id> \
  --policy <policy-id> \
  --order 100

Keep Geo gates off production traffic until the observed allow, deny, unavailable-context, and redacted-evidence paths have been reviewed for the exact Published Revision.

If the Policy references Geo but APIZ cannot verify that field, evaluation denies with policy_context_unavailable; missing Geo never becomes an empty value that accidentally passes a negative condition.

Verify Allow And Deny

Send the same Temporary Credential from one allowed source and one source outside the list. The allowed request continues through normal Policy and upstream processing. The blocked request returns HTTP 403 with:

code=apiz_forbidden
reason=api_instance_source_ip_not_allowed

The response does not reveal the observed address or configured CIDRs. An enabled filter also fails closed with request_origin_unavailable when APIZ cannot establish a trusted caller address.

For Geo, send controlled requests through known test egress locations. Confirm that an allowed country reaches the next Policy or upstream step, while a disallowed country returns the configured geo_not_allowed reason. Do not use a caller-supplied country or forwarding header as a test mechanism.

Inspect Evidence

In the Web Console, open Logs / Audit → Access Logs, select the request, and inspect Request origin and the API Instance filter outcome. Use Audit Logs to see who changed the allowlist.

With the CLI:

apiz access-log list --api-instance <api-instance-id> --since 15m --limit 50
apiz access-log request <request-id>
apiz audit list --api-instance <api-instance-id> --since 24h

Request evidence may show the canonical trusted source IP to authorized Team members, but never copies raw proxy chains or unverified forwarding headers.

Troubleshooting

SymptomWhat to check
api_instance_source_ip_not_allowedConfirm the caller's actual egress network and the complete saved CIDR list.
request_origin_unavailableAsk the APIZ operator to check Edge Trust Profile readiness; do not add a forwarded header workaround.
policy_context_unavailableThe Policy referenced trusted origin or Geo data that APIZ could not verify. Check Geo readiness and the selected field.
geo_not_allowedThe verified Geo context did not match the Policy's allowed values. Inspect the canonical country/region evidence.
Connection test succeeds but agent request is deniedExpected: connection tests do not represent a Data Plane caller. Test using the generated agent endpoint.
Every address is allowedCheck for 0.0.0.0/0 or ::/0; those are valid but non-restrictive networks.
CIDR rejectedInclude the prefix and use canonical IPv4 or IPv6 network form; multicast and unspecified-host ranges are unsupported.

Combine this gate with Structured or Scripted Policy when the decision also depends on adapter action, resource, or tags. Continue with request evidence when a request still behaves unexpectedly.