HTTP API reference
Standard service routes, request conventions, discovery, read-only RPC, metadata, and local trial endpoints.
Use the API origin for your deployment. Local examples below use http://localhost:8787; deployment information is in the network reference. The API prepares data and quotes. Wallets submit transactions through their own provider.
Request conventions
POST bodies require Content-Type: application/json. Compressed request bodies are unsupported. Quote quantities are raw decimal strings, including ETH in wei; JSON-RPC quantities are hexadecimal. Use integer arithmetic rather than JavaScript number for token quantities.
Normal API routes do not require a bearer API key. Metadata uploads require a wallet signature, and local trial setup POSTs require a process control token. Browser origins must match the configured CORS allowlist.
| Limit | Standard API |
|---|---|
| URL | At most 2,048 characters |
| Quote/availability body | 4 KiB |
| JSON-RPC body | 64 KiB |
| Metadata body | 3 MiB |
| General request rate | Per-client bucket of 300 units, replenished at 5 units/second |
| Expensive routes | Quote, availability, configured pool discovery, and metadata upload consume 20 additional units |
| RPC forwarding | Additional units equal the number of requests in the batch |
Responses default to Cache-Control: no-store. Immutable metadata and images use a one-year public cache lifetime. A rate-limit response from the standard server includes Retry-After: 2.
Service and discovery routes
| Method and path | Input | Response |
|---|---|---|
GET /health |
None | ready, indexer, decimal-string indexedBlock, and nullable millisecond lastIndexedAt; 503 when RPC is unready or indexing is degraded |
GET /v1/config |
None | Public chain, deployment, enabled-feature and index configuration |
GET /v1/baskets |
Optional limit and cursor |
baskets, nextCursor, indexedBlock, status |
GET /v1/baskets/:address |
Basket share-token address | { "basket": record }, or { "basket": null } if not indexed |
GET /v1/tokens |
Optional address, cursor; source-dependent q, sort, hideFlagged |
tokens, nextCursor, source, chainId |
GET /v1/stock-tokens |
None | Mainnet issuer identities: source: "Robinhood", chainId: 4663, tokens, nextCursor: null |
Health and configuration
curl --fail-with-body http://localhost:8787/health
curl --fail-with-body http://localhost:8787/v1/config
Example health response, using illustrative index values:
{
"ready": true,
"indexer": "ready",
"indexedBlock": "123456",
"lastIndexedAt": 1788998400000
}
ready reports RPC readiness. An indexer in syncing can still return HTTP 200 from /health; inspect its status and cursor to decide whether discovery is current enough for your application.
Public configuration includes chainId, chainName, explorerUrl, factoryAddress, deploymentBlock, ready, catalog, indexedBlock, status, indexConfirmations, and rpcPath: "/rpc". Optional fields are omitted when unconfigured:
| Field | Meaning |
|---|---|
managedFactoryAddress, managedRouterAddress |
Separate managed registry/router |
routerAddress, settlementToken, wrappedNative |
Optional settlement-token router configuration |
nativeFactoryAddress, nativeLaunch |
Native launch factory and V3 venue |
nativeTrading |
ETH trading router, two registries, and venue |
liquidity |
Liquidity helper, registries, position manager, DEX, wrapped token, quoter, router interface, quote tokens |
tokenPoolTrading |
settlementTokens enabled for Router02 token-settled pool trading |
Provider URLs, credentials, and the Codex market-data API key are not returned.
Basket pagination
limit defaults to 20 and accepts integers from 1 through 50. Results are ordered by descending creation block, log index, then address. Pass nextCursor back unchanged. Basket cursors are separate from token-directory cursors.
curl --fail-with-body 'http://localhost:8787/v1/baskets?limit=4'
A valid empty page has this shape:
{
"baskets": [],
"nextCursor": null,
"indexedBlock": "123456",
"status": "ready"
}
Each basket record contains address, creator, receiver, metadataURI, transactionHash, decimal-string blockNumber, and millisecond createdAt. It does not include live reserves or balances. Fetch those from contracts. See indexing and freshness.
Token directories
Without a mainnet Codex configuration, /v1/tokens uses Blockscout. Supplying address selects that wallet’s explorer-reported ERC-20 balances on either supported network. Nonempty ranked-search parameters are rejected for Blockscout, including wallet queries.
With Codex enabled on mainnet, directory requests support:
| Query | Values |
|---|---|
q |
Trimmed plain-text query, at most 100 characters |
sort |
volume (default), liquidity, newest, trending |
hideFlagged |
true (default) or false |
cursor |
Opaque cursor returned by the same query and filters |
curl --fail-with-body 'http://localhost:8787/v1/tokens'
# Run on a mainnet service with Codex enabled:
curl --fail-with-body 'http://localhost:8787/v1/tokens?q=example&sort=liquidity&hideFlagged=true'
Token entries include address, name, symbol, and optional decimals. Wallet rows can include raw decimal-string balance. Codex rows can include chainId, logo, nullable priceUsd, volume24hUsd, liquidityUsd, and screening (flagged, not-flagged, or unknown). Unknown metrics are not zero.
Stock-token entries include address, symbol, name, decimals: 18, chainId: 4663, issuer: "Robinhood", and an optional logo. The endpoint returns 404 on testnet. It supplies issuer identity, not a price feed or evidence of an executable route.
Quotes and pool discovery
These routes accept only their documented body fields. Address examples in the quote reference are placeholders; replace them with verified addresses from your deployment.
| Method and path | Required configuration | Purpose |
|---|---|---|
POST /v1/launch/availability |
nativeLaunch |
Structural ETH-route check for selected tokens |
POST /v1/launch/quote |
nativeLaunch |
ETH-funded basket creation quote |
POST /v1/trade/quote |
nativeTrading |
Proportional ETH issuance/redemption quote |
GET /v1/liquidity/pools?basket=… |
Optional liquidity |
Pool discovery and small executable probes |
POST /v1/liquidity/funding/quote |
liquidity |
Pre-creation check of extra ETH pool-funding budget |
POST /v1/liquidity/quote |
liquidity |
Existing shares plus ETH for a full-range LP position |
POST /v1/liquidity/trade/quote |
liquidity |
ETH trade of existing shares through pools |
POST /v1/liquidity/token-trade/quote |
liquidity with Router02 and a non-wrapped quote token |
ERC-20-settled trade of existing shares |
Unconfigured quote features return 409. Unconfigured pool discovery returns 200 with enabled: false, ready: false, pools: [], quoteTokens: [], quotedBlock: "0", and the service chain and requested basket.
The quote reference documents bodies, complete response-field groups, execution limits, and the difference between issuance/redemption and secondary-market swaps.
Read-only JSON-RPC gateway
POST /rpc accepts JSON-RPC 2.0 requests with an explicit id (string, safe integer, or null). Notifications without an ID are rejected. A batch must contain 1–10 requests; malformed members reject validation of the batch.
curl --fail-with-body http://localhost:8787/rpc \
-H 'Content-Type: application/json' \
--data '{"jsonrpc":"2.0","id":1,"method":"eth_chainId","params":[]}'
Testnet response:
{"jsonrpc":"2.0","id":1,"result":"0xb626"}
| Allowed methods | Constraints |
|---|---|
eth_chainId, eth_blockNumber, eth_gasPrice, eth_maxPriorityFeePerGas |
No parameters |
eth_getCode, eth_getBalance |
Nonzero address and optional block; default latest |
eth_call, eth_estimateGas |
Existing nonzero to; optional block; constrained transaction fields |
eth_getTransactionReceipt, eth_getTransactionByHash |
One 32-byte transaction hash |
eth_getBlockByNumber |
Block and boolean full-transaction flag |
eth_feeHistory |
1–100 blocks; at most 10 strictly increasing percentiles between 0 and 100 |
eth_getLogs |
1–20 explicit addresses, numeric range of at most 1,000 blocks, at most four topic positions |
Blocks may be hex quantities or latest, pending, safe, finalized, earliest, except log ranges, which require numeric hex quantities. The allowlist does not guarantee a provider supports every accepted tag.
Calls accept to, from, data or input, gas, value, fee fields, nonce, type, and accessList. Calldata is limited to 24 KiB. Gas is capped at 15 million and defaults to that cap. Access lists allow 32 entries with up to 32 storage keys each. Contract-creation simulation, arbitrary state overrides, signing, broadcast, admin, and debug methods are unavailable through this route.
Gateway RPC errors use HTTP 200 and a JSON-RPC error; inspect both HTTP status and the JSON-RPC payload. Validation or global failures can have id: null. Per-request upstream failures retain their request ID. Revert data may be preserved as bounded hex while arbitrary upstream error text is sanitized.
{
"jsonrpc": "2.0",
"id": null,
"error": {
"code": -32601,
"message": "RPC method is not available through this read-only gateway"
}
}
Metadata and media
| Method and path | Behavior |
|---|---|
POST /v1/metadata |
Accepts { metadata, address, chainId, expires, signature }; returns HTTP 201 and { uri } |
GET /v1/metadata/:hash |
Immutable JSON, where hash is 64 lowercase SHA-256 hex characters |
GET /v1/media/:hash.webp |
Immutable image/webp with the same hash format |
There is no separate anonymous image-upload route. Images are processed as part of the signed metadata request. See the exact message format, limits, and working browser example in wallets and metadata.
Local trial routes
These exist only in the explicit loopback trial server. Standard production startup does not install them.
| Method and path | Body or result |
|---|---|
GET /v1/trial |
Base artifacts, readiness, controlToken, restoreBlocked, RPC choice, optional deployment and faucet URL |
POST /v1/trial/estimate |
{ from, data }; exact compiled base factory/token creation input; returns decimal gas and gasPrice |
POST /v1/trial/activate |
{ creator, transactions: { factory, tokenA, tokenB } }; three distinct transaction hashes |
GET /v1/trial/native |
Native artifact, constructor data, venue, readiness, optional deployment |
POST /v1/trial/native/estimate |
{ from, data }; exact compiled native-factory creation input |
POST /v1/trial/native/activate |
{ creator, transactionHash } |
GET /v1/trial/trading |
Trading artifact, readiness, and constructor data/settings once prerequisites exist |
POST /v1/trial/trading/estimate |
{ from, data }; exact compiled trading-router creation input |
POST /v1/trial/trading/activate |
{ creator, transactionHash } |
All setup POSTs require X-RRR-Trial-Token from the current process. Estimate bodies allow 128 KiB; activation bodies allow 4 KiB. Native/trading estimates return raw decimal-string gas and gasPrice. Their activation responses contain the created factory/router address, creator, transaction hash, and deployment block. Base activation returns the validated base deployment.
Before activation, the trial returns status: "awaiting-deployment" for config/discovery, a null factory, and no baskets. Its health response is HTTP 200 with ready: false, rpcReady, and that status. Do not apply the standard /health schema to an unactivated trial.
HTTP errors
Standard non-RPC failures use { "error": "message" }.
| Status | Typical cause |
|---|---|
| 400 | Invalid address, fields, amount, cursor, expiry, or JSON |
| 401 | Metadata signature does not match signer/content |
| 403 | Disallowed browser origin; invalid local trial token or host |
| 404 | Route/content absent; stock directory on testnet |
| 409 | Required feature not configured; trial setup conflict |
| 413 / 414 / 415 | Body too large / URL too long / unsupported request media or encoding |
| 422 | Validly shaped request cannot execute under token, route, balance, or price-impact constraints |
| 429 | Rate or service-capacity limit |
| 502 / 503 | Upstream quote failure, unavailable state/venue, or degraded readiness |
| 500 | Unexpected standard-service failure with a generic public message |