OPENAPI / REST

HxPay documentation

Read the API contract without signing in. Open your account to create keys and execute operations.

Quick start

  1. Create a key in your account Developer area. Keep it server-side.
  2. Send integer amounts in cents and a unique Idempotency-Key for each order.
  3. Query the payment and verify webhook signatures before updating orders.

REST API and signed webhooks to create charges and track events. Read the public contract; keep your key on the server.

Public documentation ↗
import {randomUUID} from 'node:crypto';
const auth = {'Authorization': 'Bearer ' + process.env.HXPAY_API_KEY,
  'Content-Type': 'application/json', 'X-HxPay-User-IP': 'END_USER_PUBLIC_IP'};
const quoteResponse = await fetch('https://hxpay.com.br/api/v1/quotes', {
  method: 'POST', headers: auth,
  body: JSON.stringify({amount_cents: 10000})
});
if (!quoteResponse.ok) throw new Error('Quote request failed');
const {data: quote} = await quoteResponse.json();
const paymentResponse = await fetch('https://hxpay.com.br/api/v1/payments', {
  method: 'POST', headers: {...auth, 'Idempotency-Key': randomUUID()},
  body: JSON.stringify({quote_id: quote.quote_id,
    payer: {name: 'PAYER_NAME', document: 'CPF_OR_CNPJ'},
    external_reference: 'ORDER_ID'})
});
if (!paymentResponse.ok) throw new Error('Payment request failed');
const {data: payment} = await paymentResponse.json();

HTTP 200 / 202 · JSON
{
  "data": {
    "quote_id": "EXAMPLE_QUOTE_ID", "status": "quoted",
    "amount_cents": 10000, "currency": "BRL",
    "estimated_usdt": "18.950000",
    "settlement": {"asset": "USDT0", "network": "polygon",
      "model": "routed_usdt"},
    "fees": {"commission_cents": 249, "provider_fee_cents": 99,
      "platform_fee_cents": 348}, "net_amount_cents": 9652,
    "expires_at": 1791859200
  }
}

Signed webhook: verify before acting.

HxPay-Signature: t=TIMESTAMP,v1=HMAC_SHA256
HxPay-Event-Id: EVENT_ID

{"id":"EVENT_ID","event":"payment.completed",
 "data":{"id":"PAYMENT_ID","status":"depix_sent",
 "estimated_usdt":"18.950000","received_usdt":"18.910000",
 "settlement_tx_hash":"0xTRANSACTION_HASH"}}

Verify HxPay-Signature with HMAC-SHA256 over TIMESTAMP.raw-body. Compare in constant time, allow up to 300 seconds and deduplicate using HxPay-Event-Id.

Node · HMAC-SHA256
import {createHmac, timingSafeEqual} from 'node:crypto';
function verifyWebhook(header, rawBody, secret, now = Date.now()) {
  const match = /^t=(\d+),v1=([a-f0-9]{64})$/.exec(header || '');
  if (!match || Math.abs(now / 1000 - Number(match[1])) > 300) return false;
  const expected = createHmac('sha256', secret)
    .update(match[1] + '.').update(rawBody).digest();
  return timingSafeEqual(expected, Buffer.from(match[2], 'hex'));
}
// rawBody is the exact request bytes; deduplicate HxPay-Event-Id.
// Confirm the canonical payment state with GET /api/v1/payments/{id}.

pending → approved / delayed → depix_sent · expired / refunded / under_review / error. Public documentation

Endpoints and contracts

OpenAPI specification ↗

HxPay Merchant API · 1.1.0

https://hxpay.com.br/api/v1
GET /account — Get account, wallets, pricing and availability

Recebimento configurado pelo cobrador no painel: DePix na Liquid ou USDT. O destino se aplica aos novos pagamentos na API existente, links e QR dinâmico.

HTTP 200

Account

data#/components/schemas/Account

HTTP 401

POST /quotes — Consultar o valor líquido estimado sem emitir Pix

