# BoltTx — Full API Reference (AI-friendly) > Canonical reference for AI agents, automated tooling, and LLM-assisted code generation. This file is the long-form companion to /llms.txt and mirrors the developer documentation at https://bolttx.io/docs in a single linearly readable document. BoltTx is a Solana transaction relay service. You POST signed transactions, we deliver them through an optimized on-chain submission path, track the result through an internal confirmation service, and return delivery telemetry. This file describes every public endpoint in depth so an agent can build a working integration without browsing the website. --- ## Architecture summary ``` [ your bot ] │ HTTP POST /v1/send (base64 signed tx) ▼ [ BoltTx API ] │ validates tip, rate-limits, dispatches ▼ [ Dispatcher ] ──── direct send (low TPS) │ └──── priority sort (high TPS: buffer 10ms, reorder by tip DESC) │ ▼ [ Delivery layer ] │ submits tx through optimized on-chain path ▼ [ Solana network ] │ Tx lands in a slot ▼ [ Confirmation tracker ] │ records confirm_ms for each tx ▼ [ tx_logs in Postgres ] ←── queryable via /v1/status ``` Key architectural properties: - No public mempool exposure. Direct on-chain delivery = anti-MEV by default. - We do NOT custody funds, sign transactions, hold private keys, or modify transaction contents. - Tip-based pricing: every transaction must include a SystemProgram transfer to a BoltTx tip address. Tip amount is enforced per-plan. - Multiple API keys per user account all share the same TPS budget (creating more keys does not raise your rate limits). --- ## Regional endpoints `https://bolttx.io` is the global entry point and routes internally. For latency-sensitive workloads you can instead POST directly to a regional hostname. Each regional hostname is a direct connection to a delivery node in that region — pick whichever is closest to where your bot runs, since network round-trip is usually the largest latency term you control. - `https://la.bolttx.io` — US West - `https://nj.bolttx.io` — US East - `https://fr.bolttx.io` — Europe - `https://sg.bolttx.io` — Asia-Pacific Every path documented below works identically on the global host and on all four regional hostnames. Substitute the hostname; nothing else changes. Both HTTP and HTTPS are served on every regional hostname. Reuse one connection (HTTP keep-alive) rather than opening a new one per transaction: on a reused connection HTTPS costs the same as plain HTTP, while a cold TLS handshake costs several times a warm request. ``` POST https://la.bolttx.io/v1/send POST https://nj.bolttx.io/v1/send POST https://fr.bolttx.io/v1/send POST https://sg.bolttx.io/v1/send ``` ## Endpoint: GET /health Liveness probe. No authentication, no rate limit, no request body. Use this to keep a connection warm between transactions. ``` GET https://la.bolttx.io/health ``` Note: the path is `/health`, not `/v1/health` — there is no `/v1/health` endpoint and requesting it returns 404. --- ## Authentication Both forms are accepted on every endpoint. Use whichever fits your client. **Form 1 — Authorization header (recommended for production)** ``` Authorization: Bearer YOUR_API_KEY ``` **Form 2 — URL query parameter (convenient for testing, simple clients, Solana RPC drop-in use)** ``` ?api-key=YOUR_API_KEY # or equivalently ?api_key=YOUR_API_KEY ``` API keys are format `btx_live_<32 lowercase alphanumeric>` (e.g. `btx_live_7sognc89o8eh5x81p5pms6e4j5dpcwu2`). Only sha256 hash + prefix are stored server-side; the full key is shown to the user exactly once at creation. --- ## Plans & rate limits | Plan | Send TPS | Query TPS | Min tip (SOL) | Min tip (lamports) | Auto-upgrade threshold | |---|---|---|---|---|---| | Starter | 8 | 16 | 0.0008 | 800 000 | 8 SOL cumulative tip → Growth | | Growth | 30 | 60 | 0.0005 | 500 000 | 80 SOL → Pro | | Pro | 80 | 160 | 0.0003 | 300 000 | 800 SOL → Whale | | Whale | 150 | 300 | 0.0001 | 100 000 | — (top tier) | - Rate limits use a token-bucket algorithm (1-second capacity = `max_tps(plan)`, refill rate = `max_tps(plan) / sec`). - Rate limits are PER-USER, shared across all API keys belonging to the same account. Creating more keys does not raise the limit. - The Query bucket (for `/v1/status`) is independent from the Send bucket; polling status does not consume your send budget. - When the tip bucket on a user's account crosses a threshold, the plan auto-upgrades on the next send. --- ## Tip addresses (9 production BoLt1-9 vanity addresses) A valid transaction MUST include a SystemProgram transfer to ONE of these addresses. The amount must meet or exceed your plan's minimum tip. Transactions without a valid tip are rejected with HTTP 402. ``` BoLt1A77XnXgmLPTWFXztQ9oZRrTPuQHV7cChFCt35g6 BoLt2zHYz1VoNbw2hoKZGaJcEXe2aNGP8EweZx1Z48wr BoLt3D1LXn3ne9t569Csq373xoau1fFbFpU6SSc6QaH2 BoLt4MWGU9mQHkUzEvbfmaiDFv4DGHA4aaz3WLAAyf8G BoLt5YM7HtjWvNTe7yZYArbFLc4ZvrJBMGra4axNCwoH BoLt6TxL6NsFkYPBzRgZwbxui9WUYGRZM4NynbhBXY4n BoLt7AZCGzHGSkq5Q97vyb8nxg3nZJCUQ4Mx2tkgdYg2 BoLt8TNYGrqdxMZTeg5yRdMnoWn1PghKyga8D5XxVFQ8 BoLt9VAW1CprYRL13HZCWi7UYgZwVmQJZ35jFYem44Fq ``` Pick any one. For best performance include the tip as the LAST instruction in your transaction (after compute-budget + your actual ix). --- ## Endpoint: POST /v1/send Submit a single signed transaction. **Request** ``` POST https://bolttx.io/v1/send Authorization: Bearer YOUR_API_KEY Content-Type: application/json { "transaction": "", "options": { "skip_preflight": true, "max_retries": 3, "anti_mev": true } } ``` `options` is optional. Defaults: `skip_preflight=true`, `max_retries=3`, `anti_mev=true`. `anti_mev` is effectively always on because BoltTx delivers through a path that never exposes the tx to a public mempool, but the flag is accepted for forward compatibility. **Response (200)** ```json { "success": true, "signature": "5xKnR8qXeVm3pN...", "slot": 234567890 } ``` **Error responses** | Code | Body | Cause | |---|---|---| | 400 | `{"success":false,"error":"Invalid base64 encoding"}` | base64 decode failed | | 400 | `{"success":false,"error":"Invalid transaction format"}` | bincode deserialize failed (not a VersionedTransaction) | | 401 | `{"success":false,"error":"Missing API key"}` | no Authorization header and no ?api-key= | | 401 | `{"success":false,"error":"Invalid API key"}` | key not found or revoked | | 402 | `{"success":false,"error":"Transaction must include a tip transfer to a BoltTx tip address"}` | no SystemProgram transfer to any tip address | | 402 | `{"success":false,"error":"Insufficient tip: X lamports (plan 'starter' requires minimum 800000 lamports / 0.0008 SOL)"}` | tip below plan minimum | | 429 | `{"success":false,"error":"Rate limit exceeded for plan 'starter' (8 TPS). Retry in ~XXXms."}` | TPS exceeded | | 500 | `{"success":false,"error":""}` | On-chain delivery failed | --- ## Endpoint: POST /v1/send/batch Submit up to 100 transactions in one request. Transactions are dispatched concurrently (not serially) on-chain. **Request** ``` POST https://bolttx.io/v1/send/batch Authorization: Bearer YOUR_API_KEY Content-Type: application/json { "transactions": [ "", "", ... ] } ``` - Hard cap: 100 transactions per batch. - Rate limit: a batch of N transactions consumes N tokens from your TPS bucket atomically (all-or-nothing). A Starter user cannot bypass the 8 TPS cap by batching 100 in one HTTP request. **Response (200)** ```json { "success": true, "results": [ { "index": 0, "signature": "...", "status": "sent" }, { "index": 1, "signature": "...", "status": "sent" }, { "index": 2, "signature": null, "status": "failed", "error": "Invalid base64" } ] } ``` Each tx is reported independently. `status` is either `"sent"` (accepted and dispatched) or `"failed"` (decode/send error for this specific tx). **Error responses (whole batch)** | Code | Cause | |---|---| | 400 | `Max 100 transactions per batch` | | 401 | Missing or invalid API key | | 429 | Batch size N exceeds current TPS budget | --- ## Endpoint: POST /v1/send/binary Submit a raw bincode-serialized transaction without the JSON wrapper or base64 overhead. Lowest latency option (~0.5-1ms saved vs `/v1/send`). **Request** ``` POST https://bolttx.io/v1/send/binary Authorization: Bearer YOUR_API_KEY Content-Type: application/octet-stream ``` **Response** — same shape as `/v1/send`. Use this if you have tight control over the client side (Rust, Go, native code). Most TypeScript/Python users should stick with `/v1/send`. --- ## Endpoint: POST / (site root) — Solana JSON-RPC drop-in If you already use the official `@solana/web3.js` Connection object or any Solana RPC client library, you can swap your RPC URL to `https://bolttx.io/?api-key=YOUR_API_KEY` with zero code changes. Only the `sendTransaction` method is routed through BoltTx; other methods are unsupported. **Request** ``` POST https://bolttx.io/?api-key=YOUR_API_KEY Content-Type: application/json { "jsonrpc": "2.0", "id": 1, "method": "sendTransaction", "params": [ "", { "encoding": "base64", "skipPreflight": true, "maxRetries": 3 } ] } ``` **Response (success)** ```json { "jsonrpc": "2.0", "id": 1, "result": "5xKnR8qXeVm3pN..." } ``` **JSON-RPC error codes** | Code | Meaning | |---|---| | -32600 | Invalid request | | -32601 | Method not found (only `sendTransaction` is supported) | | -32602 | Invalid params | | -32603 | Internal error | | 401 | Missing API key | | 402 | Missing or insufficient tip | | 403 | Invalid API key | | 429 | Rate limit exceeded | **Drop-in example (TypeScript)** ```typescript import { Connection, Keypair, ... } from "@solana/web3.js"; // Swap your RPC URL — all sendTransaction calls now go through BoltTx. // Keep using your regular Solana RPC for read methods. const connection = new Connection("https://bolttx.io/?api-key=btx_live_xxx"); const sig = await connection.sendTransaction(tx, [payer], { skipPreflight: true, maxRetries: 3, }); ``` --- ## Endpoint: GET /v1/status/{signature} Query BoltTx's delivery telemetry for a transaction YOU submitted. This is NOT a general on-chain status oracle — it only returns transactions your account's API keys actually sent through BoltTx. **Request** ``` GET https://bolttx.io/v1/status/ Authorization: Bearer YOUR_API_KEY ``` URL auth also works: `GET https://bolttx.io/v1/status/?api-key=YOUR_API_KEY` **Response (200)** ```json { "signature": "5xKnR8qXeVm3pN...", "status": "confirmed", "submitted_at": "2026-04-14T08:21:33.086Z", "confirmed_at": "2026-04-14T08:21:33.594Z", "latency_ms": 508, "slot": 234567890, "api_key_name": "prod-bot-1" } ``` **Response fields** | Field | Type | Meaning | |---|---|---| | `signature` | string | The transaction signature you queried | | `status` | `"sent"` / `"confirmed"` / `"failed"` | BoltTx-tracked lifecycle (not Solana commitment) | | `submitted_at` | ISO-8601 UTC | When BoltTx accepted and sent this tx | | `confirmed_at` | ISO-8601 UTC or null | When our tracker saw the tx land on-chain. Null until terminal. | | `latency_ms` | number or null | Submit→confirm wall-clock, measured by BoltTx. Null until terminal. | | `slot` | number or null | Slot the tx landed in | | `api_key_name` | string | Friendly name of the API key that submitted this tx (helps you identify which of your bots sent it) | **Deliberate omissions**: We do NOT return `confirmation_status` (processed/confirmed/finalized) or on-chain `error` details. For those, query your own Solana RPC's `getSignatureStatuses`. BoltTx is a delivery service, not a chain query service — omitting these keeps our endpoint at ~1ms latency instead of 10-50ms (which would be dominated by an upstream RPC call). **Error responses** | Code | Cause | |---|---| | 400 | `Invalid signature` — malformed base58 | | 401 | Missing or invalid API key | | 404 | `Transaction not found in your account.` — either never went through BoltTx, or was submitted by a different user's keys | | 429 | Query bucket exhausted (2× your plan's Send TPS) | | 500 | Database error | --- ## Status lifecycle values - `sent` — Transaction has been submitted; our tracker has not yet seen it confirmed - `confirmed` — Transaction landed on-chain and executed successfully - `failed` — Transaction landed but execution reverted (you'll need to query your own RPC for the on-chain error details) --- ## Headers overview (every endpoint) **Request headers** | Header | Values | Required | |---|---|---| | `Authorization` | `Bearer YOUR_API_KEY` | Required (unless using `?api-key=` query) | | `Content-Type` | `application/json` (send/batch), `application/octet-stream` (binary) | Required on POST | **Response headers** | Header | Meaning | |---|---| | `Content-Type` | `application/json` on all endpoints | | `x-request-id` | Opaque per-request ID (echo this when reporting issues) | --- ## Complete working examples ### TypeScript — /v1/send ```typescript import { Connection, Keypair, SystemProgram, Transaction, PublicKey, } from "@solana/web3.js"; const BOLTTX_API = "https://bolttx.io/v1/send"; const API_KEY = process.env.BOLTTX_API_KEY!; const TIP_ADDR = new PublicKey("BoLt1A77XnXgmLPTWFXztQ9oZRrTPuQHV7cChFCt35g6"); const MIN_TIP = 800_000; // Starter: 0.0008 SOL async function send(payer: Keypair, recipient: PublicKey, lamports: number) { const rpc = new Connection("https://api.mainnet-beta.solana.com"); const { blockhash } = await rpc.getLatestBlockhash(); const tx = new Transaction({ feePayer: payer.publicKey, recentBlockhash: blockhash }); // 1. Your actual instruction(s) tx.add(SystemProgram.transfer({ fromPubkey: payer.publicKey, toPubkey: recipient, lamports, })); // 2. Tip to BoltTx (MUST be included, put it last for best delivery ordering) tx.add(SystemProgram.transfer({ fromPubkey: payer.publicKey, toPubkey: TIP_ADDR, lamports: MIN_TIP, })); tx.sign(payer); const res = await fetch(BOLTTX_API, { method: "POST", headers: { "Authorization": `Bearer ${API_KEY}`, "Content-Type": "application/json", }, body: JSON.stringify({ transaction: tx.serialize().toString("base64"), options: { skip_preflight: true, max_retries: 3 }, }), }); if (!res.ok) { const err = await res.json(); throw new Error(`BoltTx ${res.status}: ${err.error}`); } return await res.json(); } ``` ### Python — /v1/send ```python import base64, os, requests from solders.keypair import Keypair from solders.pubkey import Pubkey from solders.system_program import TransferParams, transfer from solders.transaction import Transaction from solana.rpc.api import Client API_KEY = os.environ["BOLTTX_API_KEY"] TIP_ADDR = Pubkey.from_string("BoLt1A77XnXgmLPTWFXztQ9oZRrTPuQHV7cChFCt35g6") MIN_TIP = 800_000 rpc = Client("https://api.mainnet-beta.solana.com") payer = Keypair.from_base58_string(os.environ["PAYER_SECRET"]) blockhash = rpc.get_latest_blockhash().value.blockhash ix_payment = transfer(TransferParams( from_pubkey=payer.pubkey(), to_pubkey=Pubkey.from_string("..."), lamports=100_000, )) ix_tip = transfer(TransferParams( from_pubkey=payer.pubkey(), to_pubkey=TIP_ADDR, lamports=MIN_TIP, )) tx = Transaction.new_signed_with_payer( [ix_payment, ix_tip], payer.pubkey(), [payer], blockhash, ) tx_b64 = base64.b64encode(bytes(tx)).decode() res = requests.post( "https://bolttx.io/v1/send", headers={"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"}, json={"transaction": tx_b64}, ) print(res.json()) ``` ### Rust — /v1/send ```rust use base64::Engine; use solana_client::nonblocking::rpc_client::RpcClient; use solana_sdk::{ pubkey::Pubkey, signature::Keypair, signer::Signer, system_instruction, transaction::Transaction, }; use std::str::FromStr; const TIP_ADDR: &str = "BoLt1A77XnXgmLPTWFXztQ9oZRrTPuQHV7cChFCt35g6"; const MIN_TIP: u64 = 800_000; async fn send( payer: &Keypair, recipient: &Pubkey, lamports: u64, api_key: &str, ) -> anyhow::Result<()> { let rpc = RpcClient::new("https://api.mainnet-beta.solana.com".into()); let blockhash = rpc.get_latest_blockhash().await?; let tip = Pubkey::from_str(TIP_ADDR)?; let ixs = vec![ system_instruction::transfer(&payer.pubkey(), recipient, lamports), system_instruction::transfer(&payer.pubkey(), &tip, MIN_TIP), ]; let tx = Transaction::new_signed_with_payer(&ixs, Some(&payer.pubkey()), &[payer], blockhash); let tx_bytes = bincode::serialize(&tx)?; let tx_b64 = base64::engine::general_purpose::STANDARD.encode(&tx_bytes); let client = reqwest::Client::new(); let body = serde_json::json!({ "transaction": tx_b64 }); let res = client.post("https://bolttx.io/v1/send") .header("Authorization", format!("Bearer {}", api_key)) .json(&body) .send().await?; let out: serde_json::Value = res.json().await?; println!("{}", out); Ok(()) } ``` ### cURL — status query (both auth forms) ```bash # Header auth curl https://bolttx.io/v1/status/5xKnR8qXeVm3pN... \ -H "Authorization: Bearer btx_live_xxx" # URL auth (for quick debugging) curl "https://bolttx.io/v1/status/5xKnR8qXeVm3pN...?api-key=btx_live_xxx" ``` --- ## Error handling best practices - Treat `429` as a signal to backoff. The error body includes `retry_after_ms` — respect it. - On `402` (insufficient tip), check `min_tip_lamports(plan)` before retrying. Don't just bump tip blindly; rebuild the tx with the correct tip amount. - On `401`, your key is invalid or revoked. Do NOT retry — surface the error to the user / operator. - On `500`, retry with exponential backoff (start at 100ms, cap at 2s, max 3 attempts). BoltTx upstream errors are usually transient. - Build idempotent logic: if `/v1/send` returns 500 but your tx already reached the network, retrying with the same signed tx is safe (Solana rejects duplicate signatures). --- ## Design guarantees worth knowing - **Bytes fidelity**: the exact bytes you POST are the exact bytes that land on-chain. We do not re-sign, mutate, or inspect transaction contents. - **Ordering by tip**: within BoltTx's queue, higher tip = higher priority. During high-TPS bursts (>30 TPS globally), we briefly buffer for 10ms and sort by tip descending before forwarding. Below 30 TPS it's first-come-first-served. - **No retry without consent**: if on-chain delivery fails, we do NOT automatically retry unless `options.max_retries > 0`. This prevents duplicate delivery when your client is already retrying. - **Signature ownership**: the `/v1/status` endpoint enforces per-account ownership. User A cannot look up user B's transaction signatures. Both "never sent through BoltTx" and "sent by a different user" collapse into 404 (indistinguishable to the caller — deliberate, to prevent enumeration). --- ## Dashboard & account management - Dashboard: https://bolttx.io/dashboard - API key management: https://bolttx.io/dashboard/api-keys - Transaction logs: https://bolttx.io/dashboard/logs - Usage statistics: https://bolttx.io/dashboard/usage - Settings: https://bolttx.io/dashboard/settings Up to 10 active API keys per account. Revoking a key is a soft-delete — historical transaction logs preserve the key name for attribution. Plan upgrades are automatic based on cumulative tip paid and take effect within 30 seconds. --- ## Companion documents - Short summary: https://bolttx.io/llms.txt - Full HTML docs: https://bolttx.io/docs - Quickstart guide: https://bolttx.io/docs/quickstart - Anti-MEV details: https://bolttx.io/docs/advanced/anti-mev - Durable nonce pattern: https://bolttx.io/docs/advanced/durable-nonce - Best practices: https://bolttx.io/docs/advanced/best-practices --- ## Contact - General + privacy: contact@bolttx.io - Dashboard: https://bolttx.io/dashboard --- *This file is updated whenever the public API surface changes. Last updated: April 2026.*