openapi: 3.0.3
info:
  title: KAPAY Gateway Pix API
  description: |
    Documentacao oficial da API KAPAY para integracao com servicos Pix In, Pix Out,
    split de pagamento, financeiro, webhooks e tratativas de infracoes Pix/MED.

    A API utiliza OAuth2 Client Credentials como metodo principal de autenticacao.
    Clientes legados podem utilizar token Bearer fixo mediante habilitacao especifica,
    porem essa alternativa nao e recomendada para novas integracoes.

    Todas as operacoes devem ser realizadas exclusivamente via HTTPS.
  version: 1.0.0
servers:
- url: https://api.kapay.com.br/v1
  description: Producao
- url: https://api.kapay.com.br/sandbox/v1
  description: Sandbox
security:
- BearerAuth: []
- LegacyBearerToken: []
tags:
- name: Introducao
  description: Visao geral da API KAPAY.
- name: Ambientes
  description: URLs de producao e sandbox para homologacao.
- name: Autenticacao
  description: Geracao de token OAuth2 e uso de credenciais.
- name: Seguranca
  description: Recomendacoes e requisitos de seguranca.
- name: Rate limit
  description: Limites de requisicao por modulo.
- name: Codigos de erro
  description: Padrao de erro e codigos HTTP.
- name: Financeiro
  description: Saldo e extrato financeiro.
- name: Pix In
  description: Cobrancas Pix por QR Code.
- name: Pix Out
  description: Transferencias Pix.
- name: Split de Pagamento
  description: Divisao automatica de cobrancas Pix entre recebedores vinculados.
- name: Webhooks
  description: Eventos assinados enviados pela KAPAY.
- name: Infracoes Pix/MED
  description: Consulta e defesa de infracoes Pix/MED.
- name: Exemplos de integracao
  description: Exemplos praticos para integradores.
