Voltar
Fortbix
Documentação da API

Webhooks

Webhooks permitem que sua aplicação reaja a eventos em tempo real. A Fortbix envia uma requisição POST para a URL que você cadastrar sempre que um evento inscrito ocorrer.

Como cadastrar

O cadastro de webhooks não é feito via API com a sua api-key. A api-key serve apenas para autenticar as chamadas aos endpoints da API. Webhooks são gerenciados no Portal do Desenvolvedor, com a sua sessão autenticada.

Acesse o portal e configure seus webhooks:

https://app.fortbix.com/integracao/webhooks 

No portal você escolhe o ambiente (Sandbox ou Produção), informa a URL de callback (HTTPS) e seleciona os eventos desejados. Ao criar o webhook, a Fortbix gera um signing secret (prefixo whsec_) que é exibido apenas uma vez — guarde-o em local seguro. É esse valor que você usa para validar a assinatura das notificações (o WEBHOOK_SECRET dos exemplos abaixo).

Caso perca o secret, use as opções de revelar ou rotacionar secret na própria tela do webhook no portal.

Eventos Disponíveis

Os eventos são organizados por categoria, conforme exibido no portal.

Conta

EventoDescrição
transaction.createdTransação criada
transaction.processingTransação em processamento
transaction.settledTransação liquidada
transaction.failedFalha na transação
transaction.reversedTransação estornada

Garantias

EventoDescrição
collateral.createdGarantia criada
collateral.liquidatedGarantia liquidada
collateral.margin_callMargin call
collateral.ltv_alertAlerta de LTV
collateral.removedGarantia removida

Cadastros

EventoDescrição
wallet.registeredCarteira registrada
wallet.verifiedCarteira verificada
beneficiary.createdBeneficiário criado — reservado, em breve
beneficiary.approvedBeneficiário aprovado — reservado, em breve

Cripto

EventoDescrição
crypto.depositDepósito de cripto

Estrutura da Requisição

Cada notificação chega com os seguintes headers:

HeaderDescrição
X-Webhook-Event-IdID único do evento
X-Webhook-Event-TypeTipo do evento (ex: transaction.settled)
X-Webhook-SignatureAssinatura HMAC-SHA256 no formato sha256=<hash>
X-Webhook-Delivery-IdID único desta entrega (útil para idempotência)

E o corpo (JSON) segue o formato:

{
  "eventId": "d5a51404-84d7-4080-bff2-39b3d3935ca7",
  "eventType": "transaction.settled",
  "occurredAt": "2024-05-12T15:30:00Z",
  "environment": "production",
  "resource": {
    "type": "transaction",
    "id": "txn_789"
  },
  "data": {
    "amount": 50000,
    "currency": "USD"
  }
}

O campo environment indica o ambiente de origem do evento (production ou sandbox). O conteúdo de resource e data varia conforme o evento — veja a seção Payload por evento.

Payload por evento

Todos os eventos seguem o mesmo envelope (eventId, eventType, occurredAt, environment, resource, data). O que muda entre eles é o resource e o conteúdo de data. Abaixo, o formato de data de cada evento emitido.

Conta — transaction.*

Eventos: transaction.created, transaction.processing, transaction.settled, transaction.failed, transaction.reversed. Todos compartilham o mesmo formato (resource.type = "transaction").

{
  "eventType": "transaction.settled",
  "resource": { "type": "transaction", "id": "txn_789" },
  "data": {
    "transactionId": "txn_789",
    "status": "settled",
    "accountId": "acc_123",
    "amount": "50000",
    "currency": "USD"
  }
}
CampoTipoDescrição
transactionIdstringIdentificador da transação
statusstringStatus atual da transação
accountIdstringConta global associada
amountstringValor da transação
currencystringMoeda (ex: USD, BRL)

Garantias — collateral.created

Emitido quando uma garantia é criada a partir de um contrato (resource.type = "collateral").

{
  "eventType": "collateral.created",
  "resource": { "type": "collateral", "id": "42" },
  "data": {
    "contractId": 100,
    "guaranteeId": 42,
    "status": "PENDING",
    "requiredFiatAmount": 250000,
    "fiatCurrency": "BRL"
  }
}
CampoTipoDescrição
contractIdnumberID do contrato
guaranteeIdnumberID da garantia
statusstringStatus da garantia
requiredFiatAmountnumberValor fiduciário exigido
fiatCurrencystringMoeda do valor exigido

Garantias — collateral.ltv_alert / collateral.liquidated

Emitidos pelo motor de LTV quando o índice atinge o limite de alerta (collateral.ltv_alert) ou de liquidação (collateral.liquidated). Mesmo formato de data (resource.type = "collateral", id = ID do contrato).

