Solana TPU Sender HTTP JSON-RPC API
HTTP JSON-RPC sendTransaction with Bearer or X-Api-Key authentication, base64 signed transactions, examples and retry handling.
// updated 2026-10-23
This page covers the HTTP JSON-RPC interface of the TPU Sender. The separate QUIK transport is listed on Endpoints and requires its own authorization and client setup.
Request format
Use your issued endpoint, for example https://sfls.l2.p2p.org. Send a signed base64 transaction containing a sufficient tip.
| Header | Value |
|---|---|
Content-Type | application/json |
Authorization | Bearer YOUR_API_KEY (preferred) |
X-Api-Key | YOUR_API_KEY (alternative) |
If both key headers are present, Authorization: Bearer takes priority.
# SIGNED_TX_BASE64 must already contain a tip of at least 150,000 lamports.
curl "$SENDER_URL" \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer $SENDER_API_KEY" \
-d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"sendTransaction\",\"params\":[\"$SIGNED_TX_BASE64\",{\"encoding\":\"base64\",\"skipPreflight\":true}]}"
TypeScript / Node.js
// Build the transaction with its tip, sign it, then serialize to base64.
const endpoint = process.env.SENDER_URL;
const apiKey = process.env.SENDER_API_KEY;
const signedTx = process.env.SIGNED_TX_BASE64;
if (!endpoint || !apiKey || !signedTx) throw new Error('Missing sender configuration');
const response = await fetch(endpoint, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${apiKey}`,
},
body: JSON.stringify({
jsonrpc: '2.0', id: 1, method: 'sendTransaction',
params: [signedTx, { encoding: 'base64', skipPreflight: true }],
}),
});
const body = await response.json();
if (!response.ok || body.error) {
throw new Error(JSON.stringify({ status: response.status, error: body.error }));
}
const signature = body.result;
// Confirm signature with getSignatureStatuses on your normal Solana RPC.
Success returns {"jsonrpc":"2.0","result":"TRANSACTION_SIGNATURE","id":1}. Submission and on-chain confirmation are separate events.
Errors
| JSON-RPC code | HTTP status | Meaning |
|---|---|---|
-32700 | 400 | Malformed JSON |
-32600 | 400 / 403 | Invalid request or authentication failure |
-32601 | 200 | Method unavailable |
-32602 | 200 / 400 | Invalid parameters, missing tip or insufficient tip |
-32603 | 500 | Internal error |
-32000 | 500 | Server error |
-32005 | 429 | Client rate exceeded |
Check the JSON-RPC error even when HTTP returns 200. Tip errors include Missing tip: no transfer to tip accounts found or Insufficient tip: provided X lamports, required Y lamports.
Connections and retries
Reuse HTTP connections. The documented keep-alive timeout is 30 seconds.
- 429: wait for
Retry-After.X-RateLimit-LimitandX-RateLimit-Remainingdescribe the current quota. - 400: correct the request before resubmitting.
- 500 or network failure: check signature status, then retry the same signed transaction with exponential backoff while its blockhash remains valid.
- Signature returned: track confirmation. Avoid blindly rebuilding and signing another transaction after an ambiguous timeout.
Reads, simulation and confirmation should use your regular RPC. Private-profile read access is optional; ask Supanode if you need it.