openapi: 3.0.0
info:
  title: GYRA+ API - MCP Server
  description: API da Gyra+ para analise de credito. Spec curada para uso com agentes AI via MCP.
  version: '1.0'
  contact: {}
servers:
  - url: 'https://gyra-core.gyramais.com.br'
    description: Producao
paths:
  /auth/authenticate:
    post:
      operationId: AuthController_generateAccessToken
      parameters:
        - name: gyra-client-secret
          in: header
          description: 'Client Secret da credencial. Gerado no Toolbox em Configuracoes > API & MCP e mostrado uma unica vez.'
          schema:
            type: string
          required: true
        - name: gyra-client-id
          in: header
          description: 'Client ID da credencial. Gerado no Toolbox em Configuracoes > API & MCP.'
          schema:
            type: string
          required: true
      responses:
        '200':
          description: 'Sessao criada: accessToken (JWT) e expiresAt (24 horas apos a emissao).'
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: string
                  accessToken:
                    type: string
                    description: 'JWT. Vai no header Authorization como `Bearer <token>`.'
                  expiresAt:
                    type: string
                    format: date-time
                    description: Validade de 24 horas. Renove antes de expirar.
                  userId:
                    type: string
                  organizationId:
                    type: string
                  loggedOutAt:
                    type: string
                    nullable: true
                    format: date-time
                  createdAt:
                    type: string
                    format: date-time
                  updatedAt:
                    type: string
                    format: date-time
              example:
                id: 6612a7f3a1b2c3d400000000
                createdAt: '2026-07-31T13:40:02.118Z'
                updatedAt: '2026-07-31T13:40:02.118Z'
                expiresAt: '2026-08-01T13:40:02.114Z'
                accessToken: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
                userId: 6612a7f3b4c5d6e700000000
                loggedOutAt: null
                organizationId: 6612a7f30000000000000001
        '400':
          description: O gyra-client-id nao corresponde a nenhuma credencial (inclusive credencial revogada).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 400
                message: ClientId inválido.
        '401':
          description: O gyra-client-secret nao confere com o client id.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 401
                message: ClientSecret inválido.
        '500':
          description: 'Falha nossa. Tente de novo; se persistir, acione o suporte com o horario da chamada.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 500
                message: Internal server error
      tags:
        - auth
      summary: Gerar token de acesso JWT
      description: |
          Autentica via client credentials (client-id e client-secret) e retorna um JWT.
          
          Este e o primeiro passo para usar a API. O token retornado deve ser enviado
          no header Authorization de todas as requisicoes subsequentes.
          
          NOTA: No MCP server, a autenticacao e automatica, e este tool e exposto apenas
          para uso manual ou debug. O server gerencia o token internamente.
      x-codeSamples:
        - lang: cURL
          label: cURL
          source: |
              curl --request POST 'https://gyra-core.gyramais.com.br/auth/authenticate' \
                --header 'gyra-client-id: SEU_CLIENT_ID' \
                --header 'gyra-client-secret: SEU_CLIENT_SECRET'
        - lang: JavaScript
          label: Node
          source: |
              const resposta = await fetch("https://gyra-core.gyramais.com.br/auth/authenticate", {
                method: "POST",
                headers: {
                  "gyra-client-id": process.env.GYRA_CLIENT_ID,
                  "gyra-client-secret": process.env.GYRA_CLIENT_SECRET,
                },
              });
              
              const dados = await resposta.json();
        - lang: Python
          label: Python
          source: |
              import requests
              
              resposta = requests.post(
                  "https://gyra-core.gyramais.com.br/auth/authenticate",
                  headers={
                      "gyra-client-id": client_id,
                      "gyra-client-secret": client_secret,
                  },
              )
              
              dados = resposta.json()
  /webhook:
    post:
      operationId: WebhookController_create
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateWebhookDto'
            example:
              type: REPORT_FINISHED
              url: 'https://api.suaempresa.com/gyra/webhook'
      responses:
        '200':
          description: 'Webhook criado com id, type, url e organizationId.'
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: string
                  type:
                    type: string
                  url:
                    type: string
                  apiKey:
                    type: string
                    nullable: true
                  organizationId:
                    type: string
                  createdAt:
                    type: string
                    format: date-time
              example:
                id: 6612a7f344eb43f000000000
                createdAt: '2026-07-31T13:40:02.118Z'
                updatedAt: '2026-07-31T13:40:02.118Z'
                organizationId: 6612a7f3fa9e086b00000000
                type: REPORT_FINISHED
                url: 'https://api.suaempresa.com/gyra/webhook'
                apiKey: null
        '400':
          description: 'Tipo invalido, url ausente, ou a URL nao respondeu 2xx ao POST de teste feito antes de salvar.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 400
                message: URL de webhook inválida.
        '401':
          description: 'Token ausente, expirado ou invalido. Gere outro em POST /auth/authenticate.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 401
                message: Token de acesso inválido.
        '500':
          description: 'Falha nossa. Tente de novo; se persistir, acione o suporte com o horario da chamada.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 500
                message: Internal server error
      tags:
        - webhook
      summary: Criar webhook para notificacoes
      description: |
          Registra uma URL que recebe um POST a cada evento do tipo escolhido. Cada webhook
          escuta um tipo; para varios tipos, cadastre varios webhooks.
          
          Antes de salvar, a GYRA+ faz um POST de teste na URL com o corpo
          {"message": "Teste de webhook cadastrado com sucesso!"}. Se a URL nao responder 2xx,
          o cadastro e recusado com 400 "URL de webhook inválida.".
          
          Tipos:
          - REPORT: cada secao do relatorio atualizada (varios disparos por relatorio)
          - REPORT_FINISHED: todas as fontes do relatorio terminaram
          - REPORT_STATUS: decisao gravada no relatorio (manual ou automatica)
          - CREDIT_POLICY: o resultado da politica de credito mudou de status
          - REPORT_EXPORTED: arquivo exportado pronto (ou falha da exportacao)
          - COMMITTEE_FINISHED: o Comite de Credito IA concluiu ou falhou
          - OPERATION: execucao de esteira concluiu com status final
          - OPTIN: fluxo de opt-in
          
          Envelope de todo evento: { organizationId, webhookType, data }. Se apiKey for
          informada, vai no header api-key. Entrega com falha de rede, 5xx, 408, 425 ou 429
          e tentada de novo ate 3 vezes.
          
          REPORT, REPORT_FINISHED e COMMITTEE_FINISHED so saem para relatorios criados
          depois do cadastro do webhook.
      x-codeSamples:
        - lang: cURL
          label: cURL
          source: |
              curl --request POST 'https://gyra-core.gyramais.com.br/webhook' \
                --header 'Authorization: Bearer <token>' \
                --header 'Content-Type: application/json' \
                --data '{"type":"REPORT_FINISHED","url":"https://api.suaempresa.com/gyra/webhook"}'
        - lang: JavaScript
          label: Node
          source: |
              const resposta = await fetch("https://gyra-core.gyramais.com.br/webhook", {
                method: "POST",
                headers: {
                  Authorization: `Bearer ${token}`,
                  "Content-Type": "application/json",
                },
                body: JSON.stringify({
                  "type": "REPORT_FINISHED",
                  "url": "https://api.suaempresa.com/gyra/webhook"
                }),
              });
              
              const dados = await resposta.json();
        - lang: Python
          label: Python
          source: |
              import requests
              
              resposta = requests.post(
                  "https://gyra-core.gyramais.com.br/webhook",
                  headers={"Authorization": f"Bearer {token}"},
                  json={
                      "type": "REPORT_FINISHED",
                      "url": "https://api.suaempresa.com/gyra/webhook"
                  },
              )
              
              dados = resposta.json()
  /webhook/findBy:
    get:
      operationId: WebhookController_find
      parameters:
        - name: webhookId
          required: false
          in: query
          description: 'ID de um webhook (opcional). Sem este parametro, retorna todos os webhooks da organizacao do token. A resposta e sempre um array.'
          schema:
            example: 664b63037707171ba58cf311
            type: string
      responses:
        '200':
          description: 'Webhook(s) com id, type, url, apiKey e organizationId.'
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
                  additionalProperties: true
                  description: Um webhook de relatorio e credito.
              example:
                - id: 6612a7f344eb43f000000000
                  createdAt: '2026-06-18T23:48:24.706Z'
                  updatedAt: '2026-06-18T23:48:24.706Z'
                  organizationId: 6612a7f3fa9e086b00000000
                  type: REPORT_FINISHED
                  url: 'https://api.suaempresa.com/gyra/webhook'
                  apiKey: null
        '400':
          description: webhookId enviado vazio.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 400
                message: id should not be empty
        '401':
          description: 'Token ausente, expirado ou invalido. Gere outro em POST /auth/authenticate.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 401
                message: Token de acesso inválido.
        '500':
          description: 'Falha nossa. Tente de novo; se persistir, acione o suporte com o horario da chamada.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 500
                message: Internal server error
      tags:
        - webhook
      summary: Consultar webhooks cadastrados
      description: |
          Busca webhooks cadastrados na organizacao.
          
          Se webhookId for informado, retorna o webhook especifico.
          Caso contrario, retorna todos os webhooks da organizacao autenticada.
      x-codeSamples:
        - lang: cURL
          label: cURL
          source: |
              curl --request GET 'https://gyra-core.gyramais.com.br/webhook/findBy' \
                --header 'Authorization: Bearer <token>'
        - lang: JavaScript
          label: Node
          source: |
              const resposta = await fetch("https://gyra-core.gyramais.com.br/webhook/findBy", {
                method: "GET",
                headers: { Authorization: `Bearer ${token}` },
              });
              
              const dados = await resposta.json();
        - lang: Python
          label: Python
          source: |
              import requests
              
              resposta = requests.get(
                  "https://gyra-core.gyramais.com.br/webhook/findBy",
                  headers={"Authorization": f"Bearer {token}"},
              )
              
              dados = resposta.json()
  /webhook/{id}:
    delete:
      operationId: WebhookController_delete
      parameters:
        - name: id
          required: true
          in: path
          description: ID do webhook a remover.
          schema:
            example: 664b63037707171ba58cf311
            type: string
      responses:
        '200':
          description: O webhook removido.
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: string
                  type:
                    type: string
                  url:
                    type: string
                  apiKey:
                    type: string
                    nullable: true
                  organizationId:
                    type: string
                  createdAt:
                    type: string
                    format: date-time
                  updatedAt:
                    type: string
                    format: date-time
              example:
                id: 6612a7f344eb43f000000000
                createdAt: '2026-07-31T18:02:54.965Z'
                updatedAt: '2026-07-31T18:02:54.965Z'
                organizationId: 6612a7f3fa9e086b00000000
                type: REPORT_FINISHED
                url: 'https://api.suaempresa.com/gyra/webhook'
                apiKey: null
        '401':
          description: 'Token ausente, expirado ou invalido. Gere outro em POST /auth/authenticate.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 401
                message: Token de acesso inválido.
        '404':
          description: Webhook inexistente.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 404
                message: An operation failed because it depends on one or more records that were required but not found. Record to delete does not exist.
        '500':
          description: 'Falha nossa. Tente de novo; se persistir, acione o suporte com o horario da chamada.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 500
                message: Internal server error
      tags:
        - webhook
      summary: Deletar webhook
      description: Remove um webhook cadastrado. A URL deixa de receber notificacoes imediatamente.
      x-codeSamples:
        - lang: cURL
          label: cURL
          source: |
              curl --request DELETE 'https://gyra-core.gyramais.com.br/webhook/6612a7f30000000000000001' \
                --header 'Authorization: Bearer <token>'
        - lang: JavaScript
          label: Node
          source: |
              const resposta = await fetch("https://gyra-core.gyramais.com.br/webhook/6612a7f30000000000000001", {
                method: "DELETE",
                headers: { Authorization: `Bearer ${token}` },
              });
              
              const dados = await resposta.json();
        - lang: Python
          label: Python
          source: |
              import requests
              
              resposta = requests.delete(
                  "https://gyra-core.gyramais.com.br/webhook/6612a7f30000000000000001",
                  headers={"Authorization": f"Bearer {token}"},
              )
              
              dados = resposta.json()
  /report/section/{id}:
    get:
      operationId: SectionController_get
      parameters:
        - name: id
          required: true
          in: path
          schema:
            type: string
          description: 'ID da secao (ObjectId). Disponivel no array sections[] do relatorio.'
      responses:
        '200':
          description: 'Secao completa com dados detalhados, status de finalizacao e metadados.'
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
                description: A secao por id. Mesma forma da consulta por tipo.
              example:
                id: 6612a7f3dc5b830500000000
                type:
                  id: 6612a7f3ae223a4700000000
                  value: PROTESTS
                sectionDetails:
                  - values:
                      bureau:
                        protestsQuantity: 15
        '401':
          description: 'Token ausente, expirado ou invalido. Gere outro em POST /auth/authenticate.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 401
                message: Token de acesso inválido.
        '403':
          description: O usuario autenticado nao tem a permissao exigida pela rota.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 403
                message: Você não tem permissão para acessar este recurso.
        '500':
          description: 'Falha nossa. Tente de novo; se persistir, acione o suporte com o horario da chamada.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 500
                message: Internal server error
      tags:
        - report
      security:
        - authorization: []
      summary: Consultar secao por ID
      description: |
          Retorna os dados detalhados de uma secao especifica de um relatorio.
          
          Cada relatorio e composto por varias secoes que contem dados de diferentes fontes:
          - Informacoes basicas (CNPJ/CPF, endereco, socios, QSA)
          - Processos judiciais
          - Protestos em cartorio
          - Dividas Pefin/Refin
          - Dados SCR / Open Finance (Banco Central)
          - PEP e sancoes internacionais
          - Resultado da politica de credito
          
          Use get_report para obter a lista de secoes e seus IDs. Um id que nao
          corresponde a nenhuma secao responde 200 sem corpo.
      x-codeSamples:
        - lang: cURL
          label: cURL
          source: |
              curl --request GET 'https://gyra-core.gyramais.com.br/report/section/6612a7f30000000000000001' \
                --header 'Authorization: Bearer <token>'
        - lang: JavaScript
          label: Node
          source: |
              const resposta = await fetch("https://gyra-core.gyramais.com.br/report/section/6612a7f30000000000000001", {
                method: "GET",
                headers: { Authorization: `Bearer ${token}` },
              });
              
              const dados = await resposta.json();
        - lang: Python
          label: Python
          source: |
              import requests
              
              resposta = requests.get(
                  "https://gyra-core.gyramais.com.br/report/section/6612a7f30000000000000001",
                  headers={"Authorization": f"Bearer {token}"},
              )
              
              dados = resposta.json()
  /report:
    post:
      operationId: ReportController_create
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateReportDto'
            example:
              policyId: 6612a7f3625ea4ab00000000
              document: '11222333000181'
      responses:
        '200':
          description: 'Objeto do relatorio com id, status (PENDING), document, type e createdAt.'
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
                description: O relatorio recem-criado (API v1).
              example:
                id: 6612a7f3a19b467000000000
                document: '43591367000130'
                organizationId: 6612a7f3fa9e086b00000000
                status:
                  id: 6612a7f33fdd7d9400000000
                  value: PENDING
                createdAt: '2026-07-31T13:42:37.059Z'
        '400':
          description: CPF ou CNPJ invalido no corpo.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 400
                message: Você precisa inserir um CNPJ ou CPF válido.
        '401':
          description: 'Token ausente, expirado ou invalido. Gere outro em POST /auth/authenticate.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 401
                message: Token de acesso inválido.
        '403':
          description: O usuario autenticado nao tem a permissao exigida pela rota.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 403
                message: Você não tem permissão para acessar este recurso.
        '500':
          description: 'Falha nossa. Tente de novo; se persistir, acione o suporte com o horario da chamada.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 500
                message: Internal server error
      tags:
        - report
      security:
        - authorization: []
      summary: Criar relatorio (padrao de integracao com webhook)
      description: |
          PADRAO DE INTEGRACAO, use quando voce esta ajudando um desenvolvedor a
          implementar integracao programatica com webhook. Para um usuario apenas
          gerando relatorio no chat, use create_report_and_wait.
          
          Cria um novo relatorio de analise de credito para um CPF ou CNPJ.
          
          O processamento e ASSINCRONO: voce recebe o reportId imediatamente com
          status PENDING. O cliente acompanha o ciclo via:
            1. Webhook configurado (create_webhook), recomendado para integracoes.
            2. Polling em get_report ate reportProgress.isFinalized === true.
          
          Status do relatorio: PENDING ate uma decisao; APPROVED ou REJECTED depois de
          analyze_report. O resultado da politica fica em policyStatus.
          
          O tipo de relatorio (SIMPLES, ESSENCIAL, COMPLETO, COMPLETO+) e determinado
          pela politica de credito (policyId) utilizada.
          
          Use list_policies (ou find_policy_by_name pra fluxo interativo) para obter
          os policyIds disponiveis na organizacao.
      x-codeSamples:
        - lang: cURL
          label: cURL
          source: |
              curl --request POST 'https://gyra-core.gyramais.com.br/report' \
                --header 'Authorization: Bearer <token>' \
                --header 'Content-Type: application/json' \
                --data '{"policyId":"6612a7f3625ea4ab00000000","document":"11222333000181"}'
        - lang: JavaScript
          label: Node
          source: |
              const resposta = await fetch("https://gyra-core.gyramais.com.br/report", {
                method: "POST",
                headers: {
                  Authorization: `Bearer ${token}`,
                  "Content-Type": "application/json",
                },
                body: JSON.stringify({
                  "policyId": "6612a7f3625ea4ab00000000",
                  "document": "11222333000181"
                }),
              });
              
              const dados = await resposta.json();
        - lang: Python
          label: Python
          source: |
              import requests
              
              resposta = requests.post(
                  "https://gyra-core.gyramais.com.br/report",
                  headers={"Authorization": f"Bearer {token}"},
                  json={
                      "policyId": "6612a7f3625ea4ab00000000",
                      "document": "11222333000181"
                  },
              )
              
              dados = resposta.json()
  /report/list:
    get:
      operationId: ReportController_list
      parameters:
        - name: take
          in: query
          required: false
          schema:
            type: integer
          description: Quantidade maxima de registros.
        - name: skip
          in: query
          required: false
          schema:
            type: integer
          description: Offset de paginacao.
        - name: statusValue
          in: query
          required: false
          schema:
            type: string
            enum:
              - PENDING
              - APPROVED
              - REJECTED
          description: 'Status do relatorio, em maiusculas.'
        - name: document
          in: query
          required: false
          schema:
            type: string
          description: 'CPF ou CNPJ sem mascara, com digito verificador valido.'
        - name: userId
          in: query
          required: false
          schema:
            type: string
          description: ID do usuario criador. O valor api-user traz so os relatorios criados pela API.
        - name: createdAtBetween
          in: query
          required: false
          schema:
            type: array
            items:
              type: string
          description: 'Intervalo [startISO, endISO].'
        - name: productIds
          in: query
          required: false
          schema:
            type: array
            items:
              type: string
          description: Filtrar por productIds.
        - name: operationResultId
          in: query
          required: false
          schema:
            type: string
          description: ID do resultado de operacao.
        - name: reportIds
          in: query
          required: false
          schema:
            type: array
            items:
              type: string
          description: IDs especificos de relatorios.
        - name: batchId
          in: query
          required: false
          schema:
            type: string
          description: ID do batch.
      responses:
        '200':
          description: Array de relatorios com metadados (sem secoes detalhadas).
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
                  additionalProperties: true
                  description: Um relatorio da listagem.
              example:
                - id: 6612a7f3fe1b3b8900000000
                  policyId: 6612a7f3625ea4ab00000000
                  policyName: Completo+
                  policyStatus: DENIED
                  name: EMPRESA EXEMPLO LTDA
                  score: 1
                  document: '43591367000130'
                  committeeStatus: null
                  committeeDecision: null
                  createdAt: '2026-07-31T17:47:43.007Z'
                  yearMonthDay: 20260731
                  verified: true
                  exportUrl: 'https://exemplo.gyramais.com.br/arquivo'
                  status:
                    id: 6612a7f3410dcd8100000000
                    title: Não iniciado
                    value: PENDING
                    color: '#FBBB3B'
                  reportProgress:
                    isFinalized: true
                    finalizedAt: '2026-07-31T17:50:11.585Z'
                    elapsedTimeMs: 148578
        '400':
          description: 'statusValue fora de PENDING, APPROVED ou REJECTED, ou document com digito verificador invalido.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 400
                message: Você precisa inserir um status de relatório válido.
        '401':
          description: 'Token ausente, expirado ou invalido. Gere outro em POST /auth/authenticate.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 401
                message: Token de acesso inválido.
        '403':
          description: O usuario autenticado nao tem a permissao exigida pela rota.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 403
                message: Você não tem permissão para acessar este recurso.
        '500':
          description: 'Falha nossa. Tente de novo; se persistir, acione o suporte com o horario da chamada.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 500
                message: Internal server error
      tags:
        - report
      security:
        - authorization: []
      summary: Listar relatorios da organizacao
      description: |
          Lista relatorios com filtros opcionais. Retorna relatorios da organizacao
          autenticada. Analistas de credito veem apenas os proprios relatorios.
          
          Suporta paginacao (take/skip) e filtros por status, documento, usuario, periodo,
          produtos, operacao, batch.
      x-codeSamples:
        - lang: cURL
          label: cURL
          source: |
              curl --request GET 'https://gyra-core.gyramais.com.br/report/list' \
                --header 'Authorization: Bearer <token>'
        - lang: JavaScript
          label: Node
          source: |
              const resposta = await fetch("https://gyra-core.gyramais.com.br/report/list", {
                method: "GET",
                headers: { Authorization: `Bearer ${token}` },
              });
              
              const dados = await resposta.json();
        - lang: Python
          label: Python
          source: |
              import requests
              
              resposta = requests.get(
                  "https://gyra-core.gyramais.com.br/report/list",
                  headers={"Authorization": f"Bearer {token}"},
              )
              
              dados = resposta.json()
  /report/count:
    get:
      operationId: ReportController_count
      parameters:
        - name: statusValue
          in: query
          required: false
          schema:
            type: string
            enum:
              - PENDING
              - APPROVED
              - REJECTED
          description: 'Status do relatorio, em maiusculas.'
        - name: document
          in: query
          required: false
          schema:
            type: string
          description: 'CPF ou CNPJ sem mascara, com digito verificador valido.'
        - name: userId
          in: query
          required: false
          schema:
            type: string
          description: ID do usuario criador. O valor api-user traz so os relatorios criados pela API.
        - name: createdAtBetween
          in: query
          required: false
          schema:
            type: array
            items:
              type: string
          description: 'Intervalo [startISO, endISO].'
        - name: productIds
          in: query
          required: false
          schema:
            type: array
            items:
              type: string
          description: Filtrar por productIds.
        - name: operationResultId
          in: query
          required: false
          schema:
            type: string
          description: ID do resultado de operacao.
        - name: batchId
          in: query
          required: false
          schema:
            type: string
          description: ID do batch.
      responses:
        '200':
          description: Numero de relatorios que atendem aos filtros (o corpo e o proprio numero).
          content:
            application/json:
              schema:
                type: integer
              example: 128
        '400':
          description: 'statusValue fora de PENDING, APPROVED ou REJECTED, ou document com digito verificador invalido.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 400
                message: Você precisa inserir um status de relatório válido.
        '401':
          description: 'Token ausente, expirado ou invalido. Gere outro em POST /auth/authenticate.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 401
                message: Token de acesso inválido.
        '403':
          description: O usuario autenticado nao tem a permissao exigida pela rota.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 403
                message: Você não tem permissão para acessar este recurso.
        '500':
          description: 'Falha nossa. Tente de novo; se persistir, acione o suporte com o horario da chamada.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 500
                message: Internal server error
      tags:
        - report
      security:
        - authorization: []
      summary: Contar relatorios
      description: |
          Retorna a contagem de relatorios que correspondem aos filtros aplicados.
          Util para dashboards e analytics sem carregar os dados completos. Aceita os mesmos
          filtros de list_reports.
      x-codeSamples:
        - lang: cURL
          label: cURL
          source: |
              curl --request GET 'https://gyra-core.gyramais.com.br/report/count' \
                --header 'Authorization: Bearer <token>'
        - lang: JavaScript
          label: Node
          source: |
              const resposta = await fetch("https://gyra-core.gyramais.com.br/report/count", {
                method: "GET",
                headers: { Authorization: `Bearer ${token}` },
              });
              
              const dados = await resposta.json();
        - lang: Python
          label: Python
          source: |
              import requests
              
              resposta = requests.get(
                  "https://gyra-core.gyramais.com.br/report/count",
                  headers={"Authorization": f"Bearer {token}"},
              )
              
              dados = resposta.json()
  /report/export/{id}:
    get:
      operationId: ReportController_export
      parameters:
        - name: id
          required: true
          in: path
          schema:
            type: string
          description: ID do relatorio a exportar.
        - name: type
          required: true
          in: query
          schema:
            type: string
            enum:
              - REPORT
              - REPORT_MINIFIED
          description: 'Obrigatorio. Use REPORT. Sem ele, a resposta e 400.'
        - name: exportFormat
          required: false
          in: query
          schema:
            type: string
            enum:
              - pdf
              - excel
              - both
          description: 'pdf (padrao), excel ou both. Com both saem dois arquivos e dois webhooks.'
        - name: sectionOrder
          required: false
          in: query
          schema:
            type: array
            items:
              type: string
          description: 'Secoes do arquivo, na ordem desejada. Repita o parametro para cada secao. Sem ele, valem as secoes e a ordem do modelo.'
        - name: templateId
          required: false
          in: query
          schema:
            type: string
          description: ID de um modelo de exportacao da organizacao.
        - name: systemTemplate
          required: false
          in: query
          schema:
            type: string
            enum:
              - COMPLETE
              - COMPACT
          description: Modelo nativo de exportacao.
      responses:
        '202':
          description: 'Objeto { status: "processing", reportId }. O arquivo chega pelo webhook REPORT_EXPORTED.'
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    description: 'processing: o arquivo chega pelo webhook REPORT_EXPORTED.'
                  reportId:
                    type: string
              example:
                status: processing
                reportId: 6612a7f3a19b467000000000
        '400':
          description: 'Parametro type ausente ou invalido, ou exportFormat fora de pdf, excel, both.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 400
                message: 'type must be one of the following values: REPORT, REPORT_MINIFIED,type should not be empty'
        '401':
          description: 'Token ausente, expirado ou invalido. Gere outro em POST /auth/authenticate.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 401
                message: Token de acesso inválido.
        '403':
          description: O usuario autenticado nao tem a permissao exigida pela rota.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 403
                message: Você não tem permissão para acessar este recurso.
        '500':
          description: 'Falha nossa. Tente de novo; se persistir, acione o suporte com o horario da chamada.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 500
                message: Internal server error
      tags:
        - report
      security:
        - authorization: []
      summary: Exportar relatorio em PDF/Excel via webhook (padrao de integracao)
      description: |
          PADRAO DE INTEGRACAO, use quando voce esta ajudando um desenvolvedor a
          implementar integracao programatica com o Gyra+. Para um usuario apenas exportando
          no chat, use export_report_and_wait.
          
          Solicita a geracao de PDF/Excel de um relatorio. Processamento assincrono:
          retorna imediatamente com { status: "processing", reportId } e o arquivo e
          entregue via webhook configurado pelo cliente (create_webhook).
          
          Use quando:
          - O cliente ja tem (ou esta implementando) um endpoint pra receber webhook.
          - Precisa processar muitos relatorios em lote.
          - Latencia nao e critica e o webhook fecha o ciclo.
          
          Para fluxo interativo de agente (sem webhook), prefira export_report_and_wait.
          Para chamada bloqueante direta (cliente HTTP suporta long timeout), use
          export_report_sync.
      x-codeSamples:
        - lang: cURL
          label: cURL
          source: |
              curl --request GET 'https://gyra-core.gyramais.com.br/report/export/6612a7f30000000000000001?type=REPORT' \
                --header 'Authorization: Bearer <token>'
        - lang: JavaScript
          label: Node
          source: |
              const resposta = await fetch("https://gyra-core.gyramais.com.br/report/export/6612a7f30000000000000001?type=REPORT", {
                method: "GET",
                headers: { Authorization: `Bearer ${token}` },
              });
              
              const dados = await resposta.json();
        - lang: Python
          label: Python
          source: |
              import requests
              
              resposta = requests.get(
                  "https://gyra-core.gyramais.com.br/report/export/6612a7f30000000000000001?type=REPORT",
                  headers={"Authorization": f"Bearer {token}"},
              )
              
              dados = resposta.json()
  /report/export-sync/{id}:
    get:
      operationId: ReportController_exportSync
      parameters:
        - name: id
          required: true
          in: path
          schema:
            type: string
          description: ID do relatorio a exportar.
        - name: type
          required: true
          in: query
          schema:
            type: string
            enum:
              - REPORT
              - REPORT_MINIFIED
          description: 'Obrigatorio. Use REPORT. Sem ele, a resposta e 400.'
        - name: exportFormat
          required: false
          in: query
          schema:
            type: string
            enum:
              - pdf
              - excel
              - both
          description: 'pdf (padrao) ou excel. both nao e suportado nesta rota: use a exportacao assincrona.'
        - name: sectionOrder
          required: false
          in: query
          schema:
            type: array
            items:
              type: string
          description: 'Secoes do arquivo, na ordem desejada. Repita o parametro para cada secao. Sem ele, valem as secoes e a ordem do modelo.'
        - name: templateId
          required: false
          in: query
          schema:
            type: string
          description: ID de um modelo de exportacao da organizacao.
        - name: systemTemplate
          required: false
          in: query
          schema:
            type: string
            enum:
              - COMPLETE
              - COMPACT
          description: Modelo nativo de exportacao.
      responses:
        '202':
          description: 'Registro da exportacao, com o arquivo ja pronto. O link esta em url.'
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: string
                  url:
                    type: string
                    description: Link do arquivo gerado.
                  payload:
                    type: object
                    properties:
                      reportId:
                        type: string
                      type:
                        type: string
                        description: 'PDFMAKE para PDF, EXCEL para Excel.'
                      generatedAt:
                        type: string
                        format: date-time
                  userId:
                    type: string
                  organizationId:
                    type: string
                  typeId:
                    type: string
                  createdAt:
                    type: string
                    format: date-time
                  updatedAt:
                    type: string
                    format: date-time
              example:
                id: 6612a7f32b77480800000000
                createdAt: '2026-07-31T18:03:37.465Z'
                updatedAt: '2026-07-31T18:03:37.465Z'
                userId: 6612a7f3615ff3f200000000
                organizationId: 6612a7f3fa9e086b00000000
                typeId: 6612a7f371f08b3400000000
                url: 'https://exemplo.gyramais.com.br/relatorio.pdf'
                payload:
                  reportId: 6612a7f3a19b467000000000
                  type: PDFMAKE
                  generatedAt: '2026-07-31T18:03:37.464Z'
        '400':
          description: 'Parametro type ausente ou invalido, ou exportFormat fora de pdf, excel, both.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 400
                message: 'type must be one of the following values: REPORT, REPORT_MINIFIED,type should not be empty'
        '401':
          description: 'Token ausente, expirado ou invalido. Gere outro em POST /auth/authenticate.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 401
                message: Token de acesso inválido.
        '403':
          description: O usuario autenticado nao tem a permissao exigida pela rota.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 403
                message: Você não tem permissão para acessar este recurso.
        '500':
          description: 'Falha nossa. Tente de novo; se persistir, acione o suporte com o horario da chamada.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 500
                message: Internal server error
      tags:
        - report
      security:
        - authorization: []
      summary: Exportar relatorio bloqueante (padrao de integracao)
      description: |
          PADRAO DE INTEGRACAO, use quando voce esta ajudando um desenvolvedor a
          implementar integracao com cliente HTTP que suporta timeout longo (>= 6 min).
          Para um usuario apenas exportando no chat, use export_report_and_wait.
          
          O endpoint BLOQUEIA ate a geracao concluir e responde 202 com o registro da
          exportacao (link em url). Use timeout longo no cliente HTTP.
          
          Para fluxo interativo de agente, prefira export_report_and_wait (timeout
          previsivel de 2min, com aviso quando relatorio nao esta finalizado).
          Para integracao com webhook, use export_report_via_webhook.
      x-codeSamples:
        - lang: cURL
          label: cURL
          source: |
              curl --request GET 'https://gyra-core.gyramais.com.br/report/export-sync/6612a7f30000000000000001?type=REPORT' \
                --header 'Authorization: Bearer <token>'
        - lang: JavaScript
          label: Node
          source: |
              const resposta = await fetch("https://gyra-core.gyramais.com.br/report/export-sync/6612a7f30000000000000001?type=REPORT", {
                method: "GET",
                headers: { Authorization: `Bearer ${token}` },
              });
              
              const dados = await resposta.json();
        - lang: Python
          label: Python
          source: |
              import requests
              
              resposta = requests.get(
                  "https://gyra-core.gyramais.com.br/report/export-sync/6612a7f30000000000000001?type=REPORT",
                  headers={"Authorization": f"Bearer {token}"},
              )
              
              dados = resposta.json()
  /report/{id}:
    get:
      operationId: ReportController_get
      parameters:
        - name: id
          required: true
          in: path
          schema:
            type: string
          description: ID do relatorio (ObjectId). Retornado pelo create_report.
        - name: details
          required: false
          in: query
          description: Defina como "false" para omitir detalhes das secoes. Util para verificar status rapidamente.
          schema:
            type: string
      responses:
        '200':
          description: 'Relatorio completo com secoes, decisao e metadados.'
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
                description: O relatorio. Com `details=true` vem tambem o conteudo das secoes; o dicionario esta em /data/estrutura-relatorio.
              example:
                id: 6612a7f3a19b467000000000
                document: '43591367000130'
                name: EMPRESA EXEMPLO LTDA
                score: 1
                policyStatus: DENIED
                status:
                  id: 6612a7f3410dcd8100000000
                  title: Não iniciado
                  value: PENDING
                  color: '#FBBB3B'
                reportProgress:
                  isFinalized: true
                  finalizedAt: '2026-07-31T17:50:11.585Z'
                  elapsedTimeMs: 148578
                createdAt: '2026-07-31T17:47:43.007Z'
        '401':
          description: 'Token ausente, expirado ou invalido. Gere outro em POST /auth/authenticate.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 401
                message: Token de acesso inválido.
        '403':
          description: O usuario autenticado nao tem a permissao exigida pela rota.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 403
                message: Você não tem permissão para acessar este recurso.
        '500':
          description: 'Falha nossa. Tente de novo; se persistir, acione o suporte com o horario da chamada.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 500
                message: Internal server error
      tags:
        - report
      security:
        - authorization: []
      summary: Consultar relatorio por ID
      description: |
          Retorna o relatorio com secoes, decisao e metadados.
          
          status.value e PENDING ate uma decisao, e APPROVED ou REJECTED depois. O
          resultado da politica fica em policyStatus; a decisao manual, em analystName e
          commentary.
          
          Com credencial de API, a resposta tem a mesma forma de GET /v2/report/{id} e os
          parametros details e tabType sao ignorados. Para integracoes novas, use
          GET /v2/report/{id}.
      x-codeSamples:
        - lang: cURL
          label: cURL
          source: |
              curl --request GET 'https://gyra-core.gyramais.com.br/report/6612a7f30000000000000001' \
                --header 'Authorization: Bearer <token>'
        - lang: JavaScript
          label: Node
          source: |
              const resposta = await fetch("https://gyra-core.gyramais.com.br/report/6612a7f30000000000000001", {
                method: "GET",
                headers: { Authorization: `Bearer ${token}` },
              });
              
              const dados = await resposta.json();
        - lang: Python
          label: Python
          source: |
              import requests
              
              resposta = requests.get(
                  "https://gyra-core.gyramais.com.br/report/6612a7f30000000000000001",
                  headers={"Authorization": f"Bearer {token}"},
              )
              
              dados = resposta.json()
  /report/{id}/section/{sectionType}:
    get:
      operationId: ReportController_getReportSection
      parameters:
        - name: id
          required: true
          in: path
          schema:
            type: string
          description: ID do relatorio.
        - name: sectionType
          required: true
          in: path
          schema:
            type: string
          description: 'Tipo da secao (ex: BASIC_INFORMATION, PROCESSES, SCR, CREDIT_POLICY).'
      responses:
        '200':
          description: Secao com dados detalhados do tipo solicitado.
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
                description: 'A secao pedida. Os campos de `sectionDetails[].values` mudam por tipo de secao; o dicionario esta em /data/estrutura-relatorio.'
              example:
                id: 6612a7f3dc5b830500000000
                report:
                  id: 6612a7f3a19b467000000000
                  organizationId: 6612a7f3fa9e086b00000000
                type:
                  id: 6612a7f3ae223a4700000000
                  value: PROTESTS
                  tabs:
                    - type: RESTRICTIVE
                      order: 5
                      side: null
                createdAt: '2026-07-31T13:42:37.059Z'
                updatedAt: '2026-07-31T13:43:12.180Z'
                sectionDetails:
                  - values:
                      bureau:
                        injunction: false
                        protestsQuantity: 15
                        protestsTotalValue: 'R$ 102.390,05'
        '401':
          description: 'Token ausente, expirado ou invalido. Gere outro em POST /auth/authenticate.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 401
                message: Token de acesso inválido.
        '403':
          description: O usuario autenticado nao tem a permissao exigida pela rota.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 403
                message: Você não tem permissão para acessar este recurso.
        '500':
          description: 'Falha nossa. Tente de novo; se persistir, acione o suporte com o horario da chamada.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 500
                message: Internal server error
      tags:
        - report
      security:
        - authorization: []
      summary: Consultar secao especifica do relatorio
      description: |
          Retorna uma secao de um relatorio pelo tipo (sectionType, em maiusculas).
          
          Exemplos de tipo: BASIC_INFORMATION, LOCATION, RELATIONS, SCORE, PROCESSES,
          PROTESTS, PEFIN, REFIN, SCR, SCR_SUMMARY, PEP, SANCTIONS, BALANCE_SHEET, DRE,
          FINANCIAL_INDICATORS, FINANCIAL_INSIGHTS, CREDIT_POLICY, PRICING. Lista completa
          em /api-reference/report/get-report-section.
          
          404 "Tipo de seção não encontrado" para tipo invalido, 404 "Seção não encontrada"
          quando o relatorio nao tem a secao, 404 "Relatório não encontrado" para relatorio
          inexistente ou de outra organizacao.
      x-codeSamples:
        - lang: cURL
          label: cURL
          source: |
              curl --request GET 'https://gyra-core.gyramais.com.br/report/6612a7f30000000000000001/section/PROTESTS' \
                --header 'Authorization: Bearer <token>'
        - lang: JavaScript
          label: Node
          source: |
              const resposta = await fetch("https://gyra-core.gyramais.com.br/report/6612a7f30000000000000001/section/PROTESTS", {
                method: "GET",
                headers: { Authorization: `Bearer ${token}` },
              });
              
              const dados = await resposta.json();
        - lang: Python
          label: Python
          source: |
              import requests
              
              resposta = requests.get(
                  "https://gyra-core.gyramais.com.br/report/6612a7f30000000000000001/section/PROTESTS",
                  headers={"Authorization": f"Bearer {token}"},
              )
              
              dados = resposta.json()
  /report/{id}/insights:
    get:
      operationId: ReportController_getReportInsights
      parameters:
        - name: id
          required: true
          in: path
          schema:
            type: string
          description: ID do relatorio.
        - name: section
          in: query
          required: false
          schema:
            type: string
          description: 'Filtra o parecer de UMA secao (ex: PROCESSES, SCR, PEFIN). Sem o parametro, retorna todos os pareceres concluidos. Tipo de secao invalido responde 400; secao sem parecer responde insights vazio.'
      responses:
        '200':
          description: 'Envelope com reportId, document, committee { status, decision, result, at } e insights[] (parecer por secao).'
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
                description: Pareceres por secao e o resumo da decisao do comite. A leitura completa esta em /concepts/pareceres-gyra-ia.
              example:
                reportId: 6612a7f3a19b467000000000
                document: '43591367000130'
                committee:
                  status: DONE
                  decision: REJECTED
                  result:
                    decision: REJECTED
                    synthesis:
                      decision: REJECTED
                      resumo: 'Comitê confirma negativa da política: CNPJ suspenso e passivos relevantes inviabilizam a concessão.'
                      proximaAcao: Arquivar o processo e não retomar sem regularização cadastral comprovada.
                      confidence: 0.97
                      conditions: []
                      alcadaLevel: null
                  at: '2026-07-31T13:46:02.511Z'
                insights:
                  - section: PROTESTS
                    score: 40
                    riskLevel: HIGH
                    parecer: 'A empresa tem dois protestos recentes em São Paulo, somando R$ 5.850,33...'
                    highlights:
                      - severity: warning
                        label: Protestos nos últimos 90 dias
                    at: '2026-07-31T13:44:10.204Z'
        '400':
          description: Valor de section fora da lista de tipos de secao.
        '401':
          description: 'Token ausente, expirado ou invalido. Gere outro em POST /auth/authenticate.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 401
                message: Token de acesso inválido.
        '403':
          description: O usuario autenticado nao tem a permissao exigida pela rota.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 403
                message: Você não tem permissão para acessar este recurso.
        '404':
          description: Relatorio nao encontrado ou de outra organizacao.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 404
                message: Relatório não encontrado.
        '500':
          description: 'Falha nossa. Tente de novo; se persistir, acione o suporte com o horario da chamada.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 500
                message: Internal server error
      tags:
        - report
      security:
        - authorization: []
      summary: Consultar pareceres do relatorio
      description: |
          Leitura enxuta do relatorio: apenas os pareceres de IA por secao (texto, score,
          nivel de risco e destaques) e o resumo da deliberacao do comite. Nao traz os
          payloads pesados de integracao.
          
          Pensado para consumo barato por agentes de IA e para telas de resumo executivo.
          Tambem serve para verificar se os pareceres ja terminaram antes de convocar o
          comite com POST /report/{id}/committee.
          
          Só entram no array insights[] as secoes com parecer concluido. Relatorio ainda em
          processamento devolve insights vazio ou parcial e committee.status null.
      x-codeSamples:
        - lang: cURL
          label: cURL
          source: |
              curl --request GET 'https://gyra-core.gyramais.com.br/report/6612a7f30000000000000001/insights' \
                --header 'Authorization: Bearer <token>'
        - lang: JavaScript
          label: Node
          source: |
              const resposta = await fetch("https://gyra-core.gyramais.com.br/report/6612a7f30000000000000001/insights", {
                method: "GET",
                headers: { Authorization: `Bearer ${token}` },
              });
              
              const dados = await resposta.json();
        - lang: Python
          label: Python
          source: |
              import requests
              
              resposta = requests.get(
                  "https://gyra-core.gyramais.com.br/report/6612a7f30000000000000001/insights",
                  headers={"Authorization": f"Bearer {token}"},
              )
              
              dados = resposta.json()
  /report/analyze:
    post:
      operationId: ReportController_analyze
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                id:
                  type: string
                  description: ID do relatorio a analisar.
                approved:
                  type: boolean
                  description: 'true para aprovar, false para negar.'
                commentary:
                  type: string
                  description: Comentario do analista (opcional).
              required:
                - id
                - approved
            example:
              id: 6612a7f3a19b467000000000
              approved: true
              commentary: Aprovado após análise manual.
      responses:
        '200':
          description: Relatorio atualizado com a analise registrada.
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
                description: O relatorio com a decisao manual registrada.
              example:
                id: 6612a7f3a19b467000000000
                organizationId: 6612a7f3fa9e086b00000000
                policyId: 6612a7f3625ea4ab00000000
                analystId: 6612a7f3615ff3f200000000
                analystName: Usuário API
                commentary: Aprovado após análise manual.
                policyStatus: APPROVED
                operationResultId: null
                document: '11222333000181'
                status:
                  id: 6612a7f33fdd7d9400000000
                  title: Aprovado
                  value: APPROVED
                  color: '#74DA42'
        '400':
          description: 'Corpo sem id ou approved, ou relatorio ja decidido (use POST /report/re-analyze).'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 400
                message: O relatório já foi analisado.
        '401':
          description: 'Token ausente, expirado ou invalido. Gere outro em POST /auth/authenticate.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 401
                message: Token de acesso inválido.
        '403':
          description: O usuario autenticado nao tem a permissao exigida pela rota.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 403
                message: Você não tem permissão para acessar este recurso.
        '404':
          description: Relatorio inexistente.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 404
                message: O relatório não foi encontrado.
        '500':
          description: 'Falha nossa. Tente de novo; se persistir, acione o suporte com o horario da chamada.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 500
                message: Internal server error
      tags:
        - report
      security:
        - authorization: []
      summary: Analisar/aprovar relatorio
      description: |
          Registra a decisao manual de um relatorio PENDING: approved true vira APPROVED,
          false vira REJECTED. commentary e opcional. Vale uma vez por relatorio: num
          relatorio ja decidido a resposta e 400 "O relatório já foi analisado." (use
          re-analyze). Com credencial de API, a decisao fica assinada como "Usuário API".
          Dispara o webhook REPORT_STATUS.
      x-codeSamples:
        - lang: cURL
          label: cURL
          source: |
              curl --request POST 'https://gyra-core.gyramais.com.br/report/analyze' \
                --header 'Authorization: Bearer <token>' \
                --header 'Content-Type: application/json' \
                --data '{"id":"6612a7f3a19b467000000000","approved":true,"commentary":"Aprovado após análise manual."}'
        - lang: JavaScript
          label: Node
          source: |
              const resposta = await fetch("https://gyra-core.gyramais.com.br/report/analyze", {
                method: "POST",
                headers: {
                  Authorization: `Bearer ${token}`,
                  "Content-Type": "application/json",
                },
                body: JSON.stringify({
                  "id": "6612a7f3a19b467000000000",
                  "approved": true,
                  "commentary": "Aprovado após análise manual."
                }),
              });
              
              const dados = await resposta.json();
        - lang: Python
          label: Python
          source: |
              import requests
              
              resposta = requests.post(
                  "https://gyra-core.gyramais.com.br/report/analyze",
                  headers={"Authorization": f"Bearer {token}"},
                  json={
                      "id": "6612a7f3a19b467000000000",
                      "approved": True,
                      "commentary": "Aprovado após análise manual."
                  },
              )
              
              dados = resposta.json()
  /report/re-analyze:
    post:
      operationId: ReportController_reAnalyze
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                id:
                  type: string
                  description: ID do relatorio a re-analisar.
                approved:
                  type: boolean
                  description: 'Nova decisao: true aprova, false reprova.'
              required:
                - id
                - approved
            example:
              id: 6612a7f3a19b467000000000
              approved: false
      responses:
        '200':
          description: Relatorio atualizado com a nova analise.
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
                description: O relatorio com a decisao manual substituida.
              example:
                id: 6612a7f3a19b467000000000
                organizationId: 6612a7f3fa9e086b00000000
                policyId: 6612a7f3625ea4ab00000000
                analystId: 6612a7f3b4c5d6e700000000
                analystName: Maria Souza
                commentary: Aprovado após análise manual.
                previousAnalystId: 6612a7f3615ff3f200000000
                previousAnalystName: Usuário API
                status:
                  id: 6612a7f3410dcd8100000002
                  value: REJECTED
                previousStatus:
                  id: 6612a7f33fdd7d9400000000
                  title: Aprovado
                  value: APPROVED
                  color: '#74DA42'
                analyzedAt: '2026-08-01T10:12:40.110Z'
                previousAnalyzedAt: '2026-07-31T18:20:02.004Z'
        '400':
          description: Corpo sem id ou approved.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 400
                message: 'id should not be empty,id must be a string,approved should not be empty,approved must be a boolean value'
        '401':
          description: 'Token ausente, expirado ou invalido. Gere outro em POST /auth/authenticate.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 401
                message: Token de acesso inválido.
        '403':
          description: O usuario autenticado nao tem a permissao exigida pela rota.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 403
                message: Você não tem permissão para acessar este recurso.
        '500':
          description: 'Falha nossa. Tente de novo; se persistir, acione o suporte com o horario da chamada.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 500
                message: Internal server error
      tags:
        - report
      security:
        - authorization: []
      summary: Re-analisar relatorio
      description: |
          Troca a decisao de um relatorio e guarda a anterior em previousStatus,
          previousAnalystId, previousAnalystName e previousAnalyzedAt. So refaz quem esta
          na lista de quem pode editar relatorios da politica (por usuario ou papel); fora
          dela a resposta e 401 "Você não tem permissão para reanalisar esse relatório.".
          O campo commentary nao e alterado nesta rota.
          
          Util quando dados adicionais foram obtidos ou a decisao precisa ser revisada.
      x-codeSamples:
        - lang: cURL
          label: cURL
          source: |
              curl --request POST 'https://gyra-core.gyramais.com.br/report/re-analyze' \
                --header 'Authorization: Bearer <token>' \
                --header 'Content-Type: application/json' \
                --data '{"id":"6612a7f3a19b467000000000","approved":false}'
        - lang: JavaScript
          label: Node
          source: |
              const resposta = await fetch("https://gyra-core.gyramais.com.br/report/re-analyze", {
                method: "POST",
                headers: {
                  Authorization: `Bearer ${token}`,
                  "Content-Type": "application/json",
                },
                body: JSON.stringify({
                  "id": "6612a7f3a19b467000000000",
                  "approved": false
                }),
              });
              
              const dados = await resposta.json();
        - lang: Python
          label: Python
          source: |
              import requests
              
              resposta = requests.post(
                  "https://gyra-core.gyramais.com.br/report/re-analyze",
                  headers={"Authorization": f"Bearer {token}"},
                  json={
                      "id": "6612a7f3a19b467000000000",
                      "approved": False
                  },
              )
              
              dados = resposta.json()
  /credit-policy/policy:
    get:
      operationId: PolicyController_find
      parameters:
        - name: percentages
          required: false
          in: query
          description: 'true acrescenta percentages, a distribuicao dos resultados de cada politica.'
          schema:
            type: string
            enum:
              - 'true'
              - 'false'
        - name: enabled
          required: false
          in: query
          description: 'true traz so as politicas habilitadas para a organizacao; false, so as desabilitadas.'
          schema:
            type: string
            enum:
              - 'true'
              - 'false'
        - name: protected
          required: false
          in: query
          description: 'true inclui tambem as politicas protegidas, que nao pertencem a organizacao.'
          schema:
            type: string
            enum:
              - 'true'
              - 'false'
        - name: usage
          required: false
          in: query
          description: 'REPORT (roda sozinha, inclusive em POST /v2/report) ou PIPELINE (so roda dentro de esteira).'
          schema:
            type: string
            enum:
              - REPORT
              - PIPELINE
        - name: includeUser
          required: false
          in: query
          description: 'true acrescenta user, com quem criou a politica.'
          schema:
            type: string
            enum:
              - 'true'
              - 'false'
      responses:
        '200':
          description: 'Array de politicas com id, name, enabled, documentType, grupos de regras e configuracoes.'
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
                  properties:
                    id:
                      type: string
                    name:
                      type: string
                    reportType:
                      type: string
                    documentType:
                      type: string
                      enum:
                        - CNPJ
                        - CPF
                    bureauType:
                      type: string
                    hasSCR:
                      type: boolean
                    balanceRuleEnabled:
                      type: boolean
                    enabled:
                      type: boolean
                      description: Politica desabilitada nao pode ser executada.
                    usage:
                      type: string
                      enum:
                        - REPORT
                        - PIPELINE
                      description: So REPORT roda em POST /v2/report.
                    kind:
                      type: string
                      enum:
                        - BASE
                        - LAYER
                    version:
                      type: number
                    parecerEnabled:
                      type: boolean
                    integrationGroup:
                      type: object
                      nullable: true
                      additionalProperties: true
                    organizationId:
                      type: string
                    createdAt:
                      type: string
                      format: date-time
              example:
                - id: 6612a7f3625ea4ab00000000
                  name: Crédito PJ Completo+
                  kind: BASE
                  usage: REPORT
                  reportType: CUSTOMER_GYRA_360_PLUS
                  documentType: CNPJ
                  bureauType: BOAVISTA
                  hasSCR: true
                  balanceRuleEnabled: false
                  version: 3
                  enabled: true
                  parecerEnabled: true
                  integrationGroup:
                    id: 6612a7f3ae25b13000000000
                    documentType: CNPJ
                    label: Completo+
                    name: CUSTOMER_GYRA_360_PLUS
                    hasParecer: true
                  organizationId: 6612a7f3fa9e086b00000000
                  createdAt: '2026-05-12T14:03:51.896Z'
        '400':
          description: usage fora de REPORT ou PIPELINE.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 400
                message: 'usage must be one of the following values: REPORT, PIPELINE'
        '401':
          description: 'Token ausente, expirado ou invalido. Gere outro em POST /auth/authenticate.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 401
                message: Token de acesso inválido.
        '403':
          description: O usuario autenticado nao tem a permissao exigida pela rota.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 403
                message: Você não tem permissão para acessar este recurso.
        '500':
          description: 'Falha nossa. Tente de novo; se persistir, acione o suporte com o horario da chamada.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 500
                message: Internal server error
      tags:
        - credit-policy/policy
      security:
        - authorization: []
      summary: Listar politicas de credito
      description: |
          Lista as politicas de credito da organizacao.
          
          Cada politica define:
          - Quais fontes de dados consultar (bureau de credito, SCR/Open Finance, etc.)
          - Regras de aprovacao automatica (score, limites, restricoes)
          - Tipo de relatorio gerado (SIMPLES, ESSENCIAL, COMPLETO, COMPLETO+)
          - Grupos de regras com pesos e thresholds
          
          O policyId retornado e necessario para criar relatorios (create_report). Para
          a API, use uma politica com enabled true e usage REPORT.
          
          Filtros opcionais (valores como string):
          - enabled: true para ver apenas politicas habilitadas
          - usage: REPORT ou PIPELINE
          - protected: true para incluir politicas protegidas
      x-codeSamples:
        - lang: cURL
          label: cURL
          source: |
              curl --request GET 'https://gyra-core.gyramais.com.br/credit-policy/policy' \
                --header 'Authorization: Bearer <token>'
        - lang: JavaScript
          label: Node
          source: |
              const resposta = await fetch("https://gyra-core.gyramais.com.br/credit-policy/policy", {
                method: "GET",
                headers: { Authorization: `Bearer ${token}` },
              });
              
              const dados = await resposta.json();
        - lang: Python
          label: Python
          source: |
              import requests
              
              resposta = requests.get(
                  "https://gyra-core.gyramais.com.br/credit-policy/policy",
                  headers={"Authorization": f"Bearer {token}"},
              )
              
              dados = resposta.json()
  /v2/report:
    post:
      operationId: ReportApiController_create
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateReportDto'
            example:
              document: '11222333000181'
              policyId: 6612a7f3625ea4ab00000000
      responses:
        '200':
          description: Sucesso.
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
                description: 'O relatorio criado. O processamento e assincrono: acompanhe pelo webhook REPORT_FINISHED ou por GET /v2/report/{id}. Mesmo documento, politica, versao e dia devolvem o mesmo relatorio.'
              example:
                reportProgress:
                  steps:
                    - event: REPORT_CHECKING
                      message: Report sent to check the document.
                id: 6612a7f3a19b467000000000
                createdAt: '2026-07-31T13:42:37.059Z'
                updatedAt: '2026-07-31T13:42:37.059Z'
                document: '11222333000181'
                organizationId: 6612a7f3fa9e086b00000000
                customerId: 6612a7f388be48e900000000
                months: 12
                policyVersion: 3
                verified: false
                operationId: null
                operationResultId: null
                status:
                  id: 6612a7f3410dcd8100000000
                  value: PENDING
        '400':
          description: 'Corpo invalido: document com digito verificador invalido, policyId ausente, politica nao habilitada ou politica de esteira.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 400
                message: Você precisa inserir um CNPJ ou CPF válido.
        '401':
          description: 'Token ausente, expirado ou invalido. Gere outro em POST /auth/authenticate.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 401
                message: Token de acesso inválido.
        '403':
          description: O usuario autenticado nao tem a permissao exigida pela rota.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 403
                message: Você não tem permissão para acessar este recurso.
        '500':
          description: 'Falha nossa. Tente de novo; se persistir, acione o suporte com o horario da chamada.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 500
                message: Internal server error
      tags:
        - report
      security:
        - authorization: []
      summary: Criar relatorio (API v2)
      description: |
          Cria a analise de um CPF ou CNPJ com a politica informada. Use para novas
          integracoes. Corpo: document (obrigatorio, digito verificador validado),
          policyId (obrigatorio, politica habilitada e de usage REPORT) e months (opcional).
          O campo type e ignorado: o tipo vem da politica.
          
          Mesmo documento, politica, versao da politica e dia: devolve o relatorio que ja
          existe (decidido, sem reprocessar; PENDING, com a coleta disparada de novo).
          
          Erros: 400 politica ausente, nao habilitada ou de esteira; 422 documento de tipo
          diferente do da politica; 503 com reportId quando o relatorio foi criado mas a
          analise nao foi enfileirada.
      x-codeSamples:
        - lang: cURL
          label: cURL
          source: |
              curl --request POST 'https://gyra-core.gyramais.com.br/v2/report' \
                --header 'Authorization: Bearer <token>' \
                --header 'Content-Type: application/json' \
                --data '{"document":"11222333000181","policyId":"6612a7f3625ea4ab00000000"}'
        - lang: JavaScript
          label: Node
          source: |
              const resposta = await fetch("https://gyra-core.gyramais.com.br/v2/report", {
                method: "POST",
                headers: {
                  Authorization: `Bearer ${token}`,
                  "Content-Type": "application/json",
                },
                body: JSON.stringify({
                  "document": "11222333000181",
                  "policyId": "6612a7f3625ea4ab00000000"
                }),
              });
              
              const dados = await resposta.json();
        - lang: Python
          label: Python
          source: |
              import requests
              
              resposta = requests.post(
                  "https://gyra-core.gyramais.com.br/v2/report",
                  headers={"Authorization": f"Bearer {token}"},
                  json={
                      "document": "11222333000181",
                      "policyId": "6612a7f3625ea4ab00000000"
                  },
              )
              
              dados = resposta.json()
  /v2/report/{id}:
    get:
      operationId: ReportApiController_get
      parameters:
        - name: id
          required: true
          in: path
          schema:
            type: string
          description: ID do relatorio.
      responses:
        '200':
          description: Sucesso.
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
                description: 'O relatorio com status, progresso e todas as secoes (com conteudo, pareceres e erros). O dicionario das secoes esta em /data/estrutura-relatorio.'
              example:
                id: 6612a7f3a19b467000000000
                createdAt: '2026-07-31T13:42:37.059Z'
                updatedAt: '2026-07-31T13:43:28.150Z'
                document: '11222333000181'
                yearMonthDay: 20260731
                policyId: 6612a7f3625ea4ab00000000
                policyVersion: 3
                policyName: Completo+
                organizationId: 6612a7f3fa9e086b00000000
                commentary: null
                userId: 6612a7f338154f0100000000
                status:
                  id: 6612a7f33fdd7d9400000000
                  value: APPROVED
                reportProgress:
                  isFinalized: true
                  finalizedAt: '2026-07-31T13:43:24.194Z'
                  steps: []
                analystId: null
                analystName: null
                sections:
                  - id: 6612a7f30a2c8b1a00000000
                    type:
                      id: 6612a7f3cd81d4f900000000
                      title: Sanções
                      value: SANCTIONS
                    comments: []
                    sectionDetails:
                      - values: {}
                        errors: []
                    parecer: Texto do parecer da seção...
                    parecerScore: 10
                    parecerRiskLevel: LOW
                    parecerStatus: DONE
                    parecerFeedback: null
                    errors: []
                verified: true
                exportUrl: null
                exportExcelUrl: null
                parecerEnabled: true
                committeeStatus: null
                committeeDecision: null
                committeeResult: null
        '401':
          description: 'Token ausente, expirado ou invalido. Gere outro em POST /auth/authenticate.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 401
                message: Token de acesso inválido.
        '403':
          description: O usuario autenticado nao tem a permissao exigida pela rota.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 403
                message: Você não tem permissão para acessar este recurso.
        '404':
          description: Relatorio inexistente ou de outra organizacao.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 404
                message: Relatório não encontrado
        '500':
          description: 'Falha nossa. Tente de novo; se persistir, acione o suporte com o horario da chamada.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 500
                message: Internal server error
      tags:
        - report
      security:
        - authorization: []
      summary: Consultar relatorio (API v2)
      description: |
          Retorna o relatorio completo: status (PENDING, APPROVED, REJECTED), progresso,
          politica, decisao manual, todas as secoes com conteudo e Parecer IA, e o resultado
          do Comite de Credito IA. Nao aceita filtros. Relatorio inexistente ou de outra
          organizacao responde 404 "Relatório não encontrado".
      x-codeSamples:
        - lang: cURL
          label: cURL
          source: |
              curl --request GET 'https://gyra-core.gyramais.com.br/v2/report/6612a7f30000000000000001' \
                --header 'Authorization: Bearer <token>'
        - lang: JavaScript
          label: Node
          source: |
              const resposta = await fetch("https://gyra-core.gyramais.com.br/v2/report/6612a7f30000000000000001", {
                method: "GET",
                headers: { Authorization: `Bearer ${token}` },
              });
              
              const dados = await resposta.json();
        - lang: Python
          label: Python
          source: |
              import requests
              
              resposta = requests.get(
                  "https://gyra-core.gyramais.com.br/v2/report/6612a7f30000000000000001",
                  headers={"Authorization": f"Bearer {token}"},
              )
              
              dados = resposta.json()
  /v1/registry:
    post:
      operationId: RegistryController_create
      summary: Criar (ou recuperar) o cadastro de um CNPJ/CPF
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateRegistryDto'
            example:
              document: 11.444.777/0001-61
              name: AURORA COMPONENTES INDUSTRIAIS LTDA
      responses:
        '201':
          description: 'Cadastro com id, document, entityType (COMPANY/PERSON), name, kycStatus e completeness.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Registry'
              example:
                id: 6612a7f30000000000000001
                document: '11444777000161'
                entityType: COMPANY
                name: AURORA COMPONENTES INDUSTRIAIS LTDA
                tradeName: AURORA
                legalNature: Sociedade Empresária Limitada
                kycStatus: PENDING
                kycRenewalDue: null
                completeness: 0
                documentsCount: 0
                pendingCount: 0
                reportId: null
                basicDataSyncedAt: '2026-09-05T12:58:10.000Z'
                crossDocument: null
                createdAt: '2026-09-05T12:58:10.000Z'
                updatedAt: '2026-09-05T12:58:10.000Z'
                completenessSlots:
                  - key: CONTRATO_SOCIAL
                    types:
                      - CONTRATO_SOCIAL
                      - ALTERACAO_CONTRATUAL
                      - ESTATUTO_SOCIAL
                      - REQUERIMENTO_EMPRESARIO
                    filled: false
                    documentId: null
                  - key: IRPJ_ECF
                    types:
                      - IRPJ_ECF
                    filled: false
                    documentId: null
                  - key: CERTIDAO_JUNTA
                    types:
                      - CERTIDAO_JUNTA
                    filled: false
                    documentId: null
                signingAuthority: null
        '400':
          description: Corpo invalido. A mensagem concatena todas as falhas por virgula.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 400
                message: Você precisa inserir um CNPJ ou CPF válido.
        '401':
          description: 'Token ausente, expirado ou invalido. Gere outro em POST /auth/authenticate.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 401
                message: Token de acesso inválido.
        '403':
          description: O usuario autenticado nao tem a permissao exigida pela rota.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 403
                message: Você não tem permissão para acessar este recurso.
        '404':
          description: 'O modulo Onboarding nao esta liberado para a organizacao: para ela, a rota nao existe.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 404
                message: Recurso não encontrado.
        '500':
          description: 'Falha nossa. Tente de novo; se persistir, acione o suporte com o horario da chamada.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 500
                message: Internal server error
        '502':
          description: O servico de cadastro nao respondeu. Tente de novo.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 502
                message: Não foi possível criar o cadastro.
      tags:
        - registry
      security:
        - authorization: []
      description: |
          Cria o dossie documental de um CNPJ ou CPF na organizacao autenticada.
          
          IDEMPOTENTE POR DOCUMENTO: chamar de novo com o mesmo CNPJ devolve o cadastro que ja existe,
          em vez de duplicar. E seguro chamar no inicio de qualquer jornada. Cadastro removido antes
          volta a ficar ativo, com o historico que ja tinha.
          
          A resposta traz o mesmo corpo do detalhe do cadastro, inclusive `completenessSlots` e
          `signingAuthority`.
      x-codeSamples:
        - lang: cURL
          label: cURL
          source: |
              curl --request POST 'https://gyra-core.gyramais.com.br/v1/registry' \
                --header 'Authorization: Bearer <token>' \
                --header 'Content-Type: application/json' \
                --data '{"document":"11.444.777/0001-61","name":"AURORA COMPONENTES INDUSTRIAIS LTDA"}'
        - lang: JavaScript
          label: Node
          source: |
              const resposta = await fetch("https://gyra-core.gyramais.com.br/v1/registry", {
                method: "POST",
                headers: {
                  Authorization: `Bearer ${token}`,
                  "Content-Type": "application/json",
                },
                body: JSON.stringify({
                  "document": "11.444.777/0001-61",
                  "name": "AURORA COMPONENTES INDUSTRIAIS LTDA"
                }),
              });
              
              const dados = await resposta.json();
        - lang: Python
          label: Python
          source: |
              import requests
              
              resposta = requests.post(
                  "https://gyra-core.gyramais.com.br/v1/registry",
                  headers={"Authorization": f"Bearer {token}"},
                  json={
                      "document": "11.444.777/0001-61",
                      "name": "AURORA COMPONENTES INDUSTRIAIS LTDA"
                  },
              )
              
              dados = resposta.json()
    get:
      operationId: RegistryController_list
      summary: Listar cadastros da organizacao
      parameters:
        - name: search
          required: false
          in: query
          schema:
            type: string
          description: 'Casa por razao social, nome fantasia ou parte do CNPJ/CPF (mascara e ignorada).'
        - name: entityType
          required: false
          in: query
          schema:
            type: string
            enum:
              - COMPANY
              - PERSON
          description: COMPANY (pessoa juridica) ou PERSON (pessoa fisica).
        - name: kycStatus
          required: false
          in: query
          schema:
            type: array
            items:
              type: string
              enum:
                - PENDING
                - PROCESSING
                - UP_TO_DATE
                - ATTENTION
                - EXPIRED
                - RENEWING
          description: Uma ou mais situacoes. Repita o parametro para varias.
        - name: skip
          required: false
          in: query
          schema:
            type: integer
            minimum: 0
          description: Quantos pular. Padrao 0.
        - name: take
          required: false
          in: query
          schema:
            type: integer
            minimum: 1
            maximum: 50
          description: 'Tamanho da pagina. Padrao 20, maximo 50.'
      responses:
        '200':
          description: Pagina de cadastros com situacao e completude.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RegistryListResponse'
              example:
                items:
                  - id: 6612a7f30000000000000001
                    document: '11444777000161'
                    entityType: COMPANY
                    name: AURORA COMPONENTES INDUSTRIAIS LTDA
                    tradeName: AURORA
                    legalNature: Sociedade Empresária Limitada
                    kycStatus: ATTENTION
                    kycRenewalDue: '2027-03-31T00:00:00.000Z'
                    completeness: 0.66
                    documentsCount: 4
                    pendingCount: 1
                    reportId: null
                    basicDataSyncedAt: '2026-09-05T12:58:10.000Z'
                    crossDocument: null
                    createdAt: '2026-09-05T12:58:10.000Z'
                    updatedAt: '2026-09-05T13:07:44.000Z'
                total: 1
        '400':
          description: 'Parametro invalido, inclusive valor de kycStatus fora da lista. A mensagem concatena todas as falhas por virgula.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 400
                message: 'each value in kycStatus must be one of the following values: PENDING, PROCESSING, UP_TO_DATE, ATTENTION, EXPIRED, RENEWING'
        '401':
          description: 'Token ausente, expirado ou invalido. Gere outro em POST /auth/authenticate.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 401
                message: Token de acesso inválido.
        '403':
          description: O usuario autenticado nao tem a permissao exigida pela rota.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 403
                message: Você não tem permissão para acessar este recurso.
        '404':
          description: 'O modulo Onboarding nao esta liberado para a organizacao: para ela, a rota nao existe.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 404
                message: Recurso não encontrado.
        '500':
          description: 'Falha nossa. Tente de novo; se persistir, acione o suporte com o horario da chamada.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 500
                message: Internal server error
      tags:
        - registry
      security:
        - authorization: []
      description: |
          Lista os cadastros, com busca e filtro por situacao, do atualizado mais recentemente para o
          mais antigo. Cadastro removido nao aparece.
          
          Situacoes: PENDING (sem documento validado), PROCESSING (documento em analise),
          UP_TO_DATE (tudo validado), ATTENTION (divergencia, vencimento proximo ou ressalva),
          EXPIRED (renovacao vencida), RENEWING (renovacao em curso).
          
          Valor de kycStatus fora dessa lista e recusado com 400.
          
          `completenessSlots` e `signingAuthority` so vem no detalhe do cadastro.
      x-codeSamples:
        - lang: cURL
          label: cURL
          source: |
              curl --request GET 'https://gyra-core.gyramais.com.br/v1/registry' \
                --header 'Authorization: Bearer <token>'
        - lang: JavaScript
          label: Node
          source: |
              const resposta = await fetch("https://gyra-core.gyramais.com.br/v1/registry", {
                method: "GET",
                headers: { Authorization: `Bearer ${token}` },
              });
              
              const dados = await resposta.json();
        - lang: Python
          label: Python
          source: |
              import requests
              
              resposta = requests.get(
                  "https://gyra-core.gyramais.com.br/v1/registry",
                  headers={"Authorization": f"Bearer {token}"},
              )
              
              dados = resposta.json()
  /v1/registry/validate-document:
    post:
      operationId: RegistryController_validateDocument
      summary: Validar um documento e receber o parecer
      description: |
          Manda UM arquivo (PDF, JPG ou PNG, ate 15MB) e recebe classificacao, campos extraidos, verificacoes e parecer.
          
          A ENTRADA E UNICA: voce nao diz que documento e. A plataforma reconhece sozinha 24 tipos
          (contrato social, alteracao contratual, estatuto, ata de assembleia, requerimento de
          empresario, procuracao PJ/PF, certidao da Junta, QSA, IRPJ/ECF, declaracao de faturamento,
          extrato bancario, certidao PGFN, FGTS, CADIN federal/estadual, Simples Nacional, eSocial,
          documento de identidade, comprovante de residencia, DIRPF, comprovante de renda,
          certidao PF, estado civil). O balanco (DEMONSTRACOES_FINANCEIRAS) e o 25o tipo com leitura
          propria, mas NAO e reconhecido sozinho: mande typeHint DEMONSTRACOES_FINANCEIRAS.
          
          O FORMATO DA SAIDA DEPENDE DO TIPO IDENTIFICADO: o objeto `extraction` traz os campos
          daquele tipo. Todo campo folha vem como { value, confidence, page }; campo ausente vem
          com value null e confidence 0, nunca inventado.
          
          Responde 200 com o resultado quando o pipeline fecha dentro de `waitSeconds`, ou 202 com
          { documentId, statusUrl } quando passa. No 202, continue com get_document_status.
          
          Use `expectedType` para conferir se veio o documento CERTO: a classificacao roda normal e o
          tipo lido e confrontado com o pedido. E o que pega o arquivo legitimo enviado no campo errado.
          Use `typeHint` so quando a origem ja garante o tipo: ele PULA a classificacao.
          
          O arquivo e arquivado no cadastro de `expectedDocument`, criando o cadastro se nao existir.
      parameters: []
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              required:
                - file
                - expectedDocument
              properties:
                file:
                  type: string
                  format: binary
                  description: 'O arquivo, em multipart/form-data. PDF, JPG ou PNG, ate 15MB. Acima disso use presign_registry_document + confirm_registry_document.'
                expectedDocument:
                  type: string
                  description: 'CNPJ ou CPF da jornada, com ou sem mascara. Obrigatorio: e o dono do cadastro onde o documento sera arquivado.'
                expectedName:
                  type: string
                  description: Razao social ou nome da jornada. Alimenta a verificacao EXPECTED_NAME_MATCH.
                waitSeconds:
                  type: integer
                  minimum: 5
                  maximum: 55
                  description: 'Espera maxima pela resposta sincrona, de 5 a 55. Padrao 45.'
                typeHint:
                  type: string
                  enum:
                    - CONTRATO_SOCIAL
                    - ALTERACAO_CONTRATUAL
                    - ESTATUTO_SOCIAL
                    - REQUERIMENTO_EMPRESARIO
                    - PROCURACAO_PJ
                    - IRPJ_ECF
                    - DECLARACAO_FATURAMENTO
                    - CERTIDAO_JUNTA
                    - ATA_ASSEMBLEIA
                    - DOC_IDENTIDADE
                    - COMPROVANTE_RESIDENCIA
                    - DIRPF
                    - COMPROVANTE_RENDA
                    - CERTIDAO_PF
                    - PROCURACAO_PF
                    - FORA_DE_ESCOPO
                    - NAO_IDENTIFICADO
                    - CERTIDAO_PGFN_PJ
                    - CERTIDAO_FGTS
                    - CADIN_FEDERAL
                    - CADIN_ESTADUAL
                    - CERTIDAO_QSA
                    - CERTIFICADO_SIMPLES_NACIONAL
                    - ESOCIAL_PJ
                    - COMPROVACAO_ESTADO_CIVIL
                    - DEMONSTRACOES_FINANCEIRAS
                    - EXTRATO_BANCARIO
                  description: 'AFIRMA o tipo do arquivo: o pipeline adota e pula a classificacao. So use quando a origem ja garante o tipo.'
                expectedType:
                  type: string
                  enum:
                    - CONTRATO_SOCIAL
                    - ALTERACAO_CONTRATUAL
                    - ESTATUTO_SOCIAL
                    - REQUERIMENTO_EMPRESARIO
                    - PROCURACAO_PJ
                    - IRPJ_ECF
                    - DECLARACAO_FATURAMENTO
                    - CERTIDAO_JUNTA
                    - ATA_ASSEMBLEIA
                    - DOC_IDENTIDADE
                    - COMPROVANTE_RESIDENCIA
                    - DIRPF
                    - COMPROVANTE_RENDA
                    - CERTIDAO_PF
                    - PROCURACAO_PF
                    - FORA_DE_ESCOPO
                    - NAO_IDENTIFICADO
                    - CERTIDAO_PGFN_PJ
                    - CERTIDAO_FGTS
                    - CADIN_FEDERAL
                    - CADIN_ESTADUAL
                    - CERTIDAO_QSA
                    - CERTIFICADO_SIMPLES_NACIONAL
                    - ESOCIAL_PJ
                    - COMPROVACAO_ESTADO_CIVIL
                    - DEMONSTRACOES_FINANCEIRAS
                    - EXTRATO_BANCARIO
                  description: 'PEDE um tipo: a classificacao roda e o tipo lido e confrontado (verificacao EXPECTED_TYPE_MATCH). E o campo que pega documento trocado.'
      responses:
        '200':
          description: 'Resultado completo (200) com type, extraction, validation.checks[] e assessment; ou { documentId, statusUrl } (202) quando ainda processa.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RegistryDocumentResult'
              example:
                documentId: 6612a7f30000000000000031
                registryId: 6612a7f30000000000000001
                type: CONTRATO_SOCIAL
                expectedType: CONTRATO_SOCIAL
                expectedTypes: []
                status: VALIDATED
                version: 2
                isCurrent: true
                classification:
                  type: CONTRATO_SOCIAL
                  confidence: 0.94
                  alternatives:
                    - type: ALTERACAO_CONTRATUAL
                      confidence: 0.21
                ambiguous: false
                statusReason: null
                stages:
                  executed:
                    - CLASSIFY
                    - EXTRACT
                    - VALIDATE
                  reused: []
                extraction:
                  cnpj:
                    value: '11444777000161'
                    confidence: 0.97
                    page: 1
                  companyName:
                    value: AURORA COMPONENTES INDUSTRIAIS LTDA
                    confidence: 0.96
                    page: 1
                  signatureDate:
                    value: 2021-04-30
                    confidence: 0.93
                    page: 8
                  capitalAmount:
                    value: 1200000
                    confidence: 0.95
                    page: 3
                  capitalCurrency:
                    value: BRL
                    confidence: 0.99
                    page: 3
                  quotaUnitValue:
                    value: null
                    confidence: 0
                    page: null
                  partners:
                    - name:
                        value: CARLOS EDUARDO SILVA
                        confidence: 0.96
                        page: 1
                      document:
                        value: '52998224725'
                        confidence: 0.95
                        page: 1
                      documentType:
                        value: CPF
                        confidence: 0.99
                        page: 1
                      sharePercent:
                        value: 60
                        confidence: 0.95
                        page: 3
                      isAdministrator:
                        value: true
                        confidence: 0.92
                        page: 4
                  representation:
                    regime:
                      value: ISOLADA
                      confidence: 0.95
                      page: 4
                    signersRequired:
                      value: 1
                      confidence: 0.95
                      page: 4
                    clauseNumber:
                      value: CLÁUSULA 8ª
                      confidence: 0.94
                      page: 4
                    clauseExcerpt:
                      value: A administração da sociedade caberá isoladamente ao sócio CARLOS EDUARDO SILVA...
                      confidence: 0.94
                      page: 4
                  certification:
                    certificationKind:
                      value: ORGAO_EMISSOR
                      confidence: 0.97
                      page: 1
                    certificationDetail:
                      value: Chancela digital da Junta Comercial
                      confidence: 0.96
                      page: 1
                    verificationCode:
                      value: A1B2C3D4E5
                      confidence: 0.98
                      page: 1
                fieldConfidences:
                  cnpj: 0.97
                  companyName: 0.96
                  capitalAmount: 0.95
                validation:
                  checks:
                    - code: EXPECTED_DOCUMENT_MATCH
                      result: PASS
                      message: O CNPJ do documento é o mesmo da análise.
                      evidence:
                        page: 1
                        excerpt: CNPJ 11.444.777/0001-61
                      source: DETERMINISTIC
                    - code: QSA_SHARE_SUM
                      result: WARN
                      message: 'A soma das participações fecha 98%, fora da tolerância de 0,5 ponto.'
                      evidence:
                        page: 3
                        excerpt: CARLOS EDUARDO SILVA 60% ... MARIA HELENA SOUZA 38%
                      source: DETERMINISTIC
                  reconciliation:
                    qsaMatched: true
                assessment:
                  verdict: VALIDO
                  score: 0.91
                  justification: 'Documento íntegro, titularidade confirmada e registro na Junta conferido. A soma das quotas ficou 2 pontos abaixo de 100%, o que é ressalva e não impedimento.'
                  evidences: []
                  ruleSetVersion: org-v7
                  contentHash: 9f2b7c1e4a...
                  feedbackVerdict: null
                  feedbackComment: null
                  feedbackAt: null
                  feedbackUserId: null
                  effectiveVerdict: VALIDO
                  decidedByOperator: false
                processedAt: '2026-09-05T13:07:44.000Z'
                attempt: 1
        '202':
          description: 'O pipeline nao fechou dentro de `waitSeconds`. `statusUrl` e um caminho relativo, sem o prefixo de versao: continue por GET nele (ou em /v1/registry/documents/{docId}/status), ou assine o webhook `registry.document.assessed` e pare de fazer polling.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RegistryValidateAccepted'
              example:
                documentId: 6612a7f30000000000000031
                statusUrl: /registry/documents/6612a7f30000000000000031/status
        '400':
          description: 'Corpo invalido, arquivo ausente, tipo de arquivo fora de PDF/JPG/PNG ou conteudo que nao confere com o tipo declarado.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 400
                message: O arquivo do documento é obrigatório (campo "file").
        '401':
          description: 'Token ausente, expirado ou invalido. Gere outro em POST /auth/authenticate.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 401
                message: Token de acesso inválido.
        '403':
          description: O usuario autenticado nao tem a permissao exigida pela rota.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 403
                message: Você não tem permissão para acessar este recurso.
        '404':
          description: 'O modulo Onboarding nao esta liberado para a organizacao: para ela, a rota nao existe.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 404
                message: Recurso não encontrado.
        '413':
          description: 'Arquivo acima de 15MB. Para arquivos maiores, use o envio por URL assinada (presign + confirmacao).'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 413
                message: File too large
        '500':
          description: 'Falha nossa. Tente de novo; se persistir, acione o suporte com o horario da chamada.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 500
                message: Internal server error
        '502':
          description: O armazenamento ou o servico de cadastro nao respondeu. Tente de novo.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 502
                message: Não foi possível iniciar a validação do documento.
      tags:
        - registry
      security:
        - authorization: []
      x-codeSamples:
        - lang: cURL
          label: cURL
          source: |
              curl --request POST 'https://gyra-core.gyramais.com.br/v1/registry/validate-document' \
                --header 'Authorization: Bearer <token>' \
                --form 'file=@"/caminho/contrato-social.pdf"' \
                --form 'expectedDocument="11444777000161"'
        - lang: JavaScript
          label: Node
          source: |
              import fs from "node:fs";
              
              const form = new FormData();
              form.append("file", new Blob([fs.readFileSync("/caminho/contrato-social.pdf")]), "contrato-social.pdf");
              form.append("expectedDocument", "11444777000161");
              
              const resposta = await fetch("https://gyra-core.gyramais.com.br/v1/registry/validate-document", {
                method: "POST",
                headers: { Authorization: `Bearer ${token}` },
                body: form,
              });
              
              const dados = await resposta.json();
        - lang: Python
          label: Python
          source: |
              import requests
              
              with open("/caminho/contrato-social.pdf", "rb") as arquivo:
                  resposta = requests.post(
                      "https://gyra-core.gyramais.com.br/v1/registry/validate-document",
                      headers={"Authorization": f"Bearer {token}"},
                      files={"file": arquivo},
                      data={"expectedDocument": "11444777000161"},
                  )
              
              dados = resposta.json()
  /v1/registry/documents/{docId}/status:
    get:
      operationId: RegistryController_documentStatus
      summary: Status e resultado de um documento em analise
      description: |
          Consulta um documento pelo id, sem precisar do id do cadastro. E o caminho de polling
          depois de um 202 do validate_document.
          
          Status terminais: VALIDATED, FAILED, OUT_OF_SCOPE, MANUAL_REVIEW, REJECTED_QUALITY.
          Enquanto nao for terminal, o documento ainda esta no pipeline.
          
          Devolve o mesmo corpo do resultado completo, incluindo `statusReason` (por que parou num
          terminal que nao e falha tecnica) e `stages` (o que rodou e o que veio reaproveitado).
          
          PREFIRA WEBHOOK: assine registry.document.assessed em vez de fazer polling em laco.
      parameters:
        - name: docId
          required: true
          in: path
          schema:
            type: string
          description: 'Id do documento, devolvido pelo validate_document ou pelo confirm_registry_document.'
      responses:
        '200':
          description: 'Documento com status, classification, extraction, validation e assessment.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RegistryDocumentResult'
              example:
                documentId: 6612a7f30000000000000031
                registryId: 6612a7f30000000000000001
                type: CONTRATO_SOCIAL
                expectedType: CONTRATO_SOCIAL
                expectedTypes: []
                status: VALIDATED
                version: 2
                isCurrent: true
                classification:
                  type: CONTRATO_SOCIAL
                  confidence: 0.94
                  alternatives:
                    - type: ALTERACAO_CONTRATUAL
                      confidence: 0.21
                ambiguous: false
                statusReason: null
                stages:
                  executed:
                    - CLASSIFY
                    - EXTRACT
                    - VALIDATE
                  reused: []
                extraction:
                  cnpj:
                    value: '11444777000161'
                    confidence: 0.97
                    page: 1
                  companyName:
                    value: AURORA COMPONENTES INDUSTRIAIS LTDA
                    confidence: 0.96
                    page: 1
                  signatureDate:
                    value: 2021-04-30
                    confidence: 0.93
                    page: 8
                  capitalAmount:
                    value: 1200000
                    confidence: 0.95
                    page: 3
                  capitalCurrency:
                    value: BRL
                    confidence: 0.99
                    page: 3
                  quotaUnitValue:
                    value: null
                    confidence: 0
                    page: null
                  partners:
                    - name:
                        value: CARLOS EDUARDO SILVA
                        confidence: 0.96
                        page: 1
                      document:
                        value: '52998224725'
                        confidence: 0.95
                        page: 1
                      documentType:
                        value: CPF
                        confidence: 0.99
                        page: 1
                      sharePercent:
                        value: 60
                        confidence: 0.95
                        page: 3
                      isAdministrator:
                        value: true
                        confidence: 0.92
                        page: 4
                  representation:
                    regime:
                      value: ISOLADA
                      confidence: 0.95
                      page: 4
                    signersRequired:
                      value: 1
                      confidence: 0.95
                      page: 4
                    clauseNumber:
                      value: CLÁUSULA 8ª
                      confidence: 0.94
                      page: 4
                    clauseExcerpt:
                      value: A administração da sociedade caberá isoladamente ao sócio CARLOS EDUARDO SILVA...
                      confidence: 0.94
                      page: 4
                  certification:
                    certificationKind:
                      value: ORGAO_EMISSOR
                      confidence: 0.97
                      page: 1
                    certificationDetail:
                      value: Chancela digital da Junta Comercial
                      confidence: 0.96
                      page: 1
                    verificationCode:
                      value: A1B2C3D4E5
                      confidence: 0.98
                      page: 1
                fieldConfidences:
                  cnpj: 0.97
                  companyName: 0.96
                  capitalAmount: 0.95
                validation:
                  checks:
                    - code: EXPECTED_DOCUMENT_MATCH
                      result: PASS
                      message: O CNPJ do documento é o mesmo da análise.
                      evidence:
                        page: 1
                        excerpt: CNPJ 11.444.777/0001-61
                      source: DETERMINISTIC
                    - code: QSA_SHARE_SUM
                      result: WARN
                      message: 'A soma das participações fecha 98%, fora da tolerância de 0,5 ponto.'
                      evidence:
                        page: 3
                        excerpt: CARLOS EDUARDO SILVA 60% ... MARIA HELENA SOUZA 38%
                      source: DETERMINISTIC
                  reconciliation:
                    qsaMatched: true
                assessment:
                  verdict: VALIDO
                  score: 0.91
                  justification: 'Documento íntegro, titularidade confirmada e registro na Junta conferido. A soma das quotas ficou 2 pontos abaixo de 100%, o que é ressalva e não impedimento.'
                  evidences: []
                  ruleSetVersion: org-v7
                  contentHash: 9f2b7c1e4a...
                  feedbackVerdict: null
                  feedbackComment: null
                  feedbackAt: null
                  feedbackUserId: null
                  effectiveVerdict: VALIDO
                  decidedByOperator: false
                processedAt: '2026-09-05T13:07:44.000Z'
                attempt: 1
        '400':
          description: Identificador fora do formato ObjectId (24 caracteres hexadecimais).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 400
                message: O identificador informado em "docId" não é válido.
        '401':
          description: 'Token ausente, expirado ou invalido. Gere outro em POST /auth/authenticate.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 401
                message: Token de acesso inválido.
        '403':
          description: O usuario autenticado nao tem a permissao exigida pela rota.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 403
                message: Você não tem permissão para acessar este recurso.
        '404':
          description: 'Documento inexistente na organizacao, ou modulo Onboarding nao liberado (nesse caso a mensagem e "Recurso não encontrado."). As duas coisas respondem 404 de proposito: para quem nao tem o modulo, a rota nao existe.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 404
                message: Documento não encontrado.
        '500':
          description: 'Falha nossa. Tente de novo; se persistir, acione o suporte com o horario da chamada.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 500
                message: Internal server error
        '502':
          description: O servico de cadastro nao respondeu. Tente de novo.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 502
                message: Não foi possível consultar o status do documento.
      tags:
        - registry
      security:
        - authorization: []
      x-codeSamples:
        - lang: cURL
          label: cURL
          source: |
              curl --request GET 'https://gyra-core.gyramais.com.br/v1/registry/documents/6612a7f30000000000000001/status' \
                --header 'Authorization: Bearer <token>'
        - lang: JavaScript
          label: Node
          source: |
              const resposta = await fetch("https://gyra-core.gyramais.com.br/v1/registry/documents/6612a7f30000000000000001/status", {
                method: "GET",
                headers: { Authorization: `Bearer ${token}` },
              });
              
              const dados = await resposta.json();
        - lang: Python
          label: Python
          source: |
              import requests
              
              resposta = requests.get(
                  "https://gyra-core.gyramais.com.br/v1/registry/documents/6612a7f30000000000000001/status",
                  headers={"Authorization": f"Bearer {token}"},
              )
              
              dados = resposta.json()
  /v1/registry/by-document/{document}:
    get:
      operationId: RegistryController_findByDocument
      summary: Consultar o cadastro pelo CNPJ/CPF
      parameters:
        - name: document
          required: true
          in: path
          schema:
            type: string
          description: 'CNPJ ou CPF, com ou sem mascara.'
      responses:
        '200':
          description: 'Cadastro com situacao, completude, dados basicos oficiais e as exigencias em aberto.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Registry'
              example:
                id: 6612a7f30000000000000001
                document: '11444777000161'
                entityType: COMPANY
                name: AURORA COMPONENTES INDUSTRIAIS LTDA
                tradeName: AURORA
                legalNature: Sociedade Empresária Limitada
                kycStatus: ATTENTION
                kycRenewalDue: '2027-03-31T00:00:00.000Z'
                completeness: 0.66
                documentsCount: 4
                pendingCount: 1
                reportId: null
                basicDataSyncedAt: '2026-09-05T12:58:10.000Z'
                crossDocument: null
                createdAt: '2026-09-05T12:58:10.000Z'
                updatedAt: '2026-09-05T13:07:44.000Z'
                completenessSlots:
                  - key: CONTRATO_SOCIAL
                    types:
                      - CONTRATO_SOCIAL
                      - ALTERACAO_CONTRATUAL
                      - ESTATUTO_SOCIAL
                      - REQUERIMENTO_EMPRESARIO
                    filled: true
                    documentId: 6612a7f30000000000000031
                  - key: IRPJ_ECF
                    types:
                      - IRPJ_ECF
                    filled: true
                    documentId: 6612a7f30000000000000032
                  - key: CERTIDAO_JUNTA
                    types:
                      - CERTIDAO_JUNTA
                    filled: false
                    documentId: null
                signingAuthority: null
        '401':
          description: 'Token ausente, expirado ou invalido. Gere outro em POST /auth/authenticate.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 401
                message: Token de acesso inválido.
        '403':
          description: O usuario autenticado nao tem a permissao exigida pela rota.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 403
                message: Você não tem permissão para acessar este recurso.
        '404':
          description: 'Recurso inexistente OU capacidade nao liberada para a organizacao. As duas coisas respondem 404 de proposito: para quem nao tem o modulo, a rota nao existe.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 404
                message: Cadastro não encontrado.
        '500':
          description: 'Falha nossa. Tente de novo; se persistir, acione o suporte com o horario da chamada.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 500
                message: Internal server error
        '502':
          description: O servico de cadastro nao respondeu. Tente de novo.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 502
                message: Não foi possível consultar o cadastro.
      tags:
        - registry
      security:
        - authorization: []
      description: |
          Busca o dossie pelo documento, sem precisar saber o id.
          
          E a tool para responder "o que ja temos deste CNPJ?" antes de pedir documento ao cliente:
          a completude e a situacao dizem se falta alguma coisa.
      x-codeSamples:
        - lang: cURL
          label: cURL
          source: |
              curl --request GET 'https://gyra-core.gyramais.com.br/v1/registry/by-document/11444777000161' \
                --header 'Authorization: Bearer <token>'
        - lang: JavaScript
          label: Node
          source: |
              const resposta = await fetch("https://gyra-core.gyramais.com.br/v1/registry/by-document/11444777000161", {
                method: "GET",
                headers: { Authorization: `Bearer ${token}` },
              });
              
              const dados = await resposta.json();
        - lang: Python
          label: Python
          source: |
              import requests
              
              resposta = requests.get(
                  "https://gyra-core.gyramais.com.br/v1/registry/by-document/11444777000161",
                  headers={"Authorization": f"Bearer {token}"},
              )
              
              dados = resposta.json()
  /v1/registry/{id}:
    get:
      operationId: RegistryController_findOne
      summary: Consultar um cadastro pelo id
      parameters:
        - name: id
          required: true
          in: path
          schema:
            type: string
          description: Id do cadastro.
      responses:
        '200':
          description: 'Cadastro completo, com completude aberta por exigencia.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Registry'
              example:
                id: 6612a7f30000000000000001
                document: '11444777000161'
                entityType: COMPANY
                name: AURORA COMPONENTES INDUSTRIAIS LTDA
                tradeName: AURORA
                legalNature: Sociedade Empresária Limitada
                kycStatus: ATTENTION
                kycRenewalDue: '2027-03-31T00:00:00.000Z'
                completeness: 0.66
                documentsCount: 4
                pendingCount: 1
                reportId: null
                basicDataSyncedAt: '2026-09-05T12:58:10.000Z'
                crossDocument: null
                createdAt: '2026-09-05T12:58:10.000Z'
                updatedAt: '2026-09-05T13:07:44.000Z'
                completenessSlots:
                  - key: CONTRATO_SOCIAL
                    types:
                      - CONTRATO_SOCIAL
                      - ALTERACAO_CONTRATUAL
                      - ESTATUTO_SOCIAL
                      - REQUERIMENTO_EMPRESARIO
                    filled: true
                    documentId: 6612a7f30000000000000031
                  - key: IRPJ_ECF
                    types:
                      - IRPJ_ECF
                    filled: true
                    documentId: 6612a7f30000000000000032
                  - key: CERTIDAO_JUNTA
                    types:
                      - CERTIDAO_JUNTA
                    filled: false
                    documentId: null
                signingAuthority:
                  regime: ISOLADA
                  signersRequired: 1
                  anySignerAlone: true
                  signers:
                    - name: CARLOS EDUARDO SILVA
                      document: '52998224725'
                      role: Sócio administrador
                      signsAlone: true
                      jointSignatureThreshold: null
                      mandateEndDate: null
                      restrictions: null
                  thresholds: []
                  prohibitions: []
                  mandate: null
                  source:
                    documentId: 6612a7f30000000000000031
                    documentType: CONTRATO_SOCIAL
                    fileName: contrato-social.pdf
                    version: 2
                    validatedAt: '2026-09-05T13:07:44.000Z'
                    clauseNumber: CLÁUSULA 8ª
                    clauseExcerpt: A administração da sociedade caberá isoladamente ao sócio CARLOS EDUARDO SILVA...
                    confidence: 0.94
        '400':
          description: Identificador fora do formato ObjectId (24 caracteres hexadecimais).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 400
                message: O identificador informado em "id" não é válido.
        '401':
          description: 'Token ausente, expirado ou invalido. Gere outro em POST /auth/authenticate.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 401
                message: Token de acesso inválido.
        '403':
          description: O usuario autenticado nao tem a permissao exigida pela rota.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 403
                message: Você não tem permissão para acessar este recurso.
        '404':
          description: 'Recurso inexistente OU capacidade nao liberada para a organizacao. As duas coisas respondem 404 de proposito: para quem nao tem o modulo, a rota nao existe.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 404
                message: Cadastro não encontrado.
        '500':
          description: 'Falha nossa. Tente de novo; se persistir, acione o suporte com o horario da chamada.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 500
                message: Internal server error
        '502':
          description: O servico de cadastro nao respondeu. Tente de novo.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 502
                message: Não foi possível consultar o cadastro.
      tags:
        - registry
      security:
        - authorization: []
      description: |
          Detalhe do dossie: situacao, completude, dados basicos oficiais e o bloco de quem
          pode assinar pela empresa (regime ISOLADA/CONJUNTA/MISTA/INDETERMINADO, quantas assinaturas
          a regra geral exige e quem assina sozinho), consolidado do documento societario vigente.
      x-codeSamples:
        - lang: cURL
          label: cURL
          source: |
              curl --request GET 'https://gyra-core.gyramais.com.br/v1/registry/6612a7f30000000000000001' \
                --header 'Authorization: Bearer <token>'
        - lang: JavaScript
          label: Node
          source: |
              const resposta = await fetch("https://gyra-core.gyramais.com.br/v1/registry/6612a7f30000000000000001", {
                method: "GET",
                headers: { Authorization: `Bearer ${token}` },
              });
              
              const dados = await resposta.json();
        - lang: Python
          label: Python
          source: |
              import requests
              
              resposta = requests.get(
                  "https://gyra-core.gyramais.com.br/v1/registry/6612a7f30000000000000001",
                  headers={"Authorization": f"Bearer {token}"},
              )
              
              dados = resposta.json()
  /v1/registry/{id}/documents/presign:
    post:
      operationId: RegistryController_presignDocument
      summary: Preparar o envio de um documento (URL assinada)
      parameters:
        - name: id
          required: true
          in: path
          schema:
            type: string
          description: Id do cadastro.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PresignRegistryDocumentDto'
            example:
              fileName: contrato-social.pdf
              size: 1843200
              mimeType: application/pdf
      responses:
        '201':
          description: URL assinada para o PUT e a key a usar na confirmacao.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RegistryPresignResponse'
              example:
                key: presigned/contrato-social-3f6c2a9e-8b1d-4c7a-9e2f-5a1b7c3d9e40.pdf
                uploadUrl: 'https://<bucket>.s3.amazonaws.com/presigned/contrato-social-3f6c2a9e-8b1d-4c7a-9e2f-5a1b7c3d9e40.pdf?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Signature=...'
                expiresInSeconds: 900
        '400':
          description: 'Corpo invalido: nome ausente, tamanho acima de 50MB (52.428.800 bytes) ou tipo fora de PDF, JPG e PNG. A mensagem concatena todas as falhas por virgula.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 400
                message: Arquivo maior que 50MB.
        '401':
          description: 'Token ausente, expirado ou invalido. Gere outro em POST /auth/authenticate.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 401
                message: Token de acesso inválido.
        '403':
          description: O usuario autenticado nao tem a permissao exigida pela rota.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 403
                message: Você não tem permissão para acessar este recurso.
        '404':
          description: 'Recurso inexistente OU capacidade nao liberada para a organizacao. As duas coisas respondem 404 de proposito: para quem nao tem o modulo, a rota nao existe.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 404
                message: Recurso não encontrado.
        '500':
          description: 'Falha nossa. Tente de novo; se persistir, acione o suporte com o horario da chamada.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 500
                message: Internal server error
        '502':
          description: O armazenamento nao respondeu. Tente de novo.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 502
                message: Não foi possível preparar o upload do documento.
      tags:
        - registry
      security:
        - authorization: []
      description: |
          Primeiro passo do envio assincrono, para arquivos de ate 50MB (acima do teto de 15MB
          do validate_document).
          
          Devolve a URL assinada para o PUT e a `key` do arquivo. Suba o arquivo direto nessa URL, com o
          mesmo Content-Type e o mesmo tamanho declarados, e depois chame confirm_registry_document com a
          key que veio aqui. Nunca monte a key voce mesmo.
      x-codeSamples:
        - lang: cURL
          label: cURL
          source: |
              curl --request POST 'https://gyra-core.gyramais.com.br/v1/registry/6612a7f30000000000000001/documents/presign' \
                --header 'Authorization: Bearer <token>' \
                --header 'Content-Type: application/json' \
                --data '{"fileName":"contrato-social.pdf","size":1843200,"mimeType":"application/pdf"}'
        - lang: JavaScript
          label: Node
          source: |
              const resposta = await fetch("https://gyra-core.gyramais.com.br/v1/registry/6612a7f30000000000000001/documents/presign", {
                method: "POST",
                headers: {
                  Authorization: `Bearer ${token}`,
                  "Content-Type": "application/json",
                },
                body: JSON.stringify({
                  "fileName": "contrato-social.pdf",
                  "size": 1843200,
                  "mimeType": "application/pdf"
                }),
              });
              
              const dados = await resposta.json();
        - lang: Python
          label: Python
          source: |
              import requests
              
              resposta = requests.post(
                  "https://gyra-core.gyramais.com.br/v1/registry/6612a7f30000000000000001/documents/presign",
                  headers={"Authorization": f"Bearer {token}"},
                  json={
                      "fileName": "contrato-social.pdf",
                      "size": 1843200,
                      "mimeType": "application/pdf"
                  },
              )
              
              dados = resposta.json()
  /v1/registry/{id}/documents:
    post:
      operationId: RegistryController_confirmDocument
      summary: Confirmar o upload e disparar a analise
      description: |
          Segundo passo do envio assincrono: confirma o arquivo que ja foi para o armazenamento e
          dispara o pipeline. Responde 202 com o documentId.
          
          O resultado chega por webhook (registry.document.assessed) ou por get_document_status.
          
          Sobre os dois campos de tipo: `expectedType` PEDE um tipo e a conferencia roda; `typeHint`
          AFIRMA o tipo e a classificacao e pulada. Enviando os dois, typeHint vence.
      parameters:
        - name: id
          required: true
          in: path
          schema:
            type: string
          description: Id do cadastro.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ConfirmRegistryDocumentDto'
            example:
              key: presigned/contrato-social-3f6c2a9e-8b1d-4c7a-9e2f-5a1b7c3d9e40.pdf
              fileName: contrato-social.pdf
              expectedType: CONTRATO_SOCIAL
              callbackUrl: 'https://api.suaempresa.com/gyra/kyc'
      responses:
        '202':
          description: documentId do documento em processamento (202).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RegistryConfirmResponse'
              example:
                documentId: 6612a7f30000000000000031
                status: RECEIVED
        '400':
          description: Corpo invalido (key e fileName sao obrigatorios). A mensagem concatena todas as falhas por virgula.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 400
                message: 'key should not be empty,key must be a string'
        '401':
          description: 'Token ausente, expirado ou invalido. Gere outro em POST /auth/authenticate.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 401
                message: Token de acesso inválido.
        '403':
          description: O usuario autenticado nao tem a permissao exigida pela rota.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 403
                message: Você não tem permissão para acessar este recurso.
        '404':
          description: 'Cadastro inexistente, personDocument que nao e pessoa deste cadastro ("Pessoa não encontrada neste cadastro."), ou modulo Onboarding nao liberado ("Recurso não encontrado.").'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 404
                message: Cadastro não encontrado.
        '409':
          description: O mesmo arquivo (mesmo conteudo) ja esta neste cadastro.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 409
                message: Este arquivo já existe neste cadastro.
        '500':
          description: 'Falha nossa. Tente de novo; se persistir, acione o suporte com o horario da chamada.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 500
                message: Internal server error
        '502':
          description: O armazenamento ou o servico de cadastro nao respondeu. Tente de novo.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 502
                message: Não foi possível registrar o documento.
      tags:
        - registry
      security:
        - authorization: []
      x-codeSamples:
        - lang: cURL
          label: cURL
          source: |
              curl --request POST 'https://gyra-core.gyramais.com.br/v1/registry/6612a7f30000000000000001/documents' \
                --header 'Authorization: Bearer <token>' \
                --header 'Content-Type: application/json' \
                --data '{"key":"presigned/contrato-social-3f6c2a9e-8b1d-4c7a-9e2f-5a1b7c3d9e40.pdf","fileName":"contrato-social.pdf","expectedType":"CONTRATO_SOCIAL","callbackUrl":"https://api.suaempresa.com/gyra/kyc"}'
        - lang: JavaScript
          label: Node
          source: |
              const resposta = await fetch("https://gyra-core.gyramais.com.br/v1/registry/6612a7f30000000000000001/documents", {
                method: "POST",
                headers: {
                  Authorization: `Bearer ${token}`,
                  "Content-Type": "application/json",
                },
                body: JSON.stringify({
                  "key": "presigned/contrato-social-3f6c2a9e-8b1d-4c7a-9e2f-5a1b7c3d9e40.pdf",
                  "fileName": "contrato-social.pdf",
                  "expectedType": "CONTRATO_SOCIAL",
                  "callbackUrl": "https://api.suaempresa.com/gyra/kyc"
                }),
              });
              
              const dados = await resposta.json();
        - lang: Python
          label: Python
          source: |
              import requests
              
              resposta = requests.post(
                  "https://gyra-core.gyramais.com.br/v1/registry/6612a7f30000000000000001/documents",
                  headers={"Authorization": f"Bearer {token}"},
                  json={
                      "key": "presigned/contrato-social-3f6c2a9e-8b1d-4c7a-9e2f-5a1b7c3d9e40.pdf",
                      "fileName": "contrato-social.pdf",
                      "expectedType": "CONTRATO_SOCIAL",
                      "callbackUrl": "https://api.suaempresa.com/gyra/kyc"
                  },
              )
              
              dados = resposta.json()
    get:
      operationId: RegistryController_listDocuments
      summary: Listar os documentos de um cadastro
      parameters:
        - name: id
          required: true
          in: path
          schema:
            type: string
          description: Id do cadastro.
        - name: type
          required: false
          in: query
          schema:
            type: string
            enum:
              - CONTRATO_SOCIAL
              - ALTERACAO_CONTRATUAL
              - ESTATUTO_SOCIAL
              - REQUERIMENTO_EMPRESARIO
              - PROCURACAO_PJ
              - IRPJ_ECF
              - DECLARACAO_FATURAMENTO
              - CERTIDAO_JUNTA
              - ATA_ASSEMBLEIA
              - DOC_IDENTIDADE
              - COMPROVANTE_RESIDENCIA
              - DIRPF
              - COMPROVANTE_RENDA
              - CERTIDAO_PF
              - PROCURACAO_PF
              - FORA_DE_ESCOPO
              - NAO_IDENTIFICADO
              - CERTIDAO_PGFN_PJ
              - CERTIDAO_FGTS
              - CADIN_FEDERAL
              - CADIN_ESTADUAL
              - CERTIDAO_QSA
              - CERTIFICADO_SIMPLES_NACIONAL
              - ESOCIAL_PJ
              - COMPROVACAO_ESTADO_CIVIL
              - DEMONSTRACOES_FINANCEIRAS
              - EXTRATO_BANCARIO
          description: So os documentos deste tipo.
        - name: includeHistory
          required: false
          in: query
          schema:
            type: boolean
          description: true traz tambem as versoes aprovadas que ja foram substituidas por uma mais nova do mesmo tipo.
      responses:
        '200':
          description: 'Documentos com tipo, versao, status, veredito e data, dentro de `documents`.'
          content:
            application/json:
              schema:
                type: object
                properties:
                  documents:
                    type: array
                    items:
                      $ref: '#/components/schemas/RegistryDocument'
              example:
                documents:
                  - id: 6612a7f30000000000000031
                    registryId: 6612a7f30000000000000001
                    personId: null
                    type: CONTRATO_SOCIAL
                    expectedType: CONTRATO_SOCIAL
                    status: VALIDATED
                    version: 2
                    isCurrent: true
                    supersedesId: 6612a7f30000000000000030
                    fileUrl: 'https://<bucket>.s3.amazonaws.com/presigned/contrato-social-3f6c2a9e-8b1d-4c7a-9e2f-5a1b7c3d9e40.pdf'
                    fileName: contrato-social.pdf
                    mimeType: application/pdf
                    sizeBytes: 1843200
                    pageCount: 12
                    parentDocumentId: null
                    classification:
                      type: CONTRATO_SOCIAL
                      confidence: 0.94
                    yearReference: null
                    attempt: 1
                    lastError: null
                    statusReason: null
                    verdict: VALIDO
                    createdAt: '2026-09-05T13:02:11.000Z'
                    updatedAt: '2026-09-05T13:07:44.000Z'
        '400':
          description: 'Identificador fora do formato ObjectId, ou `type` fora da lista.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 400
                message: O identificador informado em "id" não é válido.
        '401':
          description: 'Token ausente, expirado ou invalido. Gere outro em POST /auth/authenticate.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 401
                message: Token de acesso inválido.
        '403':
          description: O usuario autenticado nao tem a permissao exigida pela rota.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 403
                message: Você não tem permissão para acessar este recurso.
        '404':
          description: 'Recurso inexistente OU capacidade nao liberada para a organizacao. As duas coisas respondem 404 de proposito: para quem nao tem o modulo, a rota nao existe.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 404
                message: Cadastro não encontrado.
        '500':
          description: 'Falha nossa. Tente de novo; se persistir, acione o suporte com o horario da chamada.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 500
                message: Internal server error
      tags:
        - registry
      security:
        - authorization: []
      description: |
          Lista os documentos do dossie, agrupados por tipo e do mais novo para o mais antigo. Cada
          documento traz `verdict`, o veredito que vale hoje (a decisao do operador, quando houver,
          vence o parecer automatico).
          
          Por padrao some so a versao APROVADA que ja foi substituida por uma vigente do mesmo tipo
          (e da mesma pessoa). Documento reprovado, inconclusivo, em analise ou em processamento
          aparece sempre. Com includeHistory, traz todas as versoes.
          
          Nada e sobrescrito: uma alteracao contratual nova nao apaga a antiga, vira a versao vigente.
      x-codeSamples:
        - lang: cURL
          label: cURL
          source: |
              curl --request GET 'https://gyra-core.gyramais.com.br/v1/registry/6612a7f30000000000000001/documents' \
                --header 'Authorization: Bearer <token>'
        - lang: JavaScript
          label: Node
          source: |
              const resposta = await fetch("https://gyra-core.gyramais.com.br/v1/registry/6612a7f30000000000000001/documents", {
                method: "GET",
                headers: { Authorization: `Bearer ${token}` },
              });
              
              const dados = await resposta.json();
        - lang: Python
          label: Python
          source: |
              import requests
              
              resposta = requests.get(
                  "https://gyra-core.gyramais.com.br/v1/registry/6612a7f30000000000000001/documents",
                  headers={"Authorization": f"Bearer {token}"},
              )
              
              dados = resposta.json()
  /v1/registry/{id}/documents/{docId}/result:
    get:
      operationId: RegistryController_documentResult
      summary: Resultado completo de um documento
      description: |
          Da classificacao ao parecer, para um documento do cadastro.
          
          Traz `extraction` (os campos daquele tipo, cada um com value/confidence/page),
          `validation.checks[]` (cada verificacao com PASS/WARN/FAIL/SKIP, mensagem e evidencia com
          pagina e trecho) e `assessment`.
          
          USE assessment.effectiveVerdict, NAO assessment.verdict. O primeiro e o veredito que vale hoje;
          o segundo e o parecer da IA, que nunca e reescrito. Quando um operador discorda, a decisao dele
          entra em feedbackVerdict e effectiveVerdict passa a ser ela, com decidedByOperator true.
          
          Tambem devolve `statusReason` (por que parou), `stages` (o que rodou e o que foi reaproveitado)
          e o par expectedType/type, que explica a verificacao EXPECTED_TYPE_MATCH.
      parameters:
        - name: id
          required: true
          in: path
          schema:
            type: string
          description: Id do cadastro.
        - name: docId
          required: true
          in: path
          schema:
            type: string
          description: Id do documento.
      responses:
        '200':
          description: 'Classificacao, extracao, verificacoes e parecer, com o selo contentHash.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RegistryDocumentResult'
              example:
                documentId: 6612a7f30000000000000031
                registryId: 6612a7f30000000000000001
                type: CONTRATO_SOCIAL
                expectedType: CONTRATO_SOCIAL
                expectedTypes: []
                status: VALIDATED
                version: 2
                isCurrent: true
                classification:
                  type: CONTRATO_SOCIAL
                  confidence: 0.94
                  alternatives:
                    - type: ALTERACAO_CONTRATUAL
                      confidence: 0.21
                ambiguous: false
                statusReason: null
                stages:
                  executed:
                    - CLASSIFY
                    - EXTRACT
                    - VALIDATE
                  reused: []
                extraction:
                  cnpj:
                    value: '11444777000161'
                    confidence: 0.97
                    page: 1
                  companyName:
                    value: AURORA COMPONENTES INDUSTRIAIS LTDA
                    confidence: 0.96
                    page: 1
                  signatureDate:
                    value: 2021-04-30
                    confidence: 0.93
                    page: 8
                  capitalAmount:
                    value: 1200000
                    confidence: 0.95
                    page: 3
                  capitalCurrency:
                    value: BRL
                    confidence: 0.99
                    page: 3
                  quotaUnitValue:
                    value: null
                    confidence: 0
                    page: null
                  partners:
                    - name:
                        value: CARLOS EDUARDO SILVA
                        confidence: 0.96
                        page: 1
                      document:
                        value: '52998224725'
                        confidence: 0.95
                        page: 1
                      documentType:
                        value: CPF
                        confidence: 0.99
                        page: 1
                      sharePercent:
                        value: 60
                        confidence: 0.95
                        page: 3
                      isAdministrator:
                        value: true
                        confidence: 0.92
                        page: 4
                  representation:
                    regime:
                      value: ISOLADA
                      confidence: 0.95
                      page: 4
                    signersRequired:
                      value: 1
                      confidence: 0.95
                      page: 4
                    clauseNumber:
                      value: CLÁUSULA 8ª
                      confidence: 0.94
                      page: 4
                    clauseExcerpt:
                      value: A administração da sociedade caberá isoladamente ao sócio CARLOS EDUARDO SILVA...
                      confidence: 0.94
                      page: 4
                  certification:
                    certificationKind:
                      value: ORGAO_EMISSOR
                      confidence: 0.97
                      page: 1
                    certificationDetail:
                      value: Chancela digital da Junta Comercial
                      confidence: 0.96
                      page: 1
                    verificationCode:
                      value: A1B2C3D4E5
                      confidence: 0.98
                      page: 1
                fieldConfidences:
                  cnpj: 0.97
                  companyName: 0.96
                  capitalAmount: 0.95
                validation:
                  checks:
                    - code: EXPECTED_DOCUMENT_MATCH
                      result: PASS
                      message: O CNPJ do documento é o mesmo da análise.
                      evidence:
                        page: 1
                        excerpt: CNPJ 11.444.777/0001-61
                      source: DETERMINISTIC
                    - code: QSA_SHARE_SUM
                      result: WARN
                      message: 'A soma das participações fecha 98%, fora da tolerância de 0,5 ponto.'
                      evidence:
                        page: 3
                        excerpt: CARLOS EDUARDO SILVA 60% ... MARIA HELENA SOUZA 38%
                      source: DETERMINISTIC
                  reconciliation:
                    qsaMatched: true
                assessment:
                  verdict: VALIDO
                  score: 0.91
                  justification: 'Documento íntegro, titularidade confirmada e registro na Junta conferido. A soma das quotas ficou 2 pontos abaixo de 100%, o que é ressalva e não impedimento.'
                  evidences: []
                  ruleSetVersion: org-v7
                  contentHash: 9f2b7c1e4a...
                  feedbackVerdict: null
                  feedbackComment: null
                  feedbackAt: null
                  feedbackUserId: null
                  effectiveVerdict: VALIDO
                  decidedByOperator: false
                processedAt: '2026-09-05T13:07:44.000Z'
                attempt: 1
        '400':
          description: Identificador fora do formato ObjectId (24 caracteres hexadecimais).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 400
                message: O identificador informado em "docId" não é válido.
        '401':
          description: 'Token ausente, expirado ou invalido. Gere outro em POST /auth/authenticate.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 401
                message: Token de acesso inválido.
        '403':
          description: O usuario autenticado nao tem a permissao exigida pela rota.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 403
                message: Você não tem permissão para acessar este recurso.
        '404':
          description: 'Recurso inexistente OU capacidade nao liberada para a organizacao. As duas coisas respondem 404 de proposito: para quem nao tem o modulo, a rota nao existe.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 404
                message: Documento não encontrado.
        '500':
          description: 'Falha nossa. Tente de novo; se persistir, acione o suporte com o horario da chamada.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 500
                message: Internal server error
        '502':
          description: O servico de cadastro nao respondeu. Tente de novo.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 502
                message: Não foi possível consultar o resultado do documento.
      tags:
        - registry
      security:
        - authorization: []
      x-codeSamples:
        - lang: cURL
          label: cURL
          source: |
              curl --request GET 'https://gyra-core.gyramais.com.br/v1/registry/6612a7f30000000000000001/documents/6612a7f30000000000000001/result' \
                --header 'Authorization: Bearer <token>'
        - lang: JavaScript
          label: Node
          source: |
              const resposta = await fetch("https://gyra-core.gyramais.com.br/v1/registry/6612a7f30000000000000001/documents/6612a7f30000000000000001/result", {
                method: "GET",
                headers: { Authorization: `Bearer ${token}` },
              });
              
              const dados = await resposta.json();
        - lang: Python
          label: Python
          source: |
              import requests
              
              resposta = requests.get(
                  "https://gyra-core.gyramais.com.br/v1/registry/6612a7f30000000000000001/documents/6612a7f30000000000000001/result",
                  headers={"Authorization": f"Bearer {token}"},
              )
              
              dados = resposta.json()
  /v1/registry/{id}/documents/{docId}/reprocess:
    post:
      operationId: RegistryController_reprocessDocument
      summary: Reprocessar um documento
      description: |
          Roda o pipeline de novo. Sem `stages`, roda inteiro; com um subconjunto de
          CLASSIFY/EXTRACT/VALIDATE, as etapas de fora reaproveitam a tentativa anterior.
          
          Duas regras que evitam surpresa: pular EXTRACT so funciona quando existe extracao gravada antes,
          e reexecutar EXTRACT sempre revalida. Confira stages.executed e stages.reused no resultado.
          
          `forceType` corrige uma classificacao errada; como afirma o tipo, a conferencia
          EXPECTED_TYPE_MATCH sai SKIP naquela tentativa.
          
          REPROCESSAR NAO COBRA DE NOVO: a cobranca e por documento, nao por tentativa.
      parameters:
        - name: id
          required: true
          in: path
          schema:
            type: string
          description: Id do cadastro.
        - name: docId
          required: true
          in: path
          schema:
            type: string
          description: Id do documento.
      requestBody:
        required: false
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ReprocessRegistryDocumentDto'
            example:
              stages:
                - VALIDATE
              forceType: ALTERACAO_CONTRATUAL
      responses:
        '202':
          description: 'Confirmacao do reprocessamento (202), com a tentativa nova. O documento volta a RECEIVED.'
          content:
            application/json:
              schema:
                type: object
                properties:
                  documentId:
                    type: string
                  status:
                    type: string
                    description: Sempre RECEIVED nesta resposta.
                  attempt:
                    type: integer
                    description: A tentativa que acabou de comecar.
              example:
                documentId: 6612a7f30000000000000031
                status: RECEIVED
                attempt: 2
        '400':
          description: 'Corpo invalido (etapa fora de CLASSIFY/EXTRACT/VALIDATE, tipo fora da lista, URL invalida) ou identificador fora do formato ObjectId.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 400
                message: 'each value in stages must be one of the following values: CLASSIFY, EXTRACT, VALIDATE'
        '401':
          description: 'Token ausente, expirado ou invalido. Gere outro em POST /auth/authenticate.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 401
                message: Token de acesso inválido.
        '403':
          description: O usuario autenticado nao tem a permissao exigida pela rota.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 403
                message: Você não tem permissão para acessar este recurso.
        '404':
          description: 'Recurso inexistente OU capacidade nao liberada para a organizacao. As duas coisas respondem 404 de proposito: para quem nao tem o modulo, a rota nao existe.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 404
                message: Documento não encontrado.
        '409':
          description: Um operador ja decidiu este documento. Mande overrideFeedback true para substituir a decisao pelo parecer novo.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 409
                message: Este documento já foi decidido por um operador. Reprocessar vai substituir essa decisão pelo novo parecer.
        '429':
          description: O documento ja chegou ao limite de 5 tentativas.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 429
                message: Limite de reprocessamentos atingido.
        '500':
          description: 'Falha nossa. Tente de novo; se persistir, acione o suporte com o horario da chamada.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 500
                message: Internal server error
        '502':
          description: O servico de cadastro nao respondeu. Tente de novo.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 502
                message: Não foi possível reprocessar o documento.
      tags:
        - registry
      security:
        - authorization: []
      x-codeSamples:
        - lang: cURL
          label: cURL
          source: |
              curl --request POST 'https://gyra-core.gyramais.com.br/v1/registry/6612a7f30000000000000001/documents/6612a7f30000000000000001/reprocess' \
                --header 'Authorization: Bearer <token>' \
                --header 'Content-Type: application/json' \
                --data '{"stages":["VALIDATE"],"forceType":"ALTERACAO_CONTRATUAL"}'
        - lang: JavaScript
          label: Node
          source: |
              const resposta = await fetch("https://gyra-core.gyramais.com.br/v1/registry/6612a7f30000000000000001/documents/6612a7f30000000000000001/reprocess", {
                method: "POST",
                headers: {
                  Authorization: `Bearer ${token}`,
                  "Content-Type": "application/json",
                },
                body: JSON.stringify({
                  "stages": [
                    "VALIDATE"
                  ],
                  "forceType": "ALTERACAO_CONTRATUAL"
                }),
              });
              
              const dados = await resposta.json();
        - lang: Python
          label: Python
          source: |
              import requests
              
              resposta = requests.post(
                  "https://gyra-core.gyramais.com.br/v1/registry/6612a7f30000000000000001/documents/6612a7f30000000000000001/reprocess",
                  headers={"Authorization": f"Bearer {token}"},
                  json={
                      "stages": [
                          "VALIDATE"
                      ],
                      "forceType": "ALTERACAO_CONTRATUAL"
                  },
              )
              
              dados = resposta.json()
  /v1/registry/{id}/persons:
    get:
      operationId: RegistryController_persons
      summary: Arvore societaria do cadastro
      parameters:
        - name: id
          required: true
          in: path
          schema:
            type: string
          description: Id do cadastro.
      responses:
        '200':
          description: 'Pessoas com nome, documento, papel, participacao, origem, campos corrigidos e o primeiro contato guardado, dentro de `persons`.'
          content:
            application/json:
              schema:
                type: object
                properties:
                  persons:
                    type: array
                    items:
                      $ref: '#/components/schemas/RegistryPerson'
              example:
                persons:
                  - id: 6612a7f30000000000000021
                    registryId: 6612a7f30000000000000001
                    entityType: PERSON
                    document: '52998224725'
                    maskedDocument: null
                    name: CARLOS EDUARDO SILVA
                    role: Sócio administrador
                    sharePercent: 60
                    layer: 1
                    parentPersonId: null
                    isBeneficialOwner: true
                    source: FORM
                    linkedRegistryId: null
                    editedFields: []
                    contact:
                      name: CARLOS EDUARDO SILVA
                      email: carlos@aurora.com.br
                      phone: '51999998888'
                      source: FORM
                      preferred: false
                      lastUsedAt: '2026-09-05T14:20:00.000Z'
                  - id: 6612a7f30000000000000022
                    registryId: 6612a7f30000000000000001
                    entityType: PERSON
                    document: null
                    maskedDocument: '***982247**'
                    name: MARIA HELENA SOUZA
                    role: Sócio
                    sharePercent: 38
                    layer: 1
                    parentPersonId: null
                    isBeneficialOwner: true
                    source: QSA_OFICIAL
                    linkedRegistryId: null
                    editedFields: []
                    contact: null
        '400':
          description: Identificador fora do formato ObjectId (24 caracteres hexadecimais).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 400
                message: O identificador informado em "id" não é válido.
        '401':
          description: 'Token ausente, expirado ou invalido. Gere outro em POST /auth/authenticate.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 401
                message: Token de acesso inválido.
        '403':
          description: O usuario autenticado nao tem a permissao exigida pela rota.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 403
                message: Você não tem permissão para acessar este recurso.
        '404':
          description: 'Recurso inexistente OU capacidade nao liberada para a organizacao. As duas coisas respondem 404 de proposito: para quem nao tem o modulo, a rota nao existe.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 404
                message: Cadastro não encontrado.
        '500':
          description: 'Falha nossa. Tente de novo; se persistir, acione o suporte com o horario da chamada.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 500
                message: Internal server error
      tags:
        - registry
      security:
        - authorization: []
      description: |
          Socios e administradores do cadastro, por camada e da maior participacao para a menor, com a
          origem de cada um: QSA_OFICIAL (quadro societario da fonte oficial), DOCUMENT_EXTRACTION (lido
          de contrato, estatuto, ata ou certidao), MANUAL (criado por um operador) ou FORM (declarado
          pelo cliente num formulario de solicitacao).
          
          `editedFields` lista os campos que um operador corrigiu; a atualizacao do quadro oficial nao
          passa por cima deles. `contact` e o primeiro contato guardado da pessoa (o preferido, senao o
          mais recente), ou null.
          
          E a base para pedir documento de socio: cada pessoa pode ganhar cadastro proprio.
      x-codeSamples:
        - lang: cURL
          label: cURL
          source: |
              curl --request GET 'https://gyra-core.gyramais.com.br/v1/registry/6612a7f30000000000000001/persons' \
                --header 'Authorization: Bearer <token>'
        - lang: JavaScript
          label: Node
          source: |
              const resposta = await fetch("https://gyra-core.gyramais.com.br/v1/registry/6612a7f30000000000000001/persons", {
                method: "GET",
                headers: { Authorization: `Bearer ${token}` },
              });
              
              const dados = await resposta.json();
        - lang: Python
          label: Python
          source: |
              import requests
              
              resposta = requests.get(
                  "https://gyra-core.gyramais.com.br/v1/registry/6612a7f30000000000000001/persons",
                  headers={"Authorization": f"Bearer {token}"},
              )
              
              dados = resposta.json()
  /v1/webhook/events:
    get:
      operationId: WebhookController_catalog
      summary: Catalogo de eventos de webhook disponiveis
      parameters: []
      responses:
        '200':
          description: 'Grupos com titulo e a lista de nomes de evento, mais a lista plana.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WebhookEventCatalog'
              example:
                groups:
                  - title: Relatórios e crédito
                    events:
                      - report.section.updated
                      - report.finished
                      - report.status.changed
                      - report.exported
                      - committee.finished
                      - credit-policy.evaluated
                      - operation.updated
                      - optin.updated
                  - title: Documento
                    events:
                      - registry.document.received
                      - registry.document.progress
                      - registry.document.assessed
                      - registry.document.failed
                      - registry.document.reprocessed
                      - registry.document.decided
                  - title: Cadastro
                    events:
                      - registry.updated
                      - registry.financial.extracted
                  - title: Solicitação
                    events:
                      - collection.created
                      - collection.sent
                      - collection.canceled
                      - collection.completed
                      - collection.expired
                  - title: Mensagens
                    events:
                      - collection.message.sent
                      - collection.message.reminded
                      - collection.recipient.opened
                      - collection.message.failed
                events:
                  - report.section.updated
                  - report.finished
                  - report.status.changed
                  - report.exported
                  - committee.finished
                  - credit-policy.evaluated
                  - operation.updated
                  - optin.updated
                  - registry.document.received
                  - registry.document.assessed
                  - collection.completed
                  - collection.message.failed
                eventLabels:
                  report.section.updated: Seção do relatório atualizada
                  report.finished: Relatório concluído
                  report.status.changed: Relatório aprovado ou negado
                  report.exported: PDF do relatório pronto
                  committee.finished: Comitê de crédito concluiu a deliberação
                  credit-policy.evaluated: Política de crédito avaliada
                  operation.updated: Operação atualizada
                  optin.updated: Opt-in atualizado
        '401':
          description: 'Token ausente, expirado ou invalido. Gere outro em POST /auth/authenticate.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 401
                message: Token de acesso inválido.
        '403':
          description: O usuario autenticado nao tem a permissao exigida pela rota.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 403
                message: Você não tem permissão para acessar este recurso.
        '500':
          description: 'Falha nossa. Tente de novo; se persistir, acione o suporte com o horario da chamada.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 500
                message: Internal server error
      tags:
        - collections
      security:
        - authorization: []
      description: |
          Todos os eventos que a organizacao pode assinar, agrupados por categoria.
          
          Categorias: Documento (registry.document.*), Cadastro (registry.*), Solicitacao (collection.*),
          Itens (collection.item.*), Formulario e assinatura, Mensagens, e Relatorios e credito
          (report.finished, credit-policy.evaluated, committee.finished e os demais).
          
          LEIA DAQUI em vez de fixar a lista: evento novo aparece no catalogo no mesmo deploy.
      x-codeSamples:
        - lang: cURL
          label: cURL
          source: |
              curl --request GET 'https://gyra-core.gyramais.com.br/v1/webhook/events' \
                --header 'Authorization: Bearer <token>'
        - lang: JavaScript
          label: Node
          source: |
              const resposta = await fetch("https://gyra-core.gyramais.com.br/v1/webhook/events", {
                method: "GET",
                headers: { Authorization: `Bearer ${token}` },
              });
              
              const dados = await resposta.json();
        - lang: Python
          label: Python
          source: |
              import requests
              
              resposta = requests.get(
                  "https://gyra-core.gyramais.com.br/v1/webhook/events",
                  headers={"Authorization": f"Bearer {token}"},
              )
              
              dados = resposta.json()
  /v1/webhook/endpoints:
    get:
      operationId: WebhookController_list
      summary: Assinaturas de webhook configuradas
      parameters: []
      responses:
        '200':
          description: 'Assinaturas com url, label, events, enabled, secretHint e ultimo status de entrega.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WebhookEndpointListResponse'
              example:
                endpoints:
                  - id: 6612a7f30000000000000091
                    url: 'https://api.suaempresa.com/gyra/webhook'
                    label: 'Produção, esteira de crédito'
                    events:
                      - registry.document.assessed
                      - collection.completed
                    enabled: true
                    secretHint: …egredo
                    consecutiveFailures: 0
                    lastDeliveryStatus: 200
                    lastDeliveryError: null
                    lastDeliveryAt: '2026-09-06T09:58:11.000Z'
                    createdAt: '2026-09-05T18:40:00.000Z'
                    updatedAt: '2026-09-06T09:58:11.000Z'
        '401':
          description: 'Token ausente, expirado ou invalido. Gere outro em POST /auth/authenticate.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 401
                message: Token de acesso inválido.
        '403':
          description: O usuario autenticado nao tem a permissao exigida pela rota.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 403
                message: Você não tem permissão para acessar este recurso.
        '500':
          description: 'Falha nossa. Tente de novo; se persistir, acione o suporte com o horario da chamada.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 500
                message: Internal server error
      tags:
        - collections
      security:
        - authorization: []
      description: |
          As assinaturas da organizacao, com URL, rotulo, eventos escutados, se esta ativa e o
          estado da ultima entrega.
          
          O segredo NAO volta aqui: so uma dica com os ultimos caracteres. Ele e mostrado uma unica vez,
          na criacao e na rotacao.
          
          Assinatura que acumula 20 falhas seguidas e desligada sozinha, com o motivo. Se o cliente diz que
          "parou de receber", e a primeira coisa a olhar.
      x-codeSamples:
        - lang: cURL
          label: cURL
          source: |
              curl --request GET 'https://gyra-core.gyramais.com.br/v1/webhook/endpoints' \
                --header 'Authorization: Bearer <token>'
        - lang: JavaScript
          label: Node
          source: |
              const resposta = await fetch("https://gyra-core.gyramais.com.br/v1/webhook/endpoints", {
                method: "GET",
                headers: { Authorization: `Bearer ${token}` },
              });
              
              const dados = await resposta.json();
        - lang: Python
          label: Python
          source: |
              import requests
              
              resposta = requests.get(
                  "https://gyra-core.gyramais.com.br/v1/webhook/endpoints",
                  headers={"Authorization": f"Bearer {token}"},
              )
              
              dados = resposta.json()
    post:
      operationId: WebhookController_save
      summary: Criar ou atualizar uma assinatura de webhook
      description: |
          Cria (sem id) ou atualiza (com id) uma assinatura de webhook. A mesma assinatura pode escutar
          eventos do Onboarding e eventos de relatorio e credito.
          
          Quando os eventos de relatorio e credito nao puderem ser gravados (o endereco precisa responder
          a um POST de teste no momento do cadastro), a resposta continua 200 e traz `warning` com o motivo.
          
          LISTA DE EVENTOS VAZIA QUER DIZER TODOS. Quem esta comecando nao sabe de quais precisa, e
          escolher antes de conhecer produz assinatura errada e evento perdido em silencio.
          
          O segredo e gerado pela plataforma e devolvido UMA VEZ, na criacao. Ele e por assinatura: um
          endpoint comprometido nao permite forjar evento para os outros.
          
          A URL precisa ser publica; endereco interno e recusado, e o nome e resolvido de novo a cada
          tentativa de entrega.
          
          Confira a assinatura com HMAC_SHA256(segredo, "<X-Gyra-Timestamp>.<corpo cru>") e recuse o que
          estiver fora de uma janela de cinco minutos.
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SaveWebhookEndpointDto'
            example:
              url: 'https://api.suaempresa.com/gyra/webhook'
              label: 'Produção, esteira de crédito'
              events:
                - registry.document.assessed
                - collection.completed
                - collection.message.failed
              enabled: true
      responses:
        '200':
          description: 'Assinatura salva. Na criacao e na rotacao, inclui o secret em claro (unica vez).'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WebhookEndpointSaved'
              example:
                id: 6612a7f30000000000000091
                url: 'https://api.suaempresa.com/gyra/webhook'
                label: 'Produção, esteira de crédito'
                events:
                  - registry.document.assessed
                  - collection.completed
                  - collection.message.failed
                enabled: true
                secretHint: …egredo
                secret: whsec_exemplo_nao_e_um_segredo
                createdAt: '2026-09-05T18:40:00.000Z'
                organizationId: 6612a7f30000000000000009
                consecutiveFailures: 0
                lastDeliveryStatus: null
                lastDeliveryError: null
                lastDeliveryAt: null
                updatedAt: '2026-09-06T10:12:00.000Z'
        '400':
          description: 'Corpo invalido (URL fora do formato, evento repetido, rotulo acima de 80 caracteres). A mensagem concatena todas as falhas por virgula.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 400
                message: url must be a URL address
        '401':
          description: 'Token ausente, expirado ou invalido. Gere outro em POST /auth/authenticate.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 401
                message: Token de acesso inválido.
        '403':
          description: O usuario autenticado nao tem a permissao exigida pela rota.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 403
                message: Você não tem permissão para acessar este recurso.
        '404':
          description: 'id de assinatura inexistente na atualizacao, ou modulo nao liberado ("Recurso não encontrado.").'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 404
                message: Assinatura de webhook não encontrada.
        '500':
          description: 'Falha nossa. Tente de novo; se persistir, acione o suporte com o horario da chamada.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 500
                message: Internal server error
        '502':
          description: O servico de webhooks nao respondeu. Tente de novo.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 502
                message: Não foi possível salvar a assinatura.
      tags:
        - collections
      security:
        - authorization: []
      x-codeSamples:
        - lang: cURL
          label: cURL
          source: |
              curl --request POST 'https://gyra-core.gyramais.com.br/v1/webhook/endpoints' \
                --header 'Authorization: Bearer <token>' \
                --header 'Content-Type: application/json' \
                --data '{"url":"https://api.suaempresa.com/gyra/webhook","label":"Produção, esteira de crédito","events":["registry.document.assessed","collection.completed","collection.message.failed"],"enabled":true}'
        - lang: JavaScript
          label: Node
          source: |
              const resposta = await fetch("https://gyra-core.gyramais.com.br/v1/webhook/endpoints", {
                method: "POST",
                headers: {
                  Authorization: `Bearer ${token}`,
                  "Content-Type": "application/json",
                },
                body: JSON.stringify({
                  "url": "https://api.suaempresa.com/gyra/webhook",
                  "label": "Produção, esteira de crédito",
                  "events": [
                    "registry.document.assessed",
                    "collection.completed",
                    "collection.message.failed"
                  ],
                  "enabled": true
                }),
              });
              
              const dados = await resposta.json();
        - lang: Python
          label: Python
          source: |
              import requests
              
              resposta = requests.post(
                  "https://gyra-core.gyramais.com.br/v1/webhook/endpoints",
                  headers={"Authorization": f"Bearer {token}"},
                  json={
                      "url": "https://api.suaempresa.com/gyra/webhook",
                      "label": "Produção, esteira de crédito",
                      "events": [
                          "registry.document.assessed",
                          "collection.completed",
                          "collection.message.failed"
                      ],
                      "enabled": True
                  },
              )
              
              dados = resposta.json()
  /v1/collections:
    post:
      operationId: CollectionController_create
      summary: Criar uma solicitacao de documentos ao cliente
      description: |
          Cria o pedido a partir de um MODELO e manda o link para um ou mais destinatarios.
          
          O modelo diz O QUE se pede (documento, formulario, termo, assinatura, identidade); aqui voce diz
          PARA QUEM e SOBRE QUEM. Use list_collection_templates para descobrir os modelos disponiveis.
          
          O cadastro e obrigatorio, por `document` (CNPJ/CPF, e o cadastro e resolvido ou criado) ou por
          `registryId`. Um dos dois.
          
          CANAL: EMAIL, WHATSAPP, BOTH, ou NONE. Com NONE a plataforma NAO avisa ninguem: a solicitacao e
          criada, os links voltam na resposta (publicUrl e links[]) e quem entrega e voce. Lembrete tambem
          nao sai. E o caminho para quem ja fala com o cliente pelo canal proprio.
          
          O que o cadastro ja tem e validado nao e pedido de novo. Para pedir mesmo assim, liste as chaves
          em `forceItemKeys`.
          
          Com `draft: true` (ou send: false), cria sem enviar.
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateCollectionDto'
            example:
              template: onboarding-pj
              document: 11.444.777/0001-61
              recipients:
                - name: Ana Souza
                  document: 529.982.247-25
                  email: ana@exemplo.com.br
                  phone: +5551999998888
                  role: Sócia administradora · 60%
              dueInDays: 10
              channel: BOTH
              responseMode: REVIEW
              message: Precisamos destes documentos para liberar seu limite.
              callbackUrl: 'https://api.suaempresa.com/gyra/kyc'
              send: true
      responses:
        '201':
          description: 'Solicitacao com id, status, dueAt, publicUrl, links[] por destinatario e a lista de itens.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CollectionCreateResponse'
              example:
                id: 6612a7f30000000000000051
                registryId: 6612a7f30000000000000001
                templateId: 6612a7f30000000000000041
                templateSlug: onboarding-pj
                templateName: Onboarding PJ
                templateVersion: 3
                status: SENT
                responseMode: REVIEW
                channel: BOTH
                reminders:
                  - 2
                  - 5
                behavior:
                  acceptPartial: false
                  requestResendOnReject: true
                  notifyOnComplete: true
                  skipItemsAlreadyOnFile: true
                message: Precisamos destes documentos para liberar seu limite.
                dueAt: '2026-09-15T23:59:59.000Z'
                sentAt: '2026-09-05T14:20:00.000Z'
                completedAt: null
                canceledAt: null
                subjectName: AURORA COMPONENTES INDUSTRIAIS LTDA
                subjectDocument: '11444777000161'
                items:
                  - id: 6612a7f30000000000000071
                    collectionId: 6612a7f30000000000000051
                    recipientId: 6612a7f30000000000000061
                    order: 1
                    kind: DOCUMENT
                    documentType: CONTRATO_SOCIAL
                    label: Contrato social consolidado
                    instructions: 'Envie a última alteração consolidada, com a chancela da Junta.'
                    required: true
                    rules:
                      maxAgeDays: 365
                      allowMultipleFiles: true
                      maxFiles: 5
                    status: PENDING
                    registryDocumentId: null
                    attempt: null
                    verdict: null
                    score: null
                    rejectionReason: null
                    submittedAt: null
                    resendCount: 0
                    files: []
                    signatureMode: INDIVIDUAL
                    signaturePackage: null
                    resolvedAt: null
                recipients:
                  - id: 6612a7f30000000000000061
                    collectionId: 6612a7f30000000000000051
                    name: Ana Souza
                    document: '52998224725'
                    email: ana@exemplo.com.br
                    phone: 5551999998888
                    role: Sócia administradora · 60%
                    registryPersonId: 6612a7f30000000000000021
                    status: DELIVERED
                    emailDelivery: DELIVERED
                    whatsappDelivery: SENT
                    deliveryError: null
                    tokenExpiresAt: '2026-09-15T23:59:59.000Z'
                    lastSentAt: '2026-09-05T14:20:03.000Z'
                    openedAt: null
                    completedAt: null
                    remindersSent: 0
                    lastReminderAt: null
                    revoked: false
                createdAt: '2026-09-05T14:19:58.000Z'
                updatedAt: '2026-09-05T14:20:03.000Z'
                collectionId: 6612a7f30000000000000051
                publicUrl: 'https://toolbox.gyramais.com.br/envio/2f8cQ1r7aWxK9pLmN3bV5tYzE6uH0sJdR4gXoC8ifAe'
                notified: true
                links:
                  - recipientId: 6612a7f30000000000000061
                    name: Ana Souza
                    document: '52998224725'
                    link: 'https://toolbox.gyramais.com.br/envio/2f8cQ1r7aWxK9pLmN3bV5tYzE6uH0sJdR4gXoC8ifAe'
                    publicUrl: 'https://toolbox.gyramais.com.br/envio/2f8cQ1r7aWxK9pLmN3bV5tYzE6uH0sJdR4gXoC8ifAe'
        '400':
          description: Corpo invalido. A mensagem concatena todas as falhas por virgula.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 400
                message: Informe o documento ou o identificador do cadastro.
        '401':
          description: 'Token ausente, expirado ou invalido. Gere outro em POST /auth/authenticate.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 401
                message: Token de acesso inválido.
        '403':
          description: O usuario autenticado nao tem a permissao exigida pela rota.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 403
                message: Você não tem permissão para acessar este recurso.
        '404':
          description: 'Modelo inexistente ("Modelo não encontrado."), registryId inexistente ("Cadastro não encontrado.") ou modulo nao liberado para a organizacao ("Recurso não encontrado.").'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 404
                message: Modelo não encontrado.
        '500':
          description: 'Falha nossa. Tente de novo; se persistir, acione o suporte com o horario da chamada.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 500
                message: Internal server error
        '502':
          description: O servico de solicitacoes nao respondeu. Tente de novo.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 502
                message: Não foi possível criar a solicitação.
      tags:
        - collections
      security:
        - authorization: []
      x-codeSamples:
        - lang: cURL
          label: cURL
          source: |
              curl --request POST 'https://gyra-core.gyramais.com.br/v1/collections' \
                --header 'Authorization: Bearer <token>' \
                --header 'Content-Type: application/json' \
                --data '{"template":"onboarding-pj","document":"11.444.777/0001-61","recipients":[{"name":"Ana Souza","document":"529.982.247-25","email":"ana@exemplo.com.br","phone":"+5551999998888","role":"Sócia administradora · 60%"}],"dueInDays":10,"channel":"BOTH","responseMode":"REVIEW","message":"Precisamos destes documentos para liberar seu limite.","callbackUrl":"https://api.suaempresa.com/gyra/kyc","send":true}'
        - lang: JavaScript
          label: Node
          source: |
              const resposta = await fetch("https://gyra-core.gyramais.com.br/v1/collections", {
                method: "POST",
                headers: {
                  Authorization: `Bearer ${token}`,
                  "Content-Type": "application/json",
                },
                body: JSON.stringify({
                  "template": "onboarding-pj",
                  "document": "11.444.777/0001-61",
                  "recipients": [
                    {
                      "name": "Ana Souza",
                      "document": "529.982.247-25",
                      "email": "ana@exemplo.com.br",
                      "phone": "+5551999998888",
                      "role": "Sócia administradora · 60%"
                    }
                  ],
                  "dueInDays": 10,
                  "channel": "BOTH",
                  "responseMode": "REVIEW",
                  "message": "Precisamos destes documentos para liberar seu limite.",
                  "callbackUrl": "https://api.suaempresa.com/gyra/kyc",
                  "send": true
                }),
              });
              
              const dados = await resposta.json();
        - lang: Python
          label: Python
          source: |
              import requests
              
              resposta = requests.post(
                  "https://gyra-core.gyramais.com.br/v1/collections",
                  headers={"Authorization": f"Bearer {token}"},
                  json={
                      "template": "onboarding-pj",
                      "document": "11.444.777/0001-61",
                      "recipients": [
                          {
                              "name": "Ana Souza",
                              "document": "529.982.247-25",
                              "email": "ana@exemplo.com.br",
                              "phone": "+5551999998888",
                              "role": "Sócia administradora · 60%"
                          }
                      ],
                      "dueInDays": 10,
                      "channel": "BOTH",
                      "responseMode": "REVIEW",
                      "message": "Precisamos destes documentos para liberar seu limite.",
                      "callbackUrl": "https://api.suaempresa.com/gyra/kyc",
                      "send": True
                  },
              )
              
              dados = resposta.json()
    get:
      operationId: CollectionController_list
      summary: Listar solicitacoes
      parameters:
        - name: status
          required: false
          in: query
          schema:
            type: array
            items:
              type: string
              enum:
                - DRAFT
                - SENT
                - IN_PROGRESS
                - COMPLETED
                - EXPIRED
                - CANCELED
          description: Um ou mais status. Repita o parametro para varios.
        - name: registryId
          required: false
          in: query
          schema:
            type: string
          description: Filtra por cadastro.
        - name: document
          required: false
          in: query
          description: Filtra pelo CNPJ/CPF do cadastro.
          schema:
            type: string
        - name: search
          required: false
          in: query
          description: Casa por nome ou documento.
          schema:
            maxLength: 120
            type: string
        - name: templateId
          required: false
          in: query
          schema:
            type: string
          description: Filtra por modelo.
        - name: from
          required: false
          in: query
          description: 'Inicio do periodo de criacao, ISO 8601.'
          schema:
            type: string
        - name: to
          required: false
          in: query
          description: 'Fim do periodo de criacao, ISO 8601.'
          schema:
            type: string
        - name: skip
          required: false
          in: query
          schema:
            type: number
          description: Deslocamento da pagina.
        - name: take
          required: false
          in: query
          schema:
            maximum: 100
            type: number
          description: Tamanho da pagina.
      responses:
        '200':
          description: 'Pagina de solicitacoes com status, cadastro, prazo e progresso.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CollectionListResponse'
              example:
                items:
                  - id: 6612a7f30000000000000051
                    registryId: 6612a7f30000000000000001
                    templateId: 6612a7f30000000000000041
                    templateName: Onboarding PJ
                    status: IN_PROGRESS
                    responseMode: REVIEW
                    channel: BOTH
                    subjectName: AURORA COMPONENTES INDUSTRIAIS LTDA
                    subjectDocument: '11444777000161'
                    itemsTotal: 5
                    itemsResolved: 3
                    itemsAwaitingOperator: 1
                    dueAt: '2026-09-15T23:59:59.000Z'
                    sentAt: '2026-09-05T14:20:00.000Z'
                    progress:
                      total: 5
                      resolved: 3
                      validated: 3
                      awaitingOperator: 1
                      rejected: 0
                      pending: 1
                    hasScrConsent: true
                    scrConsentItemId: 6612a7f30000000000000073
                    signingDueAt: null
                    createdAt: '2026-09-05T14:19:58.000Z'
                    updatedAt: '2026-09-06T09:11:20.000Z'
                total: 1
        '400':
          description: 'Parametro invalido (status fora da lista, data fora do ISO 8601, take acima de 100). A mensagem concatena todas as falhas por virgula.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 400
                message: take must not be greater than 100
        '401':
          description: 'Token ausente, expirado ou invalido. Gere outro em POST /auth/authenticate.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 401
                message: Token de acesso inválido.
        '403':
          description: O usuario autenticado nao tem a permissao exigida pela rota.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 403
                message: Você não tem permissão para acessar este recurso.
        '500':
          description: 'Falha nossa. Tente de novo; se persistir, acione o suporte com o horario da chamada.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 500
                message: Internal server error
      tags:
        - collections
      security:
        - authorization: []
      description: |
          Lista as solicitacoes da organizacao, com filtro por situacao, cadastro, modelo e periodo.
          
          Situacoes: DRAFT, SENT, IN_PROGRESS, COMPLETED, EXPIRED, CANCELED.
          
          E a tool para responder "quem esta devendo documento?" -- filtre por SENT e IN_PROGRESS e olhe
          o prazo.
      x-codeSamples:
        - lang: cURL
          label: cURL
          source: |
              curl --request GET 'https://gyra-core.gyramais.com.br/v1/collections' \
                --header 'Authorization: Bearer <token>'
        - lang: JavaScript
          label: Node
          source: |
              const resposta = await fetch("https://gyra-core.gyramais.com.br/v1/collections", {
                method: "GET",
                headers: { Authorization: `Bearer ${token}` },
              });
              
              const dados = await resposta.json();
        - lang: Python
          label: Python
          source: |
              import requests
              
              resposta = requests.get(
                  "https://gyra-core.gyramais.com.br/v1/collections",
                  headers={"Authorization": f"Bearer {token}"},
              )
              
              dados = resposta.json()
  /v1/collections/{id}:
    get:
      operationId: CollectionController_findOne
      summary: Detalhe de uma solicitacao
      parameters:
        - name: id
          required: true
          in: path
          schema:
            type: string
          description: Id da solicitacao.
      responses:
        '200':
          description: 'Solicitacao com itens, destinatarios, links e trilha.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Collection'
              example:
                id: 6612a7f30000000000000051
                registryId: 6612a7f30000000000000001
                templateId: 6612a7f30000000000000041
                templateSlug: onboarding-pj
                templateName: Onboarding PJ
                templateVersion: 3
                status: SENT
                responseMode: REVIEW
                channel: BOTH
                reminders:
                  - 2
                  - 5
                behavior:
                  acceptPartial: false
                  requestResendOnReject: true
                  notifyOnComplete: true
                  skipItemsAlreadyOnFile: true
                message: Precisamos destes documentos para liberar seu limite.
                dueAt: '2026-09-15T23:59:59.000Z'
                sentAt: '2026-09-05T14:20:00.000Z'
                completedAt: null
                canceledAt: null
                subjectName: AURORA COMPONENTES INDUSTRIAIS LTDA
                subjectDocument: '11444777000161'
                items:
                  - id: 6612a7f30000000000000071
                    collectionId: 6612a7f30000000000000051
                    recipientId: 6612a7f30000000000000061
                    order: 1
                    kind: DOCUMENT
                    documentType: CONTRATO_SOCIAL
                    label: Contrato social consolidado
                    instructions: 'Envie a última alteração consolidada, com a chancela da Junta.'
                    required: true
                    rules:
                      maxAgeDays: 365
                      allowMultipleFiles: true
                      maxFiles: 5
                    status: PENDING
                    registryDocumentId: null
                    attempt: null
                    verdict: null
                    score: null
                    rejectionReason: null
                    submittedAt: null
                    resendCount: 0
                    files: []
                    signatureMode: INDIVIDUAL
                    signaturePackage: null
                    resolvedAt: null
                recipients:
                  - id: 6612a7f30000000000000061
                    collectionId: 6612a7f30000000000000051
                    name: Ana Souza
                    document: '52998224725'
                    email: ana@exemplo.com.br
                    phone: +5551999998888
                    role: Sócia administradora · 60%
                    registryPersonId: 6612a7f30000000000000021
                    status: DELIVERED
                    emailDelivery: DELIVERED
                    whatsappDelivery: SENT
                    deliveryError: null
                    tokenExpiresAt: '2026-09-15T23:59:59.000Z'
                    lastSentAt: '2026-09-05T14:20:03.000Z'
                    openedAt: null
                    completedAt: null
                    remindersSent: 0
                    lastReminderAt: null
                    revoked: false
                createdAt: '2026-09-05T14:19:58.000Z'
                updatedAt: '2026-09-05T14:20:03.000Z'
        '400':
          description: 'Corpo ou parametro invalido. A mensagem aponta o campo, e concatena todas as falhas por virgula.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 400
                message: O identificador informado em "id" não é válido.
        '401':
          description: 'Token ausente, expirado ou invalido. Gere outro em POST /auth/authenticate.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 401
                message: Token de acesso inválido.
        '403':
          description: O usuario autenticado nao tem a permissao exigida pela rota.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 403
                message: Você não tem permissão para acessar este recurso.
        '404':
          description: 'Solicitacao inexistente na organizacao, ou modulo nao liberado ("Recurso não encontrado.").'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 404
                message: Solicitação não encontrada.
        '500':
          description: 'Falha nossa. Tente de novo; se persistir, acione o suporte com o horario da chamada.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 500
                message: Internal server error
      tags:
        - collections
      security:
        - authorization: []
      description: |
          Traz os itens (com status e o parecer de cada um), os destinatarios (com o estado da
          entrega), o cadastro alvo em `registry`, a contagem em `progress` e a trilha. O link de cada
          destinatario NAO volta aqui: ele so existe na resposta de criacao e na de envio.
          
          Status de item: PENDING, ALREADY_ON_FILE, SUBMITTED, PROCESSING, VALIDATED, REJECTED,
          MANUAL_REVIEW, AWAITING_OPERATOR (a IA avaliou e espera decisao humana), WAIVED, EXPIRED.
          
          Estado do destinatario: PENDING, DELIVERED, OPENED, IN_PROGRESS, COMPLETED, FAILED e
          NO_ITEMS (nao sobrou item para essa pessoa).
          
          FAILED no destinatario quer dizer que a MENSAGEM nao chegou. E o caso de ligar para o cliente.
      x-codeSamples:
        - lang: cURL
          label: cURL
          source: |
              curl --request GET 'https://gyra-core.gyramais.com.br/v1/collections/6612a7f30000000000000001' \
                --header 'Authorization: Bearer <token>'
        - lang: JavaScript
          label: Node
          source: |
              const resposta = await fetch("https://gyra-core.gyramais.com.br/v1/collections/6612a7f30000000000000001", {
                method: "GET",
                headers: { Authorization: `Bearer ${token}` },
              });
              
              const dados = await resposta.json();
        - lang: Python
          label: Python
          source: |
              import requests
              
              resposta = requests.get(
                  "https://gyra-core.gyramais.com.br/v1/collections/6612a7f30000000000000001",
                  headers={"Authorization": f"Bearer {token}"},
              )
              
              dados = resposta.json()
  /v1/collections/{id}/send:
    post:
      operationId: CollectionController_send
      summary: Enviar ou reenviar uma solicitacao
      parameters:
        - name: id
          required: true
          in: path
          schema:
            type: string
          description: Id da solicitacao.
      responses:
        '200':
          description: 'O detalhe da solicitacao (mesmo corpo de GET /v1/collections/{id}) mais os links por destinatario, `publicUrl` e `notified`. Cada destinatario enviado traz tambem `link`.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CollectionCreateResponse'
              example:
                id: 6612a7f30000000000000051
                registryId: 6612a7f30000000000000001
                templateSlug: onboarding-pj
                templateName: Onboarding PJ
                status: SENT
                channel: BOTH
                sentAt: '2026-09-05T14:20:00.000Z'
                subjectName: AURORA COMPONENTES INDUSTRIAIS LTDA
                subjectDocument: '11444777000161'
                itemsTotal: 5
                itemsResolved: 0
                itemsAwaitingOperator: 0
                publicUrl: 'https://toolbox.gyramais.com.br/envio/2f8cQ1r7aWxK9pLmN3bV5tYzE6uH0sJdR4gXoC8ifAe'
                notified: true
                links:
                  - recipientId: 6612a7f30000000000000061
                    name: Ana Souza
                    document: '52998224725'
                    link: 'https://toolbox.gyramais.com.br/envio/2f8cQ1r7aWxK9pLmN3bV5tYzE6uH0sJdR4gXoC8ifAe'
                    publicUrl: 'https://toolbox.gyramais.com.br/envio/2f8cQ1r7aWxK9pLmN3bV5tYzE6uH0sJdR4gXoC8ifAe'
        '400':
          description: 'Nenhum destinatario pendente (todos ja concluiram), ou identificador fora do formato ObjectId.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 400
                message: Nenhum destinatário pendente para enviar.
        '401':
          description: 'Token ausente, expirado ou invalido. Gere outro em POST /auth/authenticate.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 401
                message: Token de acesso inválido.
        '403':
          description: O usuario autenticado nao tem a permissao exigida pela rota.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 403
                message: Você não tem permissão para acessar este recurso.
        '404':
          description: 'Recurso inexistente OU capacidade nao liberada para a organizacao. As duas coisas respondem 404 de proposito: para quem nao tem o modulo, a rota nao existe.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 404
                message: Solicitação não encontrada.
        '409':
          description: 'A solicitacao ja foi concluida, cancelada ou expirou.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 409
                message: Esta solicitação não está mais aberta para envio.
        '500':
          description: 'Falha nossa. Tente de novo; se persistir, acione o suporte com o horario da chamada.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 500
                message: Internal server error
        '502':
          description: O servico de solicitacoes nao respondeu. Tente de novo.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 502
                message: Não foi possível enviar a solicitação.
      tags:
        - collections
      security:
        - authorization: []
      description: |
          Dispara o envio para os destinatarios que ainda nao concluiram e devolve o detalhe da
          solicitacao com os links por destinatario.
          
          Serve tanto para o primeiro envio de um rascunho quanto para reenviar um pedido que o cliente
          nao respondeu. Sem corpo: o recado do operador e o que foi gravado na criacao.
          
          Com channel NONE ninguem e avisado (`notified` false) e os links voltam so nesta resposta.
      x-codeSamples:
        - lang: cURL
          label: cURL
          source: |
              curl --request POST 'https://gyra-core.gyramais.com.br/v1/collections/6612a7f30000000000000001/send' \
                --header 'Authorization: Bearer <token>'
        - lang: JavaScript
          label: Node
          source: |
              const resposta = await fetch("https://gyra-core.gyramais.com.br/v1/collections/6612a7f30000000000000001/send", {
                method: "POST",
                headers: { Authorization: `Bearer ${token}` },
              });
              
              const dados = await resposta.json();
        - lang: Python
          label: Python
          source: |
              import requests
              
              resposta = requests.post(
                  "https://gyra-core.gyramais.com.br/v1/collections/6612a7f30000000000000001/send",
                  headers={"Authorization": f"Bearer {token}"},
              )
              
              dados = resposta.json()
  /v1/collections/{id}/cancel:
    post:
      operationId: CollectionController_cancel
      summary: Cancelar uma solicitacao
      parameters:
        - name: id
          required: true
          in: path
          schema:
            type: string
          description: Id da solicitacao.
      requestBody:
        required: false
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CancelCollectionDto'
            example:
              reason: Operação desistida pelo cliente.
      responses:
        '200':
          description: 'O detalhe da solicitacao, ja em CANCELED (mesmo corpo de GET /v1/collections/{id}).'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Collection'
              example:
                id: 6612a7f30000000000000051
                registryId: 6612a7f30000000000000001
                templateSlug: onboarding-pj
                templateName: Onboarding PJ
                status: CANCELED
                canceledAt: '2026-09-06T10:02:00.000Z'
                subjectName: AURORA COMPONENTES INDUSTRIAIS LTDA
                subjectDocument: '11444777000161'
                itemsTotal: 5
                itemsResolved: 3
                itemsAwaitingOperator: 0
        '400':
          description: 'Motivo acima de 500 caracteres, ou identificador fora do formato ObjectId.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 400
                message: reason must be shorter than or equal to 500 characters
        '401':
          description: 'Token ausente, expirado ou invalido. Gere outro em POST /auth/authenticate.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 401
                message: Token de acesso inválido.
        '403':
          description: O usuario autenticado nao tem a permissao exigida pela rota.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 403
                message: Você não tem permissão para acessar este recurso.
        '404':
          description: 'Recurso inexistente OU capacidade nao liberada para a organizacao. As duas coisas respondem 404 de proposito: para quem nao tem o modulo, a rota nao existe.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 404
                message: Solicitação não encontrada.
        '409':
          description: 'A solicitacao ja esta concluida, cancelada ou expirada.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 409
                message: Esta solicitação já está encerrada.
        '500':
          description: 'Falha nossa. Tente de novo; se persistir, acione o suporte com o horario da chamada.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 500
                message: Internal server error
        '502':
          description: 'O servico de solicitacoes nao respondeu, ou a Clicksign recusou o cancelamento do contrato (nesse caso a mensagem diz o motivo).'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 502
                message: Não foi possível cancelar a solicitação.
      tags:
        - collections
      security:
        - authorization: []
      description: |
          Encerra a solicitacao. Corpo opcional, com `reason` de ate 500 caracteres. Os links param de funcionar e nenhum lembrete sai.
          
          O motivo fica na trilha.
      x-codeSamples:
        - lang: cURL
          label: cURL
          source: |
              curl --request POST 'https://gyra-core.gyramais.com.br/v1/collections/6612a7f30000000000000001/cancel' \
                --header 'Authorization: Bearer <token>' \
                --header 'Content-Type: application/json' \
                --data '{"reason":"Operação desistida pelo cliente."}'
        - lang: JavaScript
          label: Node
          source: |
              const resposta = await fetch("https://gyra-core.gyramais.com.br/v1/collections/6612a7f30000000000000001/cancel", {
                method: "POST",
                headers: {
                  Authorization: `Bearer ${token}`,
                  "Content-Type": "application/json",
                },
                body: JSON.stringify({
                  "reason": "Operação desistida pelo cliente."
                }),
              });
              
              const dados = await resposta.json();
        - lang: Python
          label: Python
          source: |
              import requests
              
              resposta = requests.post(
                  "https://gyra-core.gyramais.com.br/v1/collections/6612a7f30000000000000001/cancel",
                  headers={"Authorization": f"Bearer {token}"},
                  json={
                      "reason": "Operação desistida pelo cliente."
                  },
              )
              
              dados = resposta.json()
  /v1/collections/{id}/items/{itemId}/review:
    post:
      operationId: CollectionController_review
      summary: Decidir sobre um item em revisao
      description: |
          A decisao do operador sobre um item em AWAITING_OPERATOR, MANUAL_REVIEW, REJECTED, SUBMITTED
          ou PROCESSING. Em outro status, responde 409. Cada item aceita ate 3 pedidos de reenvio;
          depois disso, aprove ou dispense.
          
          Tres saidas:
          - APPROVED: o item fecha;
          - RESEND_REQUESTED: o destinatario recebe o pedido de novo. O comentario e OBRIGATORIO aqui, e
            e ele que o cliente le, entao escreva o que precisa ser corrigido, nao o codigo do check;
          - WAIVED: o item sai do pedido.
      parameters:
        - name: id
          required: true
          in: path
          schema:
            type: string
          description: Id da solicitacao.
        - name: itemId
          required: true
          in: path
          schema:
            type: string
          description: Id do item.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ReviewCollectionItemDto'
            example:
              decision: RESEND_REQUESTED
              comment: O comprovante está no nome de outra pessoa. Envie um no seu nome.
      responses:
        '200':
          description: 'O detalhe da solicitacao inteira, ja com o item no status resultante (mesmo corpo de GET /v1/collections/{id}). APPROVED leva o item a VALIDATED, WAIVED a WAIVED e RESEND_REQUESTED de volta a PENDING, com o comentario em rejectionReason.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Collection'
              example:
                id: 6612a7f30000000000000051
                registryId: 6612a7f30000000000000001
                status: IN_PROGRESS
                itemsTotal: 5
                itemsResolved: 3
                itemsAwaitingOperator: 0
                items:
                  - id: 6612a7f30000000000000072
                    collectionId: 6612a7f30000000000000051
                    recipientId: 6612a7f30000000000000061
                    order: 2
                    kind: DOCUMENT
                    documentType: COMPROVANTE_RESIDENCIA
                    label: Comprovante de residência
                    required: true
                    status: PENDING
                    verdict: INVALIDO
                    rejectionReason: O comprovante está no nome de outra pessoa. Envie um no seu nome.
                    resendCount: 1
                    resendRequestedAt: '2026-09-06T10:05:00.000Z'
                    reviewDecision: RESEND_REQUESTED
                    reviewComment: O comprovante está no nome de outra pessoa. Envie um no seu nome.
                    reviewedAt: '2026-09-06T10:05:00.000Z'
                    resolvedAt: null
        '400':
          description: 'Decisao fora da lista, comentario ausente em RESEND_REQUESTED, comentario acima de 500 caracteres ou identificador fora do formato ObjectId.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 400
                message: Informe o motivo do pedido de reenvio.
        '401':
          description: 'Token ausente, expirado ou invalido. Gere outro em POST /auth/authenticate.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 401
                message: Token de acesso inválido.
        '403':
          description: O usuario autenticado nao tem a permissao exigida pela rota.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 403
                message: Você não tem permissão para acessar este recurso.
        '404':
          description: 'Recurso inexistente OU capacidade nao liberada para a organizacao. As duas coisas respondem 404 de proposito: para quem nao tem o modulo, a rota nao existe.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 404
                message: Item não encontrado nesta solicitação.
        '409':
          description: 'O item nao esta aguardando decisao, ou ja chegou ao limite de reenvios.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 409
                message: Este item não está aguardando decisão.
        '500':
          description: 'Falha nossa. Tente de novo; se persistir, acione o suporte com o horario da chamada.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 500
                message: Internal server error
        '502':
          description: O servico de solicitacoes nao respondeu. Tente de novo.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 502
                message: Não foi possível registrar a decisão.
      tags:
        - collections
      security:
        - authorization: []
      x-codeSamples:
        - lang: cURL
          label: cURL
          source: |
              curl --request POST 'https://gyra-core.gyramais.com.br/v1/collections/6612a7f30000000000000001/items/6612a7f30000000000000001/review' \
                --header 'Authorization: Bearer <token>' \
                --header 'Content-Type: application/json' \
                --data '{"decision":"RESEND_REQUESTED","comment":"O comprovante está no nome de outra pessoa. Envie um no seu nome."}'
        - lang: JavaScript
          label: Node
          source: |
              const resposta = await fetch("https://gyra-core.gyramais.com.br/v1/collections/6612a7f30000000000000001/items/6612a7f30000000000000001/review", {
                method: "POST",
                headers: {
                  Authorization: `Bearer ${token}`,
                  "Content-Type": "application/json",
                },
                body: JSON.stringify({
                  "decision": "RESEND_REQUESTED",
                  "comment": "O comprovante está no nome de outra pessoa. Envie um no seu nome."
                }),
              });
              
              const dados = await resposta.json();
        - lang: Python
          label: Python
          source: |
              import requests
              
              resposta = requests.post(
                  "https://gyra-core.gyramais.com.br/v1/collections/6612a7f30000000000000001/items/6612a7f30000000000000001/review",
                  headers={"Authorization": f"Bearer {token}"},
                  json={
                      "decision": "RESEND_REQUESTED",
                      "comment": "O comprovante está no nome de outra pessoa. Envie um no seu nome."
                  },
              )
              
              dados = resposta.json()
  /v1/collection-templates:
    get:
      operationId: CollectionTemplateController_list
      summary: Listar modelos de coleta
      parameters:
        - name: search
          required: false
          in: query
          description: 'Casa por nome ou pela chave, sem acento e sem caixa.'
          schema:
            maxLength: 120
            type: string
        - name: scope
          required: false
          in: query
          schema:
            enum:
              - ORGANIZATION
              - SYSTEM
            type: string
          description: 'ORGANIZATION (modelos da sua organizacao) ou SYSTEM (modelos GYRA+). Sem o parametro, os dois.'
        - name: enabled
          required: false
          in: query
          schema:
            type: boolean
          description: 'true devolve so os modelos ligados. Sem o parametro (ou com false), ligados e desligados.'
        - name: itemKind
          required: false
          in: query
          schema:
            type: array
            items:
              type: string
          description: 'So modelos que pedem itens destes tipos (DOCUMENT, FORM, SIGNATURE, CONSENT, IDENTITY, CUSTOM). Repita para varios.'
        - name: skip
          required: false
          in: query
          schema:
            type: number
        - name: take
          required: false
          in: query
          schema:
            maximum: 100
            type: number
      responses:
        '200':
          description: 'Modelos com slug, nome, descricao, itens e uso.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CollectionTemplateListResponse'
              example:
                items:
                  - id: 6612a7f30000000000000041
                    scope: ORGANIZATION
                    name: Onboarding PJ
                    slug: onboarding-pj
                    description: Documentos mínimos para abrir limite de PJ.
                    items:
                      - key: constitutivo
                        kind: DOCUMENT
                        requirement: CONSTITUTIVO_VIGENTE
                        label: Documento constitutivo vigente
                        required: true
                      - key: identidade
                        kind: IDENTITY
                        label: Verificação de identidade
                        required: true
                    dueInDays: 10
                    reminders:
                      - 2
                      - 5
                      - 8
                    channel: BOTH
                    responseMode: REVIEW
                    behavior:
                      acceptPartial: false
                      skipItemsAlreadyOnFile: true
                    onCompleted:
                      kind: NONE
                      id: null
                      byEntityType:
                        COMPANY:
                          kind: POLICY
                          id: 6612a7f300000000000000c1
                    version: 3
                    isCurrent: true
                    enabled: true
                    metrics:
                      collections: 42
                      completedCollections: 33
                      completionRate: 0.7857
                      averageCompletionHours: 31.5
                    createdAt: '2026-07-02T09:00:00.000Z'
                    updatedAt: '2026-08-28T17:41:00.000Z'
                total: 1
        '400':
          description: 'Parametro invalido (scope fora da lista, take acima de 100, busca acima de 120 caracteres). A mensagem concatena todas as falhas por virgula.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 400
                message: 'scope must be one of the following values: ORGANIZATION, SYSTEM'
        '401':
          description: 'Token ausente, expirado ou invalido. Gere outro em POST /auth/authenticate.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 401
                message: Token de acesso inválido.
        '403':
          description: O usuario autenticado nao tem a permissao exigida pela rota.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 403
                message: Você não tem permissão para acessar este recurso.
        '404':
          description: 'O modulo Onboarding nao esta liberado para a organizacao: para ela, a rota nao existe.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 404
                message: Recurso não encontrado.
        '500':
          description: 'Falha nossa. Tente de novo; se persistir, acione o suporte com o horario da chamada.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: 500
                message: Internal server error
      tags:
        - collections
      security:
        - authorization: []
      description: |
          Os modelos vigentes que a organizacao enxerga (os dela e os modelos GYRA+), com metricas de
          uso, dos mais usados para os menos usados. Cada um diz o que sera pedido. Pagina padrao de
          50, maximo 100.
          
          Para montar um seletor, use enabled=true: modelo desligado continua na listagem sem o filtro.
          
          O `slug` daqui e o que entra em create_collection. Chame esta tool primeiro: criar solicitacao
          com slug inventado falha.
      x-codeSamples:
        - lang: cURL
          label: cURL
          source: |
              curl --request GET 'https://gyra-core.gyramais.com.br/v1/collection-templates' \
                --header 'Authorization: Bearer <token>'
        - lang: JavaScript
          label: Node
          source: |
              const resposta = await fetch("https://gyra-core.gyramais.com.br/v1/collection-templates", {
                method: "GET",
                headers: { Authorization: `Bearer ${token}` },
              });
              
              const dados = await resposta.json();
        - lang: Python
          label: Python
          source: |
              import requests
              
              resposta = requests.get(
                  "https://gyra-core.gyramais.com.br/v1/collection-templates",
                  headers={"Authorization": f"Bearer {token}"},
              )
              
              dados = resposta.json()
  /report/{id}/financial-tab:
    post:
      operationId: ReportController_financialSection
      parameters:
        - name: id
          required: true
          in: path
          schema:
            type: string
          description: ID do relatorio (CNPJ) que vai receber as demonstracoes.
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                files:
                  type: array
                  items:
                    type: string
                    format: binary
                  description: |
                      PDFs do balanco patrimonial e/ou da DRE. Repita o campo `files`
                      para enviar mais de um arquivo. Ate 10 arquivos por chamada,
                      50MB cada, somente PDF.
              required:
                - files
      responses:
        '200':
          description: 'Relatorio atualizado, com as secoes financeiras marcadas como em processamento.'
        '400':
          description: 'Nenhum arquivo enviado, arquivo que nao e um PDF valido ou mais de 10 arquivos.'
        '404':
          description: Relatorio nao encontrado ou de outra organizacao.
        '413':
          description: Arquivo maior que 50MB.
      tags:
        - report
      security:
        - authorization: []
      summary: Enviar balanco e DRE
      description: |
          Envia um ou mais PDFs de balanco patrimonial e DRE para um relatorio de CNPJ
          ja existente. A extracao transforma as demonstracoes em dados estruturados
          (balanco, DRE e indicadores) e as disponibiliza como secoes do relatorio.
          
          A chamada e ASSINCRONA: responde 200 assim que os arquivos sao aceitos e
          enfileirados, sem os dados estruturados. O resultado sai depois em
          GET /report/{id}/section/BALANCE_SHEET (idem DRE e FINANCIAL_INDICATORS).
          
          Envie apenas as paginas do balanco e da DRE: quanto mais enxuto o PDF,
          mais rapido e barato o processamento.
  /report/{id}/committee:
    post:
      operationId: ReportController_conveneCommittee
      parameters:
        - name: id
          required: true
          in: path
          schema:
            type: string
          description: ID do relatorio que vai a comite.
      requestBody:
        required: false
        content:
          application/json:
            schema:
              type: object
              properties:
                force:
                  type: boolean
                  description: Ignora o cache da deliberacao e reprocessa do zero. Padrao false.
                  default: false
      responses:
        '200':
          description: 'Deliberacao aceita e iniciada: { status: "RUNNING", trigger: "MANUAL" | "RERUN" }.'
        '400':
          description: 'Relatorio ainda nao esta pronto para o comite (pareceres ou politica pendentes, ou parecer nao habilitado na politica).'
        '404':
          description: Relatorio nao encontrado ou de outra organizacao.
        '409':
          description: Ja existe uma deliberacao em andamento para este relatorio.
      tags:
        - report
      security:
        - authorization: []
      summary: Convocar o Comite de Credito IA
      description: |
          Dispara manualmente a deliberacao do Comite de Credito IA sobre um relatorio.
          
          Use quando a politica esta em "Nao convocar automaticamente" e o comite deve rodar
          sob demanda, ou para reconvocar um relatorio que ja deliberou (DONE), falhou
          (ERROR) ou foi pulado (SKIPPED).
          
          Pre-requisitos (senao retorna 400):
          - a politica do relatorio habilita o pipeline de parecer;
          - os pareceres por secao ja finalizaram;
          - a politica de credito ja concluiu (quando o relatorio tem politica).
          
          A chamada e assincrona: o 200 confirma que a deliberacao iniciou, nao que terminou.
          Convocacao manual sempre entra como sugestao e nao altera o status do relatorio,
          mesmo numa politica em "Convocar comite e decisao automatica".
          Para saber o resultado, registre o webhook COMMITTEE_FINISHED ou consulte
          GET /report/{id}/insights.
  /committee/deliberations/{reportId}:
    get:
      operationId: CommitteeController_getDeliberation
      parameters:
        - name: reportId
          required: true
          in: path
          schema:
            type: string
          description: ID do relatorio que foi a comite.
      responses:
        '200':
          description: 'Deliberacao completa: agentOpinions[], synthesis, finalRecommendation, versoes de prompt e telemetria.'
        '404':
          description: Nenhuma deliberacao encontrada para este relatorio.
      tags:
        - committee
      security:
        - authorization: []
      summary: Consultar deliberacao do Comite de Credito IA
      description: |
          Retorna a deliberacao completa e auditavel do Comite de Credito IA para um
          relatorio: o voto individual de cada um dos sete agentes (score, parecer,
          redFlags, positiveFactors, recommendation), a sintese do Presidente (decisao,
          justificativa, condicoes, registro de divergencia, alcada), a versao de prompt
          usada por agente e a telemetria (modelos, tokens, custo, duracao).
          
          Retorna sempre a deliberacao mais recente. Reconvocacoes (trigger RERUN) geram
          uma nova deliberacao, e e ela que passa a ser devolvida.
          
          Para o fluxo do dia a dia, GET /report/{id}/insights e mais leve.