{
  "eventType": "collateral.ltv_alert",
  "resource": { "type": "collateral", "id": "100" },
  "data": {
    "contractId": 100,
    "status": "ALERT",
    "currentLtv": 0.78,
    "alertLtv": 0.75,
    "releaseLiquidationLtv": 0.85,
    "trigger": "PRICE_CHANGE",
    "reason": "LTV acima do limite de alerta"
  }
}
CampoTipoDescrição
contractIdnumberID do contrato
statusstringStatus do LTV (ALERT, RELEASE_LIQUIDATION)
currentLtvnumberLTV atual (fração, ex: 0.78 = 78%)
alertLtvnumberLimite de alerta
releaseLiquidationLtvnumberLimite de liquidação
triggerstringOrigem do recálculo (ex: PRICE_CHANGE)
reasonstringDescrição do motivo

Cadastros — wallet.registered / wallet.verified

wallet.registered é emitido ao cadastrar uma carteira externa; wallet.verified ao aprová-la. Mesmo formato (resource.type = "wallet").

{
  "eventType": "wallet.verified",
  "resource": { "type": "wallet", "id": "15" },
  "data": {
    "walletId": 15,
    "address": "0xabc...123",
    "network": "ETHEREUM",
    "status": "APPROVED",
    "fireblocksExternalWalletId": "fb_ext_987"
  }
}
CampoTipoDescrição
walletIdnumberID interno da carteira
addressstringEndereço on-chain
networkstringRede da carteira (ex: ETHEREUM)
statusstringStatus (PENDING, APPROVED)
fireblocksExternalWalletIdstringID da carteira externa no provedor

Cripto — crypto.deposit

Emitido quando um depósito de cripto é confirmado em uma vault de custódia (resource.type = "transaction").

{
  "eventType": "crypto.deposit",
  "resource": { "type": "transaction", "id": "555" },
  "data": {
    "transactionId": 555,
    "txHash": "0xdef...456",
    "amount": "1.25",
    "tokenSymbol": "ETH",
    "network": "ETHEREUM",
    "fromAddress": "0xfrom...111",
    "toAddress": "0xto...222",
    "status": "CONFIRMED",
    "confirmedAt": "2026-05-31T12:36:35.000Z"
  }
}
CampoTipoDescrição
transactionIdnumberID da transação de depósito
txHashstringHash da transação on-chain
amountstringQuantidade depositada
tokenSymbolstringSímbolo do token (ex: ETH, USDC)
networkstringRede do depósito
fromAddressstringEndereço de origem
toAddressstringEndereço de destino (vault)
statusstringStatus do depósito
confirmedAtstringData/hora da confirmação (ISO 8601)

Validar Assinatura

A assinatura é o HMAC-SHA256 do corpo bruto (raw body) da requisição, calculado com o seu signing secret. Compare-a em tempo constante:

const crypto = require('crypto')
 
function verifyWebhookSignature(rawBody, signatureHeader, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(rawBody)
    .digest('hex')
 
  const received = signatureHeader.split('=')[1]
 
  return crypto.timingSafeEqual(
    Buffer.from(received),
    Buffer.from(expected)
  )
}
 
// Uso (Express com body bruto)
app.post(
  '/webhooks/fortbix',
  express.raw({ type: 'application/json' }),
  (req, res) => {
    const signature = req.headers['x-webhook-signature']
    const rawBody = req.body // Buffer/string bruto, não use JSON.stringify
 
    if (!verifyWebhookSignature(rawBody, signature, process.env.WEBHOOK_SECRET)) {
      return res.status(401).send('Invalid signature')
    }
 
    const event = JSON.parse(rawBody)
    handleWebhookEvent(event)
    res.send('OK')
  }
)

O WEBHOOK_SECRET é o signing secret (whsec_...) que você obteve ao criar o webhook no portal. Ele é diferente da api-key.

Reentrega

Se sua endpoint não responder com sucesso (status fora da faixa 2xx) ou exceder o timeout de 10 segundos, a entrega é considerada falha e a Fortbix reenvia o evento automaticamente com novas tentativas. Use o X-Webhook-Delivery-Id e o X-Webhook-Event-Id para tratar entregas duplicadas de forma idempotente.

Você pode acompanhar e reenviar entregas manualmente pela aba de entregas (deliveries) no portal.

Testar Localmente

Use o ngrok para expor seu localhost e cadastre a URL gerada no portal (ambiente Sandbox):

ngrok http 3000
# Seu URL: https://abc123.ngrok.io
# Cadastre https://abc123.ngrok.io/webhooks/fortbix em:
# https://app.fortbix.com/integracao/webhooks