> For the complete documentation index, see [llms.txt](https://docs.triton.one/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.triton.one/solana/sending-transactions/quickstart.md).

# Sending transactions quickstart

Send a Solana transaction with POST /sendtx or JSON-RPC sendTransaction, then confirm it with getSignatureStatuses.

`/sendtx` is available on every Triton mainnet endpoint. It and `sendTransaction` both go through our Jet engine, with SWQoS applied on mainnet.

## 0. Prerequisites

* An active Triton subscription.
* Your endpoint URL and secret token from the [customer dashboard](https://customers.triton.one).
* A funded keypair and a way to build and sign a transaction (`@solana/web3.js`, `@solana/kit`, or your SDK of choice).
* The samples use `@solana/web3.js` 1.x: `npm i @solana/web3.js@1 bs58`.
* The TypeScript samples use top-level `await`: set `"type": "module"` in `package.json`.

## 1. Build and sign a transaction

Build and sign as usual, then serialize it to raw bytes. The signature is deterministic, so you can read it from the signed transaction before you send.

```ts
import {
  Connection, Keypair, PublicKey, SystemProgram, Transaction,
} from "@solana/web3.js";
import bs58 from "bs58";

const connection = new Connection("https://<your-endpoint>.mainnet.rpcpool.com/<your-token>", "confirmed");
const payer = Keypair.fromSecretKey(Uint8Array.from(JSON.parse(process.env.SECRET_KEY!))); // 64-byte secret key

const tx = new Transaction().add(
  SystemProgram.transfer({
    fromPubkey: payer.publicKey,
    toPubkey: new PublicKey("RecipientAddressBase58"),
    lamports: 1000,
  }),
);
tx.recentBlockhash = (await connection.getLatestBlockhash()).blockhash;
tx.feePayer = payer.publicKey;
tx.sign(payer);

const wire = tx.serialize();           // raw bytes
const expectedSignature = bs58.encode(tx.signature!); // base58 signature, known before you send
```

## 2. Submit it

{% tabs %}
{% tab title="/sendtx" %}
{% tabs %}
{% tab title="TypeScript" %}

```ts
const res = await fetch(
  "https://<your-endpoint>.mainnet.rpcpool.com/<your-token>/sendtx?response=signature",
  {
    method: "POST",
    headers: { "Content-Type": "application/octet-stream" },
    body: new Uint8Array(wire), // plain Uint8Array copy: TypeScript's fetch BodyInit type rejects a Buffer
  },
);

console.log("Signature:", await res.text());
```

{% endtab %}

{% tab title="curl (raw bytes)" %}

```bash
curl -X POST 'https://<your-endpoint>.mainnet.rpcpool.com/<your-token>/sendtx?response=signature' \
  -H 'Content-Type: application/octet-stream' \
  --data-binary @transaction.bin
```

{% endtab %}

{% tab title="curl (base64)" %}

```bash
curl -X POST 'https://<your-endpoint>.mainnet.rpcpool.com/<your-token>/sendtx?encoding=base64&response=signature' \
  -H 'Content-Type: text/plain' \
  -d 'BASE64_SIGNED_TX'
```

{% endtab %}
{% endtabs %}

Query parameters:

* `encoding`: `base58` (default) or `base64`, for text bodies. Rejected with `application/octet-stream`.
* `response=signature`: returns the signature on success. Without it, the response body is empty.
* `max_retries`: accepted, but it adds no retries. Triton doesn't retry on the server, so rebroadcast the same signed bytes from your client until the transaction confirms or its blockhash expires.

Optional header: `Solana-ForwardingPolicies` takes comma-separated [Yellowstone Shield](/solana/sending-transactions/shield-mev-protection.md) policy addresses to apply when forwarding.

{% hint style="warning" %}
`/sendtx` always skips preflight, so `skipPreflight: false` and simulation are not supported on it, and it serves no other RPC methods. Use `sendTransaction` if you need preflight, though we recommend running `simulateTransaction` as a separate call either way.
{% endhint %}

On success, `/sendtx` returns HTTP 200. With `response=signature`, the body is the transaction signature as plain text, not JSON:

```
5j7s4Hk3vQmPq8nLZ9xTe8oP...
```

An invalid request returns HTTP 400 with a plain-text error message, and methods other than POST return HTTP 405, except the CORS preflight `OPTIONS` request. Rate limiting and server errors return other 4xx or 5xx statuses.
{% endtab %}

{% tab title="sendTransaction" %}
{% tabs %}
{% tab title="TypeScript" %}

```ts
const signature = await connection.sendRawTransaction(wire);
console.log("Signature:", signature);
```

{% endtab %}

{% tab title="curl" %}

```bash
curl https://<your-endpoint>.mainnet.rpcpool.com/<your-token> -s -X POST \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "sendTransaction",
    "params": ["BASE64_SIGNED_TX", { "encoding": "base64" }]
  }'
```

{% endtab %}
{% endtabs %}

The JSON-RPC result is the transaction signature:

```json
{ "jsonrpc": "2.0", "result": "5j7s4Hk3vQmPq8nLZ9xTe8oP...", "id": 1 }
```

{% endtab %}
{% endtabs %}

`/sendtx` skips the JSON-RPC envelope, so there is no JSON parsing and the request body is smaller. See the [sendTx](/solana/rpc-methods/sending-transactions/sendtx.md) reference for CORS behavior, parameters, headers, and responses, and [sendTransaction](/solana/rpc-methods/sending-transactions/sendtransaction.md) for the standard JSON-RPC interface.

## 3. Verify it landed

{% tabs %}
{% tab title="curl" %}

```bash
curl https://<your-endpoint>.mainnet.rpcpool.com/<your-token> -s -X POST \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "getSignatureStatuses",
    "params": [["YOUR_SIGNATURE"], { "searchTransactionHistory": true }]
  }'
```

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "result": {
    "context": { "slot": 460215362 },
    "value": [
      { "slot": 460215360, "confirmations": null, "err": null, "status": { "Ok": null }, "confirmationStatus": "finalized" }
    ]
  },
  "id": 1
}
```

{% endtab %}
{% endtabs %}

A `confirmationStatus` of `confirmed` or `finalized` means it landed, and `"err": null` means it also succeeded. If the status is still `null`, resend the same `wire` bytes until it lands or its blockhash expires; don't re-sign while the original can still land. See [Handle retries yourself](/solana/sending-transactions/best-practices.md#handle-retries-yourself).

## What's next

<table data-card-size="large" data-view="cards"><thead><tr><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><i class="fa-paper-plane">:paper-plane:</i> <strong>Yellowstone Jet TPU client</strong></td><td>Send transactions straight to leaders over QUIC from Rust, with leader tracking and per-transaction callbacks.</td><td><a href="/solana/quickstart/sending-transactions/yellowstone-jet-tpu-client.md">Yellowstone Jet TPU client</a></td></tr><tr><td><i class="fa-arrow-trend-up">:arrow-trend-up:</i> <strong>Priority fees API</strong></td><td>getRecentPrioritizationFees with a percentile parameter, to choose a priority fee.</td><td><a href="/solana/sending-transactions/priority-fees-api.md">Priority fees API</a></td></tr><tr><td><i class="fa-list-check">:list-check:</i> <strong>Sending transactions best practices</strong></td><td>Simulation, retries, /sendtx, confirmation, and Shield.</td><td><a href="/solana/sending-transactions/best-practices.md">Sending transactions best practices</a></td></tr></tbody></table>

***

<i class="fa-life-ring">:life-ring:</i> Contact support by clicking the chat icon in your [customer dashboard](https://customers.triton.one)\ <i class="fa-briefcase">:briefcase:</i> Sales questions? [Contact us](https://triton.one/contact)\ <i class="fa-sparkles">:sparkles:</i> AI agent? Read [llms.txt](https://docs.triton.one/llms.txt)\ <i class="fa-rss">:rss:</i> Follow updates: [Blog](https://blog.triton.one) · [X](https://x.com/triton_one) · [YouTube](https://www.youtube.com/@triton_one_ltd) · [Telegram](https://t.me/tritonone) · [GitHub](https://github.com/rpcpool)