Cria uma cotação de curta duração usando o destino de recebimento configurado na conta. Não emite Pix nem inicia movimentação financeira. estimated_usdt é uma estimativa; o valor definitivo é recebido em received_usdt após payment.completed.

application/json

amount_centsintegerValor bruto que o pagador pagará, em centavos de BRL

HTTP 200

Cotação criada

data#/components/schemas/Quote

HTTP 400

HTTP 401

HTTP 429

GET /payments — List payments

[
  {
    "$ref": "#/components/parameters/Limit"
  },
  {
    "$ref": "#/components/parameters/Cursor"
  }
]

HTTP 200

Payment page

itemsarray
has_moreboolean
next_cursorstring,null

HTTP 401

POST /payments — Create an idempotent Pix payment

O nome e CPF/CNPJ são do pagador. Envie quote_id para consumir uma cotação criada em POST /quotes, sem repetir amount_cents; ou mantenha o fluxo compatível enviando amount_cents diretamente. O destino de recebimento é definido pelo cobrador e fica congelado na cotação. Pix já emitidos mantêm seu destino. USDT acrescenta 0,5 ponto percentual à comissão da conta. payment.completed só é emitido após entrega; blockchain_tx_id é a etapa Liquid e settlement_tx_hash/settlement_explorer_url são o comprovante final. Valores acima de R$ 500 sem EUID seguem automaticamente com liberação D+1 tanto em DePix na Liquid quanto em USDT, sujeitos somente ao teto da conta.

[
  {
    "name": "Idempotency-Key",
    "in": "header",
    "required": true,
    "schema": {
      "type": "string",
      "minLength": 16,
      "maxLength": 128,
      "pattern": "^[A-Za-z0-9_-]+

Loading the public specification…

quot; } } ]

application/json

quote_idstringCotação criada em POST /quotes. Quando informado, não envie amount_cents ou wallet_id.
amount_centsinteger
payer#/components/schemas/Payer
wallet_idstring
external_referencestring
new_payer_policystring

HTTP 200

HTTP 202

HTTP 400

HTTP 409

GET /payments/{payment_id} — Get and refresh a payment

[
  {
    "$ref": "#/components/parameters/PaymentId"
  }
]

HTTP 200

HTTP 404

GET /payments/{payment_id}/evidence — Get normalized settlement evidence

[
  {
    "$ref": "#/components/parameters/PaymentId"
  }
]

HTTP 200

Evidence

{
  "type": "object",
  "additionalProperties": true
}
POST /crypto/payments — Criar Pix com entrega DePix ou USDT na carteira do cobrador

Nome/documento em payer pertencem ao pagador. receiving é definido pelo servidor do cobrador, ou omitido para usar o destino padrão salvo. Escopos read e payments:write. Mesma Idempotency-Key e JSON retornam a mesma operação. Valores acima de R$ 500 sem EUID recebem a política D+1 do servidor em DePix ou USDT, respeitando o limite da conta. Operações já emitidas mantêm sua referência e acompanhamento.

[
  {
    "name": "Idempotency-Key",
    "in": "header",
    "required": true,
    "schema": {
      "type": "string",
      "minLength": 8,
      "maxLength": 128
    }
  }
]

application/json

amount_centsinteger
external_referencestring
payerobject
receivingobject

HTTP 200

Mesma operação, com código Pix/status/estimativa

HTTP 202

Emissão em acompanhamento; não gerar outra cobrança

HTTP 409

Idempotency-Key conflitante ou requisição incompatível com uma operação existente

GET /crypto/payments — Histórico cripto da própria conta

HTTP 200

items de operações, sem dados privados do pagador

GET /crypto/account — Destinos públicos salvos e redes da conta do cobrador

HTTP 200

data.receiving com addresses e default_network; max_single_cents é o teto habilitado da conta

GET /crypto/payments/{id} — Acompanhar Pix, conversão e entrega na carteira

