Falcon Cloud RPC gateway
Falcon PL is a testnet. FPL testnet tokens have no monetary value and cannot be bought or sold. Paid plans pay for RPC capacity and support only.
Base URL: https://rpc.falcon-fpl.com
Authentication
Every RPC call needs an API key. Send it as Authorization: Bearer fplk_… or X-API-Key: fplk_….
Keys are shown once when issued and stored only as a SHA-256 hash. Keep them server-side; never ship a key in browser code or a public repo. Every plan, including Free, needs a key. Keys are issued on request through BEARTEC: see get an API key.
Endpoints
| Route | Key | Notes |
|---|---|---|
| POST /v1/rpc | yes | JSON-RPC 2.0, one request per call |
| GET /v1/usage | yes | Your key’s month-to-date usage and limits |
| GET /v1/health | no | Gateway and node liveness |
| GET /v1/tiers | no | Current tier table |
Browser calls (CORS)
Browser requests are accepted only from approved origins: https://falcon-fpl.comhttps://www.beartec.uk. Call the gateway from your own server for anything else.
Not supported yet
- Batch requests (a JSON array) return HTTP 400. Send one request per call.
- There is no WebSocket or subscription endpoint. Poll instead.
Both are planned for a later release.
Allowed methods
Read methods plus transaction submit. Node admin and operator calls are never exposed.
| Method | Params | Returns | Units |
|---|---|---|---|
| fpl_status | — | Brief chain status (tip height, rails). Never includes the account dump. | 1 |
| fpl_health | warnings? (0–64) | Node health snapshot (falcon.health.v1). | 1 |
| fpl_getAccount | account | Sequence, balance, claimable, assets. | 1 |
| fpl_orderBook | pair, levels? (≤200) | Order book depth and pool spot. | 1 |
| fpl_openOrders | account | An account's open orders. | 1 |
| fpl_fills | pair?, account?, limit? (≤200) | Recent fills, newest first. | 1 |
| fpl_submitTx | tx (signed transaction object) | { msg } on acceptance into the mempool. | 5 |
curl
curl -s https://rpc.falcon-fpl.com/v1/rpc \
-H "Authorization: Bearer $FPL_API_KEY" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"fpl_getAccount","params":{"account":"alice"}}'JavaScript
// Node 18+ / browsers. Keep the key server-side.
async function fpl(method, params = {}, tries = 4) {
for (let i = 0; i < tries; i++) {
const r = await fetch('https://rpc.falcon-fpl.com/v1/rpc', {
method: 'POST',
headers: { Authorization: `Bearer ${process.env.FPL_API_KEY}`, 'Content-Type': 'application/json' },
body: JSON.stringify({ jsonrpc: '2.0', id: 1, method, params }),
})
if (r.status === 429) {
const wait = Number(r.headers.get('retry-after') ?? 1)
await new Promise((ok) => setTimeout(ok, wait * 1000))
continue
}
const body = await r.json()
if (body.error) throw new Error(`${body.error.code}: ${body.error.message}`)
return body.result
}
throw new Error('rate limited')
}
const status = await fpl('fpl_status')Python
import os, time, requests
def fpl(method, params=None, tries=4):
for _ in range(tries):
r = requests.post(
"https://rpc.falcon-fpl.com/v1/rpc",
headers={"Authorization": f"Bearer {os.environ['FPL_API_KEY']}"},
json={"jsonrpc": "2.0", "id": 1, "method": method, "params": params or {}},
timeout=10,
)
if r.status_code == 429:
time.sleep(int(r.headers.get("Retry-After", "1")))
continue
body = r.json()
if "error" in body:
raise RuntimeError(f"{body['error']['code']}: {body['error']['message']}")
return body["result"]
raise RuntimeError("rate limited")
print(fpl("fpl_orderBook", {"pair": "BTC4-FPL", "levels": 10}))Errors
Errors use the JSON-RPC envelope { "error": { "code", "message" } }.
| HTTP | Code | Meaning | What to do |
|---|---|---|---|
| 401 | -32001 | Missing or invalid API key | Send Authorization: Bearer fplk_… or X-API-Key. |
| 429 | -32005 | Rate limit, tx-submit limit or monthly quota reached | Wait Retry-After seconds. Quota errors reset on the 1st (00:00 UTC). |
| 200 | -32601 | Method not allowed | Only the methods listed above are available. |
| 200 | -32602 | Invalid params | Check the params object. |
| 200 | -32000 | Node rejected the request | Read error.message (e.g. unknown account, bad tx). |
| 400 | -32700 | Body is not valid JSON | Send one JSON-RPC 2.0 object. |
| 400 | -32600 | Batch requests are not supported yet | Send one request per call. |
| 413 | — | Body larger than 64 KiB | Transactions are far smaller; check what you send. |
| 502 | -32002 | Node unavailable | Retry with backoff. |
| 503 | -32003 | Gateway busy | Retry with backoff. |
Handling 429
Each key has a per-second rate with a short burst allowance, a separate per-minute limit for fpl_submitTx, and a monthly quota in units. When you exceed a rate, the gateway answers HTTP 429 with a Retry-After header in seconds: wait that long, then retry. The examples above do this. A quota 429 has no Retry-After and lasts until the 1st of the month (00:00 UTC). Check GET /v1/usage to see where you are. Limits per plan: pricing.