{
  "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_-]+$"
            }
          }
        ],
        "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"
          }
        }
      }
    },
    "/payouts": {
      "post": {
        "operationId": "createPayout",
        "summary": "Reserve an idempotent Pix payout for external Liquid funding",
        "description": "Requires payouts:write. HxPay reserves the Pix withdrawal exactly once and returns a short-lived DePix funding address. The merchant treasury signs and broadcasts the Liquid transfer outside HxPay.",
        "parameters": [{
          "name": "Idempotency-Key", "in": "header", "required": true,
          "schema": {"type": "string", "minLength": 16, "maxLength": 128, "pattern": "^[A-Za-z0-9_-]+$"}
        }],
        "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/CreatePayout"}}}},
        "responses": {
          "200": {"$ref": "#/components/responses/Payout"},
          "202": {"$ref": "#/components/responses/Payout"},
          "400": {"$ref": "#/components/responses/Error"},
          "403": {"$ref": "#/components/responses/Error"},
          "409": {"$ref": "#/components/responses/Error"}
        }
      }
    },
    "/payouts/{payout_id}": {
      "get": {
        "operationId": "getPayout",
        "summary": "Get and reconcile a merchant-funded Pix payout",
        "parameters": [{"$ref": "#/components/parameters/PayoutId"}],
        "responses": {"200": {"$ref": "#/components/responses/Payout"}, "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"
        }
      },
      "PayoutId": {
        "name": "payout_id", "in": "path", "required": true,
        "schema": {"type": "string", "pattern": "^[a-f0-9]{32}$"}
      },
      "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"
              ]
            }
          }
        }
      },
      "Payout": {
        "description": "Pix payout reservation",
        "content": {"application/json": {"schema": {"type": "object", "required": ["data"], "properties": {"data": {"$ref": "#/components/schemas/Payout"}}}}}
      },
      "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}$"
            },
            "status": {
              "const": "quoted"
            },
            "amount_cents": {
              "type": "integer"
            },
            "currency": {
              "const": "BRL"
            },
            "estimated_usdt": {
              "type": "string",
              "pattern": "^[0-9]+\\.[0-9]{6}$"
            },
            "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"
          }
        }
      },
      "CreatePayout": {
        "type": "object", "additionalProperties": false,
        "required": ["deposit_amount_cents", "recipient", "refund_address"],
        "properties": {
          "deposit_amount_cents": {"type": "integer", "minimum": 500, "maximum": 50000},
          "recipient": {"type": "object", "additionalProperties": false, "required": ["pix_key", "tax_number"], "properties": {
            "pix_key": {"type": "string", "minLength": 1, "maxLength": 200},
            "tax_number": {"type": "string", "maxLength": 20}
          }},
          "refund_address": {"type": "string", "description": "Liquid address controlled by the merchant treasury"},
          "external_reference": {"type": "string", "maxLength": 120}
        }
      },
      "Payout": {
        "type": "object", "required": ["id", "status", "deposit_amount_cents"],
        "properties": {
          "id": {"type": "string"}, "status": {"type": "string"},
          "deposit_amount_cents": {"type": "integer"}, "recipient_amount_cents": {"type": "integer"},
          "external_reference": {"type": "string"}, "withdrawal_id": {"type": "string"},
          "central_bank_id": {"type": "string"},
          "funding": {"type": "object", "required": ["network", "asset", "address", "amount_cents"], "properties": {
            "network": {"const": "liquid"}, "asset": {"const": "DePix"},
            "address": {"type": "string"}, "amount_cents": {"type": "integer"}
          }}
        }
      },
        "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}$",
              "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"
          }
        }
      }
    }
  }
}
