---
title: "Networks and bring-your-own RPC endpoints"
description: "Bring-your-own endpoints, how resolution picks one, and reading the x-rpc-source header."
---

> Documentation Index
> Fetch the complete documentation index at: https://tee.hypetrade.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Networks and bring-your-own RPC endpoints

## The networks a workspace starts with

Every workspace's registry is seeded from the same ten built-in networks:

| Slug | Network | VM | Chain ID |
|---|---|---|---|
| `ethereum` | Ethereum | `evm` | 1 |
| `base` | Base | `evm` | 8453 |
| `bnbchain` | BNB Chain | `evm` | 56 |
| `arbitrum` | Arbitrum | `evm` | 42161 |
| `optimism` | OP Mainnet | `evm` | 10 |
| `sepolia` | Sepolia | `evm` | 11155111 |
| `arbitrum-sepolia` | Arbitrum Sepolia | `evm` | 421614 |
| `solana` | Solana | `svm` | 101 |
| `solana-testnet` | Solana Testnet | `svm` | 102 |
| `solana-devnet` | Solana Devnet | `svm` | 103 |

These slugs are what every `network` selector and `defaultNetwork` accepts. A
well-formed slug that is not one of them — or one your operator removed — is a
`404`, not a `400`.

**Use a testnet while you are integrating.** `sepolia` and `solana-devnet`
carry no real value, and every example in these docs uses `ethereum` only
because it is the obvious name. A first transaction on `ethereum` is a real
mainnet transaction.

TEE Docker ships **no RPC service**. Anything that touches a chain — building,
simulating, submitting, or checking a transaction — runs against an endpoint you
or your operator supplied.

## Resolution

An endpoint can come from three places. They are not searched in turn at
request time — the workspace's own network registry is read once, and each
entry already carries the provenance it was given:

1. **Step 1**

### The workspace registry — authoritative

   What a route actually reads. `PUT /v1/workspace/networks/{slug}` writes
   straight into it, and is how an endpoint changes once a workspace exists.

2. **Step 2**

### The tenant `rpc` map — a seed, not a lookup

   Your operator's map is copied into the registry **when the workspace is
   created**, over the built-in defaults. That is the only moment it is read.

3. **Step 3**

### A wative-core built-in — permitted, not searched

   Networks your operator never configured keep the URL wative-core ships. That
   entry is usable only where `allowDefaultRpc` permits it, and permission is
   checked on **every** call, not once at creation.

So a registry entry is necessary but not sufficient. A call fails with `409`
and `rpc_not_configured` in two cases: the network has no URL at all, or it has
a built-in one and `allowDefaultRpc` is off.

Provenance is about how an endpoint was set, not what it points at. An explicit
`PUT` or an operator seed counts as `tenant` even when its URL happens to equal
the one wative-core ships.

> **A tenant rpc change does not reach existing workspaces**
>
> Because the tenant map is copied in at creation time and never re-read, editing
> it moves nothing that already exists. Workspaces created before the change keep
> using the endpoint they were seeded with, indefinitely. To move an existing
> workspace, call `PUT /v1/workspace/networks/{slug}` on it — or create it fresh.

## Every answer says where its endpoint came from

Resolution is never ambiguous. The reported source is one of three values:

| `rpcSource` | Meaning |
|---|---|
| `tenant` | A workspace-registered or tenant-configured endpoint answered |
| `builtin` | wative-core's shipped default answered — an endpoint nobody here chose |
| `none` | Nothing usable is configured for this network |

`GET /v1/workspace/networks` reports it per network, and is the only place
`none` appears — it is a description of configuration, not of a call.

The four transaction routes stamp the source on the response as the
**`x-rpc-source` header**, so "why is this slow" or "which endpoint actually
served this" is answerable from the response alone. The header only ever reads
`tenant` or `builtin`: a network that would resolve to `none` fails with `409`
before a response exists to stamp.

