Skip to content

OTC ​

Todos os endpoints exigem Authorization: Bearer <token> e o header x-client-id: <seu Client_ID> — o tenant id é o mesmo valor do Client_ID do OAuth (detalhes); sem ele a chamada falha com 400 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 a walletAddress que 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 em pixIn. 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_QRCODE e 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; no PIX_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:

  1. Cotar (GET /v1/otc/quote) — preço + volume/valor resultante (no BUY, indicativo).
  2. Solicitar o trade (POST /v1/otc/trades).
  3. Acompanhar (GET /v1/otc/trades/{id}) o status até 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:

ParamTypeRequiredDescription
coinstringYesAtivo, ex.: USDT
sidestringYesBUY | SELL
modestringYesBY_FIAT (você fixa o BRL) | BY_CRYPTO (você fixa o volume do ativo)
amountnumberYesBRL quando BY_FIAT; volume do ativo quando BY_CRYPTO

Response 200 OK:

json
{
  "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"
  }
}
FieldDescription
price / clientRatePreç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).
volumeQuantidade do ativo
fiatAmountValor total em BRL
quoteIdIdentificador da cotação. No SELL, passe-o no POST /v1/otc/trades para executar contra o preço travado.
expiresAtInstante 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:

HeaderValue
AuthorizationBearer <token>
Content-Typeapplication/json

Request Body (BUY — onramp):

json
{
  "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):

json
{
  "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):

json
{
  "asset": "USDT",
  "side": "SELL",
  "mode": "BY_CRYPTO",
  "amount": 18000,
  "quoteId": "liq-9f2c...",
  "fromAddress": "TYyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy",
  "walletNetwork": "TRON",
  "pixKey": "[email protected]"
}
FieldTypeRequiredDescription
assetstringYesAtivo negociado (ex.: USDT). Aceita também coin.
sidestringYesBUY | SELL
modestringYesBY_FIAT | BY_CRYPTO
amountnumberYesBRL (BY_FIAT) ou volume (BY_CRYPTO)
walletAddressstringBUYBUY: endereço de destino que receberá a cripto (obrigatório). SELL: não usado — informe fromAddress.
walletNetworkstringYesRede de entrega da cripto: TRON (USDT-TRC20) ou ETH (USDT-ERC20). Ver Redes de entrega.
fromAddressstringSELLSELL: endereço de origem — carteira custodial do seu tenant (criada via POST /v1/crypto/wallets), não bloqueada.
pixKeystringNo (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.
paymentMethodstringNo (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.
quoteIdstringNoSELL: cotação travada (do GET /v1/otc/quote). BUY: opcional/indicativo — o preço final é travado na confirmação.
bankingAccountIdstringNoConta do tenant; por padrão usa a conta ativa mais recente.

Response 200 OK:

json
{
  "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_DEBIT a perna fiat é um débito PIX automático da sua conta de OTC — não envie nada manualmente. Com PIX_QRCODE a resposta inclui paymentMethod: "PIX_QRCODE" e o bloco pixIn a 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:

HTTPMotivo
400Faltam campos / falta clientId / amount fora dos limites de ticket / fromAddress ausente no SELL
403fromAddress (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
404Sem cotação para o ativo / sem conta bancária ativa para o tenant
409QUOTE_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)
429Rate-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):

json
{
  "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
    }
  }
}
CampoDescrição
pixIn.emvPayload do QR (PIX copia-e-cola). Renderize como QR code ou cole no app do banco.
pixIn.amountValor exato em BRL a pagar. Pagamento com valor diferente não é conciliado.
pixIn.expiresAtPrazo de pagamento. Sem PIX até esse instante, o trade vira FAILED (PIX_IN_EXPIRED).
pixIn.payerDocumentO CNPJ que deve ser o pagador (o documento cadastrado para o seu tenant).
pixIn.paidtrue 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 vira FAILED (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 pixIn também aparece em GET /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 webhooks otc.trade.settled / otc.trade.failed ou 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:

json
{
  "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) ​

StatusSignificado
PENDINGRecebido, ainda não iniciado
PROCESSINGEm processamento (débito fiat e/ou liquidação cripto em andamento)
SETTLEDConcluído
FAILEDFalhou
CANCELLEDCancelado

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 eventos otc.trade.settled e otc.trade.failed e 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:

RedewalletNetworkPadrão do endereçoExemplo
TRON (TRC-20)TRONBase58, começa com T, 34 caracteresTXxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Ethereum (ERC-20)ETH (ou ETHEREUM)Hex, começa com 0x, 40 caracteres0xAbC1230000000000000000000000000000000000

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.