paths:
  /oauth/token:
    post:
      tags:
      - Autenticacao
      summary: Gerar token de acesso
      description: |
        Gera um token de acesso usando OAuth2 Client Credentials.

        Envie `client_key` como usuario e `client_secret` como senha no Basic Auth.
        O corpo da requisicao deve usar `application/x-www-form-urlencoded` com
        `grant_type=client_credentials`.
      requestBody:
        content:
          application/x-www-form-urlencoded:
            schema:
              $ref: "#/components/schemas/oauth_token_body"
            example:
              grant_type: client_credentials
        required: true
      responses:
        "200":
          description: Token gerado com sucesso.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OAuthTokenResponse"
              example:
                access_token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.kapay_payload.signature
                token_type: Bearer
                expires_in: 1800
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
      security:
      - BasicAuth: []
  /balance:
    get:
      tags:
      - Financeiro
      summary: Consultar saldo
      description: "Retorna saldo disponivel, saldo bloqueado e moeda da conta KAPAY."
      responses:
        "200":
          description: Saldo consultado com sucesso.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/BalanceResponse"
              example:
                available_balance: 15420.75
                blocked_balance: 320
                currency: BRL
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
  /transactions:
    get:
      tags:
      - Financeiro
      summary: Consultar extrato
      description: "Lista movimentacoes financeiras com filtros por periodo, tipo e status."
      parameters:
      - name: initialDate
        in: query
        required: false
        schema:
          type: string
          format: date-time
        example: 2026-06-01T00:00:00Z
      - name: finalDate
        in: query
        required: false
        schema:
          type: string
          format: date-time
        example: 2026-06-02T23:59:59Z
      - name: type
        in: query
        required: false
        schema:
          type: string
          enum:
          - PIX_IN
          - PIX_OUT
          - REFUND
          - FEE
          - ADJUSTMENT
        example: PIX_IN
      - name: status
        in: query
        required: false
        schema:
          type: string
        example: PAID
      - name: page
        in: query
        required: false
        schema:
          minimum: 1
          type: integer
          default: 1
        example: 1
      - name: pageSize
        in: query
        required: false
        schema:
          maximum: 100
          minimum: 1
          type: integer
          default: 20
        example: 20
      responses:
        "200":
          description: Extrato consultado com sucesso.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TransactionListResponse"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
  /pix/qrcode:
    post:
      tags:
      - Pix In
      summary: Criar cobranca Pix com QR Code
      description: Cria uma cobranca Pix e retorna o codigo copia e cola e o QR Code em base64.
      parameters:
      - name: Idempotency-Key
        in: header
        description: "Chave unica por operacao para evitar duplicidade em Pix In, Pix Out e devolucoes."
        required: true
        schema:
          maxLength: 100
          type: string
        example: idem_20260602_0001
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreatePixQrCodeRequest"
            example:
              amount: 129.9
              external_id: order_20260602_0001
              description: Pedido online 0001
              expiration: 1800
              payer:
                name: Cliente Exemplo
                document: '***456789**'
                email: cliente.exemplo@dominio.test
                phone: "+5511999990000"
        required: true
      responses:
        "201":
          description: Cobranca criada com sucesso.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PixQrCodeResponse"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "409":
          $ref: "#/components/responses/Conflict"
        "422":
          $ref: "#/components/responses/UnprocessableEntity"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
  /pix/qrcode/{transaction_id}:
    get:
      tags:
      - Pix In
      summary: Consultar cobranca Pix
      parameters:
      - name: transaction_id
        in: path
        required: true
        schema:
          type: string
        example: trx_01HYZK7QK4N8A2B6C0D9E1F3G5
      responses:
        "200":
          description: Cobranca encontrada.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PixQrCodeResponse"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          $ref: "#/components/responses/NotFound"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
  /pix/qrcode/list:
    get:
      tags:
      - Pix In
      summary: Listar cobrancas Pix
      parameters:
      - name: initialDate
        in: query
        required: false
        schema:
          type: string
          format: date-time
        example: 2026-06-01T00:00:00Z
      - name: finalDate
        in: query
        required: false
        schema:
          type: string
          format: date-time
        example: 2026-06-02T23:59:59Z
      - name: status
        in: query
        required: false
        schema:
          $ref: "#/components/schemas/PixInStatus"
      - name: transaction_id
        in: query
        required: false
        schema:
          type: string
        example: trx_01HYZK7QK4N8A2B6C0D9E1F3G5
      - name: external_id
        in: query
        required: false
        schema:
          type: string
        example: order_20260602_0001
      - name: page
        in: query
        required: false
        schema:
          minimum: 1
          type: integer
          default: 1
        example: 1
      - name: pageSize
        in: query
        required: false
        schema:
          maximum: 100
          minimum: 1
          type: integer
          default: 20
        example: 20
      responses:
        "200":
          description: Cobrancas listadas com sucesso.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PixQrCodeListResponse"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
  /pix/qrcode/split:
    post:
      tags:
      - Split de Pagamento
      summary: Criar cobranca Pix com split
      description: |
        Cria uma cobranca Pix com divisao automatica do valor entre uma ou mais
        contas recebedoras vinculadas a KAPAY.

        O split pode ser definido por valor fixo ou percentual. O valor restante
        permanece com a conta principal que criou a cobranca. A liquidacao do split
        ocorre somente apos a confirmacao do pagamento Pix.

        Se `split_type` for `FIXED`, informe `amount`. Se `split_type` for
        `PERCENTAGE`, informe `percentage`. A soma dos valores fixos nao pode
        ultrapassar o valor total da cobranca e a soma dos percentuais nao pode
        ultrapassar 100%.
      parameters:
      - name: Idempotency-Key
        in: header
        description: "Chave unica por operacao para evitar duplicidade em Pix In, Pix Out e devolucoes."
        required: true
        schema:
          maxLength: 100
          type: string
        example: idem_20260602_0001
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreatePixQrCodeSplitRequest"
            example:
              amount: 100
              external_id: order_20260602_0001
              description: Pedido com split
              expiration: 1800
              payer:
                name: Cliente Exemplo
                document: '***456789**'
                email: cliente.exemplo@dominio.test
                phone: "+5511999990000"
              split_rules:
              - recipient_identifier_type: USERNAME
                recipient_identifier: parceiro01
                split_type: PERCENTAGE
                percentage: 20
                description: Comissao parceiro
              - recipient_identifier_type: ACCOUNT_ID
                recipient_identifier: acc_01HXKAPAY000000001
                split_type: FIXED
                amount: 5
                description: Taxa operacional
        required: true
      responses:
        "201":
          description: Cobranca com split criada com sucesso.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PixQrCodeSplitResponse"
              example:
                transaction_id: trx_01HYZK7QK4N8A2B6C0D9E1F3G5
                external_id: order_20260602_0001
                status: PENDING
                amount: 100
                pix_code: 00020101021226860014br.gov.bcb.pix2564qrcode.kapay.com.br/pix/split/abc1235204000053039865406100.005802BR5905KAPAY6009SAO PAULO62070503***6304B2C3
                qr_code_base64: iVBORw0KGgoAAAANSUhEUgAA...
                split_summary:
                  total_amount: 100
                  main_account_amount: 75
                  split_total_amount: 25
                  recipients:
                  - recipient_identifier_type: USERNAME
                    recipient_identifier: parceiro01
                    split_type: PERCENTAGE
                    percentage: 20
                    calculated_amount: 20
                    status: PENDING
                  - recipient_identifier_type: ACCOUNT_ID
                    recipient_identifier: acc_01HXKAPAY000000001
                    split_type: FIXED
                    amount: 5
                    calculated_amount: 5
                    status: PENDING
                expires_at: 2026-06-02T15:00:00Z
                created_at: 2026-06-02T14:30:00Z
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "409":
          $ref: "#/components/responses/Conflict"
        "422":
          $ref: "#/components/responses/UnprocessableEntity"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
  /pix/qrcode/{transaction_id}/split:
    get:
      tags:
      - Split de Pagamento
      summary: Consultar split de cobranca Pix
      description: Consulta os detalhes de split vinculados a uma cobranca Pix.
      parameters:
      - name: transaction_id
        in: path
        required: true
        schema:
          type: string
        example: trx_01HYZK7QK4N8A2B6C0D9E1F3G5
      responses:
        "200":
          description: Split consultado com sucesso.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PixQrCodeSplitDetailsResponse"
              example:
                transaction_id: trx_01HYZK7QK4N8A2B6C0D9E1F3G5
                external_id: order_20260602_0001
                status: PAID
                amount: 100
                split_summary:
                  total_amount: 100
                  main_account_amount: 75
                  split_total_amount: 25
                  recipients:
                  - recipient_identifier_type: USERNAME
                    recipient_identifier: parceiro01
                    split_type: PERCENTAGE
                    percentage: 20
                    calculated_amount: 20
                    status: SETTLED
                  - recipient_identifier_type: ACCOUNT_ID
                    recipient_identifier: acc_01HXKAPAY000000001
                    split_type: FIXED
                    amount: 5
                    calculated_amount: 5
                    status: SETTLED
                created_at: 2026-06-02T14:30:00Z
                paid_at: 2026-06-02T14:42:00Z
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          $ref: "#/components/responses/NotFound"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
  /split/receivers:
    get:
      tags:
      - Split de Pagamento
      summary: Listar recebedores de split
      description: Lista contas recebedoras vinculadas e disponiveis para regras de split.
      parameters:
      - name: status
        in: query
        required: false
        schema:
          $ref: "#/components/schemas/SplitReceiverStatus"
      - name: username
        in: query
        required: false
        schema:
          type: string
        example: parceiro01
      - name: page
        in: query
        required: false
        schema:
          minimum: 1
          type: integer
          default: 1
        example: 1
      - name: pageSize
        in: query
        required: false
        schema:
          maximum: 100
          minimum: 1
          type: integer
          default: 20
        example: 20
      responses:
        "200":
          description: Recebedores listados com sucesso.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SplitReceiverListResponse"
              example:
                data:
                - account_id: acc_01HXKAPAY000000001
                  username: parceiro01
                  name: Parceiro Exemplo
                  document_masked: '***456780**'
                  status: ACTIVE
                  created_at: 2026-05-20T10:00:00Z
                pagination:
                  page: 1
                  pageSize: 20
                  total: 1
                  totalPages: 1
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
  /split/receivers/{identifier}:
    get:
      tags:
      - Split de Pagamento
      summary: Consultar recebedor de split
      description: Consulta um recebedor de split por `account_id` ou `username`.
      parameters:
      - name: identifier
        in: path
        required: true
        schema:
          type: string
        example: parceiro01
      responses:
        "200":
          description: Recebedor consultado com sucesso.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SplitReceiverDetails"
              example:
                account_id: acc_01HXKAPAY000000001
                username: parceiro01
                name: Parceiro Exemplo
                document_masked: '***456780**'
                status: ACTIVE
                can_receive_split: true
                created_at: 2026-05-20T10:00:00Z
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          $ref: "#/components/responses/NotFound"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
  /split/settlements:
    get:
      tags:
      - Split de Pagamento
      summary: Listar liquidacoes de split
      description: Lista liquidacoes geradas a partir de cobrancas Pix com split.
      parameters:
      - name: initialDate
        in: query
        required: false
        schema:
          type: string
          format: date-time
        example: 2026-06-01T00:00:00Z
      - name: finalDate
        in: query
        required: false
        schema:
          type: string
          format: date-time
        example: 2026-06-02T23:59:59Z
      - name: transaction_id
        in: query
        required: false
        schema:
          type: string
        example: trx_01HYZK7QK4N8A2B6C0D9E1F3G5
      - name: recipient_identifier
        in: query
        required: false
        schema:
          type: string
        example: parceiro01
      - name: status
        in: query
        required: false
        schema:
          $ref: "#/components/schemas/SplitStatus"
      - name: page
        in: query
        required: false
        schema:
          minimum: 1
          type: integer
          default: 1
        example: 1
      - name: pageSize
        in: query
        required: false
        schema:
          maximum: 100
          minimum: 1
          type: integer
          default: 20
        example: 20
      responses:
        "200":
          description: Liquidacoes listadas com sucesso.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SplitSettlementListResponse"
              example:
                data:
                - settlement_id: set_01HYZL7Q2A4B6C8D0E1F3G5H7
                  transaction_id: trx_01HYZK7QK4N8A2B6C0D9E1F3G5
                  external_id: order_20260602_0001
                  recipient_identifier_type: USERNAME
                  recipient_identifier: parceiro01
                  amount: 20
                  status: SETTLED
                  settled_at: 2026-06-02T14:45:00Z
                  created_at: 2026-06-02T14:42:00Z
                pagination:
                  page: 1
                  pageSize: 20
                  total: 1
                  totalPages: 1
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
  /pix/qrcode/{end_to_end_id}/reverse:
    post:
      tags:
      - Pix In
      summary: Devolver recebimento Pix
      description: Solicita devolucao total ou parcial de um Pix recebido.
      parameters:
      - name: end_to_end_id
        in: path
        required: true
        schema:
          type: string
        example: E1234567820260602143000000000001
      - name: Idempotency-Key
        in: header
        description: "Chave unica por operacao para evitar duplicidade em Pix In, Pix Out e devolucoes."
        required: true
        schema:
          maxLength: 100
          type: string
        example: idem_20260602_0001
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/PixReverseRequest"
            example:
              amount: 129.9
              reason: Devolucao solicitada pelo pagador
              external_id: refund_20260602_0001
        required: true
      responses:
        "201":
          description: Devolucao solicitada com sucesso.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PixReverseResponse"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          $ref: "#/components/responses/NotFound"
        "409":
          $ref: "#/components/responses/Conflict"
        "412":
          $ref: "#/components/responses/PreconditionFailed"
        "422":
          $ref: "#/components/responses/UnprocessableEntity"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
  /pix/payment:
    post:
      tags:
      - Pix Out
      summary: Criar transferencia Pix
      description: Cria uma transferencia Pix para uma chave informada pelo cliente.
      parameters:
      - name: Idempotency-Key
        in: header
        description: "Chave unica por operacao para evitar duplicidade em Pix In, Pix Out e devolucoes."
        required: true
        schema:
          maxLength: 100
          type: string
        example: idem_20260602_0001
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreatePixPaymentRequest"
            example:
              amount: 250
              external_id: payout_20260602_0001
              beneficiary:
                name: Beneficiario Exemplo
                document: '12345678909'
                pix_key: beneficiario.exemplo@dominio.test
                pix_key_type: EMAIL
        required: true
      responses:
        "201":
          description: Transferencia criada com sucesso.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PixPaymentResponse"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "406":
          $ref: "#/components/responses/NotAcceptable"
        "409":
          $ref: "#/components/responses/Conflict"
        "422":
          $ref: "#/components/responses/UnprocessableEntity"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
  /pix/payment/{transaction_id}/status:
    get:
      tags:
      - Pix Out
      summary: Consultar status de transferencia Pix
      parameters:
      - name: transaction_id
        in: path
        required: true
        schema:
          type: string
        example: trx_01HYZK7QK4N8A2B6C0D9E1F3G5
      responses:
        "200":
          description: Status consultado com sucesso.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PixPaymentStatusResponse"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          $ref: "#/components/responses/NotFound"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
  /pix/payment/{transaction_id}/receipt:
    get:
      tags:
      - Pix Out
      summary: Consultar comprovante de transferencia Pix
      parameters:
      - name: transaction_id
        in: path
        required: true
        schema:
          type: string
        example: trx_01HYZK7QK4N8A2B6C0D9E1F3G5
      responses:
        "200":
          description: Comprovante consultado com sucesso.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PixPaymentReceiptResponse"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          $ref: "#/components/responses/NotFound"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
  /pix/payment/list:
    get:
      tags:
      - Pix Out
      summary: Listar transferencias Pix
      parameters:
      - name: initialDate
        in: query
        required: false
        schema:
          type: string
          format: date-time
        example: 2026-06-01T00:00:00Z
      - name: finalDate
        in: query
        required: false
        schema:
          type: string
          format: date-time
        example: 2026-06-02T23:59:59Z
      - name: status
        in: query
        required: false
        schema:
          $ref: "#/components/schemas/PixOutStatus"
      - name: transaction_id
        in: query
        required: false
        schema:
          type: string
        example: trx_01HYZK7QK4N8A2B6C0D9E1F3G5
      - name: external_id
        in: query
        required: false
        schema:
          type: string
        example: order_20260602_0001
      - name: page
        in: query
        required: false
        schema:
          minimum: 1
          type: integer
          default: 1
        example: 1
      - name: pageSize
        in: query
        required: false
        schema:
          maximum: 100
          minimum: 1
          type: integer
          default: 20
        example: 20
      responses:
        "200":
          description: Transferencias listadas com sucesso.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PixPaymentListResponse"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
  /pix/infractions:
    get:
      tags:
      - Infracoes Pix/MED
      summary: Listar infracoes Pix/MED
      parameters:
      - name: initialDate
        in: query
        required: false
        schema:
          type: string
          format: date-time
        example: 2026-06-01T00:00:00Z
      - name: finalDate
        in: query
        required: false
        schema:
          type: string
          format: date-time
        example: 2026-06-02T23:59:59Z
      - name: status
        in: query
        required: false
        schema:
          $ref: "#/components/schemas/InfractionStatus"
      - name: page
        in: query
        required: false
        schema:
          minimum: 1
          type: integer
          default: 1
        example: 1
      - name: pageSize
        in: query
        required: false
        schema:
          maximum: 100
          minimum: 1
          type: integer
          default: 20
        example: 20
      responses:
        "200":
          description: Infracoes listadas com sucesso.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/InfractionListResponse"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
  /pix/infractions/{id}:
    get:
      tags:
      - Infracoes Pix/MED
      summary: Consultar infracao Pix/MED
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        example: inf_01HYZK9Q4S8N7M2A6C0B1D3E5F
      responses:
        "200":
          description: Infracao encontrada.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Infraction"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          $ref: "#/components/responses/NotFound"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
  /pix/infractions/{id}/defense:
    post:
      tags:
      - Infracoes Pix/MED
      summary: Enviar defesa da infracao
      description: Envia texto de defesa e ate 3 arquivos em base64 para analise da infracao.
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        example: inf_01HYZK9Q4S8N7M2A6C0B1D3E5F
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/InfractionDefenseRequest"
            example:
              defense_text: Transacao reconhecida pelo cliente apos conciliacao interna.
              files:
              - file_name: comprovante.pdf
                mime_type: application/pdf
                content_base64: JVBERi0xLjQKJcfs...
        required: true
      responses:
        "201":
          description: Defesa enviada com sucesso.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/InfractionDefenseResponse"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          $ref: "#/components/responses/NotFound"
        "412":
          $ref: "#/components/responses/PreconditionFailed"
        "422":
          $ref: "#/components/responses/UnprocessableEntity"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
  /webhooks/kapay:
    post:
      tags:
      - Webhooks
      summary: Receber eventos KAPAY
      description: |
        Endpoint de exemplo que deve ser implementado pelo cliente para receber eventos.
        A URL real e configurada no painel ou durante o onboarding da integracao.

        A KAPAY envia os headers `X-KAPAY-Signature`, `X-KAPAY-Timestamp`,
        `X-KAPAY-Event` e `X-KAPAY-Request-Id`. A assinatura deve ser validada com
        HMAC-SHA256 usando o `webhook_secret`.

        O cliente deve validar assinatura, timestamp, request_id, transaction_id,
        external_id, status, valor total, valores de split e recebedores do split
        antes de confirmar qualquer conciliacao.
        Em caso de falha temporaria, a KAPAY realiza retentativas com backoff exponencial.
      parameters:
      - name: X-KAPAY-Signature
        in: header
        required: true
        schema:
          type: string
        example: hmac-sha256=15c9a0b6e7f0a8c2d4e9f6b1a3c5d7e8f901234567890abcdef1234567890abcd
      - name: X-KAPAY-Timestamp
        in: header
        required: true
        schema:
          type: string
        example: 2026-06-02T14:30:00Z
      - name: X-KAPAY-Event
        in: header
        required: true
        schema:
          $ref: "#/components/schemas/WebhookEventType"
      - name: X-KAPAY-Request-Id
        in: header
        required: true
        schema:
          type: string
        example: req_01HYZK8M5K2V7Q9A1B3C4D5E6F
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/WebhookPayload"
            example:
              event: pix.qrcode.paid
              request_id: req_01HYZK8M5K2V7Q9A1B3C4D5E6F
              transaction_id: trx_01HYZK7QK4N8A2B6C0D9E1F3G5
              external_id: order_20260602_0001
              status: PAID
              amount: 129.9
              currency: BRL
              occurred_at: 2026-06-02T14:30:00Z
              data:
                end_to_end_id: E1234567820260602143000000000001
        required: true
      responses:
        "200":
          description: Evento recebido com sucesso pelo cliente.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/inline_response_200"
        "400":
          $ref: "#/components/responses/BadRequest"
      security: []
