OTC
Todos os endpoints exigem
Authorization: Bearer <token>e o headerx-client-id: <seu Client_ID>— o tenant id é o mesmo valor doClient_IDdo OAuth (detalhes); sem ele a chamada falha com400 MISSING_CLIENT_ID. As operações são escopadas ao seu tenant.
Visão geral
A API de OTC permite que o seu tenant solicite e execute trades de compra/venda de cripto (ex.: USDT/BRL) inteiramente via API. A liquidez, o provedor e a nossa conta de liquidação são resolvidos pelo nosso lado — você nunca vê a origem, o custo ou a margem; apenas o preço final aplicável ao seu tenant.
Sides:
BUY(onramp) — você compra cripto e paga em BRL. A cripto é enviada para awalletAddressque você informa.SELL(offramp) — você vende cripto e recebe BRL. A cripto sai de uma carteira custodial sua (fromAddress, gerida por nós); nós a movemos para a nossa custódia e liquidamos o BRL.
Perna fiat — como o BRL se move
- BUY (onramp): você escolhe no request, via
paymentMethod:ACCOUNT_DEBIT(padrão) — a plataforma debita automaticamente, via PIX, a conta de OTC que você tem configurada (conta → nossa conta de liquidação). Não há QR nem pagamento manual. A conta de OTC deve estar previamente fundeada em BRL.PIX_QRCODE— nós emitimos uma cobrança PIX (QR code / copia-e-cola) e devolvemos empixIn. Você paga de uma conta do próprio CNPJ do seu tenant, em qualquer banco, dentro do prazo. Veja PIX via QR code.
- SELL (offramp): após a venda da cripto, o BRL é pago via PIX na chave PIX do seu tenant — a chave configurada para você pelo operador Axia (padrão) ou a chave que você informa em
pixKey. Só pagamos chaves cujo titular seja o CNPJ do seu tenant; chave de terceiro (inclusive de cliente final) é recusada.
Titularidade por CNPJ. Tanto o PIX que você nos paga (BUY por QR) quanto o PIX que pagamos a você (SELL) ficam amarrados ao documento (CNPJ) cadastrado para o seu tenant. Isso é obrigatório para usar
PIX_QRCODEe para receber o SELL por PIX — confirme com o suporte que o CNPJ e a chave PIX do seu tenant estão cadastrados.
Preço
- BUY: o preço da cotação é indicativo. O preço final é travado no momento em que o PIX é confirmado (no
ACCOUNT_DEBIT, segundos após o débito; noPIX_QRCODE, quando o seu pagamento chega) — você recebe a cripto pelo preço daquele instante. - SELL: a cotação (
quoteId) trava o preço e a execução roda contra ele.
Fluxo típico:
- Cotar (
GET /v1/otc/quote) — preço + volume/valor resultante (noBUY, indicativo). - Solicitar o trade (
POST /v1/otc/trades). - Acompanhar (
GET /v1/otc/trades/{id}) ostatusatéSETTLED.
GET /v1/otc/quote
Retorna o preço aplicável, o volume/valor resultante e um quoteId travado (retornado em ambos os lados, BUY e SELL, sempre que a camada de liquidez o disponibiliza).
Query params:
| Param | Type | Required | Description |
|---|---|---|---|
coin | string | Yes | Ativo, ex.: USDT |
side | string | Yes | BUY | SELL |
mode | string | Yes | BY_FIAT (você fixa o BRL) | BY_CRYPTO (você fixa o volume do ativo) |
amount | number | Yes | BRL quando BY_FIAT; volume do ativo quando BY_CRYPTO |
Response 200 OK:
{
"data": {
"side": "BUY",
"mode": "BY_FIAT",
"asset": "USDT",
"price": 5.5825,
"clientRate": 5.5825,
"volume": 17912.5,
"fiatAmount": 100000,
"quoteId": "liq-9f2c...",
"expiresAt": "2026-06-18T12:00:30.000Z"
}
}| Field | Description |
|---|---|
price / clientRate | Preço por unidade do ativo (BRL) aplicável ao seu tenant. No BUY é indicativo (o preço final é travado na confirmação do débito). |
volume | Quantidade do ativo |
fiatAmount | Valor total em BRL |
quoteId | Identificador da cotação. No SELL, passe-o no POST /v1/otc/trades para executar contra o preço travado. |
expiresAt | Instante de expiração da cotação travada (ISO 8601). |
O preço é provedor-agnóstico: você nunca vê a origem da liquidez, o custo ou a margem.
POST /v1/otc/trades
Cria o trade. A execução é assíncrona (em background) e idempotente — acompanhe status até SETTLED.
Headers:
| Header | Value |
|---|---|
Authorization | Bearer <token> |
Content-Type | application/json |
Request Body (BUY — onramp):
{
"asset": "USDT",
"side": "BUY",
"mode": "BY_FIAT",
"amount": 100000,
"walletAddress": "TXxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"walletNetwork": "TRON"
}Sem paymentMethod (ou com ACCOUNT_DEBIT), a plataforma debita automaticamente a sua conta de OTC via PIX e entrega o USDT na walletAddress — não há pixIn/QR para pagar.
Request Body (BUY — onramp, pagamento por QR code):
{
"asset": "USDT",
"side": "BUY",
"mode": "BY_FIAT",
"amount": 100000,
"walletAddress": "TXxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"walletNetwork": "TRON",
"paymentMethod": "PIX_QRCODE"
}A resposta traz pixIn com o copia-e-cola a pagar do CNPJ do seu tenant até pixIn.expiresAt — ver PIX via QR code.
Request Body (SELL — offramp):
{
"asset": "USDT",
"side": "SELL",
"mode": "BY_CRYPTO",
"amount": 18000,
"quoteId": "liq-9f2c...",
"fromAddress": "TYyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy",
"walletNetwork": "TRON",
"pixKey": "[email protected]"
}| Field | Type | Required | Description |
|---|---|---|---|
asset | string | Yes | Ativo negociado (ex.: USDT). Aceita também coin. |
side | string | Yes | BUY | SELL |
mode | string | Yes | BY_FIAT | BY_CRYPTO |
amount | number | Yes | BRL (BY_FIAT) ou volume (BY_CRYPTO) |
walletAddress | string | BUY | BUY: endereço de destino que receberá a cripto (obrigatório). SELL: não usado — informe fromAddress. |
walletNetwork | string | Yes | Rede de entrega da cripto: TRON (USDT-TRC20) ou ETH (USDT-ERC20). Ver Redes de entrega. |
fromAddress | string | SELL | SELL: endereço de origem — carteira custodial do seu tenant (criada via POST /v1/crypto/wallets), não bloqueada. |
pixKey | string | No (SELL) | SELL: chave PIX que recebe o BRL. O titular tem que ser o CNPJ do seu tenant (conferido no DICT na criação e de novo antes do pagamento; chave de terceiro → 403). Ausente → usa a chave PIX configurada para o seu tenant; sem ela, a chave da sua conta de OTC cadastrada. |
paymentMethod | string | No (BUY) | BUY: ACCOUNT_DEBIT (padrão — débito automático da sua conta de OTC) ou PIX_QRCODE (nós emitimos um QR e você paga do CNPJ do seu tenant). Valor inválido → 400 INVALID_PAYMENT_METHOD. Ignorado no SELL. |
quoteId | string | No | SELL: cotação travada (do GET /v1/otc/quote). BUY: opcional/indicativo — o preço final é travado na confirmação. |
bankingAccountId | string | No | Conta do tenant; por padrão usa a conta ativa mais recente. |
Response 200 OK:
{
"data": {
"id": "a1b2c3d4-...",
"side": "BUY",
"asset": "USDT",
"quoteCurrency": "BRL",
"volume": 17912.5,
"unitPrice": 5.5825,
"totalAmount": 100000,
"walletAddress": "TXxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"walletNetwork": "TRON",
"status": "PROCESSING",
"txHash": null,
"createdAt": "2026-06-18T12:00:00.000Z",
"executedAt": null
}
}BUY (onramp): com
ACCOUNT_DEBITa perna fiat é um débito PIX automático da sua conta de OTC — não envie nada manualmente. ComPIX_QRCODEa resposta incluipaymentMethod: "PIX_QRCODE"e o blocopixIna pagar. O preço final é travado na confirmação do PIX. SELL (offramp): você não envia a cripto manualmente. Como a carteira de origem é custodiada por nós, nós iniciamos a transferência on-chain dela para a nossa custódia e seguimos com a liquidação.
Erros comuns:
| HTTP | Motivo |
|---|---|
400 | Faltam campos / falta clientId / amount fora dos limites de ticket / fromAddress ausente no SELL |
403 | fromAddress (SELL) não pertence ao seu tenant, ou a carteira está bloqueada; PIX key refused — a pixKey (SELL) não pertence ao CNPJ do seu tenant |
404 | Sem cotação para o ativo / sem conta bancária ativa para o tenant |
409 | QUOTE_EXPIRED (cotação venceu — cote novamente), SLIPPAGE_EXCEEDED (o preço saiu da tolerância — cote novamente) ou CNPJ do tenant não cadastrado (necessário para PIX_QRCODE) |
429 | Rate-limit excedido |
PIX via QR code (BUY)
Com paymentMethod: "PIX_QRCODE", em vez de debitarmos a sua conta de OTC, nós emitimos uma cobrança PIX na nossa conta de liquidação e devolvemos os dados para você pagar. O trade fica em PENDING até o PIX chegar.
Response 200 OK (trecho):
{
"data": {
"id": "a1b2c3d4-...",
"side": "BUY",
"status": "PENDING",
"paymentMethod": "PIX_QRCODE",
"totalAmount": 100000,
"pixIn": {
"emv": "00020126580014br.gov.bcb.pix...",
"pixKey": "[email protected]",
"transactionIdentification": "a1b2c3d4",
"amount": 100000,
"expiresAt": "2026-08-27T17:30:00.000Z",
"payerDocument": "12345678000199",
"paid": false
}
}
}| Campo | Descrição |
|---|---|
pixIn.emv | Payload do QR (PIX copia-e-cola). Renderize como QR code ou cole no app do banco. |
pixIn.amount | Valor exato em BRL a pagar. Pagamento com valor diferente não é conciliado. |
pixIn.expiresAt | Prazo de pagamento. Sem PIX até esse instante, o trade vira FAILED (PIX_IN_EXPIRED). |
pixIn.payerDocument | O CNPJ que deve ser o pagador (o documento cadastrado para o seu tenant). |
pixIn.paid | true depois que o PIX foi conciliado. |
Regras:
- O PIX tem que sair de uma conta do CNPJ em
payerDocument(qualquer banco). Um PIX pago por outro documento é recusado: o trade viraFAILED(PIX_IN_PAYER_MISMATCH), nenhuma cripto é entregue e o valor é devolvido manualmente pelo nosso time — entre em contato com o suporte. - Pague o valor exato e dentro do prazo. O
pixIntambém aparece emGET /v1/otc/trades/{id}enquanto o trade estiver pendente. - Assim que o PIX é confirmado, o preço é travado e a execução segue normalmente (
PROCESSING→SETTLED); use os webhooksotc.trade.settled/otc.trade.failedou o polling.
GET /v1/otc/trades
Lista os trades do seu tenant (apenas os originados pelo seu clientId).
Query params: limit, offset (opcionais).
Response 200 OK: array de trades (mesmo shape do POST).
GET /v1/otc/trades/{id}
Detalhe do trade. Retorna 404 se o trade não pertencer ao seu tenant.
Response 200 OK:
{
"data": {
"id": "a1b2c3d4-...",
"side": "SELL",
"asset": "USDT",
"totalAmount": 100000,
"walletAddress": "TXxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"walletNetwork": "TRON",
"status": "SETTLED",
"txHash": "0xabc...",
"createdAt": "2026-06-18T12:00:00.000Z",
"executedAt": "2026-06-18T12:03:00.000Z"
}
}Estados do trade (status)
| Status | Significado |
|---|---|
PENDING | Recebido, ainda não iniciado |
PROCESSING | Em processamento (débito fiat e/ou liquidação cripto em andamento) |
SETTLED | Concluído |
FAILED | Falhou |
CANCELLED | Cancelado |
Os estados são neutros por design — você acompanha o macro-estado do trade sem ver como a liquidez foi originada. Quando status for SETTLED, txHash traz o hash on-chain (envio da cripto no BUY; transferência da custódia no SELL).
Webhooks (alternativa ao polling): em vez de consultar
GET /v1/otc/trades/{id}atéSETTLED, você pode assinar os eventosotc.trade.settledeotc.trade.failede receber o trade final por push. Veja Webhooks.
Redes de entrega
O USDT pode ser entregue em duas redes, selecionadas pelo campo walletNetwork do trade:
| Rede | walletNetwork | Padrão do endereço | Exemplo |
|---|---|---|---|
| TRON (TRC-20) | TRON | Base58, começa com T, 34 caracteres | TXxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx |
| Ethereum (ERC-20) | ETH (ou ETHEREUM) | Hex, começa com 0x, 40 caracteres | 0xAbC1230000000000000000000000000000000000 |
Validação de endereço. O walletAddress (BUY) / fromAddress (SELL) é validado contra a rede antes de qualquer movimentação: um endereço de outra rede (ex.: um T... numa entrega Ethereum, ou um 0x... numa entrega TRON) ou um endereço malformado é rejeitado com 400. Isso protege contra perda de fundos por entrega na rede errada.
Custo por rede. A rede Ethereum tem custo de rede (gas) maior e variável; o preço final aplicável ao seu tenant já reflete a rede escolhida. A confirmação on-chain na Ethereum também pode levar mais tempo que na TRON.
As redes aceitas são TRON e Ethereum. Qualquer outra rede retorna
400.
Whitelist de saque (BUY)
Por padrão, uma ordem BUY entrega a cripto para o walletAddress informado no request. Se preferir, você pode restringir a entrega apenas a endereços previamente cadastrados: ative a whitelist e cadastre os endereços permitidos. Enquanto ligada, um BUY para um endereço fora da lista é rejeitado com 403. A whitelist não se aplica ao SELL (cujo endereço é a sua carteira custodial de origem).
Todos os endpoints são escopados pelo seu tenant (clientId do OAuth). O toggle também pode ser ligado/desligado pelo operador Axia.
GET /v1/otc/whitelist/settings
Retorna { "enabled": true|false }.
PUT /v1/otc/whitelist/settings
Liga/desliga a whitelist. Body: { "enabled": true }.
GET /v1/otc/whitelist
Lista os endereços cadastrados: [{ "id", "network", "address", "label" }].
POST /v1/otc/whitelist
Cadastra um endereço. Body: { "network": "TRON", "address": "T...", "label": "Tesouraria" }. O address é validado por rede (TRON/EVM). Endereço já cadastrado retorna 409.
DELETE /v1/otc/whitelist/{id}
Remove um endereço da sua whitelist.