Quickstart
Make your first cross-border payment in five minutes. You'll authenticate, lock a rate with a quote, commit it as an order, and track it to completion — all over stable JSON.
You'll need workspace credentials. Don't have them yet? Contact integrations@virtuabroker.com. Test everything against https://api-stage.virtuabroker.com first.
1 · Authenticate
Exchange your workspace credentials for a short-lived OAuth 2.0 bearer token using the password grant, then send it on every request. See the Authentication guide for the full flow.
export VB_TOKEN=$(curl -s https://auth2.virtuabroker.com/realms/cryptobot/protocol/openid-connect/token \ -d "grant_type=password" \ -d "client_id=$VB_CLIENT_ID" \ -d "username=$VB_USERNAME" \ -d "password=$VB_PASSWORD" | jq -r .access_token)
const res = await fetch("https://auth2.virtuabroker.com/realms/cryptobot/protocol/openid-connect/token", { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: new URLSearchParams({ grant_type: "password", client_id: process.env.VB_CLIENT_ID, username: process.env.VB_USERNAME, password: process.env.VB_PASSWORD, }), }); const { access_token } = await res.json();
import os, requests r = requests.post("https://auth2.virtuabroker.com/realms/cryptobot/protocol/openid-connect/token", data={ "grant_type": "password", "client_id": os.environ["VB_CLIENT_ID"], "username": os.environ["VB_USERNAME"], "password": os.environ["VB_PASSWORD"], }) access_token = r.json()["access_token"]
2 · Create a quote
A quote locks an exchange rate and fees for a currency pair. It's workspace-scoped and needs no customer identity. Quotes expire after a short window — create the order promptly.
curl https://api.virtuabroker.com/v1/quotes \ -H "Authorization: Bearer $VB_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "originCurrency": "EUR", "destinationCurrency": "BRL", "originAmount": 1000 }'
const res = await fetch("https://api.virtuabroker.com/v1/quotes", { method: "POST", headers: { Authorization: `Bearer ${access_token}`, "Content-Type": "application/json" }, body: JSON.stringify({ originCurrency: "EUR", destinationCurrency: "BRL", originAmount: 1000 }), }); const quote = await res.json();
quote = requests.post("https://api.virtuabroker.com/v1/quotes", headers={"Authorization": f"Bearer {access_token}"}, json={"originCurrency": "EUR", "destinationCurrency": "BRL", "originAmount": 1000}, ).json()
{
"quoteId": "d290f1ee-6c54-4b01-90e6-d701748f0851",
"originCurrency": "EUR",
"originAmount": 1000,
"destinationCurrency": "BRL",
"destinationAmount": 6094.01,
"pair": "EURBRL",
"price": 6.094,
"conversionRate": 6.1234,
"fee": 4.8,
"feeCurrency": "EUR",
"expireAt": 1694291200
}
Amounts are JSON numbers, never strings. quoteId is a UUID, conversionRate is the pair rate, price is the effective all-in rate, and expireAt is a unix timestamp in seconds — create the order before it passes.
3 · Create an order
Commit the quote to a payout destination. The fields inside destinationTransferData depend on the corridor's rail — for BRL that's a PIX key. Discover the exact fields per currency with GET /v1/currencies/{currency}/destination-schema. Paying out over SEPA instead? Also send the beneficiary's city and postalCode in destinationUserData.
curl https://api.virtuabroker.com/v1/orders \ -H "Authorization: Bearer $VB_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "quoteId": "d290f1ee-6c54-4b01-90e6-d701748f0851", "destinationTransferData": { "pixKey": "recipient@example.com", "holderName": "ACME LTDA" }, "externalReference": "invoice-2043" }'
const res = await fetch("https://api.virtuabroker.com/v1/orders", { method: "POST", headers: { Authorization: `Bearer ${access_token}`, "Content-Type": "application/json" }, body: JSON.stringify({ quoteId: "d290f1ee-6c54-4b01-90e6-d701748f0851", destinationTransferData: { pixKey: "recipient@example.com", holderName: "ACME LTDA" }, externalReference: "invoice-2043", }), }); const order = await res.json();
order = requests.post("https://api.virtuabroker.com/v1/orders", headers={"Authorization": f"Bearer {access_token}"}, json={ "quoteId": "d290f1ee-6c54-4b01-90e6-d701748f0851", "destinationTransferData": {"pixKey": "recipient@example.com", "holderName": "ACME LTDA"}, "externalReference": "invoice-2043", }, ).json()
Writes are not de-duplicated. If this call times out, do not simply resend it — the order may already exist. Reconcile with GET /v1/orders first; see Retrying a write.
4 · Track it to completion
An order moves through observable states. Poll GET /v1/orders/{id}, or — recommended — subscribe to webhooks and react to order_status_updated, checking data.status for Success or Failed.
curl https://api.virtuabroker.com/v1/orders/A7K9DP2X4Q1M \ -H "Authorization: Bearer $VB_TOKEN"