How you get in depends on your license’s authentication mode:
- IP Whitelist: the connection must come from an IP on your license’s whitelist. No key is needed, and a key alone does not get you in from any other IP. To see the IP a server connects from, run
curl -s ifconfig.meon it. - API Key Only: send your license key in the
x-tokenmetadata header, from any IP. gRPC has no query string, andx-api-keyis not accepted.
Check the connection with grpcurl
grpcurl calls a gRPC method from the command line, so you can test access without writing code. Download the protos from the SDK repository into the current folder, then:-H flag. A version string means the host is reachable and you are allowed in. Anything else, look it up below.
Errors and what they mean
Access refused
The two services report this differently, and the same message can mean different things in each authentication mode.
Jetstream closes the connection before sending any gRPC status, so
EOF or a reset is the only sign you get. If an endpoint isn’t covered by your license, hitting it results in the same EOF, in either mode. Check which regions your license includes in the dashboard.
The SDKs wrap these with the gRPC status number and the endpoint, for example grpc error (16): authentication required: provide x-token header in Rust or grpc error (14): [http://ams.jetstream.orbitflare.com] error reading from server: EOF in Go. Status 16 is Unauthenticated, 7 is PermissionDenied and 14 is Unavailable.
If the same code works from one server and fails from another, you are almost certainly in IP Whitelist mode and the second server’s IP is not on the list. If it fails everywhere in API Key Only mode, check that your client actually sends the x-token header.
Wrong transport or port
Connection limit reached
RESOURCE_EXHAUSTED: connection limit exceeded means your IP already has 50 open gRPC connections, counted across Jetstream, Yellowstone and every region. Close streams you no longer use, and put several filters on one stream instead of opening a stream per filter. See connection limits.
Connected but nothing arrives
Jetstream
Jetstream v2 tells you whether each filter was accepted. The first message on a new stream is afilterValidation for every filter you sent:
filterValidation messages, and check accepted before assuming the market is quiet.
Other causes:
- You asked for accounts. Jetstream streams transactions only. Account filters are not supported, and a v1 subscription with an
accountsfilter never sends anything. Use Yellowstone to watch account state. account_requiredis too strict.account_includematches a transaction that mentions any of the listed accounts.account_requiredmatches only transactions that mention all of them. Start withaccount_includeand narrow down from there.- You called
SubscribeParsed. It is not implemented and closes withUnavailable: EOF. UseSubscribe(v1) orSubscribeTransactions(v2) and decode instructions yourself.
Yellowstone
- The filter map is empty. A
SubscribeRequestwith no filters is valid and returns nothing. Each filter needs a name:{"accounts": {"my-filter": {"account": ["..."]}}}. - The account is not changing. Account filters send an update only when the account changes. Test with
SysvarC1ock11111111111111111111111111111111, which changes every slot. - Failed transactions are filtered out.
failed: falsedrops every transaction that errored. Leave it unset while debugging so you can see whether your transactions are landing and failing. (Thevotefilter no longer matters: since Alpenglow, validators vote off-chain and mainnet has no vote transactions.)
Streams that stop
Idle gRPC streams are closed after about 10 minutes. Send a ping on the stream every 30 seconds:- Jetstream v2: send a
pingmessage on theSubscribeTransactionsstream. The server answers with apongcarrying the same ID. - Yellowstone: send a
SubscribeRequestwith onlypingset. See Yellowstone quickstart.