# Submission methods

> Three ways to submit transactions through Sender: JSON-RPC, HTTP Plaintext, HTTP Binary.

Three ways to submit transactions, picked by latency requirement.

<Note>
**Tradeoff:** JSON-RPC is the easiest drop-in (existing Solana clients work unchanged). Plaintext and Binary trim parsing overhead for microsecond-sensitive paths. Pick by how much you care about latency vs simplicity.
</Note>

| Method | Latency | Body format | Max size |
|---|---|---|---|
| JSON-RPC | Low | JSON | - |
| HTTP Plaintext | Lower | Base64 string | 2,048 bytes |
| HTTP Binary | Lowest | Raw bincode | 1,232 bytes |

<Warning>
All methods require a valid [tip](https://supanode.xyz/docs/solana/sender/tips) in the transaction. Preflight is never run regardless of `skipPreflight` value.
</Warning>

## JSON-RPC

Standard Solana JSON-RPC `sendTransaction` format. Drop-in replacement for `https://api.mainnet-beta.solana.com`.

**Endpoint:** `http://YOUR_REGION.landing.fast`

<Tabs>
  <Tab title="curl">
    ```bash
    curl -sS 'http://fra.landing.fast' \
      -H 'Content-Type: application/json' \
      --data '{
        "jsonrpc": "2.0",
        "id": 1,
        "method": "sendTransaction",
        "params": [
          "YOUR_BASE64_ENCODED_TX",
          {
            "encoding": "base64",
            "skipPreflight": true
          }
        ]
      }'
    ```
  </Tab>
  <Tab title="JavaScript">
    ```javascript
    const response = await fetch('http://fra.landing.fast', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        jsonrpc: '2.0',
        id: 1,
        method: 'sendTransaction',
        params: [
          base64EncodedTx,
          { encoding: 'base64', skipPreflight: true },
        ],
      }),
    });

    const { result: signature } = await response.json();
    console.log('Signature:', signature);
    ```
  </Tab>
  <Tab title="Rust">
    ```rust
    use reqwest::Client;
    use serde_json::json;

    let client = Client::new();

    let response = client
        .post("http://fra.landing.fast")
        .json(&json!({
            "jsonrpc": "2.0",
            "id": 1,
            "method": "sendTransaction",
            "params": [
                base64_encoded_tx,
                { "encoding": "base64", "skipPreflight": true }
            ]
        }))
        .send()
        .await?;

    let body: serde_json::Value = response.json().await?;
    let signature = body["result"].as_str().unwrap();
    ```
  </Tab>
</Tabs>

**Response:**

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

**Required params:**
- `encoding: "base64"` - required for reliable transmission.
- `skipPreflight: true` - documented for compatibility.

## HTTP Plaintext

Lower-overhead than JSON-RPC. Body is a single base64 string. Response is a plain bs58-encoded signature.

**Endpoint:** `http://YOUR_REGION.landing.fast/plaintext`

```bash
curl -sS 'http://fra.landing.fast/plaintext' \
  -X POST \
  -H 'Content-Type: text/plain' \
  --data 'YOUR_BASE64_ENCODED_TX'
```

- **Body:** base64-encoded transaction.
- **Max size:** 2,048 bytes.
- **Response:** plain-text bs58-encoded signature.

## HTTP Binary

Lowest overhead. Body is raw bincode-serialized transaction bytes.

**Endpoint:** `http://YOUR_REGION.landing.fast/binary`

```bash
curl -sS 'http://fra.landing.fast/binary' \
  -X POST \
  -H 'Content-Type: application/octet-stream' \
  --data-binary @transaction.bin
```

- **Body:** raw transaction bytes (bincode serialized, same wire format as Solana SDK).
- **Max size:** 1,232 bytes.
- **Response:** plain-text bs58-encoded signature.

## Response codes

| Code | Meaning |
|---|---|
| `200` | Transaction accepted and forwarded |
| `429` | Rate limited - back off and retry |
| `500` | Server error - retry with backoff |

<Warning>
A `200` response means **forwarded**, not landed on-chain. Always verify with [RPC](https://supanode.xyz/docs/solana/rpc/overview) `getSignatureStatuses`.
</Warning>

## Constraints

- No preflight - validate locally first.
- No deduplication - submitting the same transaction twice forwards it twice.
- One transaction per request.

## See also

<CardGroup cols={3}>
  <Card title="Get started" icon="bolt" href="https://supanode.xyz/docs/solana/sender/start">
    First request in 5 minutes.
  </Card>
  <Card title="Tips" icon="coins" href="https://supanode.xyz/docs/solana/sender/tips">
    Minimum tip and tip addresses.
  </Card>
  <Card title="Endpoints" icon="globe" href="https://supanode.xyz/docs/solana/sender/endpoints">
    Regional endpoints.
  </Card>
</CardGroup>
