POST /swap
An unsigned swap for your wallet: the best route, simulated with its minimum, plus any approvals to send first.
POST https://uprally.co/api/v1/swap| Field | Type | Required | Meaning |
|---|---|---|---|
token | string | yes | The coin |
side | buy · sell | yes | |
amount | string | yes | Whole units: ETH to spend (buy) or coins to sell (sell) |
wallet | string | yes | A 0x address, lower case |
slippageBps | integer | Default 100 (1%) | |
feeBps | integer | Your own fee on the trade, in ETH, up to 300 (3%) | |
feeRecipient | string | Who gets feeBps | |
maxPriceImpactPct | number | Refuse past this price impact; default 50 |
Response
Section titled “Response”| Field | Type | Required | Meaning |
|---|---|---|---|
chainId | 4663 | yes | |
token | string | yes | A 0x address, lower case |
symbol | string or null | yes | |
side | buy · sell | yes | |
amountIn | object | yes | |
amountIn.amount | string | yes | Whole units, as a decimal string: “0.05” |
amountIn.wei | string | yes | The smallest unit, an integer as a string |
amountIn.symbol | string or null | yes | ETH, or the coin’s ticker |
amountOut | object | yes | What the trader ends up with, after every fee and tax, simulated |
amountOut.amount | string | yes | Whole units, as a decimal string: “0.05” |
amountOut.wei | string | yes | The smallest unit, an integer as a string |
amountOut.symbol | string or null | yes | ETH, or the coin’s ticker |
minOut | object | yes | The least the transaction accepts |
minOut.amount | string | yes | Whole units, as a decimal string: “0.05” |
minOut.wei | string | yes | The smallest unit, an integer as a string |
minOut.symbol | string or null | yes | ETH, or the coin’s ticker |
slippageBps | integer | yes | |
priceImpactPct | number or null | yes | Percent (5 means 5%); null when not known |
venue | object or object | yes | |
venue.kind | curve | yes | |
venue.launchpad | pons · flap | yes | |
venue.contract | string | yes | A 0x address, lower case |
routesCompared | integer | yes | |
fees | object | yes | |
fees.taken | boolean | yes | |
fees.list | object[] | yes | |
fees.list[].who | uprally · builder | yes | |
fees.list[].recipient | string | yes | A 0x address, lower case |
fees.list[].bps | integer | yes | |
fees.why | string | ||
sellBack | object | A buy: selling what it bought straight back, simulated | |
sellBack.ok | true | yes | |
sellBack.sharePct | number | yes | |
sellBack.eth | object | yes | |
sellBack.eth.amount | string | yes | Whole units, as a decimal string: “0.05” |
sellBack.eth.wei | string | yes | The smallest unit, an integer as a string |
simulatedFrom | wallet · test wallet · holder | yes | |
gasUsed | string | yes | The smallest unit, an integer as a string |
asOf | string | yes | |
wallet | string | yes | A 0x address, lower case |
requires | object[] | yes | Approvals to send first, in order; empty when the wallet is ready |
requires[].step | string | yes | |
requires[].explain | string | yes | |
requires[].tx | object | yes | An unsigned transaction: sign it with the wallet and send it. |
requires[].tx.chainId | 4663 | yes | Robinhood Chain |
requires[].tx.from | string | The wallet that must send it | |
requires[].tx.to | string | yes | A 0x address, lower case |
requires[].tx.data | string | yes | The call data: send it exactly as it is |
requires[].tx.value | string | yes | ETH to send with it, in wei |
requires[].tx.gas | string | A gas limit with room; absent while a step before it is still needed | |
tx | object | yes | An unsigned transaction: sign it with the wallet and send it. |
tx.chainId | 4663 | yes | Robinhood Chain |
tx.from | string | The wallet that must send it | |
tx.to | string | yes | A 0x address, lower case |
tx.data | string | yes | The call data: send it exactly as it is |
tx.value | string | yes | ETH to send with it, in wei |
tx.gas | string | A gas limit with room; absent while a step before it is still needed | |
expiresAt | string or null | yes | A router swap reverts after this |
checks | object | yes | |
checks.minimumInCalldata | true | yes | |
checks.simulated | true | yes |
A real response
Section titled “A real response”Captured from the live API on Robinhood Chain, exactly as it was sent (long calldata shortened).
{ "chainId": 4663, "token": "0x94641b97010608c3827fb058074889f19868ff33", "symbol": "VRAX", "side": "sell", "amountIn": { "amount": "1.0", "wei": "1000000000000000000", "symbol": "VRAX" }, "amountOut": { "amount": "0.000002679135485646", "wei": "2679135485646", "symbol": "ETH" }, "minOut": { "amount": "0.000002652344130789", "wei": "2652344130789", "symbol": "ETH" }, "slippageBps": 100, "priceImpactPct": 0, "venue": { "kind": "pool", "hops": [ { "dex": "uniswap", "version": "v3", "tokenIn": "0x0000000000000000000000000000000000000000", "tokenOut": "0x5fc5360d0400a0fd4f2af552add042d716f1d168", "pool": null, "fee": 100 }, { "dex": "uniswap", "version": "v4", "tokenIn": "0x5fc5360d0400a0fd4f2af552add042d716f1d168", "tokenOut": "0x94641b97010608c3827fb058074889f19868ff33", "pool": "0x338fce553e60c8b0acccde1956bc378586ef6f2935339ebae5804d429d461e44", "fee": 0, "tickSpacing": 200, "hooks": "0xe5e702641ea86f4ae6cc3cdaed2b886f976be044" } ] }, "routesCompared": 6, "fees": { "taken": true, "list": [ { "who": "builder", "recipient": "0x8888888888888888888888888888888888888888", "bps": 25 } ] }, "simulatedFrom": "wallet", "gasUsed": "292136", "asOf": "2026-10-16T03:36:40.724Z", "wallet": "0xccd858410c1ddf1b9b0c8293d38c0ed55349a15d", "requires": [ { "step": "approve-permit2", "explain": "Let Permit2 move this coin for you (once per coin): Uniswap's router takes coins only through it.", "tx": { "chainId": 4663, "from": "0xccd858410c1ddf1b9b0c8293d38c0ed55349a15d", "to": "0x94641b97010608c3827fb058074889f19868ff33", "data": "0x095ea7b3000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "value": "0" } }, { "step": "permit2-allow-router", "explain": "Let Uniswap's router take this coin through Permit2 for 30 days.", "tx": { "chainId": 4663, "from": "0xccd858410c1ddf1b9b0c8293d38c0ed55349a15d", "to": "0x000000000022d473030f116ddee9f6b43ac78ba3", "data": "0x87517c4500000000000000000000000094641b97010608c3827fb058074889f19868ff33…", "value": "0" } } ], "tx": { "chainId": 4663, "from": "0xccd858410c1ddf1b9b0c8293d38c0ed55349a15d", "to": "0x204faca1764b154221e35c0d20abb3c525710498", "data": "0x3593564c0000000000000000000000000000000000000000000000000000000000000060…", "value": "0", "gas": "488204" }, "expiresAt": "2026-10-16T03:46:39.000Z", "checks": { "minimumInCalldata": true, "simulated": true }}Errors
Section titled “Errors”Every error is { "error": { "code", "message", "fix"? } }. This endpoint can answer:
INVALID_ADDRESS: A field that must be a 0x address is not one;fieldsays which.INVALID_SIDE: side is “buy” (ETH for the coin) or “sell” (the coin for ETH).INVALID_AMOUNT: The amount is not a positive decimal in whole units.TOO_MANY_DECIMALS: The amount has more decimal places than the currency has.INVALID_BPS: slippageBps or feeBps is out of range (basis points: 100 = 1%).INVALID_QUERY: A query parameter is out of range or malformed;fieldsays which.NOT_A_COIN: The token address is not an ERC-20 on Robinhood Chain.NO_ROUTE: No pool or curve can make this trade right now (none known, or every one failed in simulation;detaillists them).QUOTE_NEEDS_WALLET: This coin’s sale can only be quoted from a wallet that holds it.PRICE_IMPACT_TOO_HIGH: The trade would move the price more than maxPriceImpactPct (default 50%): the pool is too thin for it.SIMULATION_FAILED: The trade failed when simulated again with its minimum in place: the price moved.HONEYPOT: Selling this coin straight after buying it fails through every route, in simulation: it may not be sellable.CHAIN_UNREACHABLE: Robinhood Chain could not be read or simulated just now.MARKET_UNREACHABLE: The coin’s pools could not be read just now.RATE_LIMITED: Too many requests from this address in the last minute.WALLET_REQUIRED: A swap is built for the wallet that will send it.INSUFFICIENT_BALANCE: The wallet holds less of the coin than the sale.INSUFFICIENT_FUNDS: The wallet holds less ETH than the buy.INVALID_BODY: The body is not a JSON object.INVALID_JSON: The body is not valid JSON.