BellD / DevelopersDocumentation · latest

Outbound connections

By default, a deployed app has no outbound network. You can allow it to connect to specific hosts by declaring them in package.json:

{ "belld": { "egress": ["api.openai.com", "*.example.com", "db.example.com:5432"] } }

Each entry is a host name, optionally followed by :443 or :5432. Without a port, the entry means port 443.

*.example.com matches every subdomain of example.com, but not example.com itself. Wildcards over a public suffix (such as *.com) are rejected.

Hosts served by a shared front end are rejected, because they would let the app reach other sites behind them.

You can declare at most 50 entries. Invalid entries make the descriptor confirmation fail.

Ports 443 and 5432 are open. Port 5432 accepts PostgreSQL over TLS only: use sslmode=require or stricter (with node-postgres, ssl: true). Your client must send the server name (SNI), which libpq 14 and later and node-postgres do by default. Plain-text connections, including plain-text query cancellation requests, are refused. Only IPv4 addresses are reachable, so hosts that publish only IPv6 addresses, such as Supabase direct database hosts, cannot be reached; use the provider's IPv4 connection pooler instead. Open connections can be closed when the platform restarts its network proxy, so handle connection errors in your database pool.

Declarations are frozen with each revision and sent when the revision is deployed. On a paid plan, the declared hosts are allowed once the revision is deployed. On the Free plan, they are allowed only after an owner of the workspace has connected GitHub to BellD, and only while the workspace still has an active GitHub connection; connecting or disconnecting GitHub takes effect at the next deploy or wake. Free deployments are limited to 200 MiB of outbound traffic per day, and so is each Free workspace; paid deployments are limited to 5 GiB per day, and paid workspaces to 20 GiB.

Each entry opens the whole service, not just your project or account: for example, declaring your Supabase project's host also reaches other Supabase projects. Costs charged by these third parties are not covered by BellD spending limits.

See what was allowed and what was blocked

In the Console, open Outbound, then choose a service and an environment. The page shows the declared hosts of the active deployment and whether each one was sent at the last deploy, followed by the connections blocked in the last 24 hours. Only the registrable domain of a blocked host is shown; to allow it, declare the exact host or a wildcard under that domain, then redeploy.

Call an AI or email provider from your own code

You can also call an AI or email provider's SDK directly from your server code, without a BellD credential or binding. Store the provider's key as a secret for each environment, for example belld variables set OPENAI_API_KEY --product <product> --environment production --kind secret --from-env OPENAI_API_KEY. Your app reads it from its environment at run time; secret values cannot be read back, and changes apply at the next deploy or wake. Do not put keys in package.json: a revision with a credential there is rejected. Declare the provider's API host in belld.egress, for example api.openai.com, api.anthropic.com, api.deepseek.com, api.resend.com or api.postmarkapp.com. Hosts under googleapis.com cannot be declared; to use Gemini, create a BellD credential with --provider gemini instead. The provider bills you directly: BellD does not charge Bell Credits for these calls, and they are not covered by BellD spending limits.