components:
  schemas:
    OAuthTokenResponse:
      required:
      - access_token
      - expires_in
      - token_type
      type: object
      properties:
        access_token:
          type: string
        token_type:
          type: string
          example: Bearer
        expires_in:
          type: integer
          description: Tempo de expiracao em segundos. Tokens KAPAY expiram em 30 minutos.
          example: 1800
    ErrorResponse:
      required:
      - error
      - message
      - request_id
      - statusCode
      type: object
      properties:
        statusCode:
          type: integer
          example: 401
        error:
          type: string
          example: unauthorized
        message:
          type: string
          example: Token invalido ou expirado.
        request_id:
          type: string
          example: req_01HYZK8M5K2V7Q9A1B3C4D5E6F
    MoneyAmount:
      minimum: 0.01
      type: number
      format: double
      example: 129.9
    Currency:
      type: string
      example: BRL
      enum:
      - BRL
    Pagination:
      required:
      - page
      - pageSize
      - total
      - totalPages
      type: object
      properties:
        page:
          type: integer
          example: 1
        pageSize:
          type: integer
          example: 20
        total:
          type: integer
          example: 125
        totalPages:
          type: integer
          example: 7
    BalanceResponse:
      required:
      - available_balance
      - blocked_balance
      - currency
      type: object
      properties:
        available_balance:
          $ref: "#/components/schemas/MoneyAmount"
        blocked_balance:
          minimum: 0
          type: number
          format: double
          example: 320
        currency:
          $ref: "#/components/schemas/Currency"
    Transaction:
      required:
      - amount
      - created_at
      - currency
      - status
      - transaction_id
      - type
      type: object
      properties:
        transaction_id:
          type: string
          example: trx_01HYZK7QK4N8A2B6C0D9E1F3G5
        external_id:
          type: string
          example: order_20260602_0001
        type:
          type: string
          example: PIX_IN
          enum:
          - PIX_IN
          - PIX_OUT
          - REFUND
          - FEE
          - ADJUSTMENT
        status:
          type: string
          example: PAID
        amount:
          $ref: "#/components/schemas/MoneyAmount"
        currency:
          $ref: "#/components/schemas/Currency"
        description:
          type: string
          example: Liquidacao de cobranca Pix
        created_at:
          type: string
          format: date-time
          example: 2026-06-02T14:30:00Z
    TransactionListResponse:
      required:
      - data
      - pagination
      type: object
      properties:
        data:
          type: array
          items:
            $ref: "#/components/schemas/Transaction"
        pagination:
          $ref: "#/components/schemas/Pagination"
    Payer:
      required:
      - document
      - name
      type: object
      properties:
        name:
          type: string
          example: Cliente Exemplo
        document:
          type: string
          description: CPF ou CNPJ completo, sem pontuacao. Deve ser tratado conforme LGPD.
          example: '12345678909'
        email:
          type: string
          format: email
          example: cliente.exemplo@dominio.test
        phone:
          type: string
          example: "+5511999990000"
    Beneficiary:
      required:
      - document
      - name
      - pix_key
      - pix_key_type
      type: object
      properties:
        name:
          type: string
          example: Beneficiario Exemplo
        document:
          type: string
          description: CPF ou CNPJ completo, sem pontuacao.
          example: '12345678909'
        email:
          type: string
          format: email
          description: E-mail do favorecido. Quando ausente, a KaPay usa o e-mail cadastrado na conta.
          example: beneficiario.exemplo@dominio.test
        phone:
          type: string
          description: Telefone do favorecido com DDD. Quando ausente, a KaPay usa o telefone cadastrado na conta.
          example: '+5511999999999'
        pix_key:
          type: string
          example: beneficiario.exemplo@dominio.test
        pix_key_type:
          $ref: "#/components/schemas/PixKeyType"
    PixKeyType:
      type: string
      example: EMAIL
      enum:
      - CPF
      - CNPJ
      - EMAIL
      - PHONE
      - RANDOM
    PixInStatus:
      type: string
      example: PAID
      enum:
      - PENDING
      - PAID
      - EXPIRED
      - CANCELED
      - REFUNDED
    PixOutStatus:
      type: string
      example: CONFIRMED
      enum:
      - PROCESSING
      - PENDING_APPROVAL
      - CONFIRMED
      - FAILED
      - CANCELED
      - RETURNED
    InfractionStatus:
      type: string
      example: WAITING_DEFENSE
      enum:
      - WAITING_ANALYSIS
      - WAITING_DEFENSE
      - AGREED
      - DISAGREED
      - CANCELED
    SplitRecipientIdentifierType:
      type: string
      example: USERNAME
      enum:
      - ACCOUNT_ID
      - USERNAME
    SplitType:
      type: string
      example: PERCENTAGE
      enum:
      - FIXED
      - PERCENTAGE
    SplitStatus:
      type: string
      example: PENDING
      enum:
      - PENDING
      - SCHEDULED
      - SETTLED
      - FAILED
      - CANCELED
    SplitReceiverStatus:
      type: string
      example: ACTIVE
      enum:
      - ACTIVE
      - INACTIVE
      - BLOCKED
    SplitRule:
      required:
      - recipient_identifier
      - recipient_identifier_type
      - split_type
      type: object
      properties:
        recipient_identifier_type:
          $ref: "#/components/schemas/SplitRecipientIdentifierType"
        recipient_identifier:
          type: string
          description: "Identificador do recebedor. Para `ACCOUNT_ID`, use o ID para Split exibido no painel Integrações (`kapay_cli_...` ou `kapay_mer_...`), não o Client ID OAuth2."
          example: kapay_cli_6q3dskvwlxpmy3he3yqz
        split_type:
          $ref: "#/components/schemas/SplitType"
        amount:
          minimum: 0.01
          type: number
          format: double
          nullable: true
          example: 5
        percentage:
          maximum: 100
          minimum: 0.01
          type: number
          format: double
          nullable: true
          example: 20
        description:
          maxLength: 140
          type: string
          example: Comissao parceiro
      description: |
        Regra de divisao de valor para uma cobranca Pix com split.

        Use `amount` quando `split_type` for `FIXED` e use `percentage` quando
        `split_type` for `PERCENTAGE`. A soma de valores fixos nao pode superar
        o valor total da cobranca e a soma de percentuais nao pode superar 100%.
    SplitRecipient:
      required:
      - calculated_amount
      - recipient_identifier
      - recipient_identifier_type
      - split_type
      - status
      type: object
      properties:
        recipient_identifier_type:
          $ref: "#/components/schemas/SplitRecipientIdentifierType"
        recipient_identifier:
          type: string
          example: parceiro01
        split_type:
          $ref: "#/components/schemas/SplitType"
        amount:
          type: number
          format: double
          nullable: true
          example: 5
        percentage:
          type: number
          format: double
          nullable: true
          example: 20
        calculated_amount:
          minimum: 0
          type: number
          format: double
          example: 20
        status:
          $ref: "#/components/schemas/SplitStatus"
    SplitSummary:
      required:
      - main_account_amount
      - recipients
      - split_total_amount
      - total_amount
      type: object
      properties:
        total_amount:
          $ref: "#/components/schemas/MoneyAmount"
        main_account_amount:
          minimum: 0
          type: number
          format: double
          example: 75
        split_total_amount:
          minimum: 0
          type: number
          format: double
          example: 25
        recipients:
          minItems: 1
          type: array
          items:
            $ref: "#/components/schemas/SplitRecipient"
    SplitReceiver:
      required:
      - account_id
      - created_at
      - document_masked
      - name
      - status
      - username
      type: object
      properties:
        account_id:
          type: string
          example: acc_01HXKAPAY000000001
        username:
          type: string
          example: parceiro01
        name:
          type: string
          example: Parceiro Exemplo
        document_masked:
          type: string
          description: Documento mascarado para protecao de dados pessoais.
          example: '***456780**'
        status:
          $ref: "#/components/schemas/SplitReceiverStatus"
        created_at:
          type: string
          format: date-time
          example: 2026-05-20T10:00:00Z
    SplitReceiverDetails:
      allOf:
      - $ref: "#/components/schemas/SplitReceiver"
      - required:
        - can_receive_split
        type: object
        properties:
          can_receive_split:
            type: boolean
            example: true
    SplitSettlement:
      required:
      - amount
      - created_at
      - external_id
      - recipient_identifier
      - recipient_identifier_type
      - settlement_id
      - status
      - transaction_id
      type: object
      properties:
        settlement_id:
          type: string
          example: set_01HYZL7Q2A4B6C8D0E1F3G5H7
        transaction_id:
          type: string
          example: trx_01HYZK7QK4N8A2B6C0D9E1F3G5
        external_id:
          type: string
          example: order_20260602_0001
        recipient_identifier_type:
          $ref: "#/components/schemas/SplitRecipientIdentifierType"
        recipient_identifier:
          type: string
          example: parceiro01
        amount:
          $ref: "#/components/schemas/MoneyAmount"
        status:
          $ref: "#/components/schemas/SplitStatus"
        settled_at:
          type: string
          format: date-time
          nullable: true
          example: 2026-06-02T14:45:00Z
        created_at:
          type: string
          format: date-time
          example: 2026-06-02T14:42:00Z
    SplitReceiverListResponse:
      required:
      - data
      - pagination
      type: object
      properties:
        data:
          type: array
          items:
            $ref: "#/components/schemas/SplitReceiver"
        pagination:
          $ref: "#/components/schemas/Pagination"
    SplitSettlementListResponse:
      required:
      - data
      - pagination
      type: object
      properties:
        data:
          type: array
          items:
            $ref: "#/components/schemas/SplitSettlement"
        pagination:
          $ref: "#/components/schemas/Pagination"
    SplitErrorCode:
      type: string
      example: split_rule_invalid
      enum:
      - split_recipient_not_found
      - split_recipient_inactive
      - split_amount_exceeds_total
      - split_percentage_exceeds_100
      - split_rule_invalid
      - split_not_allowed_for_account
      - idempotency_payload_conflict
    CreatePixQrCodeRequest:
      required:
      - amount
      - external_id
      - payer
      type: object
      properties:
        amount:
          $ref: "#/components/schemas/MoneyAmount"
        external_id:
          type: string
          example: order_20260602_0001
        description:
          maxLength: 140
          type: string
          example: Pedido online 0001
        expiration:
          minimum: 60
          type: integer
          description: Tempo de expiracao em segundos.
          example: 1800
        payer:
          $ref: "#/components/schemas/Payer"
    PixQrCodeResponse:
      required:
      - amount
      - created_at
      - expires_at
      - external_id
      - pix_code
      - qr_code_base64
      - status
      - transaction_id
      type: object
      properties:
        transaction_id:
          type: string
          example: trx_01HYZK7QK4N8A2B6C0D9E1F3G5
        external_id:
          type: string
          example: order_20260602_0001
        status:
          $ref: "#/components/schemas/PixInStatus"
        amount:
          $ref: "#/components/schemas/MoneyAmount"
        pix_code:
          type: string
          example: 00020101021226860014br.gov.bcb.pix2564qrcode.kapay.com.br/pix/abc1235204000053039865406129.905802BR5908KAPAY6009SAO PAULO62070503***6304A1B2
        qr_code_base64:
          type: string
          format: byte
          example: iVBORw0KGgoAAAANSUhEUgAA...
        expires_at:
          type: string
          format: date-time
          example: 2026-06-02T15:00:00Z
        created_at:
          type: string
          format: date-time
          example: 2026-06-02T14:30:00Z
    PixQrCodeListResponse:
      required:
      - data
      - pagination
      type: object
      properties:
        data:
          type: array
          items:
            $ref: "#/components/schemas/PixQrCodeResponse"
        pagination:
          $ref: "#/components/schemas/Pagination"
    CreatePixQrCodeSplitRequest:
      required:
      - amount
      - external_id
      - payer
      - split_rules
      type: object
      properties:
        amount:
          $ref: "#/components/schemas/MoneyAmount"
        external_id:
          type: string
          example: order_20260602_0001
        description:
          maxLength: 140
          type: string
          example: Pedido com split
        expiration:
          minimum: 60
          type: integer
          description: Tempo de expiracao em segundos.
          example: 1800
        payer:
          $ref: "#/components/schemas/Payer"
        split_rules:
          minItems: 1
          type: array
          items:
            $ref: "#/components/schemas/SplitRule"
    PixQrCodeSplitResponse:
      required:
      - amount
      - created_at
      - expires_at
      - external_id
      - pix_code
      - qr_code_base64
      - split_summary
      - status
      - transaction_id
      type: object
      properties:
        transaction_id:
          type: string
          example: trx_01HYZK7QK4N8A2B6C0D9E1F3G5
        external_id:
          type: string
          example: order_20260602_0001
        status:
          $ref: "#/components/schemas/PixInStatus"
        amount:
          $ref: "#/components/schemas/MoneyAmount"
        pix_code:
          type: string
          example: 00020101021226860014br.gov.bcb.pix2564qrcode.kapay.com.br/pix/split/abc1235204000053039865406100.005802BR5905KAPAY6009SAO PAULO62070503***6304B2C3
        qr_code_base64:
          type: string
          format: byte
          example: iVBORw0KGgoAAAANSUhEUgAA...
        split_summary:
          $ref: "#/components/schemas/SplitSummary"
        expires_at:
          type: string
          format: date-time
          example: 2026-06-02T15:00:00Z
        created_at:
          type: string
          format: date-time
          example: 2026-06-02T14:30:00Z
    PixQrCodeSplitDetailsResponse:
      required:
      - amount
      - created_at
      - external_id
      - split_summary
      - status
      - transaction_id
      type: object
      properties:
        transaction_id:
          type: string
          example: trx_01HYZK7QK4N8A2B6C0D9E1F3G5
        external_id:
          type: string
          example: order_20260602_0001
        status:
          $ref: "#/components/schemas/PixInStatus"
        amount:
          $ref: "#/components/schemas/MoneyAmount"
        split_summary:
          $ref: "#/components/schemas/SplitSummary"
        created_at:
          type: string
          format: date-time
          example: 2026-06-02T14:30:00Z
        paid_at:
          type: string
          format: date-time
          nullable: true
          example: 2026-06-02T14:42:00Z
    PixReverseRequest:
      required:
      - amount
      - external_id
      - reason
      type: object
      properties:
        amount:
          $ref: "#/components/schemas/MoneyAmount"
        external_id:
          type: string
          example: refund_20260602_0001
        reason:
          maxLength: 255
          type: string
          example: Devolucao solicitada pelo pagador
    PixReverseResponse:
      required:
      - amount
      - created_at
      - end_to_end_id
      - external_id
      - status
      - transaction_id
      type: object
      properties:
        transaction_id:
          type: string
          example: ref_01HYZK9Q4S8N7M2A6C0B1D3E5F
        external_id:
          type: string
          example: refund_20260602_0001
        status:
          type: string
          example: PROCESSING
          enum:
          - PROCESSING
          - CONFIRMED
          - FAILED
        amount:
          $ref: "#/components/schemas/MoneyAmount"
        end_to_end_id:
          type: string
          example: E1234567820260602143000000000001
        created_at:
          type: string
          format: date-time
          example: 2026-06-02T14:35:00Z
    CreatePixPaymentRequest:
      required:
      - amount
      - beneficiary
      - external_id
      type: object
      properties:
        amount:
          $ref: "#/components/schemas/MoneyAmount"
        external_id:
          type: string
          example: payout_20260602_0001
        beneficiary:
          $ref: "#/components/schemas/Beneficiary"
    PixPaymentResponse:
      required:
      - amount
      - created_at
      - end_to_end_id
      - external_id
      - status
      - transaction_id
      type: object
      properties:
        transaction_id:
          type: string
          example: trx_01HYZL1R7B6C9D2E5F8G0H3J4K
        external_id:
          type: string
          example: payout_20260602_0001
        status:
          $ref: "#/components/schemas/PixOutStatus"
        amount:
          $ref: "#/components/schemas/MoneyAmount"
        end_to_end_id:
          type: string
          nullable: true
          example: E1234567820260602144000000000002
        created_at:
          type: string
          format: date-time
          example: 2026-06-02T14:40:00Z
    PixPaymentStatusResponse:
      required:
      - amount
      - external_id
      - status
      - transaction_id
      - updated_at
      type: object
      properties:
        transaction_id:
          type: string
          example: trx_01HYZL1R7B6C9D2E5F8G0H3J4K
        external_id:
          type: string
          example: payout_20260602_0001
        status:
          $ref: "#/components/schemas/PixOutStatus"
        amount:
          $ref: "#/components/schemas/MoneyAmount"
        end_to_end_id:
          type: string
          nullable: true
          example: E1234567820260602144000000000002
        failure_reason:
          type: string
          nullable: true
        updated_at:
          type: string
          format: date-time
          example: 2026-06-02T14:42:00Z
    PixPaymentReceiptResponse:
      required:
      - amount
      - beneficiary
      - end_to_end_id
      - paid_at
      - status
      - transaction_id
      type: object
      properties:
        transaction_id:
          type: string
          example: trx_01HYZL1R7B6C9D2E5F8G0H3J4K
        end_to_end_id:
          type: string
          example: E1234567820260602144000000000002
        amount:
          $ref: "#/components/schemas/MoneyAmount"
        status:
          $ref: "#/components/schemas/PixOutStatus"
        paid_at:
          type: string
          format: date-time
          example: 2026-06-02T14:42:00Z
        beneficiary:
          $ref: "#/components/schemas/Beneficiary"
        receipt_url:
          type: string
          format: uri
          example: https://api.kapay.com.br/v1/pix/payment/trx_01HYZL1R7B6C9D2E5F8G0H3J4K/receipt
    PixPaymentListResponse:
      required:
      - data
      - pagination
      type: object
      properties:
        data:
          type: array
          items:
            $ref: "#/components/schemas/PixPaymentResponse"
        pagination:
          $ref: "#/components/schemas/Pagination"
    WebhookEventType:
      type: string
      example: pix.qrcode.paid
      enum:
      - pix.qrcode.created
      - pix.qrcode.paid
      - pix.qrcode.expired
      - pix.qrcode.refunded
      - pix.payment.created
      - pix.payment.processing
      - pix.payment.confirmed
      - pix.payment.failed
      - pix.payment.returned
      - pix.infraction.created
      - pix.infraction.updated
      - pix.qrcode.split.created
      - pix.qrcode.split.paid
      - split.settlement.created
      - split.settlement.settled
      - split.settlement.failed
    WebhookPayload:
      required:
      - amount
      - currency
      - event
      - external_id
      - occurred_at
      - request_id
      - status
      - transaction_id
      type: object
      properties:
        event:
          $ref: "#/components/schemas/WebhookEventType"
        request_id:
          type: string
          example: req_01HYZK8M5K2V7Q9A1B3C4D5E6F
        transaction_id:
          type: string
          example: trx_01HYZK7QK4N8A2B6C0D9E1F3G5
        external_id:
          type: string
          example: order_20260602_0001
        status:
          type: string
          example: PAID
        amount:
          $ref: "#/components/schemas/MoneyAmount"
        currency:
          $ref: "#/components/schemas/Currency"
        occurred_at:
          type: string
          format: date-time
          example: 2026-06-02T14:30:00Z
        data:
          type: object
          additionalProperties: true
    Infraction:
      required:
      - amount
      - created_at
      - id
      - reason
      - status
      - transaction_id
      type: object
      properties:
        id:
          type: string
          example: inf_01HYZK9Q4S8N7M2A6C0B1D3E5F
        status:
          $ref: "#/components/schemas/InfractionStatus"
        transaction_id:
          type: string
          example: trx_01HYZK7QK4N8A2B6C0D9E1F3G5
        end_to_end_id:
          type: string
          example: E1234567820260602143000000000001
        amount:
          $ref: "#/components/schemas/MoneyAmount"
        reason:
          type: string
          example: Contestacao aberta pelo participante recebedor.
        defense_due_at:
          type: string
          format: date-time
          nullable: true
          example: 2026-06-05T23:59:59Z
        created_at:
          type: string
          format: date-time
          example: 2026-06-02T16:00:00Z
        updated_at:
          type: string
          format: date-time
          example: 2026-06-02T16:10:00Z
    InfractionListResponse:
      required:
      - data
      - pagination
      type: object
      properties:
        data:
          type: array
          items:
            $ref: "#/components/schemas/Infraction"
        pagination:
          $ref: "#/components/schemas/Pagination"
    InfractionDefenseFile:
      required:
      - content_base64
      - file_name
      - mime_type
      type: object
      properties:
        file_name:
          type: string
          example: comprovante.pdf
        mime_type:
          type: string
          example: application/pdf
        content_base64:
          type: string
          format: byte
          example: JVBERi0xLjQKJcfs...
    InfractionDefenseRequest:
      required:
      - defense_text
      type: object
      properties:
        defense_text:
          maxLength: 4000
          minLength: 10
          type: string
          example: Transacao reconhecida pelo cliente apos conciliacao interna.
        files:
          maxItems: 3
          type: array
          items:
            $ref: "#/components/schemas/InfractionDefenseFile"
    InfractionDefenseResponse:
      required:
      - id
      - received_at
      - status
      type: object
      properties:
        id:
          type: string
          example: inf_01HYZK9Q4S8N7M2A6C0B1D3E5F
        status:
          $ref: "#/components/schemas/InfractionStatus"
        received_at:
          type: string
          format: date-time
          example: 2026-06-02T17:00:00Z
    oauth_token_body:
      required:
      - grant_type
      type: object
      properties:
        grant_type:
          type: string
          example: client_credentials
          enum:
          - client_credentials
    inline_response_200:
      type: object
      properties:
        received:
          type: boolean
      example:
        received: true
  responses:
    BadRequest:
      description: Requisicao invalida.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
          example:
            statusCode: 400
            error: bad_request
            message: Parametros invalidos ou ausentes.
            request_id: req_01HYZK8M5K2V7Q9A1B3C4D5E6F
    Unauthorized:
      description: "Credenciais ausentes, invalidas ou expiradas."
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
          example:
            statusCode: 401
            error: unauthorized
            message: Token invalido ou expirado.
            request_id: req_01HYZK8M5K2V7Q9A1B3C4D5E6F
    Forbidden:
      description: Cliente sem permissao para acessar o recurso.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
          example:
            statusCode: 403
            error: forbidden
            message: Permissao insuficiente para esta operacao.
            request_id: req_01HYZK8M5K2V7Q9A1B3C4D5E6F
    NotFound:
      description: Recurso nao encontrado.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
          example:
            statusCode: 404
            error: not_found
            message: Recurso nao encontrado.
            request_id: req_01HYZK8M5K2V7Q9A1B3C4D5E6F
    NotAcceptable:
      description: Operacao nao aceita para as condicoes informadas.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
          example:
            statusCode: 406
            error: not_acceptable
            message: Operacao nao aceita para este recurso.
            request_id: req_01HYZK8M5K2V7Q9A1B3C4D5E6F
    Conflict:
      description: Conflito com uma operacao existente.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
          example:
            statusCode: 409
            error: idempotency_payload_conflict
            message: A mesma Idempotency-Key ja foi usada com payload diferente.
            request_id: req_01HYZK8M5K2V7Q9A1B3C4D5E6F
    PreconditionFailed:
      description: Pre-condicao nao atendida.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
          example:
            statusCode: 412
            error: precondition_failed
            message: O recurso nao esta em status permitido para esta acao.
            request_id: req_01HYZK8M5K2V7Q9A1B3C4D5E6F
    UnprocessableEntity:
      description: "Dados validos em formato, mas invalidos para regra de negocio."
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
          example:
            statusCode: 422
            error: unprocessable_entity
            message: Regra de split invalida.
            request_id: req_01HYZK8M5K2V7Q9A1B3C4D5E6F
    TooManyRequests:
      description: Limite de requisicoes excedido.
      headers:
        Retry-After:
          description: Tempo em segundos ate nova tentativa.
          schema:
            type: integer
          example: 60
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
          example:
            statusCode: 429
            error: too_many_requests
            message: Limite de requisicoes excedido.
            request_id: req_01HYZK8M5K2V7Q9A1B3C4D5E6F
    InternalServerError:
      description: Erro interno.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
          example:
            statusCode: 500
            error: internal_server_error
            message: Ocorreu um erro inesperado.
            request_id: req_01HYZK8M5K2V7Q9A1B3C4D5E6F
  parameters:
    IdempotencyKey:
      name: Idempotency-Key
      in: header
      description: "Chave unica por operacao para evitar duplicidade em Pix In, Pix Out e devolucoes."
      required: true
      schema:
        maxLength: 100
        type: string
      example: idem_20260602_0001
    InitialDate:
      name: initialDate
      in: query
      required: false
      schema:
        type: string
        format: date-time
      example: 2026-06-01T00:00:00Z
    FinalDate:
      name: finalDate
      in: query
      required: false
      schema:
        type: string
        format: date-time
      example: 2026-06-02T23:59:59Z
    Page:
      name: page
      in: query
      required: false
      schema:
        minimum: 1
        type: integer
        default: 1
      example: 1
    PageSize:
      name: pageSize
      in: query
      required: false
      schema:
        maximum: 100
        minimum: 1
        type: integer
        default: 20
      example: 20
    TransactionIdPath:
      name: transaction_id
      in: path
      required: true
      schema:
        type: string
      example: trx_01HYZK7QK4N8A2B6C0D9E1F3G5
    EndToEndIdPath:
      name: end_to_end_id
      in: path
      required: true
      schema:
        type: string
      example: E1234567820260602143000000000001
    TransactionIdQuery:
      name: transaction_id
      in: query
      required: false
      schema:
        type: string
      example: trx_01HYZK7QK4N8A2B6C0D9E1F3G5
    ExternalIdQuery:
      name: external_id
      in: query
      required: false
      schema:
        type: string
      example: order_20260602_0001
  securitySchemes:
    BasicAuth:
      type: http
      description: Use `client_key` como usuario e `client_secret` como senha.
      scheme: basic
    BearerAuth:
      type: http
      description: Token OAuth2 obtido em `POST /oauth/token`.
      scheme: bearer
      bearerFormat: JWT
    LegacyBearerToken:
      type: http
      description: Token Bearer fixo para clientes legados. Alternativa nao recomendada.
      scheme: bearer
