Skip to content

Operations

IP allowlist

View as MarkdownPlain text source(opens in new tab)

Every API key is locked to a specific set of source IPs. Requests from any other IP are rejected before a token is minted.

Every API key is locked to a specific set of source IPs. Requests from any other IP are rejected with 403 forbidden_ip before a token is minted and before any WebSocket is upgraded. We enforce this on every key we issue. It’s how we make sure a key that ends up where it shouldn’t can’t be quietly used or resold from somewhere else.

Why it’s enforced

Bearer API keys are powerful, and they’re impossible to keep perfectly secret. They end up in logs, backups, build configs, third-party integrations, and developer machines. Without an IP lock, a leaked key works from anywhere on the internet. With one, it works only from servers you control. We don’t make this opt-in because the failure mode (silently reselling or reusing a leaked key) is too costly to leave to chance.

What’s allowed

  • IPv4 addresses, like 203.0.113.42
  • IPv4 CIDR ranges, like 203.0.113.0/24
  • IPv6 addresses, like 2001:db8::1
  • IPv6 CIDR ranges, like 2001:db8::/32

What you receive on a mismatch

HTTP/1.1 403 Forbidden
Content-Type: application/json

{"error":"forbidden_ip"}

Both the token mint endpoint and the WebSocket upgrade enforce the lock. You won’t get past either without an allowed IP.

The check uses your server’s public-facing IP as seen by us. If you’re behind a corporate proxy or NAT, what counts is the external IP your traffic exits with, not the internal address your application thinks it has.

Providing your IPs

You hand us the list when your key is provisioned. To change it later, email us with the updated IPs or CIDRs. Updates take effect immediately for new mint and upgrade requests.

Cross-family behavior

An IPv4 client never matches an IPv6 CIDR and vice versa. If your servers may connect from either family (some Kubernetes clusters do), give us both ranges explicitly.

Finding your servers’ IPs

If you’re not sure what your external IP looks like:

  • For a single server: run curl https://api.ipify.org from that server to see its public IP
  • For a load-balanced fleet: send us the egress IP range that fronts the fleet, not the individual hosts
  • For serverless edge platforms calling us: the source IP is typically a shared egress pool that isn’t stable enough to lock to. Route the connection through a fixed-IP proxy or a VM with a static IP instead

When your IPs change

If your egress IPs change and we haven’t been updated, you’ll see 403 forbidden_ip on every mint attempt and your connection will not open. Email us the new list before the cutover, or right after, and retry.