> **builtin is the default, not an opt-in**
>
> `allowDefaultRpc` is **on** unless your operator turns it off. A network your
> operator never configured still resolves — to wative-core's shipped public
> endpoint, which sees your transaction contents and the addresses involved.
> Check `x-rpc-source` if that matters to you; `builtin` is not only a latency
> answer, it is a "someone else saw this" answer.

> **Check the header when latency surprises you**
>
> A route that unexpectedly reports `builtin` is running on a shared public
> default, not your endpoint. That is the usual explanation for a sudden latency
> change.

When a route needs an endpoint and resolution returns `none`, the call fails
with `409` and code `rpc_not_configured`.

## Setting an endpoint

```bash
curl -X PUT "$API_URL/workspace/networks/ethereum" \
  -H "Authorization: Bearer $TOKEN" \
  -H "content-type: application/json" \
  -d '{"rpcUrl":"https://your-endpoint.example.com/eth"}'
```

The URL is admitted through a boundary check before it is stored — an endpoint
the service refuses to accept returns `400` with `rpc_endpoint_rejected`.

### What the boundary accepts

Every rule below produces that same `400`, so it is worth knowing them before
you debug one:

| Rule | Rejected |
|---|---|
| Scheme must be `https:` | Any `http://` endpoint |
| No credentials in the authority | `https://user:pass@host/…` — put an API key in the path or query instead, which is allowed |
| No fragment | `https://host/rpc#x` |
| Host must resolve to a globally routable address | `localhost`, `127.0.0.1`, `10.x`, `172.16–31.x`, `192.168.x`, `169.254.x`, CGNAT, and the IPv6 equivalents |
| Host must resolve at all | A name with no A or AAAA record |
| At most 2048 bytes | A longer URL |

There is no port restriction — a non-standard port is fine.

> **A local node cannot be registered**
>
> Between the `https:` requirement and the globally-routable requirement, an
> endpoint on your own machine or private network — `http://localhost:8545`, an
> anvil or hardhat node, an internal RPC on a VPC address — cannot be registered.
> This is deliberate: the service will not be pointed at addresses only it can
> reach. Development against a local chain means putting a public HTTPS endpoint
> in front of it.

The name is resolved when you register it **and** on every request that uses
it, and the resolved address is pinned for the connection. So an endpoint that
starts resolving to a private address later begins failing, even though it was
accepted at registration. The
update is applied transactionally: if the new endpoint cannot be resolved after
being written, the previous one is restored rather than leaving the workspace
pointing at something unusable.

Requires the `write` scope. Reading the list requires `read`.

> **Endpoint credentials belong with the operator**
>
> If your RPC URL embeds an API key, it is a credential. Keep it in operator
> configuration rather than shipping it from client code.

## Failures you should expect

Chain-touching routes surface transport problems distinctly from on-chain
outcomes:

| Code | Status | Meaning |
|---|---|---|
| `rpc_not_configured` | 409 | No usable endpoint for that network |
| `rpc_unreachable` | 502 | The endpoint did not respond, or answered non-2xx |
| `rpc_rejected` | 502 | The endpoint responded with a refusal |
| `rpc_endpoint_rejected` | 400 | The URL you supplied was refused at admission |
| `rpc_capacity_exceeded` | 429 | Too many concurrent chain operations |
| `unsupported_network` | 400 | The signing engine cannot work with that network |
| `account_not_found` | 404 | The `?network=` selector named a network this workspace does not define |

A simulation that fails *on-chain* is a `200` with `success: false` and a revert
reason. A simulation that could not complete at all is a transport error, and is
never rendered as `200`.

## Related

- [Networks endpoints](/api/networks/) — request and response shapes
- [Send transactions](/guides/send-transactions/) — where RPC actually matters
- [Errors](/errors/) — the full catalog

Source: https://tee.hypetrade.xyz/concepts/networks-and-rpc/index.mdx
