API Reference
Every Transvia endpoint — quotes, transfers, claims, approvals, and machine payments.
The API is the same rail the product runs on. Base URL for every example:
https://transvia.xyzRequests and responses are JSON. The Testnet API is open — no key required. Amounts are USDC numbers.
A typical session, as a UML sequence diagram:
UML sequence — the quote → send → poll → claim REST flow
Client Transvia API Escrow · settle engine
│ │ │
│──POST /api/quote──────▶│ │
│◀─200 quote (60s TTL)───│ │
│──POST /api/send───────▶│ deposit() │
│◀─200 intent deposited──│────────────────────────▶│
│──GET /api/intents─────▶│◀─settle() 3 legs────────│ (agent tick)
│◀─200 fx_locked… │ │
│──GET /api/intents─────▶│ poll advances state │
│◀─200 claimable │ │
│──POST /api/claim──────▶│ claim(EIP-712 sig) │
│◀─200 ok + txHash───────│────────────────────────▶│Endpoints
| Method | Path | Purpose |
|---|---|---|
| GET | /api/health | Rail mode, chain, escrow status |
| POST | /api/quote | FX quote with full fee split |
| POST | /api/send | Lock a quote into a transfer (escrow deposit) |
| POST | /api/claim | Recipient releases the payout (EIP-712) |
| GET | /api/intents | Settlement feed (advances in-flight state) |
| GET | /api/intents/{id} | One transfer plus its full event trail |
| GET | /api/agent/actions | Automation decision log |
| GET | /api/agent/payments | x402 machine-payment ledger |
| POST | /api/agent/tick | Run one automation agent cycle |
| GET | /api/approvals | Team approval queue (newest first) |
| POST | /api/approvals | Raise an approval request |
| POST | /api/approvals/{id} | Cast a reviewer vote |
| POST | /api/x402/demo | Replay a live 402 → pay → 200 handshake |
| POST | /api/mcp | MCP JSON-RPC 2.0 over Streamable HTTP |
Corridors
USD-EUR · USD-GBP · USD-MXN · USD-BRL · USD-PHP · USD-NGN ·
USD-AED · USD-SGD · USD-CAD · USD-AUD · USD-INR
FX rates are indicative — the sandbox FX source is simulated StableFX, and
every quote is labeled with it (source: "simulated-stablefx-v1").
POST /api/quote
Request: { "corridor": "USD-EUR", "amountUsdc": 100 }
{
"quote": {
"id": "qt_lz3k9f_ab12cd",
"corridor": "USD-EUR",
"amountUsdc": 100,
"fxRate": 0.923341,
"destAmount": 91.87243,
"feeLpUsdc": 0.35,
"feeAgentUsdc": 0.05,
"feeProtoUsdc": 0.1,
"source": "simulated-stablefx-v1",
"expiresAt": "2026-01-15T12:01:00.000Z"
}
}Quotes expire after 60 seconds; the per-quote cap is 1,000,000 USDC.
Machine access: callers sending x-corridor-client: external-agent
without an x-payment header receive 402 Payment Required with
machine-readable payment terms; the paid retry returns the quote. 0.01 USDC
per quote on Arc Testnet — see x402.
POST /api/send
Request: { "quoteId": "qt_lz3k9f_ab12cd", "recipientLabel": "Alice", "recipientAddr": "0x…" }
Returns { "intent": { … } } — the transfer with status deposited, rate,
destination amount, fee split, timeoutAt, the escrow txHash, and its
first events (QUOTED, DEPOSIT). A lapsed quote is 410; live-rail guard
failures (testnet cap, escrow float, placeholder recipient) are 409.
POST /api/claim
Request: { "intentId": "int_…", "signature": "0x…", "deadline": 1768483260 }
Signature and deadline are optional on the simulated rail. Live mode
verifies the recipient's EIP-712 Claim authorization. Returns
{ "ok": true, "txHash": "0x…" }. Not claimable or already claimed → 409;
a bad signature → 400.
GET /api/intents and the single-intent endpoint
{ "intents": [ … ], "agentFired": 1, "mode": "simulated" }The feed is newest first, up to 30 transfers; polling advances the
settlement state machine and runs one agent cycle, so it is always current.
GET /api/intents/{id} returns { "intent": { … } } — one transfer with
its complete event trail (actor, human-readable detail, txHash). Unknown
id → 404.
GET /api/agent/actions and GET /api/agent/payments
{
"actions": [
{
"id": "act_…",
"kind": "TIMEOUT_REFUND",
"intentId": "int_…",
"signal": "timeoutAt exceeded by 12s · status was fx_locked",
"decision": "Triggered agentFallback(TIMEOUT) on escrow — refunded 100 USDC to sender…",
"x402Cost": null,
"createdAt": "2026-01-15T12:03:40.000Z"
}
]
}The automation decision log, 50 newest. Kinds: WATCH, TIMEOUT_REFUND,
COMPLIANCE_HOLD, FX_FEED_PURCHASE, FEE_SPLIT_BATCH, X402_GUARD.
GET /api/agent/payments is the x402 machine-economy ledger (50 newest):
payer, endpoint, amount, scheme, network, status, timestamp.
POST /api/agent/tick
Body is optional: { "forceTimeoutIntentId": "int_…" } pulls a transfer's
timeout into the past so the agent's refund can be shown on cue. Returns
{ "fired": 1 }.
GET + POST /api/approvals
GET returns the queue, newest first (30 max). POST raises a request:
{ "corridor": "USD-EUR", "amountUsdc": 7500, "recipientLabel": "Acme Pte Ltd", "fxDriftPct": 0.4, "liquidity": "high" }
The verdict is recomputed server-side by the policy engine — client-supplied
reasons are never trusted, and AUTO_EXECUTE transfers are refused with
409. The stored request carries the engine's own reasons and the
quorum.
POST /api/approvals/id — cast a vote
{ "role": "Finance", "decision": "approve", "note": "Invoice #4311" }Roles: Finance, Operations, Compliance. One vote per role (repeat →
409); a reject resolves immediately; approvals resolve at the stored
quorum (2-of-3); resolved requests are closed to further votes.
POST /api/x402/demo and POST /api/mcp
No body on the demo — it replays the full x402 handshake against the live
quote endpoint (402 challenge, EIP-3009 signature, paid retry) and returns
{ "steps": [ … ], "ok": true }. See x402. /api/mcp takes
a JSON-RPC 2.0 body over Streamable HTTP — e.g.
{ "jsonrpc": "2.0", "id": 1, "method": "tools/list" }. Full tool reference
and setup in MCP.
Errors
| Status | Meaning |
|---|---|
| 400 | Invalid input, bad signature |
| 402 | Payment required (agent quote without x-payment) |
| 404 | Unknown transfer or approval request |
| 409 | State conflict — already claimed, guard failures, AUTO_EXECUTE |
| 410 | Quote expired |
| 502 | Chain failure before escrow (deposit not made) |