Skip to main content

First request (direct REST)

The OneSource REST API is plain HTTPS + JSON: any HTTP client works. The same endpoint shape covers all three access paths; only the auth header changes.

curl

# Bearer API key (from app.onesource.io/signup)
curl https://api.onesource.io/api/chain/network-info \
-H "Authorization: Bearer $ONESOURCE_API_KEY"

# x402 / MPP / no auth: OneSource will return 402 with payment challenges
curl -v https://api.onesource.io/api/chain/network-info

For wallet-paid calls, a custom HTTP client handles the 402 → sign → retry loop. See x402 on Base or MPP on Tempo.

Node.js (fetch)

const res = await fetch('https://api.onesource.io/api/chain/live-balance?' + new URLSearchParams({
address: '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045',
tokens: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48,0xdAC17F958D2ee523a2206206994597C13D831ec7',
}), {
headers: { Authorization: `Bearer ${process.env.ONESOURCE_API_KEY}` },
});

const { data, error, meta } = await res.json();
if (error) throw new Error(`${error.code}: ${error.message}`);
console.log(`Request ${meta.request_id} cost ${meta.cost_usdc ?? 'free'} USDC`);

Python (httpx)

import os, httpx

resp = httpx.get(
'https://api.onesource.io/api/chain/erc20-balance',
params={
'account': '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045',
'token': '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
},
headers={'Authorization': f"Bearer {os.environ['ONESOURCE_API_KEY']}"},
timeout=10.0,
)
resp.raise_for_status()
body = resp.json()
if body['error']:
raise RuntimeError(body['error']['message'])
print(body['data'])

Go

req, _ := http.NewRequest("GET", "https://api.onesource.io/api/chain/tx/"+hash, nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("ONESOURCE_API_KEY"))

resp, err := http.DefaultClient.Do(req)
if err != nil { return err }
defer resp.Body.Close()

var body struct {
Data json.RawMessage `json:"data"`
Error *APIError `json:"error"`
Meta map[string]any `json:"meta"`
}
if err := json.NewDecoder(resp.Body).Decode(&body); err != nil { return err }
if body.Error != nil { return fmt.Errorf("%s: %s", body.Error.Code, body.Error.Message) }

Choosing a network

Every /api/chain/* endpoint accepts an optional network query parameter. It defaults to ethereum (mainnet); pass network=sepolia for the Sepolia testnet or network=robinhood for Robinhood Chain.

# Mainnet (default): the parameter can be omitted
curl "https://api.onesource.io/api/chain/network-info" \
-H "Authorization: Bearer $ONESOURCE_API_KEY"

# Sepolia testnet: add ?network=sepolia
curl "https://api.onesource.io/api/chain/network-info?network=sepolia" \
-H "Authorization: Bearer $ONESOURCE_API_KEY"

# Robinhood Chain: add ?network=robinhood
curl "https://api.onesource.io/api/chain/network-info?network=robinhood" \
-H "Authorization: Bearer $ONESOURCE_API_KEY"

For POST endpoints, network is still a query parameter, so it goes on the URL (for example …/api/chain/call?network=sepolia), not in the JSON body. To confirm which chain a backend is on, call /api/chain/chain-id.

Networknetwork valueEIP-155 chain id
Ethereum mainnetethereum (default)1 (0x1)
Sepolia testnetsepolia11155111 (0xaa36a7)
Robinhood Chainrobinhood4663 (0x1237)

The same call can mean different things per chain

The endpoints are identical across networks, but the chains are not, and a few of the differences change how a response should be read:

Chain factWhy it matters
Block cadenceEthereum produces a block roughly every 12 seconds; Robinhood Chain does so about every 100 milliseconds. The same block range is a very different time window on each, so size ranges from the reported cadence rather than from a fixed block count.
ENSThe ENS registry is deployed on ethereum and sepolia only. On Robinhood Chain a name lookup fails because of the chain, not because the name is unregistered.
Mempoolethereum and sepolia have a public pending pool. Robinhood Chain runs a single sequencer, so /api/chain/pending reports roughly the next block rather than a queue of unconfirmed transactions.
FinalityOn Robinhood Chain, the safe and finalized block tags track settlement on Ethereum and can trail latest by a wide margin while the chain is perfectly healthy.

/api/chain/network-info reports all of these per network as a chain object, alongside head_age_seconds and stale. Call it first when you are working against a chain for the first time.

POST endpoints

A few endpoints accept JSON bodies, notably /api/chain/call (simulate eth_call) and /api/chain/estimate-gas:

curl -X POST https://api.onesource.io/api/chain/call \
-H "Authorization: Bearer $ONESOURCE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"to": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
"data": "0x18160ddd"
}'

The full request shape for each endpoint is documented in the API Reference.

Next