x-kapay-documentation:
  introducao:
    objetivo: Integrar clientes aos servicos Pix da KAPAY com autenticacao segura e contratos previsiveis.
    formato: "JSON para requisicoes e respostas, exceto autenticacao OAuth2 que usa formulario URL encoded."
  ambientes:
    producao: https://api.kapay.com.br/v1
    sandbox: https://api.kapay.com.br/sandbox/v1
  autenticacao:
    principal: OAuth2 Client Credentials com Basic Auth no endpoint POST /oauth/token.
    legado: "Token Bearer fixo pode ser habilitado para clientes legados, mas nao e recomendado."
  seguranca:
  - Todas as requisicoes devem usar HTTPS.
  - Nunca exponha client_secret em aplicacoes frontend.
  - Tokens expiram em 30 minutos.
  - A KAPAY pode aplicar whitelist de IP por cliente.
  - "Use Idempotency-Key em Pix In, Pix Out, devolucoes e pedidos com split."
  - Webhooks devem ser assinados e validados com HMAC-SHA256.
  - "Logs nao devem armazenar client_secret, token completo, documento completo ou dados sensiveis."
  - CPF e CNPJ devem ser tratados conforme a LGPD.
  - Rate limit e aplicado por IP e por cliente.
  - Credenciais podem ser bloqueadas apos tentativas suspeitas.
  - A rotacao de client_secret deve ser suportada em processos operacionais.
  - "O cliente deve validar assinatura, valor, external_id, transaction_id e status dos webhooks."
  rate_limit:
    autenticacao: 10 requisicoes por segundo.
    pix_in: 60 requisicoes por minuto.
    pix_out: 30 requisicoes por minuto.
    split: 30 requisicoes por minuto.
    consultas: 120 requisicoes por minuto.
    webhooks: Retentativas com backoff exponencial.
  exemplos_de_integracao:
    gerar_token:
      method: POST
      path: /oauth/token
      headers:
        Authorization: Basic base64(client_key:client_secret)
        Content-Type: application/x-www-form-urlencoded
      body: grant_type=client_credentials
    criar_cobranca_pix:
      method: POST
      path: /pix/qrcode
      headers:
        Authorization: "Bearer {access_token}"
        Idempotency-Key: idem_20260602_0001
    criar_transferencia_pix:
      method: POST
      path: /pix/payment
      headers:
        Authorization: "Bearer {access_token}"
        Idempotency-Key: idem_20260602_0002
    criar_cobranca_com_split:
      method: POST
      path: /pix/qrcode/split
      headers:
        Authorization: "Bearer {access_token}"
        Idempotency-Key: idem_20260602_0003
      observacao: O split e liquidado somente apos a cobranca Pix ser paga.
