---
title: "How to send a transaction without paying twice"
description: "Build, simulate, submit, and check status — including the unknown outcome that matters most."
---

> Documentation Index
> Fetch the complete documentation index at: https://tee.hypetrade.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# How to send a transaction without paying twice

All four transaction routes need the `sign` scope and a working RPC endpoint
for the address's network. Read [Networks and RPC](/concepts/networks-and-rpc/)
first if you have not configured one.

## The request body

One shape covers both VMs; which fields apply depends on the address you name.

### EVM

```json
{
  "address": "0xabc…",
  "to": "0xdef…",
  "value": "1000000000000000000",
  "data": "0x",
  "nonce": 42,
  "gasLimit": "21000",
  "maxFeePerGas": "30000000000",
  "maxPriorityFeePerGas": "1500000000"
}
```

`to` is required. Everything after it is optional — omitted fee fields and
`nonce` are filled in by the endpoint.
### SVM

```json
{
  "address": "So1abc…",
  "recipient": "So1def…",
  "amount": "1000000",
  "tokenMint": "EPjFWdd5…",
  "recentBlockhash": "9xQe…"
}
```

`recipient` and `amount` are both required. `tokenMint` selects an SPL token
instead of native SOL.

> **Large numbers travel as strings**
>
> JSON has no bigint, so `value`, `amount`, `gasLimit`, and the fee fields accept
> a decimal string (or a non-negative integer that fits safely). Send
> `"1000000000000000000"`, not `1e18`.

## Build

Produces an unsigned transaction without touching your keys:

```bash
curl -X POST "$API_URL/transactions/build" \
  -H "Authorization: Bearer $TOKEN" \
  -H "content-type: application/json" \
  -d '{"address":"0xabc…","to":"0xdef…","value":"1000000000000000000"}'
```

```json
{ "raw": { }, "vm": "evm", "network": "ethereum" }
```

The response carries an `x-rpc-source` header naming which endpoint tier served
it.

## Simulate

Same body, executed against the node without submitting:

```bash
curl -X POST "$API_URL/transactions/simulate" \
  -H "Authorization: Bearer $TOKEN" \
  -H "content-type: application/json" \
  -d '{"address":"0xabc…","to":"0xdef…","value":"1000000000000000000"}'
```

```json
{ "success": false, "error": "execution reverted: insufficient balance", "gasUsed": "21000", "logs": [] }
```

An on-chain failure is a **`200` with `success: false`** and a revert reason.
A simulation that could not complete at all — unreachable endpoint, transport
refusal — is an error status instead, never a `200`. That distinction is
deliberate: it stops a network outage from reading as "the transaction would
revert".

Provider text is bounded before it reaches you: `error` and each log entry are
truncated to 200 characters, and at most 32 logs are returned.

## Send

Builds, signs, and submits in one call:

```bash
curl -X POST "$API_URL/transactions/send" \
  -H "Authorization: Bearer $TOKEN" \
  -H "content-type: application/json" \
  -d '{"address":"0xabc…","to":"0xdef…","value":"1000000000000000000"}'
```

Returns `202` — accepted for submission, not confirmed:

```json
{ "hash": "0x…", "status": "pending", "network": "ethereum" }
```

### The two statuses, and why the second one matters

| `status` | Meaning | What to do |
|---|---|---|
| `pending` | The network accepted it | Poll for confirmation |
| `unknown` | Submission timed out; **the bytes may already have reached the network** | Poll status; see the warning below before resending |

> **Never retry an unknown submission blindly**
>
> `unknown` does not mean "it failed". It means the outcome could not be
> established — the signed transaction may well be on its way. Resending is how
> you pay twice.
>
> Call the status route with the returned `hash` first. But read the answer
> carefully: **`found: false` is not proof the transaction does not exist.** The
> status route is a passthrough to your endpoint, and an endpoint answers the
> same way for a transaction that was never broadcast, one sitting in the
> mempool, and one that was dropped. A resend on `found: false` is exactly the
> double-spend this warning is about.
>
> What `found: false` does rule out is *inclusion so far*. Treat it as "still
> unresolved", keep polling, and resend only when you have established
> independently — from the address's nonce on chain, or from your own records —
> that nothing landed.

The returned `hash` is the signed transaction's canonical identifier, computed
before submission — so it is a valid lookup key even when the status is
`unknown`.

## Check status

A stateless passthrough to the network. The service stores nothing, so the
network selector is required:

```bash
curl "$API_URL/transactions/0x…?network=ethereum" \
  -H "Authorization: Bearer $TOKEN"
```

```json
{ "hash": "0x…", "found": true, "status": "confirmed" }
```

| `status` | Meaning |
|---|---|
| `pending` | Not yet visible on the network (`found: false`) |
| `confirmed` | Included and successful — one observation, not a finality guarantee |
| `failed` | Mined but reverted, or explicitly errored |

Because there is no lifecycle tracking or webhook, polling this route is the
supported way to follow a transaction.

## Nonces are not managed for you

The service does not exclusively own your addresses, so it does not cache or
allocate nonces — pretending to would be worse than the occasional race. The
endpoint assigns one unless you pass `nonce` explicitly. If you are also sending
from the same address by other means, supply the nonce yourself.

## Failures worth handling

| Code | Status | What happened |
|---|---|---|
| `rpc_not_configured` | 409 | No usable endpoint for that network |
| `rpc_unreachable` | 502 | Endpoint did not respond |
| `rpc_rejected` | 502 | Endpoint refused the request |
| `rpc_capacity_exceeded` | 429 | Too many concurrent chain operations |
| `tx_build_failed` | 422 | The transaction could not be constructed |
| `tx_submit_failed` | 502 | The endpoint explicitly refused the submission |
| `tx_timeout` | 504 | Timed out — treat like `unknown` and check status |
| `tx_dropped` | 409 | Dropped before inclusion |
| `tx_aborted` | 409 | Aborted before submission completed |
| `unsupported_for_kind` | 422 | Field combination wrong for this address's VM |

## Related

- [Networks and RPC](/concepts/networks-and-rpc/) — endpoint resolution
- [Transactions endpoints](/api/transactions/) — exact shapes
- [Errors](/errors/) — the full catalog

Source: https://tee.hypetrade.xyz/guides/send-transactions/index.mdx
