Examples

Runnable snippets — curl, TypeScript, an x402 agent handshake, and an MCP session.

Four examples against the live Testnet API. All amounts are USDC; rates are indicative (the sandbox FX source is simulated StableFX).

1. Quote, send, and track with curl

# Quote USD → EUR
curl -s -X POST https://transvia.xyz/api/quote \
  -H "content-type: application/json" \
  -d '{"corridor":"USD-EUR","amountUsdc":100}'

# Lock the quote into a transfer (use the quote id from the response)
curl -s -X POST https://transvia.xyz/api/send \
  -H "content-type: application/json" \
  -d '{"quoteId":"qt_…","recipientLabel":"Alice","recipientAddr":"0x…"}'

# Poll the status — simulated-rail settlement completes in seconds
curl -s https://transvia.xyz/api/intents/int_…

# Release the payout to the recipient
curl -s -X POST https://transvia.xyz/api/claim \
  -H "content-type: application/json" \
  -d '{"intentId":"int_…"}'

2. Create a transfer in TypeScript

const API = "https://transvia.xyz";

async function send100UsdcToEur(recipientLabel: string) {
  const { quote } = await fetch(`${API}/api/quote`, {
    method: "POST",
    headers: { "content-type": "application/json" },
    body: JSON.stringify({ corridor: "USD-EUR", amountUsdc: 100 }),
  }).then((r) => r.json());

  const { intent } = await fetch(`${API}/api/send`, {
    method: "POST",
    headers: { "content-type": "application/json" },
    body: JSON.stringify({ quoteId: quote.id, recipientLabel }),
  }).then((r) => r.json());

  // Poll until the transfer reaches a terminal state
  let status = intent.status;
  while (!["claimable", "claimed", "refunded"].includes(status)) {
    await new Promise((r) => setTimeout(r, 2000));
    const { intent: fresh } = await fetch(`${API}/api/intents/${intent.id}`)
      .then((r) => r.json());
    status = fresh.status;
  }
  return status;
}

3. An x402 agent handshake

An agent pays 0.01 USDC per quote: request → 402 with terms → sign an EIP-3009 authorization → retry with x-payment.

const first = await fetch("https://transvia.xyz/api/quote", {
  method: "POST",
  headers: {
    "content-type": "application/json",
    "x-corridor-client": "external-agent",
  },
  body: JSON.stringify({ corridor: "USD-EUR", amountUsdc: 100 }),
});
// first.status === 402 — payment terms in (await first.json()).accepts[0]

// Build the payment: an EIP-3009 TransferWithAuthorization signed by the
// agent's wallet (viem signTypedData), then base64-encode the payload.
const payment = {
  x402Version: 1,
  scheme: "exact",
  network: "arc-testnet",
  payer: account.address,
  asset: "USDC",
  amount: "10000", // 0.01 USDC in 6-decimal units
  authorization: { from, to: payTo, value: "10000", validAfter, validBefore, nonce },
  signature,
};

const second = await fetch("https://transvia.xyz/api/quote", {
  method: "POST",
  headers: {
    "content-type": "application/json",
    "x-corridor-client": "external-agent",
    "x-payment": btoa(JSON.stringify(payment)),
  },
  body: JSON.stringify({ corridor: "USD-EUR", amountUsdc: 100 }),
});
// second.status === 200 — the verifier recovered the signer, matched the payer

Prefer not to sign anything? POST https://transvia.xyz/api/x402/demo replays the full 402 → pay → 200 handshake against the live API. See x402.

4. An MCP session with Claude Code

claude mcp add --transport http transvia https://transvia.xyz/api/mcp

Then just ask:

Quote 500 USDC to INR and send it to "Alice" — then show me the status.

Claude discovers the tools (rail_overview, corridor_quote, corridor_send, corridor_status, …), calls them, and narrates the lifecycle. Every send is policy-gated and logged like any other transfer. See MCP for the tool reference.

Prefer raw JSON-RPC? The same session over curl:

curl -s -X POST https://transvia.xyz/api/mcp \
  -H "content-type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

More endpoints in API; the full sending flow in Sending USDC.