components:
  securitySchemes:
    authorization:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: Enter JWT token
  schemas:
    ApiError:
      type: object
      description: 'Formato unico de erro da API. Nao faca match exato da mensagem: use o code.'
      properties:
        code:
          type: integer
          description: Codigo HTTP.
        message:
          type: string
          description: 'Mensagem em portugues. Em erro de validacao, traz TODAS as falhas concatenadas por virgula.'
    Registry:
      type: object
      description: O dossie documental de um CNPJ ou CPF.
      properties:
        id:
          type: string
        document:
          type: string
          description: 'CNPJ (14) ou CPF (11), so digitos.'
        entityType:
          type: string
          enum:
            - COMPANY
            - PERSON
        name:
          type: string
          nullable: true
          description: Razao social ou nome.
        tradeName:
          type: string
          nullable: true
        legalNature:
          type: string
          nullable: true
        kycStatus:
          type: string
          enum:
            - PENDING
            - PROCESSING
            - UP_TO_DATE
            - ATTENTION
            - EXPIRED
            - RENEWING
        kycRenewalDue:
          type: string
          nullable: true
          format: date-time
          description: Quando a renovacao vence.
        completeness:
          type: number
          description: 0 a 1.
        completenessSlots:
          type: array
          items:
            type: object
            properties:
              key:
                type: string
                description: 'Primeiro tipo do grupo, usado como rotulo da exigencia.'
              types:
                type: array
                items:
                  type: string
                  enum:
                    - CONTRATO_SOCIAL
                    - ALTERACAO_CONTRATUAL
                    - ESTATUTO_SOCIAL
                    - REQUERIMENTO_EMPRESARIO
                    - ATA_ASSEMBLEIA
                    - PROCURACAO_PJ
                    - CERTIDAO_JUNTA
                    - CERTIDAO_QSA
                    - IRPJ_ECF
                    - DECLARACAO_FATURAMENTO
                    - CERTIFICADO_SIMPLES_NACIONAL
                    - DEMONSTRACOES_FINANCEIRAS
                    - EXTRATO_BANCARIO
                    - CERTIDAO_PGFN_PJ
                    - CERTIDAO_FGTS
                    - CADIN_FEDERAL
                    - CADIN_ESTADUAL
                    - ESOCIAL_PJ
                    - DOC_IDENTIDADE
                    - COMPROVANTE_RESIDENCIA
                    - DIRPF
                    - COMPROVANTE_RENDA
                    - CERTIDAO_PF
                    - PROCURACAO_PF
                    - COMPROVACAO_ESTADO_CIVIL
                    - FORA_DE_ESCOPO
                    - NAO_IDENTIFICADO
                description: Tipos equivalentes que preenchem a mesma exigencia.
              filled:
                type: boolean
              documentId:
                type: string
                nullable: true
                description: Qual documento cobre a exigencia.
          description: 'A cesta de completude aberta. So no detalhe: na listagem seria N+1.'
        signingAuthority:
          type: object
          nullable: true
          description: 'Quem pode assinar pela empresa, ja achatado (sem a tripla value/confidence/page). null quando o cadastro nao tem documento societario validado com clausula de administracao legivel. So vem no DETALHE do cadastro.'
          properties:
            regime:
              type: string
              nullable: true
              enum:
                - ISOLADA
                - CONJUNTA
                - MISTA
                - INDETERMINADO
                - null
            signersRequired:
              type: integer
              nullable: true
              description: Quantas assinaturas a regra geral exige.
            anySignerAlone:
              type: boolean
              description: true quando ao menos um administrador assina sozinho.
            signers:
              type: array
              items:
                type: object
                properties:
                  name:
                    type: string
                    nullable: true
                  document:
                    type: string
                    nullable: true
                    description: 'CPF em digitos. null quando o documento societario nao o repete, o que e comum.'
                  role:
                    type: string
                    nullable: true
                  signsAlone:
                    type: boolean
                    nullable: true
                  jointSignatureThreshold:
                    type: number
                    nullable: true
                  mandateEndDate:
                    type: string
                    nullable: true
                    description: YYYY-MM-DD.
                  restrictions:
                    type: string
                    nullable: true
            thresholds:
              type: array
              items:
                type: object
                additionalProperties: true
                description: Faixa de alcada lida do documento.
            prohibitions:
              type: array
              items:
                type: object
                additionalProperties: true
                description: Vedacao expressa lida do documento.
            mandate:
              type: object
              nullable: true
              additionalProperties: true
            source:
              type: object
              description: De qual documento a leitura saiu.
              properties:
                documentId:
                  type: string
                documentType:
                  type: string
                  enum:
                    - CONTRATO_SOCIAL
                    - ALTERACAO_CONTRATUAL
                    - ESTATUTO_SOCIAL
                    - REQUERIMENTO_EMPRESARIO
                    - ATA_ASSEMBLEIA
                    - PROCURACAO_PJ
                    - CERTIDAO_JUNTA
                    - CERTIDAO_QSA
                    - IRPJ_ECF
                    - DECLARACAO_FATURAMENTO
                    - CERTIFICADO_SIMPLES_NACIONAL
                    - DEMONSTRACOES_FINANCEIRAS
                    - EXTRATO_BANCARIO
                    - CERTIDAO_PGFN_PJ
                    - CERTIDAO_FGTS
                    - CADIN_FEDERAL
                    - CADIN_ESTADUAL
                    - ESOCIAL_PJ
                    - DOC_IDENTIDADE
                    - COMPROVANTE_RESIDENCIA
                    - DIRPF
                    - COMPROVANTE_RENDA
                    - CERTIDAO_PF
                    - PROCURACAO_PF
                    - COMPROVACAO_ESTADO_CIVIL
                    - FORA_DE_ESCOPO
                    - NAO_IDENTIFICADO
                fileName:
                  type: string
                  nullable: true
                version:
                  type: integer
                  nullable: true
                validatedAt:
                  type: string
                  nullable: true
                  format: date-time
                clauseNumber:
                  type: string
                  nullable: true
                clauseExcerpt:
                  type: string
                  nullable: true
                confidence:
                  type: number
                  nullable: true
        documentsCount:
          type: integer
        pendingCount:
          type: integer
        reportId:
          type: string
          nullable: true
          description: Reservado para o relatorio mais recente do mesmo documento. Hoje vem null.
        crossDocument:
          type: object
          nullable: true
          description: 'Ultima conferencia cruzada entre os documentos do cadastro. null quando nunca houve o que cruzar, o que e diferente de conferido e consistente.'
          properties:
            status:
              type: string
              enum:
                - CONSISTENTE
                - DIVERGENTE
                - NAO_CONFERIDO
            checks:
              type: array
              items:
                type: object
                additionalProperties: true
            documentIds:
              type: array
              items:
                type: string
            triggeredByDocumentId:
              type: string
              nullable: true
            ruleSetVersion:
              type: string
            evaluatedAt:
              type: string
              format: date-time
        basicDataSyncedAt:
          type: string
          nullable: true
          format: date-time
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
    RegistryListResponse:
      type: object
      properties:
        items:
          type: array
          items:
            $ref: '#/components/schemas/Registry'
        total:
          type: integer
          description: 'Total que casa o filtro, nao o tamanho da pagina.'
    RegistryDocument:
      type: object
      properties:
        id:
          type: string
        registryId:
          type: string
        personId:
          type: string
          nullable: true
          description: Pessoa da arvore societaria a que o documento foi anexado.
        type:
          type: string
          enum:
            - CONTRATO_SOCIAL
            - ALTERACAO_CONTRATUAL
            - ESTATUTO_SOCIAL
            - REQUERIMENTO_EMPRESARIO
            - ATA_ASSEMBLEIA
            - PROCURACAO_PJ
            - CERTIDAO_JUNTA
            - CERTIDAO_QSA
            - IRPJ_ECF
            - DECLARACAO_FATURAMENTO
            - CERTIFICADO_SIMPLES_NACIONAL
            - DEMONSTRACOES_FINANCEIRAS
            - EXTRATO_BANCARIO
            - CERTIDAO_PGFN_PJ
            - CERTIDAO_FGTS
            - CADIN_FEDERAL
            - CADIN_ESTADUAL
            - ESOCIAL_PJ
            - DOC_IDENTIDADE
            - COMPROVANTE_RESIDENCIA
            - DIRPF
            - COMPROVANTE_RENDA
            - CERTIDAO_PF
            - PROCURACAO_PF
            - COMPROVACAO_ESTADO_CIVIL
            - FORA_DE_ESCOPO
            - NAO_IDENTIFICADO
        status:
          type: string
          enum:
            - RECEIVED
            - CLASSIFYING
            - CLASSIFIED
            - EXTRACTING
            - EXTRACTED
            - VALIDATING
            - VALIDATED
            - FAILED
            - MANUAL_REVIEW
            - OUT_OF_SCOPE
            - REJECTED_QUALITY
        version:
          type: integer
          description: Versao dentro do tipo. Nada e sobrescrito.
        isCurrent:
          type: boolean
          description: true na versao vigente daquele tipo.
        supersedesId:
          type: string
          nullable: true
        fileUrl:
          type: string
          description: 'URL assinada, com validade.'
        fileName:
          type: string
        mimeType:
          type: string
        sizeBytes:
          type: integer
          nullable: true
        pageCount:
          type: integer
          nullable: true
        parentDocumentId:
          type: string
          nullable: true
          description: Preenchido quando o arquivo trazia varias pecas e foi dividido.
        pageRange:
          type: string
          nullable: true
        classification:
          type: object
          nullable: true
          description: 'O que a classificacao concluiu, com as alternativas consideradas.'
          properties:
            type:
              type: string
              enum:
                - CONTRATO_SOCIAL
                - ALTERACAO_CONTRATUAL
                - ESTATUTO_SOCIAL
                - REQUERIMENTO_EMPRESARIO
                - ATA_ASSEMBLEIA
                - PROCURACAO_PJ
                - CERTIDAO_JUNTA
                - CERTIDAO_QSA
                - IRPJ_ECF
                - DECLARACAO_FATURAMENTO
                - CERTIFICADO_SIMPLES_NACIONAL
                - DEMONSTRACOES_FINANCEIRAS
                - EXTRATO_BANCARIO
                - CERTIDAO_PGFN_PJ
                - CERTIDAO_FGTS
                - CADIN_FEDERAL
                - CADIN_ESTADUAL
                - ESOCIAL_PJ
                - DOC_IDENTIDADE
                - COMPROVANTE_RESIDENCIA
                - DIRPF
                - COMPROVANTE_RENDA
                - CERTIDAO_PF
                - PROCURACAO_PF
                - COMPROVACAO_ESTADO_CIVIL
                - FORA_DE_ESCOPO
                - NAO_IDENTIFICADO
            confidence:
              type: number
              description: 0 a 1.
            alternatives:
              type: array
              items:
                type: object
                properties:
                  type:
                    type: string
                    enum:
                      - CONTRATO_SOCIAL
                      - ALTERACAO_CONTRATUAL
                      - ESTATUTO_SOCIAL
                      - REQUERIMENTO_EMPRESARIO
                      - ATA_ASSEMBLEIA
                      - PROCURACAO_PJ
                      - CERTIDAO_JUNTA
                      - CERTIDAO_QSA
                      - IRPJ_ECF
                      - DECLARACAO_FATURAMENTO
                      - CERTIFICADO_SIMPLES_NACIONAL
                      - DEMONSTRACOES_FINANCEIRAS
                      - EXTRATO_BANCARIO
                      - CERTIDAO_PGFN_PJ
                      - CERTIDAO_FGTS
                      - CADIN_FEDERAL
                      - CADIN_ESTADUAL
                      - ESOCIAL_PJ
                      - DOC_IDENTIDADE
                      - COMPROVANTE_RESIDENCIA
                      - DIRPF
                      - COMPROVANTE_RENDA
                      - CERTIDAO_PF
                      - PROCURACAO_PF
                      - COMPROVACAO_ESTADO_CIVIL
                      - FORA_DE_ESCOPO
                      - NAO_IDENTIFICADO
                  confidence:
                    type: number
        yearReference:
          type: integer
          nullable: true
          description: 'Ano-calendario, nos tipos que tem (DIRPF, IRPJ/ECF).'
        attempt:
          type: integer
        lastError:
          type: string
          nullable: true
        verdict:
          type: string
          nullable: true
          enum:
            - VALIDO
            - INVALIDO
            - INCONCLUSIVO
            - ANALISE_MANUAL
            - null
          description: 'Veredito do parecer vigente, para a coluna da listagem.'
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
    RegistryDocumentResult:
      type: object
      description: 'Resultado completo de um documento, da classificacao ao parecer.'
      properties:
        documentId:
          type: string
        registryId:
          type: string
        type:
          type: string
          enum:
            - CONTRATO_SOCIAL
            - ALTERACAO_CONTRATUAL
            - ESTATUTO_SOCIAL
            - REQUERIMENTO_EMPRESARIO
            - ATA_ASSEMBLEIA
            - PROCURACAO_PJ
            - CERTIDAO_JUNTA
            - CERTIDAO_QSA
            - IRPJ_ECF
            - DECLARACAO_FATURAMENTO
            - CERTIFICADO_SIMPLES_NACIONAL
            - DEMONSTRACOES_FINANCEIRAS
            - EXTRATO_BANCARIO
            - CERTIDAO_PGFN_PJ
            - CERTIDAO_FGTS
            - CADIN_FEDERAL
            - CADIN_ESTADUAL
            - ESOCIAL_PJ
            - DOC_IDENTIDADE
            - COMPROVANTE_RESIDENCIA
            - DIRPF
            - COMPROVANTE_RENDA
            - CERTIDAO_PF
            - PROCURACAO_PF
            - COMPROVACAO_ESTADO_CIVIL
            - FORA_DE_ESCOPO
            - NAO_IDENTIFICADO
          description: O tipo LIDO pela classificacao.
        expectedType:
          type: string
          nullable: true
          enum:
            - CONTRATO_SOCIAL
            - ALTERACAO_CONTRATUAL
            - ESTATUTO_SOCIAL
            - REQUERIMENTO_EMPRESARIO
            - ATA_ASSEMBLEIA
            - PROCURACAO_PJ
            - CERTIDAO_JUNTA
            - CERTIDAO_QSA
            - IRPJ_ECF
            - DECLARACAO_FATURAMENTO
            - CERTIFICADO_SIMPLES_NACIONAL
            - DEMONSTRACOES_FINANCEIRAS
            - EXTRATO_BANCARIO
            - CERTIDAO_PGFN_PJ
            - CERTIDAO_FGTS
            - CADIN_FEDERAL
            - CADIN_ESTADUAL
            - ESOCIAL_PJ
            - DOC_IDENTIDADE
            - COMPROVANTE_RESIDENCIA
            - DIRPF
            - COMPROVANTE_RENDA
            - CERTIDAO_PF
            - PROCURACAO_PF
            - COMPROVACAO_ESTADO_CIVIL
            - FORA_DE_ESCOPO
            - NAO_IDENTIFICADO
            - null
          description: O tipo PEDIDO no envio. Sustenta a verificacao EXPECTED_TYPE_MATCH.
        expectedTypes:
          type: array
          items:
            type: string
            enum:
              - CONTRATO_SOCIAL
              - ALTERACAO_CONTRATUAL
              - ESTATUTO_SOCIAL
              - REQUERIMENTO_EMPRESARIO
              - ATA_ASSEMBLEIA
              - PROCURACAO_PJ
              - CERTIDAO_JUNTA
              - CERTIDAO_QSA
              - IRPJ_ECF
              - DECLARACAO_FATURAMENTO
              - CERTIFICADO_SIMPLES_NACIONAL
              - DEMONSTRACOES_FINANCEIRAS
              - EXTRATO_BANCARIO
              - CERTIDAO_PGFN_PJ
              - CERTIDAO_FGTS
              - CADIN_FEDERAL
              - CADIN_ESTADUAL
              - ESOCIAL_PJ
              - DOC_IDENTIDADE
              - COMPROVANTE_RESIDENCIA
              - DIRPF
              - COMPROVANTE_RENDA
              - CERTIDAO_PF
              - PROCURACAO_PF
              - COMPROVACAO_ESTADO_CIVIL
              - FORA_DE_ESCOPO
              - NAO_IDENTIFICADO
          description: 'O CONJUNTO pedido, quando o item nasceu de um requisito societario.'
        status:
          type: string
          enum:
            - RECEIVED
            - CLASSIFYING
            - CLASSIFIED
            - EXTRACTING
            - EXTRACTED
            - VALIDATING
            - VALIDATED
            - FAILED
            - MANUAL_REVIEW
            - OUT_OF_SCOPE
            - REJECTED_QUALITY
        version:
          type: integer
        isCurrent:
          type: boolean
        classification:
          type: object
          nullable: true
          description: 'O que a classificacao concluiu, com as alternativas consideradas.'
          properties:
            type:
              type: string
              enum:
                - CONTRATO_SOCIAL
                - ALTERACAO_CONTRATUAL
                - ESTATUTO_SOCIAL
                - REQUERIMENTO_EMPRESARIO
                - ATA_ASSEMBLEIA
                - PROCURACAO_PJ
                - CERTIDAO_JUNTA
                - CERTIDAO_QSA
                - IRPJ_ECF
                - DECLARACAO_FATURAMENTO
                - CERTIFICADO_SIMPLES_NACIONAL
                - DEMONSTRACOES_FINANCEIRAS
                - EXTRATO_BANCARIO
                - CERTIDAO_PGFN_PJ
                - CERTIDAO_FGTS
                - CADIN_FEDERAL
                - CADIN_ESTADUAL
                - ESOCIAL_PJ
                - DOC_IDENTIDADE
                - COMPROVANTE_RESIDENCIA
                - DIRPF
                - COMPROVANTE_RENDA
                - CERTIDAO_PF
                - PROCURACAO_PF
                - COMPROVACAO_ESTADO_CIVIL
                - FORA_DE_ESCOPO
                - NAO_IDENTIFICADO
            confidence:
              type: number
              description: 0 a 1.
            alternatives:
              type: array
              items:
                type: object
                properties:
                  type:
                    type: string
                    enum:
                      - CONTRATO_SOCIAL
                      - ALTERACAO_CONTRATUAL
                      - ESTATUTO_SOCIAL
                      - REQUERIMENTO_EMPRESARIO
                      - ATA_ASSEMBLEIA
                      - PROCURACAO_PJ
                      - CERTIDAO_JUNTA
                      - CERTIDAO_QSA
                      - IRPJ_ECF
                      - DECLARACAO_FATURAMENTO
                      - CERTIFICADO_SIMPLES_NACIONAL
                      - DEMONSTRACOES_FINANCEIRAS
                      - EXTRATO_BANCARIO
                      - CERTIDAO_PGFN_PJ
                      - CERTIDAO_FGTS
                      - CADIN_FEDERAL
                      - CADIN_ESTADUAL
                      - ESOCIAL_PJ
                      - DOC_IDENTIDADE
                      - COMPROVANTE_RESIDENCIA
                      - DIRPF
                      - COMPROVANTE_RENDA
                      - CERTIDAO_PF
                      - PROCURACAO_PF
                      - COMPROVACAO_ESTADO_CIVIL
                      - FORA_DE_ESCOPO
                      - NAO_IDENTIFICADO
                  confidence:
                    type: number
        ambiguous:
          type: boolean
          description: 'true quando outra alternativa passou de 0,35 de confianca.'
        statusReason:
          type: string
          nullable: true
          description: Por que o documento parou num terminal que nao e falha tecnica.
        stages:
          type: object
          nullable: true
          description: O que rodou nesta tentativa e o que veio reaproveitado.
          properties:
            executed:
              type: array
              items:
                type: string
                enum:
                  - CLASSIFY
                  - EXTRACT
                  - VALIDATE
            reused:
              type: array
              items:
                type: object
                properties:
                  stage:
                    type: string
                    enum:
                      - CLASSIFY
                      - EXTRACT
                      - VALIDATE
                  fromAttempt:
                    type: integer
        extraction:
          type: object
          nullable: true
          additionalProperties: true
          description: 'Os campos lidos. A FORMA DEPENDE DO TIPO identificado: cada um dos 25 tipos tem o seu conjunto, documentado campo a campo em https://developers.gyramais.com.br/api-reference/kyc/formatos-de-retorno. Todo campo folha vem como { value, confidence, page }; campo ausente vem com value null e confidence 0.'
        fieldConfidences:
          type: object
          nullable: true
          additionalProperties:
            type: number
          description: Confianca por caminho de campo.
        validation:
          type: object
          nullable: true
          properties:
            checks:
              type: array
              items:
                $ref: '#/components/schemas/RegistryCheck'
            reconciliation:
              type: object
              nullable: true
              additionalProperties: true
              description: Conferencia contra a fonte oficial.
        assessment:
          type: object
          nullable: true
          properties:
            verdict:
              type: string
              enum:
                - VALIDO
                - INVALIDO
                - INCONCLUSIVO
                - ANALISE_MANUAL
              description: 'O parecer da IA. NAO e o veredito que vale: use effectiveVerdict.'
            score:
              type: number
              description: 0 a 1.
            justification:
              type: string
              description: 'Por que, em portugues.'
            evidences:
              type: array
              items:
                type: object
                properties:
                  page:
                    type: integer
                    nullable: true
                  excerpt:
                    type: string
                    nullable: true
                  checkCode:
                    type: string
            ruleSetVersion:
              type: string
              description: Qual versao da regua julgou este documento.
            contentHash:
              type: string
              nullable: true
              description: 'Selo do parecer, conferivel na rota de integridade.'
            feedbackVerdict:
              type: string
              nullable: true
              enum:
                - VALIDO
                - INVALIDO
                - INCONCLUSIVO
                - ANALISE_MANUAL
                - null
              description: 'A decisao que um operador registrou, quando houve.'
            feedbackComment:
              type: string
              nullable: true
            feedbackAt:
              type: string
              nullable: true
              format: date-time
            feedbackUserId:
              type: string
              nullable: true
            effectiveVerdict:
              type: string
              nullable: true
              enum:
                - VALIDO
                - INVALIDO
                - INCONCLUSIVO
                - ANALISE_MANUAL
                - null
              description: O VEREDITO QUE VALE HOJE (feedbackVerdict ?? verdict). Leia este.
            decidedByOperator:
              type: boolean
              description: 'true quando quem decidiu foi uma pessoa, e nao o pipeline.'
        processedAt:
          type: string
          nullable: true
          format: date-time
        attempt:
          type: integer
    RegistryCheck:
      type: object
      properties:
        code:
          type: string
          description: 'Codigo da verificacao no catalogo (ex.: EXPECTED_DOCUMENT_MATCH).'
        result:
          type: string
          enum:
            - PASS
            - WARN
            - FAIL
            - SKIP
          description: 'WARN e ressalva: aparece no parecer e nao reprova sozinha.'
        message:
          type: string
          description: Frase em portugues explicando o resultado.
        evidence:
          type: object
          nullable: true
          description: Onde no documento a verificacao se apoiou.
          properties:
            page:
              type: integer
              nullable: true
            excerpt:
              type: string
              nullable: true
            checkCode:
              type: string
        details:
          type: array
          items:
            type: string
          description: 'Indicios individuais, quando a verificacao produz varios.'
        source:
          type: string
          enum:
            - DETERMINISTIC
            - RECONCILIATION
            - LLM
          description: Quem produziu o resultado.
        rfi:
          type: integer
    RegistryPerson:
      type: object
      properties:
        id:
          type: string
        registryId:
          type: string
        entityType:
          type: string
          enum:
            - COMPANY
            - PERSON
        document:
          type: string
          nullable: true
        maskedDocument:
          type: string
          nullable: true
          description: O QSA da Receita devolve o CPF de pessoa fisica mascarado.
        name:
          type: string
        role:
          type: string
          nullable: true
        sharePercent:
          type: number
          nullable: true
        layer:
          type: integer
          description: 1 = quadro societario direto; 2 = socio da socia pessoa juridica.
        parentPersonId:
          type: string
          nullable: true
        isBeneficialOwner:
          type: boolean
        source:
          type: string
          enum:
            - QSA_OFICIAL
            - DOCUMENT_EXTRACTION
            - MANUAL
            - FORM
          description: De onde a pessoa veio. FORM = declarada pelo cliente num formulario de solicitacao.
        sourceDocumentId:
          type: string
          nullable: true
          description: 'Documento de onde a pessoa foi lida, quando source e DOCUMENT_EXTRACTION.'
        editedFields:
          type: array
          items:
            type: string
            enum:
              - name
              - role
              - sharePercent
              - document
          description: Campos que um operador corrigiu. A atualizacao do quadro oficial e a extracao nao passam por cima deles.
        contact:
          type: object
          nullable: true
          description: 'Primeiro contato guardado da pessoa (o preferido, senao o mais recente). null sem documento completo ou sem contato.'
          properties:
            name:
              type: string
            email:
              type: string
              nullable: true
            phone:
              type: string
              nullable: true
            source:
              type: string
              enum:
                - FORM
                - OPERATOR
                - HISTORY
            preferred:
              type: boolean
            lastUsedAt:
              type: string
              format: date-time
        linkedRegistryId:
          type: string
          nullable: true
          description: 'Cadastro proprio da pessoa, quando ja existe.'
    RegistryPresignResponse:
      type: object
      properties:
        key:
          type: string
          description: Use exatamente esta chave na confirmacao. Nunca monte a chave no cliente.
        uploadUrl:
          type: string
          description: 'URL para o PUT do arquivo, com o mesmo Content-Type e tamanho declarados.'
        expiresInSeconds:
          type: integer
    RegistryConfirmResponse:
      type: object
      properties:
        documentId:
          type: string
        status:
          type: string
          enum:
            - RECEIVED
            - CLASSIFYING
            - CLASSIFIED
            - EXTRACTING
            - EXTRACTED
            - VALIDATING
            - VALIDATED
            - FAILED
            - MANUAL_REVIEW
            - OUT_OF_SCOPE
            - REJECTED_QUALITY
    RegistryValidateAccepted:
      type: object
      description: 'Resposta 202: o pipeline nao fechou dentro de waitSeconds.'
      properties:
        documentId:
          type: string
        statusUrl:
          type: string
          description: Endereco para continuar por polling ate o status ser terminal.
    RegistryAuditEntry:
      type: object
      properties:
        id:
          type: string
        registryId:
          type: string
        registryDocumentId:
          type: string
          nullable: true
        action:
          type: string
        actorType:
          type: string
          enum:
            - USER
            - API_USER
            - SYSTEM
        actorId:
          type: string
          nullable: true
        payload:
          type: object
          nullable: true
          additionalProperties: true
        createdAt:
          type: string
          format: date-time
    RegistryRuleSet:
      type: object
      properties:
        id:
          type: string
          nullable: true
          description: null quando a organizacao ainda usa a regua padrao da plataforma.
        version:
          type: integer
        versionLabel:
          type: string
        isDefault:
          type: boolean
        rules:
          type: object
          additionalProperties: true
          description: A regua inteira. Os blocos estao documentados em /api-reference/kyc/regua-e-metricas.
        createdAt:
          type: string
          nullable: true
          format: date-time
        updatedAt:
          type: string
          nullable: true
          format: date-time
        createdByUserId:
          type: string
          nullable: true
        createdByApiUserId:
          type: string
          nullable: true
    RegistryRuleSetCatalog:
      type: object
      properties:
        checkCodes:
          type: array
          items:
            type: string
          description: Codigos aceitos em blockingChecks e disabledChecks.
        documentTypes:
          type: array
          items:
            type: string
            enum:
              - CONTRATO_SOCIAL
              - ALTERACAO_CONTRATUAL
              - ESTATUTO_SOCIAL
              - REQUERIMENTO_EMPRESARIO
              - ATA_ASSEMBLEIA
              - PROCURACAO_PJ
              - CERTIDAO_JUNTA
              - CERTIDAO_QSA
              - IRPJ_ECF
              - DECLARACAO_FATURAMENTO
              - CERTIFICADO_SIMPLES_NACIONAL
              - DEMONSTRACOES_FINANCEIRAS
              - EXTRATO_BANCARIO
              - CERTIDAO_PGFN_PJ
              - CERTIDAO_FGTS
              - CADIN_FEDERAL
              - CADIN_ESTADUAL
              - ESOCIAL_PJ
              - DOC_IDENTIDADE
              - COMPROVANTE_RESIDENCIA
              - DIRPF
              - COMPROVANTE_RENDA
              - CERTIDAO_PF
              - PROCURACAO_PF
              - COMPROVACAO_ESTADO_CIVIL
              - FORA_DE_ESCOPO
              - NAO_IDENTIFICADO
        documentTypeInfo:
          type: object
          additionalProperties:
            type: object
            properties:
              label:
                type: string
              description:
                type: string
          description: 'Nome e explicacao de cada tipo, em portugues.'
        defaults:
          type: object
          additionalProperties: true
          description: A regua padrao do motor.
        businessGroups:
          type: array
          items:
            type: object
            properties:
              key:
                type: string
              index:
                type: integer
              title:
                type: string
              hint:
                type: string
              note:
                type: string
          description: As tres perguntas que organizam a regua.
        checks:
          type: array
          items:
            type: object
            properties:
              id:
                type: string
              code:
                type: string
                nullable: true
                description: null nos blocos que reunem varios codigos num interruptor so.
              kind:
                type: string
              label:
                type: string
              description:
                type: string
              businessGroup:
                type: string
              appliesToTypes:
                type: array
                nullable: true
                items:
                  type: string
                  enum:
                    - CONTRATO_SOCIAL
                    - ALTERACAO_CONTRATUAL
                    - ESTATUTO_SOCIAL
                    - REQUERIMENTO_EMPRESARIO
                    - ATA_ASSEMBLEIA
                    - PROCURACAO_PJ
                    - CERTIDAO_JUNTA
                    - CERTIDAO_QSA
                    - IRPJ_ECF
                    - DECLARACAO_FATURAMENTO
                    - CERTIFICADO_SIMPLES_NACIONAL
                    - DEMONSTRACOES_FINANCEIRAS
                    - EXTRATO_BANCARIO
                    - CERTIDAO_PGFN_PJ
                    - CERTIDAO_FGTS
                    - CADIN_FEDERAL
                    - CADIN_ESTADUAL
                    - ESOCIAL_PJ
                    - DOC_IDENTIDADE
                    - COMPROVANTE_RESIDENCIA
                    - DIRPF
                    - COMPROVANTE_RENDA
                    - CERTIDAO_PF
                    - PROCURACAO_PF
                    - COMPROVACAO_ESTADO_CIVIL
                    - FORA_DE_ESCOPO
                    - NAO_IDENTIFICADO
                description: null = roda em todos os tipos.
              parameterKey:
                type: string
                nullable: true
              engineNote:
                type: string
                nullable: true
                description: 'Fato do motor que o operador precisa saber, e nao e editavel.'
        parameters:
          type: array
          items:
            type: object
            properties:
              key:
                type: string
              label:
                type: string
              hint:
                type: string
              unit:
                type: string
              scope:
                type: string
              path:
                type: string
        typeGroups:
          type: array
          items:
            type: object
            properties:
              key:
                type: string
              title:
                type: string
              types:
                type: array
                items:
                  type: string
                  enum:
                    - CONTRATO_SOCIAL
                    - ALTERACAO_CONTRATUAL
                    - ESTATUTO_SOCIAL
                    - REQUERIMENTO_EMPRESARIO
                    - ATA_ASSEMBLEIA
                    - PROCURACAO_PJ
                    - CERTIDAO_JUNTA
                    - CERTIDAO_QSA
                    - IRPJ_ECF
                    - DECLARACAO_FATURAMENTO
                    - CERTIFICADO_SIMPLES_NACIONAL
                    - DEMONSTRACOES_FINANCEIRAS
                    - EXTRATO_BANCARIO
                    - CERTIDAO_PGFN_PJ
                    - CERTIDAO_FGTS
                    - CADIN_FEDERAL
                    - CADIN_ESTADUAL
                    - ESOCIAL_PJ
                    - DOC_IDENTIDADE
                    - COMPROVANTE_RESIDENCIA
                    - DIRPF
                    - COMPROVANTE_RENDA
                    - CERTIDAO_PF
                    - PROCURACAO_PF
                    - COMPROVACAO_ESTADO_CIVIL
                    - FORA_DE_ESCOPO
                    - NAO_IDENTIFICADO
        certificationKinds:
          type: array
          items:
            type: object
            properties:
              value:
                type: string
              label:
                type: string
              hint:
                type: string
          description: Da mais fraca a mais forte.
        defaultVigencyDaysByType:
          type: object
          additionalProperties:
            type: integer
        defaultAcceptedSubtypesByType:
          type: object
          additionalProperties:
            type: array
            items:
              type: string
    RegistryAccuracyMetrics:
      type: object
      description: 'Volume, vereditos, taxas e confianca, por tipo documental e por campo.'
      properties:
        period:
          type: object
          properties:
            from:
              type: string
              nullable: true
            to:
              type: string
              nullable: true
        volume:
          type: object
          properties:
            totalDocuments:
              type: integer
            byStatus:
              type: object
              additionalProperties:
                type: integer
            byType:
              type: object
              additionalProperties:
                type: integer
        sample:
          type: object
          properties:
            size:
              type: integer
            limit:
              type: integer
            truncated:
              type: boolean
              description: true quando a amostra bateu no teto.
        verdicts:
          type: object
          additionalProperties:
            type: integer
        rates:
          type: object
          properties:
            manualReviewRate:
              type: number
              nullable: true
              description: 0 a 1.
            reprocessRate:
              type: number
              nullable: true
              description: 0 a 1.
        accuracy:
          type: object
          properties:
            averageConfidence:
              type: number
              nullable: true
            averageScore:
              type: number
              nullable: true
            lowConfidenceThreshold:
              type: number
        byType:
          type: array
          items:
            type: object
            properties:
              type:
                type: string
                enum:
                  - CONTRATO_SOCIAL
                  - ALTERACAO_CONTRATUAL
                  - ESTATUTO_SOCIAL
                  - REQUERIMENTO_EMPRESARIO
                  - ATA_ASSEMBLEIA
                  - PROCURACAO_PJ
                  - CERTIDAO_JUNTA
                  - CERTIDAO_QSA
                  - IRPJ_ECF
                  - DECLARACAO_FATURAMENTO
                  - CERTIFICADO_SIMPLES_NACIONAL
                  - DEMONSTRACOES_FINANCEIRAS
                  - EXTRATO_BANCARIO
                  - CERTIDAO_PGFN_PJ
                  - CERTIDAO_FGTS
                  - CADIN_FEDERAL
                  - CADIN_ESTADUAL
                  - ESOCIAL_PJ
                  - DOC_IDENTIDADE
                  - COMPROVANTE_RESIDENCIA
                  - DIRPF
                  - COMPROVANTE_RENDA
                  - CERTIDAO_PF
                  - PROCURACAO_PF
                  - COMPROVACAO_ESTADO_CIVIL
                  - FORA_DE_ESCOPO
                  - NAO_IDENTIFICADO
              documents:
                type: integer
              averageConfidence:
                type: number
                nullable: true
              averageScore:
                type: number
                nullable: true
              verdicts:
                type: object
                additionalProperties:
                  type: integer
              manualReviewRate:
                type: number
                nullable: true
              reprocessRate:
                type: number
                nullable: true
              fields:
                type: array
                items:
                  type: object
                  properties:
                    path:
                      type: string
                      description: 'Caminho do campo na extracao (ex.: partners[].name).'
                    documents:
                      type: integer
                    presenceRate:
                      type: number
                      nullable: true
                      description: Quantas vezes o campo veio preenchido.
                    averageConfidence:
                      type: number
                      nullable: true
                      description: Media SO sobre os preenchidos.
    Collection:
      type: object
      description: 'Uma solicitacao de coleta com itens, destinatarios e trilha.'
      properties:
        id:
          type: string
        registryId:
          type: string
        templateId:
          type: string
          nullable: true
        templateSlug:
          type: string
          nullable: true
        templateName:
          type: string
          nullable: true
        templateVersion:
          type: integer
          nullable: true
        status:
          type: string
          enum:
            - DRAFT
            - SENT
            - IN_PROGRESS
            - COMPLETED
            - EXPIRED
            - CANCELED
        responseMode:
          type: string
          enum:
            - AUTOMATIC
            - REVIEW
        channel:
          type: string
          enum:
            - WHATSAPP
            - EMAIL
            - BOTH
            - NONE
          description: 'NONE: a plataforma nao avisou ninguem e quem entrega o link e voce.'
        reminders:
          type: array
          items:
            type: integer
          description: Dias apos o envio.
        behavior:
          type: object
          additionalProperties: true
          description: O comportamento herdado do modelo.
        message:
          type: string
          nullable: true
          description: Recado do operador ao destinatario.
        dueAt:
          type: string
          nullable: true
          format: date-time
        sentAt:
          type: string
          nullable: true
          format: date-time
        completedAt:
          type: string
          nullable: true
          format: date-time
        canceledAt:
          type: string
          nullable: true
          format: date-time
        subjectName:
          type: string
          nullable: true
          description: 'Resumo do cadastro alvo, para evitar uma segunda chamada.'
        subjectDocument:
          type: string
          nullable: true
        items:
          type: array
          items:
            $ref: '#/components/schemas/CollectionItem'
        recipients:
          type: array
          items:
            $ref: '#/components/schemas/CollectionRecipient'
        events:
          type: array
          items:
            type: object
            properties:
              id:
                type: string
              action:
                type: string
              actorType:
                type: string
                enum:
                  - USER
                  - API_USER
                  - RECIPIENT
                  - SYSTEM
              itemId:
                type: string
                nullable: true
              recipientId:
                type: string
                nullable: true
              payload:
                type: object
                nullable: true
                additionalProperties: true
              createdAt:
                type: string
                format: date-time
          description: 'A trilha, append-only. O detalhe traz os 100 eventos mais recentes.'
        registry:
          type: object
          nullable: true
          description: 'O cadastro alvo: id, document, name e entityType.'
          properties:
            id:
              type: string
            document:
              type: string
            name:
              type: string
              nullable: true
            entityType:
              type: string
              enum:
                - COMPANY
                - PERSON
        itemsTotal:
          type: integer
        itemsResolved:
          type: integer
        itemsAwaitingOperator:
          type: integer
          description: Itens esperando decisao humana (AWAITING_OPERATOR ou MANUAL_REVIEW).
        progress:
          type: object
          additionalProperties:
            type: integer
          description: 'Contagem de itens (total, resolved, validated, awaitingOperator, rejected, pending) e de destinatarios (recipientsTotal, recipientsExpected, recipientsCompleted, recipientsWithoutItems).'
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
    CollectionItem:
      type: object
      properties:
        id:
          type: string
        collectionId:
          type: string
        recipientId:
          type: string
          nullable: true
        order:
          type: integer
        kind:
          type: string
          enum:
            - DOCUMENT
            - IDENTITY
            - CONSENT
            - SIGNATURE
            - FORM
            - CUSTOM
        documentType:
          type: string
          nullable: true
          enum:
            - CONTRATO_SOCIAL
            - ALTERACAO_CONTRATUAL
            - ESTATUTO_SOCIAL
            - REQUERIMENTO_EMPRESARIO
            - ATA_ASSEMBLEIA
            - PROCURACAO_PJ
            - CERTIDAO_JUNTA
            - CERTIDAO_QSA
            - IRPJ_ECF
            - DECLARACAO_FATURAMENTO
            - CERTIFICADO_SIMPLES_NACIONAL
            - DEMONSTRACOES_FINANCEIRAS
            - EXTRATO_BANCARIO
            - CERTIDAO_PGFN_PJ
            - CERTIDAO_FGTS
            - CADIN_FEDERAL
            - CADIN_ESTADUAL
            - ESOCIAL_PJ
            - DOC_IDENTIDADE
            - COMPROVANTE_RESIDENCIA
            - DIRPF
            - COMPROVANTE_RENDA
            - CERTIDAO_PF
            - PROCURACAO_PF
            - COMPROVACAO_ESTADO_CIVIL
            - FORA_DE_ESCOPO
            - NAO_IDENTIFICADO
            - null
        label:
          type: string
          description: O que o destinatario le.
        instructions:
          type: string
          nullable: true
        required:
          type: boolean
        rules:
          type: object
          additionalProperties: true
          description: 'Regras da coleta para este item (recencia, formatos, metodos de identidade).'
        status:
          type: string
          enum:
            - PENDING
            - ALREADY_ON_FILE
            - SUBMITTED
            - PROCESSING
            - VALIDATED
            - REJECTED
            - MANUAL_REVIEW
            - AWAITING_OPERATOR
            - WAIVED
            - EXPIRED
        registryDocumentId:
          type: string
          nullable: true
          description: O documento que este item gerou no cadastro.
        attempt:
          type: integer
          nullable: true
        verdict:
          type: string
          nullable: true
          enum:
            - VALIDO
            - INVALIDO
            - INCONCLUSIVO
            - ANALISE_MANUAL
            - null
        score:
          type: number
          nullable: true
        rejectionReason:
          type: string
          nullable: true
          description: 'Motivo tecnico, para o operador.'
        submittedAt:
          type: string
          nullable: true
          format: date-time
        resendRequestedAt:
          type: string
          nullable: true
          format: date-time
        resendCount:
          type: integer
        files:
          type: array
          items:
            type: object
            properties:
              id:
                type: string
              order:
                type: integer
              registryDocumentId:
                type: string
                nullable: true
              status:
                type: string
                enum:
                  - PENDING
                  - ALREADY_ON_FILE
                  - SUBMITTED
                  - PROCESSING
                  - VALIDATED
                  - REJECTED
                  - MANUAL_REVIEW
                  - AWAITING_OPERATOR
                  - WAIVED
                  - EXPIRED
              verdict:
                type: string
                nullable: true
                enum:
                  - VALIDO
                  - INVALIDO
                  - INCONCLUSIVO
                  - ANALISE_MANUAL
                  - null
              score:
                type: number
                nullable: true
              attempt:
                type: integer
                nullable: true
              rejectionReason:
                type: string
                nullable: true
              fileName:
                type: string
                nullable: true
              mimeType:
                type: string
                nullable: true
              sizeBytes:
                type: integer
                nullable: true
              submittedAt:
                type: string
                nullable: true
                format: date-time
              resolvedAt:
                type: string
                nullable: true
                format: date-time
          description: 'Um por arquivo enviado, com o parecer de cada um. Vazio no item que ainda nao recebeu nada.'
        consentType:
          type: string
          nullable: true
          enum:
            - SCR
            - null
        consentTemplateId:
          type: string
          nullable: true
        consentTemplateVersion:
          type: integer
          nullable: true
        optinId:
          type: string
          nullable: true
        consentAcceptedAt:
          type: string
          nullable: true
          format: date-time
        formSpec:
          type: object
          nullable: true
          additionalProperties: true
          description: O formulario pedido.
        formPrefill:
          type: object
          nullable: true
          additionalProperties: true
          description: O que a extracao sugeriu.
        formAnswer:
          type: object
          nullable: true
          additionalProperties: true
          description: O que a pessoa respondeu.
        identityProvider:
          type: string
          nullable: true
        identityStatus:
          type: string
          nullable: true
        identityEvaluation:
          type: object
          nullable: true
          additionalProperties: true
          description: 'A avaliacao da verificacao em portugues (veredito, similaridade, prova de vida, sinais de antifraude). O payload cru do provedor NAO vem aqui.'
        identityMediaCount:
          type: integer
          nullable: true
          description: 'Quantas imagens estao guardadas. Os enderecos saem por acao explicita, que fica na trilha.'
        identityStartedAt:
          type: string
          nullable: true
          format: date-time
        signedDocumentId:
          type: string
          nullable: true
        signatureMode:
          type: string
          enum:
            - INDIVIDUAL
            - JOINT
        signaturePackage:
          type: string
          nullable: true
          enum:
            - SIGNATURE
            - SIGNATURE_AND_IDENTITY
            - null
        signatureProgress:
          type: object
          nullable: true
          description: '"2 de 4 assinaram", ja pronto.'
          properties:
            total:
              type: integer
            signed:
              type: integer
            missing:
              type: array
              items:
                type: string
              description: Nome das partes obrigatorias que faltam.
            awaitingIdentity:
              type: array
              items:
                type: string
              description: Assinaram o texto e esperam a verificacao de identidade.
            awaitingContact:
              type: array
              items:
                type: string
              description: Partes sem contato para receber o link.
            complete:
              type: boolean
              description: true quando a via em PDF pode nascer.
            label:
              type: string
        signatories:
          type: array
          items:
            type: object
            additionalProperties: true
            description: Uma parte do documento conjunto. O documento vem mascarado.
        reviewDecision:
          type: string
          nullable: true
          enum:
            - APPROVED
            - RESEND_REQUESTED
            - WAIVED
            - null
        reviewComment:
          type: string
          nullable: true
        reviewedAt:
          type: string
          nullable: true
          format: date-time
        reviewedByUserId:
          type: string
          nullable: true
        alreadyOnFileReason:
          type: string
          nullable: true
          description: 'Por que o item nasceu ALREADY_ON_FILE, em portugues.'
        resolvedAt:
          type: string
          nullable: true
          format: date-time
        signedDocumentAvailable:
          type: boolean
          description: 'true quando ha via assinada para baixar em GET /v1/collections/{id}/items/{itemId}/signed-document.'
        identityEmailCandidateCount:
          type: integer
          description: Quantos e-mails foram oferecidos para a verificacao por e-mail (nunca quais).
    CollectionRecipient:
      type: object
      properties:
        id:
          type: string
        collectionId:
          type: string
        name:
          type: string
        document:
          type: string
          nullable: true
        email:
          type: string
          nullable: true
        phone:
          type: string
          nullable: true
          description: E.164.
        role:
          type: string
          nullable: true
        registryPersonId:
          type: string
          nullable: true
        status:
          type: string
          enum:
            - PENDING
            - DELIVERED
            - OPENED
            - IN_PROGRESS
            - COMPLETED
            - FAILED
            - NO_ITEMS
          description: 'FAILED quer dizer que a MENSAGEM nao chegou. NO_ITEMS: nao sobrou item para essa pessoa.'
        emailDelivery:
          type: string
          enum:
            - PENDING
            - SENT
            - DELIVERED
            - FAILED
        whatsappDelivery:
          type: string
          enum:
            - PENDING
            - SENT
            - DELIVERED
            - FAILED
        deliveryError:
          type: string
          nullable: true
        tokenExpiresAt:
          type: string
          nullable: true
          format: date-time
        lastSentAt:
          type: string
          nullable: true
          format: date-time
        openedAt:
          type: string
          nullable: true
          format: date-time
        completedAt:
          type: string
          nullable: true
          format: date-time
        remindersSent:
          type: integer
        lastReminderAt:
          type: string
          nullable: true
          format: date-time
        revoked:
          type: boolean
        link:
          type: string
          nullable: true
          description: So volta na criacao e na reemissao. O token cru nunca e persistido.
    CollectionListResponse:
      type: object
      properties:
        items:
          type: array
          items:
            type: object
            properties:
              id:
                type: string
              registryId:
                type: string
              templateId:
                type: string
                nullable: true
              templateName:
                type: string
                nullable: true
              status:
                type: string
                enum:
                  - DRAFT
                  - SENT
                  - IN_PROGRESS
                  - COMPLETED
                  - EXPIRED
                  - CANCELED
              responseMode:
                type: string
                enum:
                  - AUTOMATIC
                  - REVIEW
              channel:
                type: string
                enum:
                  - WHATSAPP
                  - EMAIL
                  - BOTH
                  - NONE
              subjectName:
                type: string
                nullable: true
              subjectDocument:
                type: string
                nullable: true
              itemsTotal:
                type: integer
              itemsResolved:
                type: integer
              itemsAwaitingOperator:
                type: integer
                description: Quantos itens esperam decisao humana.
              dueAt:
                type: string
                nullable: true
                format: date-time
              sentAt:
                type: string
                nullable: true
                format: date-time
              hasScrConsent:
                type: boolean
                description: A solicitacao tem autorizacao de SCR concedida.
              scrConsentItemId:
                type: string
                nullable: true
                description: 'Item da autorizacao de SCR com via assinada, para baixar em GET /v1/collections/{id}/items/{itemId}/signed-document. null quando nao ha PDF.'
              signingDueAt:
                type: string
                nullable: true
                format: date-time
                description: 'Prazo de assinatura na Clicksign, quando a solicitacao tem item assinado por ela.'
              progress:
                type: object
                additionalProperties:
                  type: integer
                description: 'Contagem de itens por situacao: total, resolved, validated, awaitingOperator, rejected, pending.'
              createdAt:
                type: string
                format: date-time
              updatedAt:
                type: string
                format: date-time
        total:
          type: integer
    CollectionCreateResponse:
      allOf:
        - $ref: '#/components/schemas/Collection'
        - type: object
          properties:
            collectionId:
              type: string
              description: O mesmo valor de `id`.
            publicUrl:
              type: string
              nullable: true
              description: 'O link, quando ha um destinatario so. Com varios, vem null e a resposta e `links`.'
            links:
              type: array
              items:
                type: object
                properties:
                  recipientId:
                    type: string
                  name:
                    type: string
                  document:
                    type: string
                    nullable: true
                  link:
                    type: string
                  publicUrl:
                    type: string
                    description: O mesmo endereco de `link`.
              description: Um link por destinatario enviado. Nao vem quando a solicitacao e criada como rascunho (draft true ou send false).
            notified:
              type: boolean
              description: 'false quando o canal e NONE: ninguem foi avisado e quem entrega o link e voce.'
      description: 'A solicitacao criada. Quando ela e enviada na criacao, traz tambem os links: com channel NONE e por aqui que voce recebe o link para entregar. Os links so existem nesta resposta e na de envio.'
    CollectionTemplateListResponse:
      type: object
      properties:
        items:
          type: array
          items:
            type: object
            properties:
              id:
                type: string
              scope:
                type: string
                nullable: true
                enum:
                  - SYSTEM
                  - ORGANIZATION
                  - null
                description: 'SYSTEM e modelo da GYRA+: a organizacao usa e duplica, mas nao edita.'
              name:
                type: string
              slug:
                type: string
                description: O ENDERECO ESTAVEL. E ele que entra em template ao criar solicitacao.
              description:
                type: string
                nullable: true
              items:
                type: array
                items:
                  type: object
                  additionalProperties: true
                  description: Um item do modelo.
              dueInDays:
                type: integer
              reminders:
                type: array
                items:
                  type: integer
              channel:
                type: string
                enum:
                  - WHATSAPP
                  - EMAIL
                  - BOTH
                  - NONE
              responseMode:
                type: string
                enum:
                  - AUTOMATIC
                  - REVIEW
              behavior:
                type: object
                additionalProperties: true
                description: Comportamento do modelo.
              version:
                type: integer
              isCurrent:
                type: boolean
              enabled:
                type: boolean
                description: 'false quando o modelo foi desligado para escolha. Num modelo GYRA+, vale so para a sua organizacao.'
              onCompleted:
                type: object
                nullable: true
                description: 'O que o modelo faz ao concluir. kind NONE, POLICY ou OPERATION; id e a politica ou a esteira. byEntityType, quando existe, traz um destino por tipo de cadastro (COMPANY e PERSON), cada um com kind e id.'
                properties:
                  kind:
                    type: string
                    enum:
                      - NONE
                      - POLICY
                      - OPERATION
                  id:
                    type: string
                    nullable: true
                  byEntityType:
                    type: object
                    additionalProperties:
                      type: object
                      properties:
                        kind:
                          type: string
                          enum:
                            - POLICY
                            - OPERATION
                        id:
                          type: string
              publicFormUrl:
                type: string
                description: 'Endereco do formulario publico, quando o modelo tem um.'
              metrics:
                type: object
                description: Uso do modelo na sua organizacao.
                properties:
                  collections:
                    type: integer
                    description: Solicitacoes criadas com o modelo.
                  completedCollections:
                    type: integer
                  completionRate:
                    type: number
                    description: De 0 a 1.
                  averageCompletionHours:
                    type: number
                    nullable: true
                    description: Horas medias entre envio e conclusao. null sem solicitacao concluida.
              createdAt:
                type: string
                format: date-time
              updatedAt:
                type: string
                format: date-time
        total:
          type: integer
    CollectionContactSuggestionResponse:
      type: array
      items:
        type: object
        properties:
          name:
            type: string
          email:
            type: string
            nullable: true
          phone:
            type: string
            nullable: true
          lastUsedAt:
            type: string
            format: date-time
          timesUsed:
            type: integer
      description: Contatos que este CNPJ/CPF ja usou em solicitacoes anteriores.
    CollectionSignatorySuggestionResponse:
      type: object
      properties:
        mode:
          type: string
          enum:
            - AUTOMATIC
            - HINT
            - MANUAL
          description: MANUAL quando o documento societario nao permite concluir.
        regime:
          type: string
          description: 'ISOLADA, CONJUNTA, MISTA ou INDETERMINADO.'
        signersRequired:
          type: integer
        regimeSentence:
          type: string
          description: O regime explicado em portugues.
        basisLabel:
          type: string
          nullable: true
          description: 'De onde a conclusao saiu, ex.: "contrato social, Clausula 8a".'
        signatories:
          type: array
          items:
            type: object
            additionalProperties: true
            description: 'Um signatario sugerido, com nome, documento e papel.'
        caveats:
          type: array
          items:
            type: string
          description: 'Alcada e vedacao, em portugues, como ressalva visivel.'
        manualReason:
          type: string
          nullable: true
        source:
          type: object
          nullable: true
          additionalProperties: true
    WebhookEventCatalog:
      type: object
      properties:
        groups:
          type: array
          items:
            type: object
            properties:
              title:
                type: string
              events:
                type: array
                items:
                  type: string
          description: 'Agrupamento para a tela. O contrato e o nome do evento, nunca o grupo.'
        events:
          type: array
          items:
            type: string
          description: 'Todos os nomes, em lista plana. Os de relatorio e credito vem primeiro.'
        eventLabels:
          type: object
          additionalProperties:
            type: string
          description: 'Rotulo em portugues dos eventos de relatorio e credito, por nome de evento.'
    WebhookEndpointListResponse:
      type: object
      properties:
        endpoints:
          type: array
          items:
            type: object
            properties:
              id:
                type: string
              url:
                type: string
              label:
                type: string
                nullable: true
              events:
                type: array
                items:
                  type: string
                description: Vazio quer dizer TODOS os eventos.
              enabled:
                type: boolean
              secretHint:
                type: string
                description: Os ultimos caracteres do segredo. O segredo inteiro so aparece na criacao e na rotacao.
              consecutiveFailures:
                type: integer
                description: 'Em 20, a assinatura e desligada sozinha.'
              lastDeliveryStatus:
                type: integer
                nullable: true
              lastDeliveryError:
                type: string
                nullable: true
              lastDeliveryAt:
                type: string
                nullable: true
                format: date-time
              hasApiKey:
                type: boolean
                description: 'So em destino com eventos de relatorio e credito: se ha api-key configurada.'
              createdAt:
                type: string
                format: date-time
              updatedAt:
                type: string
                format: date-time
    WebhookEndpointSaved:
      type: object
      properties:
        id:
          type: string
        url:
          type: string
        label:
          type: string
          nullable: true
        events:
          type: array
          items:
            type: string
        enabled:
          type: boolean
        secretHint:
          type: string
        secret:
          type: string
          description: 'O segredo em claro, no formato whsec_ seguido de 64 caracteres hexadecimais. SO VEM AQUI, na criacao e na rotacao. Guarde no seu cofre.'
        warning:
          type: string
          description: Presente so quando os eventos de relatorio e credito nao foram salvos; diz o motivo.
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
    WebhookTestResult:
      type: object
      properties:
        delivered:
          type: boolean
        httpStatus:
          type: integer
          nullable: true
        error:
          type: string
          nullable: true
    CreateWebhookDto:
      type: object
      properties:
        type:
          $ref: '#/components/schemas/WebhookTypeEnum'
        url:
          type: string
          description: The URL for the webhook
          example: 'https://webhook-test.com/a0a7aadb8de3e'
        apiKey:
          type: string
          description: API Key para uma requisição autenticada (será enviado como `api-key` em headers)
          example: xxx-xxx-xxx
      required:
        - type
        - url
    WebhookTypeEnum:
      type: string
      description: Type Webhook
      enum:
        - REPORT
        - OPTIN
        - CREDIT_POLICY
        - REPORT_STATUS
        - REPORT_FINISHED
        - REPORT_EXPORTED
        - COMMITTEE_FINISHED
        - OPERATION
    CreateReportDto:
      type: object
      properties:
        policyId:
          type: string
          description: Politica habilitada e de usage REPORT.
        document:
          type: string
          description: CPF ou CNPJ sem mascara. Digito verificador validado; CNPJ alfanumerico aceito.
        type:
          type: string
          deprecated: true
          description: Ignorado. O tipo vem da politica.
        months:
          type: integer
          description: 'Meses de historico do SCR. Padrao: o da politica, depois o da organizacao, depois 12.'
      required:
        - policyId
        - document
    CreateRegistryDto:
      type: object
      properties:
        document:
          type: string
          description: 'CNPJ ou CPF valido, com ou sem mascara.'
        name:
          type: string
          description: 'Razao social ou nome. Opcional: os dados basicos oficiais sao buscados na criacao.'
      required:
        - document
    PresignRegistryDocumentDto:
      type: object
      properties:
        fileName:
          type: string
          description: Nome do arquivo.
        size:
          type: integer
          minimum: 1
          maximum: 52428800
          description: 'Tamanho em bytes, ate 50MB. O PUT tem de mandar exatamente este tamanho.'
        mimeType:
          type: string
          enum:
            - application/pdf
            - image/jpeg
            - image/png
          description: O PUT tem de mandar este mesmo Content-Type.
      required:
        - fileName
        - size
        - mimeType
    ConfirmRegistryDocumentDto:
      type: object
      properties:
        typeHint:
          type: string
          enum:
            - CONTRATO_SOCIAL
            - ALTERACAO_CONTRATUAL
            - ESTATUTO_SOCIAL
            - REQUERIMENTO_EMPRESARIO
            - PROCURACAO_PJ
            - IRPJ_ECF
            - DECLARACAO_FATURAMENTO
            - CERTIDAO_JUNTA
            - ATA_ASSEMBLEIA
            - DOC_IDENTIDADE
            - COMPROVANTE_RESIDENCIA
            - DIRPF
            - COMPROVANTE_RENDA
            - CERTIDAO_PF
            - PROCURACAO_PF
            - FORA_DE_ESCOPO
            - NAO_IDENTIFICADO
            - CERTIDAO_PGFN_PJ
            - CERTIDAO_FGTS
            - CADIN_FEDERAL
            - CADIN_ESTADUAL
            - CERTIDAO_QSA
            - CERTIFICADO_SIMPLES_NACIONAL
            - ESOCIAL_PJ
            - COMPROVACAO_ESTADO_CIVIL
            - DEMONSTRACOES_FINANCEIRAS
            - EXTRATO_BANCARIO
          description: 'Afirma o tipo documental do arquivo: o pipeline ADOTA este tipo e PULA a etapa de classificação. Use quando a origem do arquivo já garante o tipo (o operador escolheu na tela, o formulário só aceita aquele documento). Como a classificação não roda, não existe leitura automática a confrontar e a verificação EXPECTED_TYPE_MATCH sai SKIP. Não use typeHint para dizer "eu pedi este documento": para isso existe o expectedType.'
        expectedType:
          type: string
          enum:
            - CONTRATO_SOCIAL
            - ALTERACAO_CONTRATUAL
            - ESTATUTO_SOCIAL
            - REQUERIMENTO_EMPRESARIO
            - PROCURACAO_PJ
            - IRPJ_ECF
            - DECLARACAO_FATURAMENTO
            - CERTIDAO_JUNTA
            - ATA_ASSEMBLEIA
            - DOC_IDENTIDADE
            - COMPROVANTE_RESIDENCIA
            - DIRPF
            - COMPROVANTE_RENDA
            - CERTIDAO_PF
            - PROCURACAO_PF
            - FORA_DE_ESCOPO
            - NAO_IDENTIFICADO
            - CERTIDAO_PGFN_PJ
            - CERTIDAO_FGTS
            - CADIN_FEDERAL
            - CADIN_ESTADUAL
            - CERTIDAO_QSA
            - CERTIFICADO_SIMPLES_NACIONAL
            - ESOCIAL_PJ
            - COMPROVACAO_ESTADO_CIVIL
            - DEMONSTRACOES_FINANCEIRAS
            - EXTRATO_BANCARIO
          description: 'Tipo documental que a solicitação PEDIU. Não força nada e não pula etapa alguma: a classificação roda normalmente e o tipo lido é confrontado com este valor na verificação EXPECTED_TYPE_MATCH. Tipo lido igual ao pedido, a verificação passa; diferente, reprova o documento (ou vira ressalva quando a leitura do tipo está com pouca confiança). É o campo que pega o arquivo legítimo enviado no campo errado (uma declaração de IR subida como comprovante de residência), que sem ele seria classificado, validado e aprovado como o tipo que de fato é. Omitir significa envio livre no dossiê: sem pedido, a verificação sai SKIP. Combinado com typeHint no mesmo envio, o typeHint vence e a verificação sai SKIP (não há classificação a confrontar).'
        key:
          type: string
          description: 'A key devolvida pelo presign, exatamente como veio.'
        fileName:
          type: string
          description: Nome do arquivo que fica no dossie.
        personDocument:
          type: string
          description: 'CPF ou CNPJ de uma pessoa do quadro deste cadastro, para anexar o documento a ela. Precisa estar na arvore societaria.'
        callbackUrl:
          type: string
          description: URL chamada quando o documento terminar de processar.
      required:
        - key
        - fileName
    ReprocessRegistryDocumentDto:
      type: object
      properties:
        forceType:
          type: string
          enum:
            - CONTRATO_SOCIAL
            - ALTERACAO_CONTRATUAL
            - ESTATUTO_SOCIAL
            - REQUERIMENTO_EMPRESARIO
            - PROCURACAO_PJ
            - IRPJ_ECF
            - DECLARACAO_FATURAMENTO
            - CERTIDAO_JUNTA
            - ATA_ASSEMBLEIA
            - DOC_IDENTIDADE
            - COMPROVANTE_RESIDENCIA
            - DIRPF
            - COMPROVANTE_RENDA
            - CERTIDAO_PF
            - PROCURACAO_PF
            - FORA_DE_ESCOPO
            - NAO_IDENTIFICADO
            - CERTIDAO_PGFN_PJ
            - CERTIDAO_FGTS
            - CADIN_FEDERAL
            - CADIN_ESTADUAL
            - CERTIDAO_QSA
            - CERTIFICADO_SIMPLES_NACIONAL
            - ESOCIAL_PJ
            - COMPROVACAO_ESTADO_CIVIL
            - DEMONSTRACOES_FINANCEIRAS
            - EXTRATO_BANCARIO
          description: 'Força o tipo documental (corrige uma classificação errada) e, com isso, dispensa a etapa de classificação.'
        stages:
          type: array
          example:
            - VALIDATE
          description: 'Etapas a reexecutar. Omitir significa reprocessar tudo (classificar, extrair e validar). Cada etapa de fora da lista é pulada e o resultado da tentativa anterior é reaproveitado, o que aparece no resultado do documento em stages.reused. Pular EXTRACT exige tentativa anterior com extração gravada: sem ela a etapa roda normalmente, nunca devolvendo resultado vazio. Reexecutar EXTRACT força a revalidação mesmo que VALIDATE não esteja na lista: parecer antigo sobre extração nova seria mentira.'
          items:
            type: string
            enum:
              - CLASSIFY
              - EXTRACT
              - VALIDATE
        callbackUrl:
          type: string
          description: Webhook chamado quando o reprocessamento terminar.
        overrideFeedback:
          type: boolean
          description: 'Confirma a substituição da decisão que um operador já tomou sobre o parecer. Sem ela, documento já decidido recusa o reprocessamento com 409: a decisão humana não pode ser apagada em silêncio pelo parecer da tentativa nova.'
    SaveWebhookEndpointDto:
      type: object
      properties:
        id:
          type: string
          description: Ausente cria; presente atualiza.
        url:
          type: string
          example: 'https://api.suaempresa.com/gyra/webhook'
          description: 'URL publica, http ou https, com dominio.'
        label:
          type: string
          description: 'Como a assinatura aparece na tela. Na atualizacao, omitir mantem o atual; string vazia limpa.'
          maxLength: 80
        events:
          description: 'Vazio ou ausente quer dizer TODOS os eventos, inclusive os de relatorio e credito. Sem repeticao.'
          type: array
          items:
            type: string
        enabled:
          type: boolean
          description: Religar zera o contador de falhas seguidas.
        apiKey:
          type: string
          description: 'Valor enviado no cabecalho api-key, so nos eventos de relatorio e credito (esses nao usam a assinatura HMAC).'
      required:
        - url
    CreateCollectionDto:
      type: object
      properties:
        template:
          type: string
          description: 'Slug do modelo (ex.: onboarding-pj).'
        document:
          type: string
          description: CNPJ ou CPF do cadastro.
        registryId:
          type: string
          description: Identificador do cadastro (Registry).
        recipients:
          type: array
          items:
            $ref: '#/components/schemas/CollectionRecipientDto'
        parties:
          type: array
          items:
            $ref: '#/components/schemas/CollectionPartyDto'
        dueInDays:
          type: number
          default: 7
        message:
          type: string
          description: Recado do operador ao destinatário.
        responseMode:
          type: string
          enum:
            - AUTOMATIC
            - REVIEW
          description: Sobrepõe o modo de resposta do modelo.
        channel:
          type: string
          enum:
            - WHATSAPP
            - EMAIL
            - BOTH
            - NONE
          description: 'Sobrepõe o canal de envio do modelo. Use `NONE` para a plataforma não avisar ninguém: a solicitação é criada, os links são gerados e voltam na resposta (`publicUrl` quando há um destinatário, `links[]` sempre), e quem entrega é você. Lembrete também não sai.'
        callbackUrl:
          type: string
          description: Webhook do integrador (mesmo HMAC X-Gyra-Signature do cadastro).
        forceItemKeys:
          type: array
          items:
            type: string
        draft:
          type: boolean
          description: Cria a solicitação sem disparar o envio (rascunho).
        send:
          type: boolean
          default: true
      required:
        - template
        - recipients
    CollectionRecipientDto:
      type: object
      properties:
        name:
          type: string
        document:
          type: string
          description: CPF/CNPJ do destinatário (só dígitos).
        email:
          type: string
        phone:
          type: string
          description: Telefone em E.164 (+5551900001234).
        role:
          type: string
          description: 'Ex.: "Sócio administrador · 47%".'
        registryPersonId:
          type: string
          description: Pessoa da árvore societária do cadastro.
        signatureRole:
          type: string
          enum:
            - SIGNATARIO
            - TESTEMUNHA
            - INTERVENIENTE
          default: SIGNATARIO
          description: Papel desta pessoa nos itens de assinatura conjunta. Ignorado quando a solicitação não tem item conjunto.
        signatureRequired:
          type: boolean
          default: true
      required:
        - name
    CollectionPartyDto:
      type: object
      properties:
        name:
          type: string
          description: 'Nome completo, como consta no documento.'
        document:
          type: string
          description: CPF ou CNPJ da parte.
        role:
          type: string
          enum:
            - SIGNATARIO
            - TESTEMUNHA
            - INTERVENIENTE
          default: SIGNATARIO
        required:
          type: boolean
          default: true
      required:
        - name
        - document
    CancelCollectionDto:
      type: object
      properties:
        reason:
          type: string
          description: Motivo do cancelamento.
    ReviewCollectionItemDto:
      type: object
      properties:
        decision:
          type: string
          enum:
            - APPROVED
            - RESEND_REQUESTED
            - WAIVED
        comment:
          type: string
          maxLength: 500
          description: 'Obrigatorio em RESEND_REQUESTED: e o texto que o destinatario le. Opcional nas outras decisoes.'
      required:
        - decision