sendTransaction — Solana JSON-RPC
Submits a fully-signed transaction to the Solana cluster for processing and returns its signature.
- Network
- Solana
- Auth
- x-token: $TRIPORT_API_KEY (or Authorization: Bearer)
- Rate limit
- free+ — free 5 rps · basic 10 rps · pro 50 rps · business 150 rps (sol_send_tx)
Endpoint and plans: Solana RPC endpoint.
sendTransaction broadcasts an already-signed, fully-serialized transaction to
the cluster for execution. The transaction must be signed by all required
signers and contain a recent blockhash before you call this method — Triport
does not sign on your behalf.
By default the receiving node runs a preflight check (a simulation against
the preflightCommitment bank) before forwarding the transaction. If preflight
fails, the call returns an error and the transaction is not forwarded by that
node. The method returns the transaction's first signature (base-58) as
soon as an upstream accepts it — this is not a confirmation. Use
getSignatureStatuses or
getTransaction to poll for confirmation.
This method is available on all tiers but is throttled separately under the
sol_send_tx category, so send throughput is independent of your read-RPC
budget. To validate a transaction without submitting it, use
simulateTransaction instead.
Endpoints for sending
| Endpoint | Path | Use it for |
|---|---|---|
https://fra.triport.io/sol | direct to Triport's Frankfurt edge, no Cloudflare | sending transactions when every millisecond counts |
https://triport.io/sol | through Cloudflare, with automatic fallback to other regions | all methods, and as the fallback for sending |
Both take the same API key and the same JSON-RPC body. fra.triport.io is
meant for sending transactions; keep reads and streams on triport.io. The
direct endpoint has no automatic failover — if it does not answer, resend
through https://triport.io/sol.
Measured on 2026-10-08 from a server in Frankfurt, in the same data center as the edge (warm keep-alive connection, 40 requests through the edge):
| Endpoint | min | p50 | p90 |
|---|---|---|---|
https://fra.triport.io/sol | 0.14 ms | ≈ 0.2 ms | ≈ 0.3 ms |
https://triport.io/sol (Cloudflare) | ≈ 14 ms | ≈ 20–35 ms | up to ≈ 100 ms |
The figures cover network plus edge handling, not the upstream's answer. Clients outside that data center add their own network distance to Frankfurt.
How Triport routes your transaction
Your request is forwarded with the transaction and config unchanged:
skipPreflight, preflightCommitment, maxRetries, minContextSlot and
encoding reach every upstream exactly as you sent them. Triport does not
rebroadcast the transaction after an upstream has accepted it; maxRetries
keeps its usual meaning on the upstream node.
On Triport's primary Solana edge a single sendTransaction request is
submitted to several upstream paths in parallel, and the first upstream
that returns a signature (result) is the answer you get:
| Path | Used when | Notes |
|---|---|---|
cohort — Triport RPC path | always | A Solana RPC node that forwards to the current leader. |
sender — Helius Sender | the transaction transfers a tip to one of the Helius Sender tip accounts (below) | Sender requires its own tip and a compute-unit price; without them it rejects the transaction and the other paths still answer. |
jito — Jito block engine | the transaction transfers a tip to one of the Jito tip accounts (below) | Used when capacity is available; check X-Triport-Send-Legs to see whether it was attempted. |
If no path returns a signature, you get the Triport RPC path's answer (for example its preflight error). Solana de-duplicates by signature, so the same signed transaction arriving over several paths is processed at most once.
Paths are chosen from the transaction's static account keys. A tip account
referenced only through an address lookup table is not detected — put the tip
account in the static keys. Requests in a JSON-RPC batch use only the
Triport RPC path. If your request is served by a fallback region, only the
Triport RPC path is used and the X-Triport-Send-* headers are absent.
Response headers
| Header | Example | Meaning |
|---|---|---|
X-Triport-Send-Winner | cohort | Path whose answer you received: cohort, sender, jito, or none when no upstream answered. |
X-Triport-Send-Legs | cohort,sender | Paths the transaction was submitted to. |
Server-Timing | send;dur=…;desc="cohort" | Time from Triport receiving the request to the winning upstream answer, measured on Triport's server. |
Tip accounts
A tip is a plain SOL transfer to one of these accounts, as an instruction of the same transaction. Include a compute-unit price (priority fee) as well.
Helius Sender (mainnet, from the Helius Sender documentation, 2026-10-08):
4ACfpUFoaSD9bfPdeu6DBt89gB6ENTeHBXCAi87NhDEE
D2L6yPZ2FmmmTKPgzaMKdhu6EWZcTpLy1Vhx8uvZe7NZ
9bnz4RShgq1hAnLnZbP8kbgBg1kEmcJBYQq3gQbmnSta
5VY91ws6B2hMmBFRsXkoAAdsPHBJwRfBht4DXox3xkwn
2nyhqdwKcJZR2vcqCyrYsaPVdAnFoJjiksCXJ7hfEYgD
2q5pghRs6arqVjRvT5gfgWfWcHWmw1ZuCzphgd5KfWGJ
wyvPkWjVZz1M8fHQnMMCDTQDbkManefNNhweYk5WkcF
3KCKozbAaF75qEU33jtzozcJ29yJuaLJTy2jFdzUY8bT
4vieeGHPYPG2MmyPRcYjdiDmmhN3ww7hsFNap8pVN3Ey
4TQLFNWK8AovT1gFvda5jfw2oJeRMKEmw7aH6MGBJ3orHelius documents a minimum Sender tip of 0.000005 SOL (single staked path) and 0.001 SOL for all of its routing paths; check their documentation for the current values.
Jito (mainnet, from the block engine's getTipAccounts, 2026-10-08):
96gYZGLnJYVFmbjzopPSU6QiEV5fGqZNyN9nmNhvrZU5
ADuUkR4vqLUMWXxW9gh6D6L8pMSawimctcNZ5pGwDcEt
DttWaMuVvTiduZRnguLF7jNxTgiMBZ1hyAumKUiL2KRL
HFqU5x63VTqvQss8hp11i4wVV8bD44PvwucfZ2bU7gRe
DfXygSm4jCyNCybVYYK6DwvWqjKee8pbDmJGcLWNDXjh
Cw8CFyM9FkoMi7K7Crf6HNQqf4uEMzpKw6QNghXLvLkY
ADaUMid9yfUytqMBgopwjb2DTLSokTSzL1zt6iGPaS49
3AVi9Tg9Uo68tJfuvoKvqKNWKkC5wPdSSdeBnizKZ6jTWhat a successful response means
result means an upstream accepted the transaction for forwarding. It
does not mean the leader received it, and it does not mean it landed — a
transaction can still be dropped or expire with its blockhash. Confirm with
getSignatureStatuses, signatureSubscribe on wss://triport.io/ws/sol, or
getTransaction.
Parameters
Positional params array: [transaction, config?].
transactionstringrequiredconfig.encoding.configobjectoptionalencoding"base58" | "base64"optionaltransaction string. base64 is recommended; base58 is slower and is supported for compatibility.skipPreflightbooleanoptionaltrue, skip the preflight simulation/checks and forward the transaction immediately. Default false.preflightCommitment"processed" | "confirmed" | "finalized"optional"finalized".minContextSlotintegeroptionalmaxRetriesintegeroptional0 disables automatic retries.Response
Response fields
| Field | Type | Description |
|---|---|---|
result | string | The transaction's first signature, base-58 encoded. Use it to track confirmation status. |
Errors
Errors are returned in the standard JSON-RPC envelope — see errors.md for the full shape.
| Code | Meaning | When it happens |
|---|---|---|
-32602 | Invalid params | transaction is malformed, unsigned, or its encoding does not match config.encoding. |
-32002 | Transaction simulation failed | Preflight rejected the transaction (e.g. expired blockhash, insufficient funds, failing instruction). Only returned when skipPreflight is false. |
401 | Unauthorized | Missing or invalid Authorization: Bearer API key. |
429 | Rate limited | Request rate exceeded your tier's sol_send_tx RPS limit (free 5 · basic 10 · pro 50 · business 150). Back off and retry. |
Examples
JavaScript (fetch)
// Direct endpoint for sending; on a network error retry via https://triport.io/sol.
const res = await fetch("https://fra.triport.io/sol", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.TRIPORT_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
jsonrpc: "2.0",
id: 1,
method: "sendTransaction",
params: [
signedTxBase64,
{ encoding: "base64", skipPreflight: false, preflightCommitment: "processed", maxRetries: 0 },
],
}),
});
const { result: signature } = await res.json();
console.log("submitted:", signature);Notes
- For time-sensitive sends, include a compute-unit price and a tip to one of
the tip accounts; keep
skipPreflight: trueonly when you have simulated the transaction yourself. - The returned signature confirms acceptance, not finality. Poll
getSignatureStatusesor fetch the transaction withgetTransactionto confirm it landed. - Set the transaction's blockhash from a recent
getLatestBlockhashresult; an expired blockhash causes preflight (or eventual processing) to fail. - Prefer
encoding: "base64"— it is more compact and faster to decode thanbase58. - To dry-run a transaction without broadcasting it, use
simulateTransaction. sendTransactionuses thesol_send_txrate-limit category, separate from read-RPC limits.- Signature but never confirmed? See why a Solana transaction never lands for dropped transactions, blockhash expiry and when it is safe to re-sign.