Skip to main content

Crypto-as-a-Service (CaaS) na API de Contas

Esta jornada usa a API de Contas (secureapi.<domínio>/api/v2) para o parceiro BaaS ou a conta operarem compra e venda de criptoativos: registrar carteiras, cotar, criar ordens e receber eventos.

O contrato público é /crypto-caas/* no prefixo /api/v2 da API de Contas. Não é um produto avulso: a autenticação, o envelope e os erros são os mesmos dos demais módulos de Contas (CryptoRisk, cobranças, webhooks).

Referência OpenAPI: API de Contas — CryptoCaas.

CaaS não substitui o CryptoRisk. CryptoRisk analisa risco de uma carteira. CaaS registra destino/origem e executa BUY/SELL.

Quando usar

Use esta API quando a sua aplicação precisa:

  1. Registrar uma carteira da conta (POST /crypto-caas/wallets)
  2. Listar as carteiras já cadastradas (GET /crypto-caas/wallets)
  3. Obter uma cotação BUY ou SELL (POST /crypto-caas/quotes)
  4. Criar a ordem a partir da cotação (POST /crypto-caas/orders)
  5. Acompanhar a ordem (GET /crypto-caas/orders/{id} e GET /crypto-caas/orders)
  6. Receber os eventos no webhook CRYPTO

O que não entra neste contrato: ids internos de catálogo (assetNetworkId), titular da carteira (ownerType, ownerDocument, ownerName), accountId no body, rotas de mesa/staff nem o canal App Finance.

Pré-requisitos

  • mTLS configurado. Veja certificado mTLS.
  • Credencial da API de Contas (Finance ou AppMobile) com os escopos crypto-caas.read e crypto-caas.write. No Finance: Configurações → API Contas → Nova credencial.
  • Token OAuth. Veja Autenticação.
  • Webhook CRYPTO se a aplicação for reagir a cadastro de carteira e a mudanças de ordem. Scope webhook.write. Veja Configurando Webhook.

Credenciais já emitidas não recebem os novos escopos automaticamente. Crie uma nova credencial ou atualize a existente incluindo crypto-caas.read e crypto-caas.write.

Credencial BaaS (clientId com prefixo baas_) opera contas filhas. Envie x-account-id com o id interno da conta alvo. Credencial de conta opera a própria conta e não precisa do cabeçalho. O x-account-id do cliente não vai no body: a API resolve a conta da credencial e não reenvia esse header ao broker.

Redes e ativos

network é a rede. USDT e USDC não são rede.

networkUso
BTCBitcoin
ETHEthereum (envelope também de USDT e USDC)
TRXTron (envelope também de USDT)
USDT, USDC ou qualquer outroNão. Responde 422 antes de qualquer chamada upstream.

Pares de cotação e ordem:

assetnetwork
BTCBTC
ETHETH
USDTETH ou TRX
USDCETH

USDC em TRX e qualquer outro par respondem 422.

Body do POST de carteira: { "network": "BTC" | "ETH" | "TRX", "address": "...", "alias": "..." }. Sem accountId no body.

Fluxo BUY

1. POST /crypto-caas/wallets { network, address, alias? }
→ 201 { data } com id da carteira
2. POST /crypto-caas/quotes { operation: BUY, network, asset, amountBrl?, destinationWalletId? }
→ 201 { data } com quoteId e validUntil
3. POST /crypto-caas/orders { operation: BUY, quoteId, amountBrl|amountAsset, destinationWalletId }
→ 201 { data } com id da ordem (UUID)
4. Acompanhe GET /crypto-caas/orders/{id} e os eventos crypto.order.updated / crypto.order.settled

BUY exige destinationWalletId na criação da ordem.

Fluxo SELL

1. A origem precisa estar cadastrada e elegível (VERIFIED na mesma rede, eligibleForSellOrigin=true)
2. POST /crypto-caas/quotes { operation: SELL, network, asset, originWalletId, amountBrl? }
→ 201 { data }
3. POST /crypto-caas/orders { operation: SELL, quoteId, amountBrl|amountAsset, originWalletId }
→ 201 { data }

SELL exige originWalletId na cotação e na ordem. Sem origem, a API de Contas responde 400 antes do broker. Origem cadastrada mas inelegível (pendente, rejeitada ou só auto-verificada como destino de BUY) é recusada pelo broker (4xx).

Primeira compra

A carteira e a cotação podem trazer isFirstPurchase, firstPurchaseLimitBrl e firstPurchaseLimitEnabled. Quando o destino está em regime de primeira compra, envie na ordem:

"firstPurchaseAcknowledgment": {
"accepted": true,
"textVersion": "v1"
}

accepted tem de ser true. O limite de primeira compra não corta o amountBrl nesta API; é sinalização (ciência do parceiro), não teto de valor.

O primeiro BUY SETTLED daquela carteira dispara crypto.wallet.first_purchase.

Idempotência

Nos POSTs, a API resolve um request id nesta ordem: Idempotency-Keyx-request-idx-correlation-id → UUID gerado. O valor é truncado em 128 caracteres. Não envie accountId no body.

Política (fail-closed)

A API de Contas não reimplementa política. O broker aplica:

  • SELL só com origem VERIFIED e eligibleForSellOrigin=true
  • Atestação de parceiro fail-closed quando a flag estiver ligada (403 permanece 403)
  • Criação de ordem é fail-closed (movimento de dinheiro não “passa quieto”)
  • Webhook/notify são fail-open: falha de publicação não desfaz a ordem nem a carteira

Envelopes

OperaçãoHTTPEnvelope
Criar carteira / cotação / ordem201{ data }
Detalhe de ordem200{ data }
Listar carteiras200{ meta: { total }, data }
Listar ordens200{ meta: { total, page, limit }, data }

Ordem de outra conta responde 404.

Erros

Os endpoints /crypto-caas/* respondem no envelope da API de Contas:

{
"detail": "network must be BTC, ETH or TRX. Received: USDT. USDT and USDC are assets on the ETH envelope (USDT also on TRX), not networks.",
"title": "Unprocessable entity",
"type": "onz-0026",
"instance": "/api/v2/crypto-caas/wallets"
}
HTTPQuando
400Body ou query inválidos (ex.: SELL sem originWalletId; quoteId que não é UUID; os dois amounts juntos)
401Token inválido ou escopo ausente
403Acesso negado, inclusive atestação de parceiro recusada
404Ordem inexistente ou de outra conta
409Conflito no broker (recurso já existente)
422Rede, ativo, operação ou par não suportados (network=USDT, USDC em TRX, etc.)
503Broker indisponível, timeout ou 401 interno do upstream (não confundir com OAuth da API de Contas)