Buy Crypto
All crypto asset purchases at XGate are conducted exclusively using the company's own balance in Brazilian Reais (BRL) directly from XGate's treasury. XGate debits the BRL amount from the corporate balance and transfers the purchased tokens directly to the company's designated destination wallet, without custodial intermediation.
Endpoint
- Method: POST
https://api.xgateglobal.com/crypto/purchases
Request
Required Headers
| Header | Value | Description |
|---|---|---|
Authorization | Bearer <your_token> | The JWT token obtained at login. |
Purchase Methods
Purchases with the company's BRL balance can be requested on-demand (directly through this endpoint) or scheduled as an additional instruction linked to a Pix deposit via POST /deposit:
- With Quote (BRL Balance)
- At Market (BRL Balance)
- Additional Instruction in Pix (POST /deposit)
Purchases using the 30-second guaranteed price obtained through a prior quote (quoteId). Asset, network, and amount are determined by the quote.
{
"externalId": "order-7781",
"quoteId": "l3m8Qm1n0pV2cXk5dY9sTg4hWz7aB6eR1uJ0****",
"address": "TQn9Y2khEsLJW1ChVWFMSMeRDow5Kc****"
}
Instant purchase debiting available BRL balance at the current execution price. Fields asset, network, and amount are required.
{
"externalId": "order-7782",
"asset": "USDT",
"network": "TRON",
"amount": "1500.00",
"addressId": "66f1a2b3c4d5e6f70819****"
}
You can create a Pix billing order in POST /deposit and attach the purchase object as an additional instruction.
As soon as the Pix is confirmed and credited to the company's balance, your company purchases the crypto asset directly from XGate's treasury using the available balance:
{
"amount": 1500.00,
"customerId": "6a1a379e1fe9bfd92d2f****",
"currency": {
"_id": "6728f0a2cba3ac9ea300****",
"name": "BRL",
"type": "PIX",
"symbol": "R$"
},
"purchase": {
"asset": "USDT",
"network": "POLYGON",
"address": "0xf73345519993edc1006388b5596100d2dd51****"
},
"externalId": "order-7783"
}
Body for Direct Request (POST /crypto/purchases)
| Field | Type | Required | Description |
|---|---|---|---|
externalId | string | Yes | Identifier for the purchase in your system. 1 to 128 printable ASCII characters, without / and not starting with $. Unique per company. |
address | string | One of both | Company destination external wallet address, valid on the network (no memo/tag). |
addressId | string | One of both | Pre-registered address ID from dashboard (buy.addresses[].addressId from Options). |
quoteId | string | Form with quote | Active quote ID. Cannot be sent together with asset, network, or amount. |
asset, network, amount | string | Form at market | Asset (USDT/USDC), network, and total in BRL debited from balance (string with 2 decimals). |
- Same
externalId+ same body → 200 OK returning the existing purchase record. - Same
externalId+ differing body →409 EXTERNAL_ID_CONFLICT.
Responses
Success (201 Created)
Returned once the amount is debited from the corporate balance and execution begins (status EXECUTING):
{
"id": "6710c2f4a1b2c3d4e5f6****",
"externalId": "order-7781",
"status": "EXECUTING",
"channel": "API",
"asset": "USDT",
"network": "TRON",
"address": "TQn9Y2khEsLJW1ChVWFMSMeRDow5Kc****",
"amount": "1500.00",
"rate": "5.45400000",
"cryptoAmount": "275.027502",
"networkFee": "0.012000",
"deliveredAmount": "275.015502",
"quoteId": "l3m8Qm1n0pV2cXk5dY9sTg4hWz7aB6eR1uJ0****",
"depositId": null,
"approval": { "required": true, "decision": null, "decidedAt": null },
"delivery": { "status": "WAITING_APPROVAL", "txHash": null, "confirmedAt": null },
"rejection": null,
"executedAt": "2026-10-13T14:03:40.512Z",
"createdAt": "2026-10-13T14:03:40.204Z",
"updatedAt": "2026-10-13T14:03:40.512Z"
}
Lifecycle
(PENDING_PAYMENT)* ──► EXECUTING ──► PENDING_APPROVAL ──► DELIVERED
│ │
└────────────────┴──────────► REJECTED
*PENDING_PAYMENT: Initial status only when scheduled as an additional instruction linked to a Pix deposit (channel = "DEPOSIT"), while the Pix awaits settlement.- Without auto-approval (
buy.autoApproval = false): purchase enters XGate's compliance approval queue (PENDING_APPROVAL). Price and amount remain locked. - With auto-approval: order immediately advances to on-chain execution until
DELIVERED. - In
DELIVERED, the public on-chain blockchain hash is provided underdelivery.txHash. - In
REJECTED, if execution fails, the full BRL amount is refunded to company balance (rejection.refunded = true).
Track updates via Query Purchase or through Purchase Webhooks (purchase.*).
Purchase Object
| Field | Type | Description |
|---|---|---|
id | string | Purchase ID at XGate. |
externalId | string | Purchase ID in your system. |
status | string | PENDING_PAYMENT · EXECUTING · PENDING_APPROVAL · DELIVERED · REJECTED · EXPIRED. |
channel | string | Instruction origin: API (direct POST), DASHBOARD (panel), or DEPOSIT (scheduled purchase triggered upon Pix confirmation). |
asset, network, address | string | Destination of crypto assets on the network. |
amount | string | null | Total BRL debited from corporate balance. |
rate | string | null | Price of 1 unit of the asset in BRL (8 decimals), fixed at execution, inclusive of margin. |
cryptoAmount | string | null | Gross quantity of crypto purchased (amount ÷ rate, 6 decimals). |
networkFee | string | null | Network gas fee deducted from final delivery. |
deliveredAmount | string | null | Net amount delivered to the destination wallet: cryptoAmount − networkFee. |
quoteId | string | null | Guaranteed quote utilized (returns null on market purchase). |
depositId | string | null | Originating deposit ID when triggered following Pix confirmation (channel = "DEPOSIT"). |
approval | object | required (boolean), decision (APPROVED | REJECTED | AUTO | null), decidedAt. |
delivery | object | status (WAITING_APPROVAL · QUEUED · SUBMITTED · CONFIRMING · CONFIRMED · null), txHash, confirmedAt. |
rejection | object | null | Rejection details: reason, message, and refunded. |
executedAt, createdAt | string | ISO 8601 timestamps (UTC). |
Common Errors
| Status | Reason |
|---|---|
| 400 | VALIDATION_FAILED, AMOUNT_MUST_BE_STRING, CONFLICTING_FIELDS |
| 401 | UNAUTHORIZED |
| 403 | PERMISSION_DENIED, COMPANY_BLOCKED, ALLOWED_IPS_REQUIRED, CLIENT_IP_NOT_ALLOWED, BUY_DISABLED |
| 404 | SAVED_ADDRESS_NOT_FOUND, QUOTE_NOT_FOUND |
| 409 | EXTERNAL_ID_CONFLICT, QUOTE_EXPIRED, QUOTE_ALREADY_USED |
| 422 | ASSET_NOT_SUPPORTED, NETWORK_NOT_SUPPORTED, AMOUNT_BELOW_MIN, AMOUNT_ABOVE_MAX, ADDRESS_INVALID_FOR_NETWORK, INSUFFICIENT_BALANCE, PRICE_UNSTABLE |
| 429 | RATE_LIMITED, DAILY_CAP_EXCEEDED, OUTFLOW_HOURLY_CAP_EXCEEDED |
| 503 | PRICE_STALE, NETWORK_FEE_UNAVAILABLE, CRYPTO_TEMPORARILY_UNAVAILABLE, SERVICE_OVERLOADED |
Integration
- Node.js
const axios = require("axios");
(async () => {
const email = "your_email@domain.com";
const password = "**************";
try {
const url_api = "https://api.xgateglobal.com";
const login = await axios.post(`${url_api}/auth/token`, { email, password });
const headers = { "Authorization": `Bearer ${login.data.token}` };
// 1. Obtain quote with price locked for 30s
const quote = await axios.post(`${url_api}/crypto/quotes`, {
asset: "USDT",
network: "TRON",
amount: "1500.00"
}, { headers });
// 2. Execute purchase directly from XGate treasury using company BRL balance
const { data } = await axios.post(`${url_api}/crypto/purchases`, {
externalId: "order-7781",
quoteId: quote.data.quoteId,
address: "TQn9Y2khEsLJW1ChVWFMSMeRDow5Kc****"
}, { headers });
console.log("Purchase ID:", data.id, "Status:", data.status);
} catch (error) {
console.log(error.response?.data?.reason, error.response?.data?.message);
}
})();