{
  "openapi": "3.1.0",
  "info": {
    "title": "PayerPix — API",
    "version": "1.0.0",
    "description": "API de pagamentos **Pix** com gestão de **merchants**, saldos isolados, saques e divisão de receita (**splits**).\n\n- **Base:** `https://api.betpaympix.com` · valores em **centavos** · datas ISO‑8601 (UTC).\n- **Autenticação:** `Authorization: Bearer PP_...` (escopos `DEPOSIT`, `WITHDRAW`, `MERCHANT`).\n\n> A criação de merchants é feita pelas rotas próprias de merchant; na cobrança Pix você apenas referencia o `merchantId`.\n\n📖 **Guias, exemplos e o passo a passo de splits:** veja a aba **Guias**."
  },
  "servers": [
    {
      "url": "https://api.betpaympix.com",
      "description": "Produção"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "tags": [
    {
      "name": "Usuário",
      "description": "Conta e saldo do usuário autenticado."
    },
    {
      "name": "Merchants",
      "description": "Criação e extrato de merchants."
    },
    {
      "name": "Cobranças Pix",
      "description": "Criação e consulta de cobranças Pix."
    },
    {
      "name": "Saques",
      "description": "Saques Pix da conta do usuário."
    }
  ],
  "paths": {
    "/v1/user": {
      "get": {
        "tags": [
          "Usuário"
        ],
        "summary": "Dados da conta",
        "description": "Retorna os dados da conta autenticada.",
        "responses": {
          "200": {
            "description": "Dados da conta",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/User"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/v1/user/balance": {
      "get": {
        "tags": [
          "Usuário"
        ],
        "summary": "Saldo do usuário",
        "responses": {
          "200": {
            "description": "Saldo",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Balance"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/v1/user/transactions": {
      "get": {
        "tags": [
          "Usuário"
        ],
        "summary": "Extrato do usuário",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/PaymentStatus"
            }
          },
          {
            "name": "type",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/PaymentType"
            }
          },
          {
            "name": "dateFrom",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "dateTo",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Lista de transações",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Payment"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/v1/user/summary": {
      "get": {
        "tags": [
          "Usuário"
        ],
        "summary": "Resumo / métricas",
        "responses": {
          "200": {
            "description": "Métricas agregadas"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/v1/merchants": {
      "post": {
        "tags": [
          "Merchants"
        ],
        "summary": "Criar merchant",
        "description": "Cria um merchant na sua conta. Requer escopo `MERCHANT`. O `id` retornado é usado para vincular cobranças (`merchantId`) e consultar o extrato.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateMerchantRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Merchant criado",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Merchant"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          }
        }
      }
    },
    "/v1/merchants/{id}/transactions": {
      "get": {
        "tags": [
          "Merchants"
        ],
        "summary": "Extrato do merchant",
        "parameters": [
          {
            "$ref": "#/components/parameters/MerchantId"
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/PaymentStatus"
            }
          },
          {
            "name": "dateFrom",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "dateTo",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Transações do merchant",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Payment"
                  }
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/v1/pix": {
      "post": {
        "tags": [
          "Cobranças Pix"
        ],
        "summary": "Criar cobrança Pix",
        "description": "Cria uma cobrança Pix com QR Code. Requer escopo `DEPOSIT`.\n\nPara vincular a cobrança a um merchant, informe o campo **`merchantId`** com o ID de um merchant já existente (criado previamente pelas rotas de merchant). Use o cabeçalho `Idempotency-Key` para evitar duplicidades em retentativas.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Chave de idempotência para evitar cobranças duplicadas."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreatePixChargeRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Cobrança criada",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PixCharge"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      },
      "get": {
        "tags": [
          "Cobranças Pix"
        ],
        "summary": "Consultar status da cobrança",
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "ID interno da cobrança (UUID)."
          }
        ],
        "responses": {
          "200": {
            "description": "Cobrança",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PixCharge"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/v1/pix/qrcode/{id}": {
      "get": {
        "tags": [
          "Cobranças Pix"
        ],
        "summary": "QR Code (PNG)",
        "description": "Retorna a imagem PNG do QR Code da cobrança. Endpoint público.",
        "security": [],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Imagem PNG",
            "content": {
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          }
        }
      }
    },
    "/v1/withdraw": {
      "post": {
        "tags": [
          "Saques"
        ],
        "summary": "Criar saque do usuário (Pix)",
        "description": "Cria um saque Pix a partir do saldo do usuário. Requer escopo `WITHDRAW`.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WithdrawRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Saque criado",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Withdraw"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "API Token com prefixo `PP_`. Envie em `Authorization: Bearer PP_...`."
      }
    },
    "parameters": {
      "MerchantId": {
        "name": "id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "format": "uuid"
        },
        "description": "ID do merchant (UUID)."
      }
    },
    "responses": {
      "Unauthorized": {
        "description": "Token ausente ou inválido",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Forbidden": {
        "description": "Sem permissão/escopo ou merchant de outro dono",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "NotFound": {
        "description": "Recurso não encontrado",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "BadRequest": {
        "description": "Payload inválido",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Conflict": {
        "description": "Conflito (ex.: externalId duplicado)",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    },
    "schemas": {
      "PaymentStatus": {
        "type": "string",
        "enum": [
          "PENDING",
          "COMPLETED",
          "CANCELED",
          "REFUNDED",
          "EXPIRED"
        ]
      },
      "PaymentType": {
        "type": "string",
        "enum": [
          "DEPOSIT",
          "WITHDRAW",
          "PAYMENT"
        ]
      },
      "PixType": {
        "type": "string",
        "enum": [
          "CPF",
          "CNPJ",
          "EMAIL",
          "PHONE",
          "EVP"
        ]
      },
      "WithdrawStatus": {
        "type": "string",
        "enum": [
          "PENDING",
          "ANALYSIS",
          "COMPLETED",
          "FAILED",
          "CANCELED"
        ]
      },
      "Error": {
        "type": "object",
        "properties": {
          "statusCode": {
            "type": "integer",
            "example": 403
          },
          "message": {
            "type": "string",
            "example": "Permissão insuficiente: requer DEPOSIT"
          },
          "error": {
            "type": "string",
            "example": "Forbidden"
          }
        }
      },
      "Balance": {
        "type": "object",
        "properties": {
          "balanceAvailable": {
            "type": "integer",
            "description": "Saldo disponível (centavos)",
            "example": 154200
          },
          "balanceBlocked": {
            "type": "integer",
            "example": 0
          },
          "total": {
            "type": "integer",
            "example": 154200
          }
        }
      },
      "User": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "username": {
            "type": "string"
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "balanceAvailable": {
            "type": "integer"
          },
          "balanceBlocked": {
            "type": "integer"
          },
          "role": {
            "type": "string",
            "enum": [
              "USER",
              "ADMIN",
              "RESELLER"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "ACTIVE",
              "SUSPENDED",
              "BLOCKED"
            ]
          }
        }
      },
      "Merchant": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string",
            "example": "Loja Exemplo"
          },
          "externalId": {
            "type": "string",
            "nullable": true,
            "example": "loja-001"
          },
          "isActive": {
            "type": "boolean",
            "example": true
          },
          "balanceAvailable": {
            "type": "integer",
            "example": 154200
          },
          "balanceBlocked": {
            "type": "integer",
            "example": 0
          },
          "commissionBasisPoints": {
            "type": "integer",
            "description": "Comissão em basis points (0–10000 = 0–100%).",
            "example": 500
          },
          "userId": {
            "type": "string",
            "format": "uuid"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "CreatePixChargeRequest": {
        "type": "object",
        "required": [
          "amount",
          "callbackUrl"
        ],
        "properties": {
          "amount": {
            "type": "integer",
            "minimum": 1,
            "description": "Valor em centavos.",
            "example": 1990
          },
          "callbackUrl": {
            "type": "string",
            "format": "uri",
            "description": "URL para receber o webhook de confirmação.",
            "example": "https://sualoja.com/webhooks/payerpix"
          },
          "merchantId": {
            "type": "string",
            "format": "uuid",
            "description": "ID de um merchant **já existente** ao qual a cobrança será vinculada.",
            "example": "b3f1c2a4-1111-2222-3333-444455556666"
          },
          "generatedName": {
            "type": "string",
            "maxLength": 100,
            "description": "Nome do pagador (opcional).",
            "example": "Cliente Final"
          },
          "generatedEmail": {
            "type": "string",
            "format": "email"
          },
          "generatedDocument": {
            "type": "string",
            "description": "CPF/CNPJ do pagador (opcional)."
          },
          "expiresIn": {
            "type": "integer",
            "description": "Validade em segundos (padrão 600).",
            "example": 600
          }
        }
      },
      "PixCharge": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "externalId": {
            "type": "string",
            "nullable": true
          },
          "status": {
            "$ref": "#/components/schemas/PaymentStatus"
          },
          "amount": {
            "type": "integer",
            "example": 1990
          },
          "type": {
            "$ref": "#/components/schemas/PaymentType"
          },
          "qrCodeText": {
            "type": "string",
            "nullable": true,
            "description": "Pix copia-e-cola (EMV)."
          },
          "qrCodeBase64": {
            "type": "string",
            "nullable": true,
            "description": "Imagem PNG em base64."
          },
          "qrCodeUrl": {
            "type": "string",
            "nullable": true
          },
          "serviceFeeCharged": {
            "type": "integer",
            "example": 0
          },
          "endToEndId": {
            "type": "string",
            "nullable": true
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "paidAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        }
      },
      "WithdrawRequest": {
        "type": "object",
        "required": [
          "amount",
          "pixKey",
          "pixType"
        ],
        "properties": {
          "amount": {
            "type": "integer",
            "minimum": 1,
            "example": 10000
          },
          "pixKey": {
            "type": "string",
            "example": "12345678909"
          },
          "pixType": {
            "$ref": "#/components/schemas/PixType"
          },
          "pin": {
            "type": "string",
            "description": "PIN de segurança (se configurado)."
          },
          "description": {
            "type": "string"
          },
          "callbackUrl": {
            "type": "string",
            "format": "uri"
          }
        }
      },
      "Withdraw": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "$ref": "#/components/schemas/WithdrawStatus"
          },
          "amount": {
            "type": "integer"
          },
          "pixKey": {
            "type": "string"
          },
          "pixType": {
            "$ref": "#/components/schemas/PixType"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "CreateMerchantRequest": {
        "type": "object",
        "required": [
          "name"
        ],
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 80,
            "example": "Loja Exemplo"
          },
          "externalId": {
            "type": "string",
            "maxLength": 80,
            "description": "Identificador externo único (opcional).",
            "example": "loja-001"
          },
          "commissionBasisPoints": {
            "type": "integer",
            "minimum": 0,
            "maximum": 10000,
            "description": "Comissão em basis points (0–10000 = 0–100%).",
            "example": 500
          }
        }
      }
    }
  }
}