VURTO SWAPAPI FOR DEVELOPERS & AGENTS
← Back to app

Connect your app or agent

Vurto Swap is reachable three ways: a plain REST API, an MCP server for AI agents, and a CLI. Same backend, same audited swap logic, no API key required.

REST

https://swap.vurto.cc/v1 — quote, build, sign, send. OpenAPI spec included.

MCP

https://swap.vurto.cc/mcp — JSON-RPC over Streamable HTTP, for Claude, Copilot, or any MCP client.

CLI

vurto-swap — quote / swap / sign / status / refund / nn-quote / nn-build, for scripts and shells. Served from this site, not from npm.

Quickest path: quote, no auth needed

curl -sS https://swap.vurto.cc/v1/quote \
  -H 'content-type: application/json' \
  --data '{"chainId":42161,"tokenIn":"USDC","tokenOut":"WETH","amount":"100"}'

Python, standard library only

Quote, pick a route, build the transaction. No packages to install: urllib and json are enough. Credentials and the base URL come from the environment, under the same variable names the CLI reads, so one export serves both.

One trap worth naming: send a User-Agent. The default Python-urllib/3.x is refused at the edge with 403 and error code: 1010. Any name of your own gets through, and requests already sends one.

swap.pyexport VURTO_SWAP_WALLET=0x… then run itDownload
#!/usr/bin/env python3
"""Quote and build a swap on Vurto. Standard library only, no packages."""
import json
import os
import urllib.error
import urllib.request

# Same variable names the CLI reads, so one export serves both.
BASE = os.environ.get("VURTO_SWAP_BASE_URL", "https://swap.vurto.cc")
KEY = os.environ.get("VURTO_SWAP_API_KEY")        # optional: raises your rate limit
WALLET = os.environ.get("VURTO_SWAP_WALLET")      # the address that will sign

CHAIN, TOKEN_IN, TOKEN_OUT, AMOUNT = 42161, "USDC", "WETH", "100"


def call(path, body):
    # Send a User-Agent. The default "Python-urllib/3.x" is refused by the
    # edge with HTTP 403 and "error code: 1010"; any name of your own works.
    headers = {"content-type": "application/json", "user-agent": "vurto-example/1.0"}
    if KEY:
        headers["authorization"] = f"Bearer {KEY}"
    request = urllib.request.Request(
        f"{BASE}{path}", data=json.dumps(body).encode(), headers=headers
    )
    try:
        with urllib.request.urlopen(request, timeout=30) as response:
            return json.load(response)
    except urllib.error.HTTPError as error:
        # Errors are JSON too: {"error":{"code":...,"message":...}}. The code is
        # the part worth branching on; the message is for humans.
        detail = json.load(error)
        raise SystemExit(f"{path} failed: {json.dumps(detail)}") from None


quote = call("/v1/quote", {
    "chainId": CHAIN, "tokenIn": TOKEN_IN, "tokenOut": TOKEN_OUT, "amount": AMOUNT,
})

for option in quote["quotes"]:
    print(f"{option['providerLabel']:<14} {option['amountOut']:>26}  {option['id']}")

if not WALLET:
    raise SystemExit("\nSet VURTO_SWAP_WALLET to build a transaction.")

plan = call("/v1/swap", {
    "chainId": CHAIN, "wallet": WALLET, "tokenIn": TOKEN_IN, "tokenOut": TOKEN_OUT,
    "amount": AMOUNT, "maxSlippageBps": 100,
})

chosen = plan["quote"]
route = " > ".join(hop.get("exchange", "") for hop in chosen.get("route", []))
print(f"\nchosen: {chosen['providerLabel']} ({route})")
print(f"out:    {chosen['amountOut']}")
# minimumAmountOut is what the router checks, BEFORE the platform fee is taken.
# What lands in the wallet is that number minus the fee, so do not read it as
# the amount you receive.
print(f"min:    {chosen['minimumAmountOut']} (gross, checked on-chain)")
print(f"steps:  {' -> '.join(step['type'] for step in plan['steps'])}")
print("\nSign each step with the wallet that owns the address above. The bytes are")
print("worthless until it does: no key ever reaches this script or the API.")

CLI, installed from here

The package is served by this site rather than published to a registry, so the URL you install from and the checksum you verify are both ours. Node 18 or newer.

npm i -g https://swap.vurto.cc/cli/vurto-swap-0.2.2.tgz

vurto-swap quote --chain arbitrum --in USDC --out WETH --amount 100

Verify before running it: vurto-swap-0.2.2.tgz.sha256. Solana signing pulls two optional peers, npm i @solana/web3.js bs58, and the EVM chains do not need them.

Solana is the same API, under /v1/svm

Nine EVM chains and Solana, same vocabulary. You pick the engine with chainId: an integer for EVM, the string "solana-mainnet" for Solana. Solana addresses are base58 and case-sensitive: lowercasing a mint gives a different, non-existent account.

curl -sS https://swap.vurto.cc/v1/svm/quote \
  -H 'content-type: application/json' \
  --data '{"chainId":"solana-mainnet","tokenIn":"So11111111111111111111111111111111111111112",
           "tokenOut":"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
           "tokenInDecimals":9,"tokenOutDecimals":6,"amountIn":"100000000","slippageBps":50}'

Three differences and no more: there is no approve, so a build has one transaction instead of a steps[] array; signing uses a Solana key; and a signature is not a receipt, so ask GET /v1/svm/tx before calling a swap done.

No API key required

Every endpoint is open, quotes and builds alike. You pass the wallet that will sign, and you get back bytes that are worthless until that wallet signs them: the product is non-custodial end to end, so there is nothing a key would be protecting. Limits are per IP.

A machine credential is still available and still worth having if you serve many users from one egress address: it moves your limit from the per-IP cap to the credential's own budget, and it is a Bearer token bound to one wallet, proven by signature at issuance, never a private key.

Where to get one: open swap.vurto.cc, connect the EVM wallet, sign in, then click the key icon on that wallet's card in the wallet panel. The secret is shown once. Issuance is proven by the wallet's signature and needs a same-origin browser request, so curl cannot do it.

Credentials are issued by an Ethereum signature, so a Solana-only wallet cannot get one. That is fine: nothing requires one.

curl -sS https://swap.vurto.cc/v1/swap \
  -H 'content-type: application/json' \
  --data '{"chainId":42161,"wallet":"0xYourWallet","tokenIn":"USDC","tokenOut":"WETH","amount":"100","maxSlippageBps":100}'

Full reference