openapi: 3.0.3
info:
  title: FastCall API de Integracao
  version: 1.1.0
  description: |
    API Publica v1 para integracoes externas com o FastCall.

    A autenticacao usa client credentials. O cliente envia client_id e
    client_secret para gerar um access_token JWT e usa o token no header
    Authorization: Bearer <token>.

    A API e multi-tenant por grupo de empresa. O id_grupo confiavel vem
    somente do token validado e nunca do body, query string ou headers.
servers:
  - url: /api
    description: Prefixo padrao do backend FastCall quando BASE_URL=/api
tags:
  - name: OAuth
    description: Geracao de token de acesso
  - name: Bens
    description: Consulta de bens patrimoniais
  - name: Planos
    description: Catalogo e simulacao comercial publica
  - name: Assinatura
    description: Consulta autenticada da assinatura do grupo
security:
  - bearerAuth: []
paths:
  /v1/oauth/token:
    post:
      tags:
        - OAuth
      summary: Gerar token de acesso
      description: |
        Gera um access_token JWT usando client credentials.

        O client_secret nunca deve ser salvo puro pelo cliente e nunca e
        retornado pela API.
      security: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/TokenRequest"
            examples:
              padrao:
                value:
                  grant_type: client_credentials
                  client_id: fc_client_8f3a91d2b7
                  client_secret: fc_secret_4aae8fd90d7e4bc1a7a2
      responses:
        "200":
          description: Token gerado
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TokenResponse"
              examples:
                sucesso:
                  value:
                    access_token: jwt_aqui
                    token_type: Bearer
                    expires_in: 3600
                    scope: bens:read bens:valor:read colaboradores_bens:read
        "400":
          description: grant_type invalido
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ApiError"
        "401":
          description: Credenciais invalidas ou inativas
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ApiError"
        "429":
          description: Limite de requisicoes excedido
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ApiError"
  /v1/bens/patrimonios/{numero_patrimonio}:
    get:
      tags:
        - Bens
      summary: Buscar bem por patrimonio
      description: |
        Busca um bem ativo pelo numero de patrimonio dentro do grupo
        autenticado. Se a credencial nao tiver acesso a todas as empresas,
        a consulta tambem respeita tb_api_cliente_empresas.

        Escopo obrigatorio: bens:read.
        Escopo opcional: bens:valor:read para retornar valor.
      security:
        - bearerAuth: []
      parameters:
        - name: numero_patrimonio
          in: path
          required: true
          schema:
            type: string
            maxLength: 100
          example: PAT-000123
      responses:
        "200":
          description: Bem encontrado
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/BemPatrimonioResponse"
              examples:
                comValor:
                  value:
                    data:
                      numero_patrimonio: PAT-000123
                      descricao: Notebook Dell Latitude 5420
                      valor:
                        amount: "3500.00"
                        currency: BRL
                semValor:
                  value:
                    data:
                      numero_patrimonio: PAT-000123
                      descricao: Notebook Dell Latitude 5420
        "401":
          description: Token ausente, invalido ou expirado
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ApiError"
        "403":
          description: Escopo insuficiente
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ApiError"
        "404":
          description: Bem nao encontrado no grupo autenticado
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ApiError"
        "422":
          description: Numero de patrimonio invalido
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ApiError"
        "429":
          description: Limite de requisicoes excedido
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ApiError"
  /v1/bens/consulta-por-colaborador:
    post:
      tags:
        - Bens
      summary: Buscar bens por CPF do colaborador
      description: |
        Consulta os bens vinculados a um colaborador pelo CPF. O CPF e
        recebido somente no body, nunca na URL.

        Escopo obrigatorio: colaboradores_bens:read.

        Por LGPD, a resposta retorna apenas CPF mascarado e nao retorna CPF
        completo nem dados pessoais desnecessarios.
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/BensColaboradorRequest"
            examples:
              padrao:
                value:
                  cpf: "12345678909"
      responses:
        "200":
          description: Consulta realizada
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/BensColaboradorResponse"
              examples:
                sucesso:
                  value:
                    data:
                      colaborador:
                        cpf_mascarado: "***.456.789-**"
                      bens:
                        - numero_patrimonio: PAT-000123
                          descricao: Notebook Dell Latitude 5420
                        - numero_patrimonio: PAT-000456
                          descricao: Celular Samsung Galaxy A55
        "401":
          description: Token ausente, invalido ou expirado
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ApiError"
        "403":
          description: Escopo insuficiente
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ApiError"
        "404":
          description: Colaborador nao encontrado no grupo autenticado
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ApiError"
        "422":
          description: CPF invalido
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ApiError"
        "429":
          description: Limite de requisicoes excedido
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ApiError"
  /planos/publicos:
    get:
      tags:
        - Planos
      summary: Consultar catalogo oficial
      description: |
        Retorna somente planos ativos, a versao de preco vigente, descontos
        oficiais e pacotes comerciais derivados. Nao retorna dados de clientes.
      security: []
      responses:
        "200":
          description: Catalogo vigente
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PlanCatalogResponse"
        "429":
          description: Limite de requisicoes excedido
  /planos/simular:
    post:
      tags:
        - Planos
      summary: Simular assinatura
      description: |
        Normaliza capacidades e recalcula todos os valores no backend usando
        precos e regras vigentes.
      security: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/PlanSimulationRequest"
      responses:
        "200":
          description: Simulacao calculada
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PlanSimulationResponse"
        "404":
          description: Plano nao encontrado
        "422":
          description: Combinacao, quantidade ou periodicidade invalida
        "429":
          description: Limite de requisicoes excedido
  /minha-assinatura:
    get:
      tags:
        - Assinatura
      summary: Consultar assinatura do grupo autenticado
      description: |
        O grupo e obtido exclusivamente do access token. O endpoint nao aceita
        id de grupo no path, query string ou body.
      security:
        - bearerAuth: []
      responses:
        "200":
          description: Assinatura atual ou assinatura nula
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CurrentSubscriptionResponse"
        "401":
          description: Token ausente, invalido ou expirado
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
  schemas:
    TokenRequest:
      type: object
      required:
        - grant_type
        - client_id
        - client_secret
      properties:
        grant_type:
          type: string
          enum:
            - client_credentials
        client_id:
          type: string
          example: fc_client_8f3a91d2b7
        client_secret:
          type: string
          example: fc_secret_4aae8fd90d7e4bc1a7a2
    TokenResponse:
      type: object
      properties:
        access_token:
          type: string
        token_type:
          type: string
          example: Bearer
        expires_in:
          type: integer
          example: 3600
        scope:
          type: string
          example: bens:read bens:valor:read colaboradores_bens:read
    ApiError:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              example: INVALID_CLIENT
            message:
              type: string
              example: Credenciais invalidas.
            request_id:
              type: string
              example: req_9a74b2d2f60e42d6b1f8e42d0b795f51
    BemPatrimonioResponse:
      type: object
      properties:
        data:
          type: object
          properties:
            numero_patrimonio:
              type: string
            descricao:
              type: string
            valor:
              type: object
              nullable: true
              properties:
                amount:
                  type: string
                  nullable: true
                currency:
                  type: string
                  example: BRL
    BensColaboradorRequest:
      type: object
      required:
        - cpf
      properties:
        cpf:
          type: string
          description: CPF com ou sem mascara.
          example: "12345678909"
    BensColaboradorResponse:
      type: object
      properties:
        data:
          type: object
          properties:
            colaborador:
              type: object
              properties:
                cpf_mascarado:
                  type: string
                  example: "***.456.789-**"
            bens:
              type: array
              items:
                type: object
                properties:
                  numero_patrimonio:
                    type: string
                  descricao:
                    type: string
    PlanCatalogResponse:
      type: object
      required:
        - moeda
        - planos
        - descontos
        - pacotesComerciais
      properties:
        moeda:
          type: string
          example: BRL
        planos:
          type: array
          items:
            type: object
            properties:
              codigo:
                type: string
                example: FROTA
              nome:
                type: string
                example: FastCall Frota
              slug:
                type: string
                example: fastcall-frota
              tipo:
                type: string
                enum:
                  - MODULO
                  - SOB_CONSULTA
              modulo:
                type: string
                nullable: true
              edicao:
                type: string
                nullable: true
              unidade:
                type: string
                nullable: true
              precoAutomatico:
                type: boolean
              periodicidadeBase:
                type: string
                nullable: true
              periodicidadesPermitidas:
                type: array
                items:
                  type: string
              valorBase:
                type: string
                nullable: true
                example: "49.90"
              quantidadeMinima:
                type: integer
                nullable: true
              quantidadeIncluida:
                type: integer
                nullable: true
              quantidadeBlocoAdicional:
                type: integer
                nullable: true
              valorBlocoAdicional:
                type: string
                nullable: true
              descontoAnualPercentual:
                type: string
                nullable: true
        descontos:
          type: object
          properties:
            doisModulosPercentual:
              type: string
              example: "5.00"
            tresModulosPercentual:
              type: string
              example: "10.00"
            pagamentoAnualPercentual:
              type: string
              example: "10.00"
            maximoAcumuladoPercentual:
              type: string
              example: "20.00"
        pacotesComerciais:
          type: array
          items:
            type: object
    PlanSimulationRequest:
      type: object
      required:
        - itens
      properties:
        itens:
          type: array
          minItems: 1
          maxItems: 10
          items:
            type: object
            required:
              - codigoPlano
              - quantidadeSolicitada
              - periodicidade
            properties:
              codigoPlano:
                type: string
                example: FROTA
              quantidadeSolicitada:
                type: integer
                minimum: 1
              periodicidade:
                type: string
                enum:
                  - MENSAL
                  - ANUAL
    PlanSimulationResponse:
      type: object
      properties:
        moeda:
          type: string
          example: BRL
        itens:
          type: array
          items:
            type: object
            properties:
              codigoPlano:
                type: string
              quantidadeSolicitada:
                type: integer
              capacidadeContratada:
                type: integer
              blocosAdicionais:
                type: integer
              valorBruto:
                type: string
              descontoAnualPercentual:
                type: string
              descontoMultimoduloPercentual:
                type: string
              descontoTotalPercentual:
                type: string
              valorLiquido:
                type: string
        quantidadeModulos:
          type: integer
        pacoteComercial:
          type: object
          nullable: true
        valorBrutoTotal:
          type: string
        valorLiquidoTotal:
          type: string
    CurrentSubscriptionResponse:
      type: object
      properties:
        assinatura:
          type: object
          nullable: true
          properties:
            status:
              type: string
            modeloContrato:
              type: string
              enum:
                - MODULAR
                - LEGADO
            modulosAtivos:
              type: array
              items:
                type: string
            pacoteComercial:
              type: object
              nullable: true
            moeda:
              type: string
            valorBrutoTotal:
              type: string
            valorContratadoTotal:
              type: string
            itens:
              type: array
              items:
                type: object
x-fastcall:
  rateLimit:
    minute: Definido por tb_api_clientes.rate_limit_minuto.
    day: Definido por tb_api_clientes.rate_limit_dia.
  scopes:
    - bens:read
    - bens:valor:read
    - colaboradores_bens:read
  errors:
    - INVALID_GRANT_TYPE
    - INVALID_CLIENT
    - INACTIVE_CLIENT
    - TOKEN_GENERATION_ERROR
    - UNAUTHORIZED
    - FORBIDDEN_SCOPE
    - RATE_LIMIT_EXCEEDED
    - ASSET_NOT_FOUND
    - INVALID_ASSET_NUMBER
    - INVALID_CPF
    - COLLABORATOR_NOT_FOUND
  changelog:
    v1.1.0:
      - Catalogo publico de planos.
      - Simulacao de capacidades, precos e descontos.
      - Consulta autenticada da assinatura atual.
    v1.0.0:
      - Geracao de token client credentials.
      - Consulta de bem por patrimonio.
      - Consulta de bens por CPF do colaborador.
