curl --request POST \
--url https://demo-api.mobula.io/api/2/swap/send \
--header 'Content-Type: application/json' \
--data '
{
"chainId": "solana:solana",
"signedTransaction": "AQABAuObQ8Adqk1eqZxRMJg4r6vGtXq9k0...base64...",
"candidates": [
{
"lander": "jito",
"signedTransaction": "AQABAuObQ8Adqk1eqZxRMJg4r6vGtXq9k0...base64..."
}
],
"awaitLanding": false,
"feeWallet": "<string>",
"feeAmountUsd": 1.25
}
'import requests
url = "https://demo-api.mobula.io/api/2/swap/send"
payload = {
"chainId": "solana:solana",
"signedTransaction": "AQABAuObQ8Adqk1eqZxRMJg4r6vGtXq9k0...base64...",
"candidates": [
{
"lander": "jito",
"signedTransaction": "AQABAuObQ8Adqk1eqZxRMJg4r6vGtXq9k0...base64..."
}
],
"awaitLanding": False,
"feeWallet": "<string>",
"feeAmountUsd": 1.25
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
chainId: 'solana:solana',
signedTransaction: 'AQABAuObQ8Adqk1eqZxRMJg4r6vGtXq9k0...base64...',
candidates: [
{
lander: 'jito',
signedTransaction: 'AQABAuObQ8Adqk1eqZxRMJg4r6vGtXq9k0...base64...'
}
],
awaitLanding: false,
feeWallet: '<string>',
feeAmountUsd: 1.25
})
};
fetch('https://demo-api.mobula.io/api/2/swap/send', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://demo-api.mobula.io/api/2/swap/send",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'chainId' => 'solana:solana',
'signedTransaction' => 'AQABAuObQ8Adqk1eqZxRMJg4r6vGtXq9k0...base64...',
'candidates' => [
[
'lander' => 'jito',
'signedTransaction' => 'AQABAuObQ8Adqk1eqZxRMJg4r6vGtXq9k0...base64...'
]
],
'awaitLanding' => false,
'feeWallet' => '<string>',
'feeAmountUsd' => 1.25
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://demo-api.mobula.io/api/2/swap/send"
payload := strings.NewReader("{\n \"chainId\": \"solana:solana\",\n \"signedTransaction\": \"AQABAuObQ8Adqk1eqZxRMJg4r6vGtXq9k0...base64...\",\n \"candidates\": [\n {\n \"lander\": \"jito\",\n \"signedTransaction\": \"AQABAuObQ8Adqk1eqZxRMJg4r6vGtXq9k0...base64...\"\n }\n ],\n \"awaitLanding\": false,\n \"feeWallet\": \"<string>\",\n \"feeAmountUsd\": 1.25\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://demo-api.mobula.io/api/2/swap/send")
.header("Content-Type", "application/json")
.body("{\n \"chainId\": \"solana:solana\",\n \"signedTransaction\": \"AQABAuObQ8Adqk1eqZxRMJg4r6vGtXq9k0...base64...\",\n \"candidates\": [\n {\n \"lander\": \"jito\",\n \"signedTransaction\": \"AQABAuObQ8Adqk1eqZxRMJg4r6vGtXq9k0...base64...\"\n }\n ],\n \"awaitLanding\": false,\n \"feeWallet\": \"<string>\",\n \"feeAmountUsd\": 1.25\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://demo-api.mobula.io/api/2/swap/send")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"chainId\": \"solana:solana\",\n \"signedTransaction\": \"AQABAuObQ8Adqk1eqZxRMJg4r6vGtXq9k0...base64...\",\n \"candidates\": [\n {\n \"lander\": \"jito\",\n \"signedTransaction\": \"AQABAuObQ8Adqk1eqZxRMJg4r6vGtXq9k0...base64...\"\n }\n ],\n \"awaitLanding\": false,\n \"feeWallet\": \"<string>\",\n \"feeAmountUsd\": 1.25\n}"
response = http.request(request)
puts response.read_body{
"data": {
"success": true,
"requestId": "<string>",
"transactionHash": "<string>",
"lander": "<string>",
"landingTimeMs": 123,
"status": "broadcasted",
"onchainLandingTimeMs": 123,
"swap": {
"tokenIn": {
"address": "<string>",
"amount": "<string>"
},
"tokenOut": {
"address": "<string>",
"amount": "<string>"
}
}
},
"error": "<string>"
}Send Swap Transaction
Broadcast a signed swap transaction to the blockchain network.
curl --request POST \
--url https://demo-api.mobula.io/api/2/swap/send \
--header 'Content-Type: application/json' \
--data '
{
"chainId": "solana:solana",
"signedTransaction": "AQABAuObQ8Adqk1eqZxRMJg4r6vGtXq9k0...base64...",
"candidates": [
{
"lander": "jito",
"signedTransaction": "AQABAuObQ8Adqk1eqZxRMJg4r6vGtXq9k0...base64..."
}
],
"awaitLanding": false,
"feeWallet": "<string>",
"feeAmountUsd": 1.25
}
'import requests
url = "https://demo-api.mobula.io/api/2/swap/send"
payload = {
"chainId": "solana:solana",
"signedTransaction": "AQABAuObQ8Adqk1eqZxRMJg4r6vGtXq9k0...base64...",
"candidates": [
{
"lander": "jito",
"signedTransaction": "AQABAuObQ8Adqk1eqZxRMJg4r6vGtXq9k0...base64..."
}
],
"awaitLanding": False,
"feeWallet": "<string>",
"feeAmountUsd": 1.25
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
chainId: 'solana:solana',
signedTransaction: 'AQABAuObQ8Adqk1eqZxRMJg4r6vGtXq9k0...base64...',
candidates: [
{
lander: 'jito',
signedTransaction: 'AQABAuObQ8Adqk1eqZxRMJg4r6vGtXq9k0...base64...'
}
],
awaitLanding: false,
feeWallet: '<string>',
feeAmountUsd: 1.25
})
};
fetch('https://demo-api.mobula.io/api/2/swap/send', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://demo-api.mobula.io/api/2/swap/send",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'chainId' => 'solana:solana',
'signedTransaction' => 'AQABAuObQ8Adqk1eqZxRMJg4r6vGtXq9k0...base64...',
'candidates' => [
[
'lander' => 'jito',
'signedTransaction' => 'AQABAuObQ8Adqk1eqZxRMJg4r6vGtXq9k0...base64...'
]
],
'awaitLanding' => false,
'feeWallet' => '<string>',
'feeAmountUsd' => 1.25
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://demo-api.mobula.io/api/2/swap/send"
payload := strings.NewReader("{\n \"chainId\": \"solana:solana\",\n \"signedTransaction\": \"AQABAuObQ8Adqk1eqZxRMJg4r6vGtXq9k0...base64...\",\n \"candidates\": [\n {\n \"lander\": \"jito\",\n \"signedTransaction\": \"AQABAuObQ8Adqk1eqZxRMJg4r6vGtXq9k0...base64...\"\n }\n ],\n \"awaitLanding\": false,\n \"feeWallet\": \"<string>\",\n \"feeAmountUsd\": 1.25\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://demo-api.mobula.io/api/2/swap/send")
.header("Content-Type", "application/json")
.body("{\n \"chainId\": \"solana:solana\",\n \"signedTransaction\": \"AQABAuObQ8Adqk1eqZxRMJg4r6vGtXq9k0...base64...\",\n \"candidates\": [\n {\n \"lander\": \"jito\",\n \"signedTransaction\": \"AQABAuObQ8Adqk1eqZxRMJg4r6vGtXq9k0...base64...\"\n }\n ],\n \"awaitLanding\": false,\n \"feeWallet\": \"<string>\",\n \"feeAmountUsd\": 1.25\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://demo-api.mobula.io/api/2/swap/send")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"chainId\": \"solana:solana\",\n \"signedTransaction\": \"AQABAuObQ8Adqk1eqZxRMJg4r6vGtXq9k0...base64...\",\n \"candidates\": [\n {\n \"lander\": \"jito\",\n \"signedTransaction\": \"AQABAuObQ8Adqk1eqZxRMJg4r6vGtXq9k0...base64...\"\n }\n ],\n \"awaitLanding\": false,\n \"feeWallet\": \"<string>\",\n \"feeAmountUsd\": 1.25\n}"
response = http.request(request)
puts response.read_body{
"data": {
"success": true,
"requestId": "<string>",
"transactionHash": "<string>",
"lander": "<string>",
"landingTimeMs": 123,
"status": "broadcasted",
"onchainLandingTimeMs": 123,
"swap": {
"tokenIn": {
"address": "<string>",
"amount": "<string>"
},
"tokenOut": {
"address": "<string>",
"amount": "<string>"
}
}
},
"error": "<string>"
}Overview
The Swap Send endpoint allows you to broadcast a signed transaction to the blockchain network. This endpoint should be used after obtaining a quote from the Swap Quoting endpoint and signing the transaction with your wallet.Request Body
The request body must be a JSON object with the following fields:Single Mode
chainId(required) — The blockchain identifier. Examples:solana:solana,evm:1(Ethereum),evm:42161(Arbitrum),evm:8453(Base),evm:137(Polygon),evm:56(BNB Chain)signedTransaction(required) — Base64-encoded signed transaction bytesawaitLanding(optional, boolean) — Whentrue, the endpoint blocks until the transaction is confirmed on-chain and returns detailed confirmation data including landing time and swap amounts. Default:false
Batch Mode (Solana MEV)
chainId(required) — The blockchain identifiercandidates(required) — Array of candidate transactions targeting different block engines (landers)lander(string) — Lander identifier (e.g.jito,nozomi,zeroslot)signedTransaction(string) — Base64-encoded signed transaction
awaitLanding(optional, boolean) — Same as single mode
Usage Examples
Fire-and-Forget (Default)
curl -X POST "https://api.mobula.io/api/2/swap/send" \
-H "Content-Type: application/json" \
-d '{
"chainId": "solana:solana",
"signedTransaction": "<base64-signed-tx>"
}'
Await Landing (Solana)
curl -X POST "https://api.mobula.io/api/2/swap/send" \
-H "Content-Type: application/json" \
-d '{
"chainId": "solana:solana",
"signedTransaction": "<base64-signed-tx>",
"awaitLanding": true
}'
Await Landing (EVM)
curl -X POST "https://api.mobula.io/api/2/swap/send" \
-H "Content-Type: application/json" \
-d '{
"chainId": "evm:42161",
"signedTransaction": "<base64-signed-tx>",
"awaitLanding": true
}'
Batch Mode (Solana MEV)
curl -X POST "https://api.mobula.io/api/2/swap/send" \
-H "Content-Type: application/json" \
-d '{
"chainId": "solana:solana",
"candidates": [
{ "lander": "jito", "signedTransaction": "<base64-jito-tx>" },
{ "lander": "nozomi", "signedTransaction": "<base64-nozomi-tx>" }
],
"awaitLanding": true
}'
Response Format
Response Fields
Data Object
success(boolean) — Whether the transaction was successfully broadcasttransactionHash(string, optional) — Transaction hash/signature on the blockchainrequestId(string) — Unique identifier for the requeststatus(string, optional) — Landing status, present whenawaitLandingis used:broadcasted— Transaction sent to the network (default whenawaitLandingis false)processed— Transaction processed by a Solana validator (fast, ~500ms, not yet confirmed by supermajority)confirmed— Transaction fully confirmed on-chain (EVM receipt or Solana RPC fallback)failed— Transaction landed on-chain but reverted/failedtimeout— Confirmation not received within the timeout period (30s Solana, 60s EVM)
onchainLandingTimeMs(number, optional) — Time in milliseconds from broadcast to on-chain confirmationlander(string, optional) — Which block engine landed the transaction (batch mode only, e.g.jito,nozomi)landingTimeMs(number, optional) — Time in milliseconds from send to first RPC acceptanceswap(object, optional) — Parsed swap data from the confirmed transaction (Solana only):tokenIn—{ address: string, amount: string }— Token senttokenOut—{ address: string, amount: string }— Token received
Error Field
error(string, optional) — Error message if the transaction failed
Example Responses
Broadcasted (fire-and-forget)
{
"data": {
"success": true,
"transactionHash": "5VERv8NMvzbJMEkV8xnrLkEaWRtSz9CosKDYjCJjBRnbJLgp8uirBgmQpjKhoR4tjF3ZpRzrFmBV6UjKdiSZkQUW",
"requestId": "550e8400-e29b-41d4-a716-446655440000",
"status": "broadcasted"
}
}
Processed (Solana with awaitLanding)
{
"data": {
"success": true,
"transactionHash": "563cifbEg4NXUmChZ8mPmXWcHYsSCQFE3nCZPuH8DPjT6TD8z425qoJvuyTwrEUAEveYqMnkZEaGnnLxELe2paGu",
"requestId": "a0f6d6ad-8b1a-4156-8efa-5ec634cc83e5",
"status": "processed",
"onchainLandingTimeMs": 535,
"swap": {
"tokenIn": {
"address": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"amount": "100000"
},
"tokenOut": {
"address": "So11111111111111111111111111111111111111112",
"amount": "1116467"
}
}
}
}
Confirmed (EVM with awaitLanding)
{
"data": {
"success": true,
"transactionHash": "0xb1c87a9045eeed21b63071f31b3ec3e51543aac6b1ca823e2d984d717c27db96",
"requestId": "8ab08aeb-ddb6-4fd8-aa0f-4fa7bd5b24c7",
"status": "confirmed",
"onchainLandingTimeMs": 1518
}
}
Failed On-Chain
{
"data": {
"success": false,
"transactionHash": "0x...",
"requestId": "770e8400-e29b-41d4-a716-446655440002",
"status": "failed",
"onchainLandingTimeMs": 2100
},
"error": "Transaction failed on-chain"
}
Broadcast Error
{
"data": {
"success": false,
"requestId": "880e8400-e29b-41d4-a716-446655440003",
"status": "broadcasted"
},
"error": "Transaction simulation failed: insufficient funds"
}
Transaction Flow
- Get Quote: Call the Swap Quoting endpoint to get a serialized transaction
- Sign Transaction: Use your wallet to sign the transaction
- For Solana: Use
@solana/web3.jsto deserialize, sign, and re-serialize - For EVM: Use
viem,ethers.js, orweb3.jsto sign with gas estimation
- For Solana: Use
- Encode to Base64: Convert the signed transaction bytes to base64
- Broadcast: Send the encoded transaction using this endpoint
- Track: Either use
awaitLanding: trueto get immediate confirmation, or track using the returned transaction hash on blockchain explorers
Status Semantics
| Status | Meaning | Reliability |
|---|---|---|
broadcasted | Transaction sent, confirmation unknown | Pending |
processed | Solana: processed by leader validator | ~99.99% reliable |
confirmed | Fully confirmed on-chain | 100% reliable |
failed | Confirmed as failed/reverted | Definitive |
timeout | No confirmation within timeout | Unknown |
Important Notes
awaitLandinglatency: Solana ~500ms (PROCESSED), EVM ~1-3s depending on chain block time- Timeouts: Solana gRPC timeout is 30s with RPC fallback, EVM polling timeout is 60s
- Transaction Validity: Transactions may expire if not sent within a certain timeframe
- Slippage: If market conditions change significantly, the transaction may fail
- Batch Mode: Only supported for Solana. All candidates share a durable nonce so only one can land
Error Handling
Common error scenarios:- Insufficient Funds: Wallet doesn’t have enough balance to cover the swap + fees
- Slippage Exceeded: Market moved beyond acceptable slippage tolerance
- Invalid Signature: Transaction was not properly signed
- Expired Transaction: Transaction validity period has passed
- Network Congestion: Blockchain network is experiencing high load
Use Cases
- Automated Trading: Execute swaps programmatically with confirmation tracking
- Trading Bots: Use
awaitLandingfor real-time execution feedback - MEV Protection: Use batch mode with multiple landers for optimal landing
- DeFi Integration: Complete swap flows with on-chain confirmation in your application
Body
Chain dispatcher. Solana: solana:solana. EVM: evm:<chainId> (e.g. evm:8453 for Base). TON: ton:mainnet or ton:testnet.
"solana:solana"
Base64 of the signed payload. Solana: signed VersionedTransaction/Transaction bytes. EVM: raw signed RLP. TON: signed external_in_message BoC.
1"AQABAuObQ8Adqk1eqZxRMJg4r6vGtXq9k0...base64..."
Multi-lander batch (Solana only). One signed candidate per lander, sharing a durable nonce — only one will commit. Mutually exclusive with signedTransaction.
1Show child attributes
Show child attributes
When true, the endpoint blocks until on-chain confirmation and returns swap data.
false
Wallet that receives the referral fee on this swap. Echo from the original /quote request.
Referral fee amount in USD for this swap (feePercentage × amountInUsd from the /quote response). Persisted for dashboard attribution; not re-validated against the signed transaction.
x >= 01.25