Skip to main content

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
Endpoint URL
https://api.xgateglobal.com/crypto/purchases

Request​

Required Headers​

HeaderValueDescription
AuthorizationBearer <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:

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****"
}

Body for Direct Request (POST /crypto/purchases)​

FieldTypeRequiredDescription
externalIdstringYesIdentifier for the purchase in your system. 1 to 128 printable ASCII characters, without / and not starting with $. Unique per company.
addressstringOne of bothCompany destination external wallet address, valid on the network (no memo/tag).
addressIdstringOne of bothPre-registered address ID from dashboard (buy.addresses[].addressId from Options).
quoteIdstringForm with quoteActive quote ID. Cannot be sent together with asset, network, or amount.
asset, network, amountstringForm at marketAsset (USDT/USDC), network, and total in BRL debited from balance (string with 2 decimals).
Idempotency via externalId
  • 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 under delivery.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​

FieldTypeDescription
idstringPurchase ID at XGate.
externalIdstringPurchase ID in your system.
statusstringPENDING_PAYMENT · EXECUTING · PENDING_APPROVAL · DELIVERED · REJECTED · EXPIRED.
channelstringInstruction origin: API (direct POST), DASHBOARD (panel), or DEPOSIT (scheduled purchase triggered upon Pix confirmation).
asset, network, addressstringDestination of crypto assets on the network.
amountstring | nullTotal BRL debited from corporate balance.
ratestring | nullPrice of 1 unit of the asset in BRL (8 decimals), fixed at execution, inclusive of margin.
cryptoAmountstring | nullGross quantity of crypto purchased (amount ÷ rate, 6 decimals).
networkFeestring | nullNetwork gas fee deducted from final delivery.
deliveredAmountstring | nullNet amount delivered to the destination wallet: cryptoAmount − networkFee.
quoteIdstring | nullGuaranteed quote utilized (returns null on market purchase).
depositIdstring | nullOriginating deposit ID when triggered following Pix confirmation (channel = "DEPOSIT").
approvalobjectrequired (boolean), decision (APPROVED | REJECTED | AUTO | null), decidedAt.
deliveryobjectstatus (WAITING_APPROVAL · QUEUED · SUBMITTED · CONFIRMING · CONFIRMED · null), txHash, confirmedAt.
rejectionobject | nullRejection details: reason, message, and refunded.
executedAt, createdAtstringISO 8601 timestamps (UTC).

Common Errors​

StatusReason
400VALIDATION_FAILED, AMOUNT_MUST_BE_STRING, CONFLICTING_FIELDS
401UNAUTHORIZED
403PERMISSION_DENIED, COMPANY_BLOCKED, ALLOWED_IPS_REQUIRED, CLIENT_IP_NOT_ALLOWED, BUY_DISABLED
404SAVED_ADDRESS_NOT_FOUND, QUOTE_NOT_FOUND
409EXTERNAL_ID_CONFLICT, QUOTE_EXPIRED, QUOTE_ALREADY_USED
422ASSET_NOT_SUPPORTED, NETWORK_NOT_SUPPORTED, AMOUNT_BELOW_MIN, AMOUNT_ABOVE_MAX, ADDRESS_INVALID_FOR_NETWORK, INSUFFICIENT_BALANCE, PRICE_UNSTABLE
429RATE_LIMITED, DAILY_CAP_EXCEEDED, OUTFLOW_HOURLY_CAP_EXCEEDED
503PRICE_STALE, NETWORK_FEE_UNAVAILABLE, CRYPTO_TEMPORARILY_UNAVAILABLE, SERVICE_OVERLOADED

Integration​

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);
}
})();