[
  {
    "name": "id",
    "in": "path",
    "required": true,
    "schema": {
      "type": "string"
    }
  }
]

HTTP 200

data com status e hashes quando confirmados

HTTP 404

Operação inexistente ou de outra conta

GET /payments/{payment_id}/receipt.pdf — Download the payment receipt

[
  {
    "$ref": "#/components/parameters/PaymentId"
  }
]

HTTP 200

PDF receipt

{
  "type": "string",
  "contentEncoding": "base64"
}

HTTP 404

JSON / OpenAPI
{
  "openapi": "3.1.0",
  "info": {
    "title": "HxPay Merchant API",
    "version": "1.1.0",
    "description": "Pix collection with automatic USDT delivery on Polygon, Ethereum, Tron, Solana, BNB Smart Chain, Arbitrum, Avalanche C-Chain or TON, or direct DePix on Liquid. Amounts are integer BRL cents. The merchant owns the receiving address; payer identity belongs to the Pix payer."
  },
  "servers": [
    {
      "url": "https://hxpay.com.br/api/v1",
      "description": "Production"
    },
    {
      "url": "http://127.0.0.1:8787/api/v1",
      "description": "Local deterministic sandbox"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "paths": {
    "/account": {
      "get": {
        "operationId": "getAccount",
        "summary": "Get account, wallets, pricing and availability",
        "responses": {
          "200": {
            "description": "Account",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Account"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error"
          }
        },
        "description": "Recebimento configurado pelo cobrador no painel: DePix na Liquid ou USDT. O destino se aplica aos novos pagamentos na API existente, links e QR dinâmico."
      }
    },
    "/quotes": {
      "post": {
        "operationId": "createQuote",
        "summary": "Consultar o valor líquido estimado sem emitir Pix",
        "description": "Cria uma cotação de curta duração usando o destino de recebimento configurado na conta. Não emite Pix nem inicia movimentação financeira. estimated_usdt é uma estimativa; o valor definitivo é recebido em received_usdt após payment.completed.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateQuote"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Cotação criada",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Quote"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/payments": {
      "get": {
        "operationId": "listPayments",
        "summary": "List payments",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "Payment page",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaymentPage"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "createPayment",
        "summary": "Create an idempotent Pix payment",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 16,
              "maxLength": 128,
              "pattern": "^[A-Za-z0-9_-]+

Loading the public specification…

quot; } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreatePayment" } } } }, "responses": { "200": { "$ref": "#/components/responses/Payment" }, "202": { "$ref": "#/components/responses/Payment" }, "400": { "$ref": "#/components/responses/Error" }, "409": { "$ref": "#/components/responses/Error" } }, "description": "O nome e CPF/CNPJ são do pagador. Envie quote_id para consumir uma cotação criada em POST /quotes, sem repetir amount_cents; ou mantenha o fluxo compatível enviando amount_cents diretamente. O destino de recebimento é definido pelo cobrador e fica congelado na cotação. Pix já emitidos mantêm seu destino. USDT acrescenta 0,5 ponto percentual à comissão da conta. payment.completed só é emitido após entrega; blockchain_tx_id é a etapa Liquid e settlement_tx_hash/settlement_explorer_url são o comprovante final. Valores acima de R$ 500 sem EUID seguem automaticamente com liberação D+1 tanto em DePix na Liquid quanto em USDT, sujeitos somente ao teto da conta." } }, "/payments/{payment_id}": { "get": { "operationId": "getPayment", "summary": "Get and refresh a payment", "parameters": [ { "$ref": "#/components/parameters/PaymentId" } ], "responses": { "200": { "$ref": "#/components/responses/Payment" }, "404": { "$ref": "#/components/responses/Error" } } } }, "/payments/{payment_id}/evidence": { "get": { "operationId": "getPaymentEvidence", "summary": "Get normalized settlement evidence", "parameters": [ { "$ref": "#/components/parameters/PaymentId" } ], "responses": { "200": { "404": { "$ref": "#/components/responses/Error" }, "description": "Evidence", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true } } } } } } }, "/crypto/payments": { "post": { "summary": "Criar Pix com entrega DePix ou USDT na carteira do cobrador", "security": [ { "bearerAuth": [] } ], "description": "Nome/documento em payer pertencem ao pagador. receiving é definido pelo servidor do cobrador, ou omitido para usar o destino padrão salvo. Escopos read e payments:write. Mesma Idempotency-Key e JSON retornam a mesma operação. Valores acima de R$ 500 sem EUID recebem a política D+1 do servidor em DePix ou USDT, respeitando o limite da conta. Operações já emitidas mantêm sua referência e acompanhamento.", "parameters": [ { "name": "Idempotency-Key", "in": "header", "required": true, "schema": { "type": "string", "minLength": 8, "maxLength": 128 } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "amount_cents", "payer" ], "properties": { "amount_cents": { "type": "integer", "minimum": 500, "maximum": 600000 }, "external_reference": { "type": "string", "maxLength": 100 }, "payer": { "type": "object", "required": [ "name", "document" ], "properties": { "name": { "type": "string" }, "document": { "type": "string", "description": "CPF/CNPJ válido do titular que fará o Pix" } } }, "receiving": { "type": "object", "required": [ "network", "address" ], "properties": { "network": { "type": "string", "enum": [ "polygon", "ethereum", "tron", "solana", "bsc", "arbitrum", "avax", "ton", "liquid" ] }, "address": { "type": "string", "description": "Endereço público de recebimento do cobrador" }, "memo": { "type": "string", "maxLength": 64, "description": "Memo/comentário opcional para TON, quando exigido pela carteira" } } } } } } } }, "responses": { "200": { "description": "Mesma operação, com código Pix/status/estimativa" }, "202": { "description": "Emissão em acompanhamento; não gerar outra cobrança" }, "409": { "description": "Idempotency-Key conflitante ou requisição incompatível com uma operação existente" } } }, "get": { "summary": "Histórico cripto da própria conta", "security": [ { "bearerAuth": [] } ], "responses": { "200": { "description": "items de operações, sem dados privados do pagador" } } } }, "/crypto/account": { "get": { "summary": "Destinos públicos salvos e redes da conta do cobrador", "security": [ { "bearerAuth": [] } ], "responses": { "200": { "description": "data.receiving com addresses e default_network; max_single_cents é o teto habilitado da conta" } } } }, "/crypto/payments/{id}": { "get": { "summary": "Acompanhar Pix, conversão e entrega na carteira", "security": [ { "bearerAuth": [] } ], "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "data com status e hashes quando confirmados" }, "404": { "description": "Operação inexistente ou de outra conta" } } } }, "/payments/{payment_id}/receipt.pdf": { "get": { "operationId": "downloadPaymentReceipt", "summary": "Download the payment receipt", "parameters": [ { "$ref": "#/components/parameters/PaymentId" } ], "responses": { "200": { "description": "PDF receipt", "content": { "application/pdf": { "schema": { "type": "string", "contentEncoding": "base64" } } } }, "404": { "$ref": "#/components/responses/Error" } } } } }, "components": { "securitySchemes": { "bearerAuth": { "type": "http", "scheme": "bearer" } }, "parameters": { "PaymentId": { "name": "payment_id", "in": "path", "required": true, "schema": { "type": "string" } }, "Limit": { "name": "limit", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 50 } }, "Cursor": { "name": "cursor", "in": "query", "schema": { "type": "string" } } }, "responses": { "Payment": { "description": "Payment", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "$ref": "#/components/schemas/Payment" } }, "required": [ "data" ] } } } }, "Error": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "schemas": { "CreateQuote": { "type": "object", "additionalProperties": false, "required": [ "amount_cents" ], "properties": { "amount_cents": { "type": "integer", "minimum": 500, "maximum": 600000, "description": "Valor bruto que o pagador pagará, em centavos de BRL" } } }, "Quote": { "type": "object", "required": [ "quote_id", "status", "amount_cents", "currency", "settlement", "fees", "expires_at" ], "properties": { "quote_id": { "type": "string", "pattern": "^[a-f0-9]{32}

Loading the public specification…

quot; }, "status": { "const": "quoted" }, "amount_cents": { "type": "integer" }, "currency": { "const": "BRL" }, "estimated_usdt": { "type": "string", "pattern": "^[0-9]+\\.[0-9]{6}

Loading the public specification…

quot; }, "estimated_depix": { "type": "string" }, "net_amount_cents": { "type": "integer" }, "settlement": { "type": "object", "additionalProperties": false, "required": [ "asset", "network", "model" ], "properties": { "asset": { "type": "string" }, "network": { "type": "string" }, "model": { "type": "string" } } }, "fees": { "type": "object", "additionalProperties": { "type": "integer" } }, "rate_type": { "type": "string" }, "expires_at": { "type": "integer", "description": "Unix timestamp em segundos" } } }, "Account": { "type": "object", "required": [ "id", "wallets", "availability", "settlement", "limits" ], "properties": { "id": { "type": "string" }, "name": { "type": "string" }, "wallets": { "type": "array", "items": { "type": "object", "additionalProperties": true } }, "scopes": { "type": "array", "items": { "type": "string" } }, "availability": { "type": "object", "additionalProperties": true }, "pricing": { "type": "object", "additionalProperties": true }, "settlement": { "type": "object", "properties": { "asset": { "const": "DePix" }, "network": { "const": "LIQUID" }, "model": { "const": "direct_to_customer" } }, "required": [ "asset", "network", "model" ] }, "limits": { "type": "object", "additionalProperties": true } } }, "Payer": { "type": "object", "additionalProperties": false, "required": [ "name", "document" ], "properties": { "name": { "type": "string", "minLength": 3, "maxLength": 120 }, "document": { "type": "string", "maxLength": 20 }, "euid": { "type": "string" } } }, "CreatePayment": { "type": "object", "additionalProperties": false, "required": [ "payer" ], "oneOf": [ { "required": [ "quote_id" ], "not": { "required": [ "amount_cents" ] } }, { "required": [ "amount_cents" ], "not": { "required": [ "quote_id" ] } } ], "properties": { "quote_id": { "type": "string", "pattern": "^[a-f0-9]{32}

Loading the public specification…

quot;, "description": "Cotação criada em POST /quotes. Quando informado, não envie amount_cents ou wallet_id." }, "amount_cents": { "type": "integer", "minimum": 500 }, "payer": { "$ref": "#/components/schemas/Payer" }, "wallet_id": { "type": "string", "maxLength": 120 }, "external_reference": { "type": "string", "maxLength": 120 }, "new_payer_policy": { "type": "string" } } }, "Payment": { "type": "object", "required": [ "id", "status", "amount_cents" ], "properties": { "id": { "type": "string" }, "status": { "type": "string" }, "amount_cents": { "type": "integer" }, "net_amount_cents": { "type": [ "integer", "null" ] }, "pix_code": { "type": "string" }, "external_reference": { "type": "string" }, "settlement_model": { "type": "string" }, "fees": { "type": "object", "additionalProperties": { "type": "integer" } }, "created_at": { "type": "string", "format": "date-time" }, "updated_at": { "type": "string", "format": "date-time" }, "settled_at": { "type": "string", "format": "date-time" } } }, "PaymentPage": { "type": "object", "required": [ "items", "has_more" ], "properties": { "items": { "type": "array", "items": { "$ref": "#/components/schemas/Payment" } }, "has_more": { "type": "boolean" }, "next_cursor": { "type": [ "string", "null" ] } } }, "Error": { "type": "object", "required": [ "error" ], "properties": { "error": { "type": "string" }, "message": { "type": "string" } } } } } }

Authenticated actions and keys stay in your account.