# Gerado por scripts/openapi-public.mjs: não edite aqui.
openapi: 3.1.0
info:
  title: Nevox API
  version: 1.0.0
  summary: Leve o atendente com IA e o conhecimento da empresa para dentro do seu sistema.
  description: |-
    API pública da Nevox, disponível nos planos com API.
    Documentação completa em https://nevox.ai/docs
  contact:
    name: Nevox
    url: https://nevox.ai/contato
servers:
  - url: https://api.nevox.ai/v1
security:
  - secretKey: []
tags:
  - name: Agentes
  - name: Conversas
  - name: Contatos
  - name: Formulários
  - name: Widget
  - name: Conhecimento
  - name: Ensino
  - name: Ações
  - name: Webhooks
  - name: Análise
  - name: Rastreamento
  - name: Uso
paths:
  /agents:
    get:
      tags:
        - Agentes
      operationId: listAgents
      summary: Listar agentes
      x-scope: agents:read
      parameters:
        - $ref: '#/components/parameters/Limit'
        - $ref: '#/components/parameters/Cursor'
      responses:
        '200':
          description: Lista de agentes
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AgentList'
        default:
          $ref: '#/components/responses/Error'
  /agents/{agent_id}:
    parameters:
      - $ref: '#/components/parameters/AgentId'
    get:
      tags:
        - Agentes
      operationId: getAgent
      summary: Ver um agente
      x-scope: agents:read
      responses:
        '200':
          description: Agente
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Agent'
        default:
          $ref: '#/components/responses/Error'
  /agents/{agent_id}/ask:
    parameters:
      - $ref: '#/components/parameters/AgentId'
    post:
      tags:
        - Conhecimento
      operationId: ask
      summary: Perguntar direto ao conhecimento
      x-scope: knowledge:read
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - question
              properties:
                question:
                  type: string
                  maxLength: 2000
                audience:
                  type: string
                  enum:
                    - customer
                    - staff
                  default: customer
                contact_external_id:
                  type: string
                language:
                  $ref: '#/components/schemas/Language'
      responses:
        '200':
          description: Resposta
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AskResult'
        default:
          $ref: '#/components/responses/Error'
  /agents/{agent_id}/knowledge:
    parameters:
      - $ref: '#/components/parameters/AgentId'
    get:
      tags:
        - Conhecimento
      operationId: listKnowledge
      summary: Listar o conhecimento
      x-scope: knowledge:read
      parameters:
        - $ref: '#/components/parameters/Limit'
        - $ref: '#/components/parameters/Cursor'
        - name: source
          in: query
          schema:
            $ref: '#/components/schemas/KnowledgeSource'
        - name: visibility
          in: query
          schema:
            type: string
            enum:
              - public
              - internal
      responses:
        '200':
          description: Itens
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/ListMeta'
                  - type: object
                    properties:
                      data:
                        type: array
                        items:
                          $ref: '#/components/schemas/KnowledgeItem'
        default:
          $ref: '#/components/responses/Error'
    post:
      tags:
        - Conhecimento
      operationId: createKnowledge
      summary: Adicionar item de conhecimento
      x-scope: knowledge:write
      parameters:
        - $ref: '#/components/parameters/IdempotencyKey'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/KnowledgeInput'
      responses:
        '201':
          description: Criado (ou atualizado, se external_id já existia)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/KnowledgeItem'
        default:
          $ref: '#/components/responses/Error'
  /agents/{agent_id}/knowledge/{knowledge_id}:
    parameters:
      - $ref: '#/components/parameters/AgentId'
      - name: knowledge_id
        in: path
        required: true
        schema:
          type: string
    get:
      tags:
        - Conhecimento
      operationId: getKnowledge
      summary: Ver item
      x-scope: knowledge:read
      responses:
        '200':
          description: Item
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/KnowledgeItem'
        default:
          $ref: '#/components/responses/Error'
    patch:
      tags:
        - Conhecimento
      operationId: updateKnowledge
      summary: Atualizar item
      x-scope: knowledge:write
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/KnowledgeInput'
      responses:
        '200':
          description: Item
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/KnowledgeItem'
        default:
          $ref: '#/components/responses/Error'
    delete:
      tags:
        - Conhecimento
      operationId: deleteKnowledge
      summary: Remover item
      x-scope: knowledge:write
      responses:
        '200':
          $ref: '#/components/responses/Deleted'
        default:
          $ref: '#/components/responses/Error'
  /agents/{agent_id}/services:
    parameters:
      - $ref: '#/components/parameters/AgentId'
    get:
      tags:
        - Conhecimento
      operationId: listServices
      summary: Ver a tabela de serviços
      x-scope: knowledge:read
      responses:
        '200':
          description: Tabela
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServiceTable'
        default:
          $ref: '#/components/responses/Error'
    put:
      tags:
        - Conhecimento
      operationId: replaceServices
      summary: Substituir a tabela de serviços
      x-scope: knowledge:write
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - currency
                - services
              properties:
                currency:
                  $ref: '#/components/schemas/Currency'
                services:
                  type: array
                  maxItems: 500
                  items:
                    $ref: '#/components/schemas/ServiceInput'
      responses:
        '200':
          description: Tabela
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServiceTable'
        default:
          $ref: '#/components/responses/Error'
  /agents/{agent_id}/services/{service_id}:
    parameters:
      - $ref: '#/components/parameters/AgentId'
      - name: service_id
        in: path
        required: true
        schema:
          type: string
    patch:
      tags:
        - Conhecimento
      operationId: updateService
      summary: Atualizar um serviço
      x-scope: knowledge:write
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ServiceInput'
      responses:
        '200':
          description: Serviço
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Service'
        default:
          $ref: '#/components/responses/Error'
  /usage:
    get:
      tags:
        - Uso
      operationId: getUsage
      summary: Consumo do mês
      responses:
        '200':
          description: Uso
          content:
            application/json:
              schema:
                type: object
                properties:
                  plan:
                    type: string
                    enum:
                      - pro
                      - ultimate
                  period:
                    type: object
                    properties:
                      start:
                        type: string
                        format: date
                      end:
                        type: string
                        format: date
                  conversations:
                    $ref: '#/components/schemas/UsageItem'
                  ask:
                    $ref: '#/components/schemas/UsageItem'
                  server_events:
                    $ref: '#/components/schemas/UsageItem'
                  api_keys:
                    $ref: '#/components/schemas/UsageItem'
                  webhook_endpoints:
                    $ref: '#/components/schemas/UsageItem'
        default:
          $ref: '#/components/responses/Error'
  /conversations:
    get:
      tags:
        - Conversas
      operationId: listConversations
      summary: Listar conversas
      x-scope: conversations:read
      parameters:
        - $ref: '#/components/parameters/Limit'
        - $ref: '#/components/parameters/Cursor'
        - name: agent_id
          in: query
          schema:
            type: string
        - name: contact_external_id
          in: query
          schema:
            type: string
        - name: status
          in: query
          schema:
            $ref: '#/components/schemas/ConversationStatus'
        - name: channel
          in: query
          schema:
            $ref: '#/components/schemas/Channel'
        - name: created_after
          in: query
          schema:
            type: string
            format: date-time
        - name: created_before
          in: query
          schema:
            type: string
            format: date-time
      responses:
        '200':
          description: Conversas
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/ListMeta'
                  - type: object
                    properties:
                      data:
                        type: array
                        items:
                          $ref: '#/components/schemas/Conversation'
        default:
          $ref: '#/components/responses/Error'
    post:
      tags:
        - Conversas
      operationId: createConversation
      summary: Abrir conversa
      x-scope: conversations:write
      parameters:
        - $ref: '#/components/parameters/IdempotencyKey'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - agent_id
              properties:
                agent_id:
                  type: string
                contact:
                  allOf:
                    - $ref: '#/components/schemas/ContactInput'
                    - type: object
                      required:
                        - external_id
                      properties:
                        external_id:
                          type: string
                channel:
                  type: string
                  enum:
                    - api
                  default: api
                metadata:
                  $ref: '#/components/schemas/Metadata'
      responses:
        '201':
          description: Conversa
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Conversation'
        default:
          $ref: '#/components/responses/Error'
  /conversations/{conversation_id}:
    parameters:
      - $ref: '#/components/parameters/ConversationId'
    get:
      tags:
        - Conversas
      operationId: getConversation
      summary: Ver conversa
      x-scope: conversations:read
      responses:
        '200':
          description: Conversa
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Conversation'
        default:
          $ref: '#/components/responses/Error'
  /conversations/{conversation_id}/messages:
    parameters:
      - $ref: '#/components/parameters/ConversationId'
    get:
      tags:
        - Conversas
      operationId: listMessages
      summary: Listar mensagens
      x-scope: conversations:read
      parameters:
        - $ref: '#/components/parameters/Limit'
        - $ref: '#/components/parameters/Cursor'
      responses:
        '200':
          description: Mensagens
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/ListMeta'
                  - type: object
                    properties:
                      data:
                        type: array
                        items:
                          $ref: '#/components/schemas/Message'
        default:
          $ref: '#/components/responses/Error'
    post:
      tags:
        - Conversas
      operationId: sendMessage
      summary: Enviar mensagem (usuário ou equipe)
      x-scope: conversations:write
      parameters:
        - $ref: '#/components/parameters/IdempotencyKey'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - content
              properties:
                content:
                  type: string
                  maxLength: 4000
                role:
                  type: string
                  enum:
                    - user
                    - staff
                  default: user
                author:
                  type: object
                  description: Obrigatório quando role=staff
                  properties:
                    id:
                      type: string
                    name:
                      type: string
                stream:
                  type: boolean
                  default: false
      responses:
        '200':
          description: |
            Resultado do turno. Com stream=true, a resposta é text/event-stream com os eventos
            message.started, action.called, message.delta, handoff, message.completed e error.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TurnResult'
            text/event-stream:
              schema:
                type: string
        default:
          $ref: '#/components/responses/Error'
  /conversations/{conversation_id}/handoff:
    parameters:
      - $ref: '#/components/parameters/ConversationId'
    post:
      tags:
        - Conversas
      operationId: handoffConversation
      summary: Passar para humano
      x-scope: conversations:write
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                reason:
                  type: string
                  maxLength: 500
      responses:
        '200':
          description: Conversa
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Conversation'
        default:
          $ref: '#/components/responses/Error'
  /conversations/{conversation_id}/resume:
    parameters:
      - $ref: '#/components/parameters/ConversationId'
    post:
      tags:
        - Conversas
      operationId: resumeConversation
      summary: Devolver para o agente
      x-scope: conversations:write
      responses:
        '200':
          description: Conversa
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Conversation'
        default:
          $ref: '#/components/responses/Error'
  /conversations/{conversation_id}/close:
    parameters:
      - $ref: '#/components/parameters/ConversationId'
    post:
      tags:
        - Conversas
      operationId: closeConversation
      summary: Encerrar conversa
      x-scope: conversations:write
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                resolution:
                  type: string
                  enum:
                    - resolved
                    - unresolved
                    - spam
                  default: resolved
      responses:
        '200':
          description: Conversa
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Conversation'
        default:
          $ref: '#/components/responses/Error'
  /messages/{message_id}/feedback:
    parameters:
      - name: message_id
        in: path
        required: true
        schema:
          type: string
    post:
      tags:
        - Ensino
      operationId: createFeedback
      summary: Corrigir ou aprovar uma resposta do agente
      x-scope: learning:write
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - rating
              properties:
                rating:
                  type: string
                  enum:
                    - correct
                    - incorrect
                correction:
                  type: string
                  maxLength: 5000
                  description: Obrigatório quando rating=incorrect
                author:
                  type: object
                  properties:
                    id:
                      type: string
                    name:
                      type: string
      responses:
        '201':
          description: Feedback registrado
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: string
                  message_id:
                    type: string
                  rating:
                    type: string
                  knowledge_item_id:
                    type:
                      - string
                      - 'null'
                  created_at:
                    type: string
                    format: date-time
        default:
          $ref: '#/components/responses/Error'
  /contacts:
    get:
      tags:
        - Contatos
      operationId: listContacts
      summary: Listar contatos
      x-scope: contacts:read
      parameters:
        - $ref: '#/components/parameters/Limit'
        - $ref: '#/components/parameters/Cursor'
        - name: tag
          in: query
          schema:
            type: string
        - name: email
          in: query
          schema:
            type: string
        - name: phone
          in: query
          schema:
            type: string
        - name: updated_after
          in: query
          schema:
            type: string
            format: date-time
      responses:
        '200':
          description: Contatos
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/ListMeta'
                  - type: object
                    properties:
                      data:
                        type: array
                        items:
                          $ref: '#/components/schemas/Contact'
        default:
          $ref: '#/components/responses/Error'
  /contacts/{external_id}:
    parameters:
      - $ref: '#/components/parameters/ExternalId'
    get:
      tags:
        - Contatos
      operationId: getContact
      summary: Ver contato
      x-scope: contacts:read
      responses:
        '200':
          description: Contato
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Contact'
        default:
          $ref: '#/components/responses/Error'
    put:
      tags:
        - Contatos
      operationId: upsertContact
      summary: Criar ou atualizar contato
      x-scope: contacts:write
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ContactInput'
      responses:
        '200':
          description: Contato
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Contact'
        default:
          $ref: '#/components/responses/Error'
    delete:
      tags:
        - Contatos
      operationId: deleteContact
      summary: Apagar contato e dados ligados
      x-scope: contacts:write
      responses:
        '200':
          $ref: '#/components/responses/Deleted'
        default:
          $ref: '#/components/responses/Error'
  /webhooks:
    get:
      tags:
        - Webhooks
      operationId: listWebhooks
      summary: Listar endpoints
      x-scope: webhooks:write
      responses:
        '200':
          description: Endpoints
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/WebhookEndpoint'
        default:
          $ref: '#/components/responses/Error'
    post:
      tags:
        - Webhooks
      operationId: createWebhook
      summary: Cadastrar endpoint
      x-scope: webhooks:write
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/WebhookInput'
      responses:
        '201':
          description: Criado. secret aparece só nesta resposta.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/WebhookEndpoint'
                  - type: object
                    properties:
                      secret:
                        type: string
        default:
          $ref: '#/components/responses/Error'
  /webhooks/{webhook_id}:
    parameters:
      - name: webhook_id
        in: path
        required: true
        schema:
          type: string
    patch:
      tags:
        - Webhooks
      operationId: updateWebhook
      summary: Atualizar endpoint
      x-scope: webhooks:write
      requestBody:
        required: true
        content:
          application/json:
            schema:
              allOf:
                - $ref: '#/components/schemas/WebhookInput'
                - type: object
                  properties:
                    status:
                      type: string
                      enum:
                        - enabled
                        - disabled
      responses:
        '200':
          description: Endpoint
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WebhookEndpoint'
        default:
          $ref: '#/components/responses/Error'
    delete:
      tags:
        - Webhooks
      operationId: deleteWebhook
      summary: Remover endpoint
      x-scope: webhooks:write
      responses:
        '200':
          $ref: '#/components/responses/Deleted'
        default:
          $ref: '#/components/responses/Error'
  /webhooks/{webhook_id}/test:
    parameters:
      - name: webhook_id
        in: path
        required: true
        schema:
          type: string
    post:
      tags:
        - Webhooks
      operationId: testWebhook
      summary: Enviar evento de teste
      x-scope: webhooks:write
      responses:
        '200':
          description: Resultado
          content:
            application/json:
              schema:
                type: object
                properties:
                  http_status:
                    type: integer
                  latency_ms:
                    type: integer
        default:
          $ref: '#/components/responses/Error'
  /webhooks/{webhook_id}/rotate-secret:
    parameters:
      - name: webhook_id
        in: path
        required: true
        schema:
          type: string
    post:
      tags:
        - Webhooks
      operationId: rotateWebhookSecret
      summary: Gerar novo segredo
      x-scope: webhooks:write
      responses:
        '200':
          description: Novo segredo (aparece só aqui)
          content:
            application/json:
              schema:
                type: object
                properties:
                  secret:
                    type: string
        default:
          $ref: '#/components/responses/Error'
  /widget/sessions:
    post:
      tags:
        - Widget
      operationId: createWidgetSession
      summary: Gerar token de sessão para o widget
      x-scope: sessions:write
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - agent_id
                - contact
              properties:
                agent_id:
                  type: string
                contact:
                  allOf:
                    - $ref: '#/components/schemas/ContactInput'
                    - type: object
                      required:
                        - external_id
                      properties:
                        external_id:
                          type: string
      responses:
        '201':
          description: Token (válido por 1 hora)
          content:
            application/json:
              schema:
                type: object
                properties:
                  token:
                    type: string
                    examples:
                      - nvx_st_9c1e...
                  expires_at:
                    type: string
                    format: date-time
                  contact_id:
                    type: string
        default:
          $ref: '#/components/responses/Error'
  /agents/{agent_id}/actions:
    parameters:
      - $ref: '#/components/parameters/AgentId'
    get:
      tags:
        - Ações
      operationId: listActions
      summary: Listar ações
      x-scope: actions:write
      responses:
        '200':
          description: Ações
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Action'
        default:
          $ref: '#/components/responses/Error'
    post:
      tags:
        - Ações
      operationId: createAction
      summary: Cadastrar ação
      x-scope: actions:write
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ActionInput'
      responses:
        '201':
          description: Criada. signing_secret aparece só nesta resposta.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/Action'
                  - type: object
                    properties:
                      signing_secret:
                        type: string
        default:
          $ref: '#/components/responses/Error'
  /agents/{agent_id}/actions/{action_id}:
    parameters:
      - $ref: '#/components/parameters/AgentId'
      - name: action_id
        in: path
        required: true
        schema:
          type: string
    patch:
      tags:
        - Ações
      operationId: updateAction
      summary: Atualizar ação
      x-scope: actions:write
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ActionInput'
      responses:
        '200':
          description: Ação
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Action'
        default:
          $ref: '#/components/responses/Error'
    delete:
      tags:
        - Ações
      operationId: deleteAction
      summary: Remover ação
      x-scope: actions:write
      responses:
        '200':
          $ref: '#/components/responses/Deleted'
        default:
          $ref: '#/components/responses/Error'
  /agents/{agent_id}/actions/{action_id}/test:
    parameters:
      - $ref: '#/components/parameters/AgentId'
      - name: action_id
        in: path
        required: true
        schema:
          type: string
    post:
      tags:
        - Ações
      operationId: testAction
      summary: Testar ação
      x-scope: actions:write
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                arguments:
                  type: object
                contact_external_id:
                  type: string
      responses:
        '200':
          description: Resultado do teste
          content:
            application/json:
              schema:
                type: object
                properties:
                  http_status:
                    type: integer
                  latency_ms:
                    type: integer
                  signature_accepted:
                    type: boolean
                  response: {}
        default:
          $ref: '#/components/responses/Error'
  /agents/{agent_id}/actions/{action_id}/rotate-secret:
    parameters:
      - $ref: '#/components/parameters/AgentId'
      - name: action_id
        in: path
        required: true
        schema:
          type: string
    post:
      tags:
        - Ações
      operationId: rotateActionSecret
      summary: Gerar novo segredo de assinatura
      x-scope: actions:write
      responses:
        '200':
          description: Novo segredo (aparece só aqui)
          content:
            application/json:
              schema:
                type: object
                properties:
                  signing_secret:
                    type: string
        default:
          $ref: '#/components/responses/Error'
  /events:
    post:
      tags:
        - Rastreamento
      operationId: sendEvents
      summary: Enviar eventos pelo servidor
      x-scope: events:write
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - events
              properties:
                events:
                  type: array
                  minItems: 1
                  maxItems: 100
                  items:
                    $ref: '#/components/schemas/ServerEvent'
      responses:
        '200':
          description: Resultado
          content:
            application/json:
              schema:
                type: object
                properties:
                  accepted:
                    type: integer
                  rejected:
                    type: array
                    items:
                      type: object
                      properties:
                        index:
                          type: integer
                        code:
                          type: string
                        message:
                          type: string
        default:
          $ref: '#/components/responses/Error'
  /collect:
    post:
      tags:
        - Rastreamento
      operationId: collect
      summary: Coleta do navegador (usado pelo widget.js)
      security:
        - publishableKey: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - key
                - session_id
                - consent
                - events
              properties:
                key:
                  type: string
                  description: Chave pública
                visitor_id:
                  type: string
                  description: nvx_vid, só com consentimento
                session_id:
                  type: string
                consent:
                  type: string
                  enum:
                    - anonymous
                    - granted
                events:
                  type: array
                  maxItems: 50
                  items:
                    type: object
                    required:
                      - name
                      - ts
                    properties:
                      name:
                        type: string
                      ts:
                        type: string
                        format: date-time
                      url:
                        type: string
                      title:
                        type: string
                      referrer:
                        type: string
                      utm:
                        type: object
                        additionalProperties:
                          type: string
                      props:
                        $ref: '#/components/schemas/Metadata'
      responses:
        '202':
          description: Aceito
        default:
          $ref: '#/components/responses/Error'
  /analytics/overview:
    get:
      tags:
        - Análise
      operationId: analyticsOverview
      summary: Visão geral
      x-scope: analytics:read
      parameters:
        - $ref: '#/components/parameters/From'
        - $ref: '#/components/parameters/To'
        - $ref: '#/components/parameters/Timezone'
        - $ref: '#/components/parameters/AgentFilter'
        - $ref: '#/components/parameters/ChannelFilter'
        - $ref: '#/components/parameters/Filters'
        - name: compare
          in: query
          schema:
            type: string
            enum:
              - previous_period
      responses:
        '200':
          description: Métricas
          content:
            application/json:
              schema:
                type: object
                properties:
                  period:
                    $ref: '#/components/schemas/Period'
                  metrics:
                    $ref: '#/components/schemas/Metrics'
                  previous:
                    $ref: '#/components/schemas/Metrics'
                  currency:
                    $ref: '#/components/schemas/Currency'
        default:
          $ref: '#/components/responses/Error'
  /analytics/timeseries:
    get:
      tags:
        - Análise
      operationId: analyticsTimeseries
      summary: Série temporal
      x-scope: analytics:read
      parameters:
        - name: metric
          in: query
          required: true
          description: Uma ou mais métricas separadas por vírgula
          schema:
            type: string
        - name: interval
          in: query
          schema:
            type: string
            enum:
              - hour
              - day
              - week
              - month
            default: day
        - $ref: '#/components/parameters/From'
        - $ref: '#/components/parameters/To'
        - $ref: '#/components/parameters/Timezone'
        - $ref: '#/components/parameters/AgentFilter'
        - $ref: '#/components/parameters/ChannelFilter'
        - $ref: '#/components/parameters/Filters'
      responses:
        '200':
          description: Série
          content:
            application/json:
              schema:
                type: object
                properties:
                  interval:
                    type: string
                  data:
                    type: array
                    items:
                      type: object
                      required:
                        - date
                      properties:
                        date:
                          type: string
                      additionalProperties:
                        type: number
        default:
          $ref: '#/components/responses/Error'
  /analytics/breakdown:
    get:
      tags:
        - Análise
      operationId: analyticsBreakdown
      summary: Quebra por dimensão
      x-scope: analytics:read
      parameters:
        - name: dimension
          in: query
          required: true
          schema:
            type: string
            enum:
              - source
              - referrer_domain
              - utm_source
              - utm_medium
              - utm_campaign
              - utm_content
              - utm_term
              - landing_page
              - page
              - device
              - browser
              - os
              - country
              - region
              - city
              - language
              - channel
              - agent_id
              - handoff_reason
              - topic
              - conversion_name
              - contact_tag
        - name: metrics
          in: query
          schema:
            type: string
            default: visitors,conversations,leads
        - name: limit
          in: query
          schema:
            type: integer
            minimum: 1
            maximum: 100
            default: 10
        - $ref: '#/components/parameters/From'
        - $ref: '#/components/parameters/To'
        - $ref: '#/components/parameters/Timezone'
        - $ref: '#/components/parameters/AgentFilter'
        - $ref: '#/components/parameters/ChannelFilter'
        - $ref: '#/components/parameters/Filters'
      responses:
        '200':
          description: Quebra
          content:
            application/json:
              schema:
                type: object
                properties:
                  dimension:
                    type: string
                  data:
                    type: array
                    items:
                      type: object
                      required:
                        - value
                      properties:
                        value:
                          type: string
                      additionalProperties:
                        type: number
        default:
          $ref: '#/components/responses/Error'
  /analytics/funnel:
    get:
      tags:
        - Análise
      operationId: analyticsFunnel
      summary: Funil
      x-scope: analytics:read
      parameters:
        - name: steps
          in: query
          description: >-
            Etapas separadas por vírgula: visited, opened_chat, conversed, lead, appointment_requested, converted, conversion:<nome>. Máximo
            8.
          schema:
            type: string
            default: visited,opened_chat,conversed,lead,appointment_requested,converted
        - $ref: '#/components/parameters/From'
        - $ref: '#/components/parameters/To'
        - $ref: '#/components/parameters/Timezone'
        - $ref: '#/components/parameters/AgentFilter'
        - $ref: '#/components/parameters/Filters'
      responses:
        '200':
          description: Funil
          content:
            application/json:
              schema:
                type: object
                properties:
                  steps:
                    type: array
                    items:
                      type: object
                      properties:
                        step:
                          type: string
                        count:
                          type: integer
                        rate_from_previous:
                          type:
                            - number
                            - 'null'
        default:
          $ref: '#/components/responses/Error'
  /analytics/topics:
    get:
      tags:
        - Análise
      operationId: analyticsTopics
      summary: Temas e perguntas sem resposta
      x-scope: analytics:read
      parameters:
        - $ref: '#/components/parameters/From'
        - $ref: '#/components/parameters/To'
        - $ref: '#/components/parameters/AgentFilter'
        - name: limit
          in: query
          schema:
            type: integer
            minimum: 1
            maximum: 100
            default: 20
      responses:
        '200':
          description: Temas
          content:
            application/json:
              schema:
                type: object
                properties:
                  topics:
                    type: array
                    items:
                      type: object
                      properties:
                        topic:
                          type: string
                        conversations:
                          type: integer
                        resolution_rate:
                          type: number
                  unanswered:
                    type: array
                    items:
                      type: object
                      properties:
                        question:
                          type: string
                        occurrences:
                          type: integer
                        last_seen_at:
                          type: string
                          format: date-time
                        example_conversation_id:
                          type: string
        default:
          $ref: '#/components/responses/Error'
  /analytics/exports:
    post:
      tags:
        - Análise
      operationId: createExport
      summary: Exportar dados (Ultimate)
      x-scope: analytics:read
      x-plan: ultimate
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - dataset
                - from
                - to
              properties:
                dataset:
                  type: string
                  enum:
                    - conversations
                    - messages
                    - visitors
                    - sessions
                    - events
                    - contacts
                from:
                  type: string
                  format: date
                to:
                  type: string
                  format: date
                format:
                  type: string
                  enum:
                    - csv
                  default: csv
      responses:
        '202':
          description: Exportação criada
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Export'
        default:
          $ref: '#/components/responses/Error'
  /analytics/exports/{export_id}:
    parameters:
      - name: export_id
        in: path
        required: true
        schema:
          type: string
    get:
      tags:
        - Análise
      operationId: getExport
      summary: Ver exportação
      x-scope: analytics:read
      x-plan: ultimate
      responses:
        '200':
          description: Exportação
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Export'
        default:
          $ref: '#/components/responses/Error'
  /agents/{agent_id}/test:
    parameters:
      - $ref: '#/components/parameters/AgentId'
    post:
      tags:
        - Ensino
      operationId: testAgent
      summary: Testar respostas incluindo rascunhos (beta)
      x-scope: knowledge:read
      x-status: beta
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - question
              properties:
                question:
                  type: string
                  maxLength: 2000
                include_drafts:
                  type: boolean
                  default: true
      responses:
        '200':
          description: Resposta de teste
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/AskResult'
                  - type: object
                    properties:
                      drafts_used:
                        type: array
                        items:
                          type: string
        default:
          $ref: '#/components/responses/Error'
  /agents/{agent_id}/knowledge/publish:
    parameters:
      - $ref: '#/components/parameters/AgentId'
    post:
      tags:
        - Ensino
      operationId: publishKnowledge
      summary: Publicar rascunhos (beta)
      x-scope: knowledge:write
      x-status: beta
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: string
      responses:
        '200':
          description: Publicados
          content:
            application/json:
              schema:
                type: object
                properties:
                  published:
                    type: integer
        default:
          $ref: '#/components/responses/Error'
  /agents/{agent_id}/learning/suggestions:
    parameters:
      - $ref: '#/components/parameters/AgentId'
    get:
      tags:
        - Ensino
      operationId: listSuggestions
      summary: Listar sugestões de aprendizado (beta)
      x-scope: learning:write
      x-status: beta
      parameters:
        - name: status
          in: query
          schema:
            type: string
            enum:
              - pending
              - approved
              - rejected
        - $ref: '#/components/parameters/Limit'
        - $ref: '#/components/parameters/Cursor'
      responses:
        '200':
          description: Sugestões
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/ListMeta'
                  - type: object
                    properties:
                      data:
                        type: array
                        items:
                          $ref: '#/components/schemas/LearningSuggestion'
        default:
          $ref: '#/components/responses/Error'
  /agents/{agent_id}/learning/suggestions/{suggestion_id}/approve:
    parameters:
      - $ref: '#/components/parameters/AgentId'
      - name: suggestion_id
        in: path
        required: true
        schema:
          type: string
    post:
      tags:
        - Ensino
      operationId: approveSuggestion
      summary: Aprovar sugestão (beta)
      x-scope: learning:write
      x-status: beta
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                answer:
                  type: string
                visibility:
                  type: string
                  enum:
                    - public
                    - internal
      responses:
        '200':
          description: Aprovada
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LearningSuggestion'
        default:
          $ref: '#/components/responses/Error'
  /agents/{agent_id}/learning/suggestions/{suggestion_id}/reject:
    parameters:
      - $ref: '#/components/parameters/AgentId'
      - name: suggestion_id
        in: path
        required: true
        schema:
          type: string
    post:
      tags:
        - Ensino
      operationId: rejectSuggestion
      summary: Rejeitar sugestão (beta)
      x-scope: learning:write
      x-status: beta
      responses:
        '200':
          description: Rejeitada
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LearningSuggestion'
        default:
          $ref: '#/components/responses/Error'
  /visitors:
    get:
      tags:
        - Análise
      operationId: listVisitors
      summary: Listar visitantes (só os com consentimento)
      x-scope: analytics:read
      parameters:
        - $ref: '#/components/parameters/Limit'
        - $ref: '#/components/parameters/Cursor'
        - name: identified
          in: query
          schema:
            type: boolean
        - name: has_conversation
          in: query
          schema:
            type: boolean
        - name: is_lead
          in: query
          schema:
            type: boolean
        - name: first_seen_after
          in: query
          schema:
            type: string
            format: date-time
        - name: utm_source
          in: query
          schema:
            type: string
        - name: country
          in: query
          schema:
            type: string
      responses:
        '200':
          description: Visitantes
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/ListMeta'
                  - type: object
                    properties:
                      data:
                        type: array
                        items:
                          $ref: '#/components/schemas/Visitor'
        default:
          $ref: '#/components/responses/Error'
  /visitors/{visitor_id}:
    parameters:
      - name: visitor_id
        in: path
        required: true
        schema:
          type: string
    get:
      tags:
        - Análise
      operationId: getVisitor
      summary: Ver visitante
      x-scope: analytics:read
      responses:
        '200':
          description: Visitante
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Visitor'
        default:
          $ref: '#/components/responses/Error'
  /contacts/{external_id}/timeline:
    parameters:
      - $ref: '#/components/parameters/ExternalId'
    get:
      tags:
        - Análise
      operationId: contactTimeline
      summary: Linha do tempo do contato
      x-scope: analytics:read
      parameters:
        - $ref: '#/components/parameters/Limit'
        - $ref: '#/components/parameters/Cursor'
      responses:
        '200':
          description: Linha do tempo
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/ListMeta'
                  - type: object
                    properties:
                      contact:
                        $ref: '#/components/schemas/ContactRef'
                      data:
                        type: array
                        items:
                          $ref: '#/components/schemas/TimelineItem'
        default:
          $ref: '#/components/responses/Error'
  /form_submissions:
    get:
      tags:
        - Formulários
      operationId: listFormSubmissions
      summary: Listar formulários enviados nos sites
      description: Cada envio de formulário dos sites da empresa feitos pela Nevox, os mais novos primeiro. O mesmo formato do webhook form.submitted.
      x-scope: forms:read
      parameters:
        - $ref: '#/components/parameters/Limit'
        - $ref: '#/components/parameters/Cursor'
        - name: site_id
          in: query
          schema:
            type: string
            format: uuid
        - name: form
          in: query
          description: Nome exato do formulário
          schema:
            type: string
        - name: created_after
          in: query
          schema:
            type: string
            format: date-time
      responses:
        '200':
          description: Formulários
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/ListMeta'
                  - type: object
                    properties:
                      data:
                        type: array
                        items:
                          $ref: '#/components/schemas/FormSubmission'
        default:
          $ref: '#/components/responses/Error'
components:
  securitySchemes:
    secretKey:
      type: http
      scheme: bearer
      description: Chave secreta nvx_sk_live_... ou nvx_sk_test_..., só no servidor.
    publishableKey:
      type: apiKey
      in: header
      name: Nevox-Publishable-Key
      description: Chave pública nvx_pk_..., também aceita no corpo como `key`.
  parameters:
    AgentId:
      name: agent_id
      in: path
      required: true
      schema:
        type: string
        examples:
          - agt_8f2k1x
    ConversationId:
      name: conversation_id
      in: path
      required: true
      schema:
        type: string
        examples:
          - conv_7mk2p9
    ExternalId:
      name: external_id
      in: path
      required: true
      description: Seu ID do contato
      schema:
        type: string
    Limit:
      name: limit
      in: query
      schema:
        type: integer
        minimum: 1
        maximum: 100
        default: 20
    Cursor:
      name: cursor
      in: query
      schema:
        type: string
    IdempotencyKey:
      name: Idempotency-Key
      in: header
      schema:
        type: string
        maxLength: 255
    From:
      name: from
      in: query
      schema:
        type: string
        format: date
    To:
      name: to
      in: query
      schema:
        type: string
        format: date
    Timezone:
      name: timezone
      in: query
      schema:
        type: string
        examples:
          - America/Sao_Paulo
    AgentFilter:
      name: agent_id
      in: query
      schema:
        type: string
    ChannelFilter:
      name: channel
      in: query
      schema:
        $ref: '#/components/schemas/Channel'
    Filters:
      name: filters
      in: query
      description: dimensão:valor separados por ;
      schema:
        type: string
        examples:
          - device:mobile;utm_source:google
  responses:
    Error:
      description: Erro
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Deleted:
      description: Removido
      content:
        application/json:
          schema:
            type: object
            properties:
              id:
                type: string
              deleted:
                type: boolean
                const: true
  schemas:
    Error:
      type: object
      required:
        - error
      properties:
        error:
          type: object
          required:
            - type
            - code
            - message
            - request_id
          properties:
            type:
              type: string
              enum:
                - invalid_request
                - authentication_error
                - permission_error
                - not_found
                - conflict
                - rate_limit_error
                - api_error
            code:
              type: string
            message:
              type: string
            param:
              type: string
            request_id:
              type: string
    ListMeta:
      type: object
      required:
        - has_more
        - next_cursor
      properties:
        has_more:
          type: boolean
        next_cursor:
          type:
            - string
            - 'null'
    Metadata:
      type: object
      maxProperties: 50
      additionalProperties:
        type:
          - string
          - number
          - boolean
    Language:
      type: string
      enum:
        - pt-BR
        - en-US
        - es
    Currency:
      type: string
      enum:
        - BRL
        - USD
    Channel:
      type: string
      enum:
        - api
        - widget
        - whatsapp
        - site
        - sms
        - voice
    ConversationStatus:
      type: string
      enum:
        - active
        - handoff
        - human
        - closed
    KnowledgeSource:
      type: string
      enum:
        - dashboard
        - api
        - vox
        - website
        - correction
        - learning
    Agent:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        language:
          $ref: '#/components/schemas/Language'
        status:
          type: string
          enum:
            - active
            - paused
        created_at:
          type: string
          format: date-time
    AgentList:
      allOf:
        - $ref: '#/components/schemas/ListMeta'
        - type: object
          properties:
            data:
              type: array
              items:
                $ref: '#/components/schemas/Agent'
    AskResult:
      type: object
      required:
        - answered
        - answer
        - sources
      properties:
        answered:
          type: boolean
        answer:
          type:
            - string
            - 'null'
        confidence:
          type: string
          enum:
            - high
            - medium
            - low
        sources:
          type: array
          items:
            type: object
            properties:
              type:
                type: string
                enum:
                  - text
                  - faq
                  - url
                  - file
                  - correction
                  - service
                  - learning
              id:
                type: string
              title:
                type: string
        usage:
          type: object
          properties:
            ask_count_month:
              type: integer
            ask_limit_month:
              type: integer
    KnowledgeInput:
      type: object
      properties:
        type:
          type: string
          enum:
            - text
            - faq
        title:
          type: string
          maxLength: 200
        content:
          type: string
          maxLength: 50000
          description: Para text.
        question:
          type: string
        answer:
          type: string
        visibility:
          type: string
          enum:
            - public
            - internal
          default: public
        external_id:
          type: string
    KnowledgeItem:
      type: object
      properties:
        id:
          type: string
        type:
          type: string
          enum:
            - text
            - faq
        title:
          type: string
        visibility:
          type: string
          enum:
            - public
            - internal
        status:
          type: string
          enum:
            - processing
            - ready
            - failed
        failure_reason:
          type:
            - string
            - 'null'
        source:
          $ref: '#/components/schemas/KnowledgeSource'
        external_id:
          type:
            - string
            - 'null'
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
    ServiceInput:
      type: object
      required:
        - name
        - price_type
      properties:
        external_id:
          type: string
        name:
          type: string
          maxLength: 200
        price_type:
          type: string
          enum:
            - fixed
            - from
            - per_unit
            - on_evaluation
        price:
          type: integer
          minimum: 0
          description: Centavos
        unit:
          type: string
          enum:
            - hour
            - m2
            - room
            - visit
            - pet
            - session
            - month
        duration_minutes:
          type: integer
          minimum: 0
        notes:
          type: string
          maxLength: 500
        active:
          type: boolean
          default: true
    Service:
      allOf:
        - $ref: '#/components/schemas/ServiceInput'
        - type: object
          properties:
            id:
              type: string
            updated_at:
              type: string
              format: date-time
    ServiceTable:
      type: object
      properties:
        currency:
          $ref: '#/components/schemas/Currency'
        services:
          type: array
          items:
            $ref: '#/components/schemas/Service'
    ContactInput:
      type: object
      properties:
        external_id:
          type: string
        name:
          type: string
        email:
          type: string
          format: email
        phone:
          type: string
          description: E.164
        language:
          $ref: '#/components/schemas/Language'
        tags:
          type: array
          maxItems: 20
          items:
            type: string
        metadata:
          $ref: '#/components/schemas/Metadata'
    Contact:
      allOf:
        - $ref: '#/components/schemas/ContactInput'
        - type: object
          properties:
            id:
              type: string
            channels:
              type: array
              items:
                $ref: '#/components/schemas/Channel'
            first_seen_at:
              type: string
              format: date-time
            last_seen_at:
              type: string
              format: date-time
            created_at:
              type: string
              format: date-time
            updated_at:
              type: string
              format: date-time
    FormSubmission:
      type: object
      properties:
        id:
          type: string
          example: frm_3f9c2a7e0b1d4c5e8f6a9b0c1d2e3f40
        site:
          type: object
          properties:
            id:
              type: string
              format: uuid
            name:
              type: string
            domain:
              type:
                - string
                - 'null'
        form:
          type: string
        name:
          type: string
        email:
          type:
            - string
            - 'null'
        phone:
          type:
            - string
            - 'null'
          description: Como a pessoa escreveu
        phone_e164:
          type:
            - string
            - 'null'
          description: +5511987654321; null quando não dá para ter certeza do país
        message:
          type:
            - string
            - 'null'
        fields:
          type: object
          additionalProperties:
            type: string
        page:
          type:
            - string
            - 'null'
        referrer:
          type:
            - string
            - 'null'
        language:
          type: string
          enum:
            - pt-BR
            - en
        utm:
          type: object
          properties:
            source:
              type:
                - string
                - 'null'
            medium:
              type:
                - string
                - 'null'
            campaign:
              type:
                - string
                - 'null'
            term:
              type:
                - string
                - 'null'
            content:
              type:
                - string
                - 'null'
        created_at:
          type: string
          format: date-time
    ContactRef:
      type: object
      properties:
        id:
          type: string
        external_id:
          type:
            - string
            - 'null'
        name:
          type:
            - string
            - 'null'
    Conversation:
      type: object
      properties:
        id:
          type: string
        agent_id:
          type: string
        contact_id:
          type:
            - string
            - 'null'
        channel:
          $ref: '#/components/schemas/Channel'
        status:
          $ref: '#/components/schemas/ConversationStatus'
        handoff_reason:
          type:
            - string
            - 'null'
        resolution:
          type:
            - string
            - 'null'
          enum:
            - resolved
            - unresolved
            - spam
            - inactive
            - null
        summary:
          type:
            - string
            - 'null'
        metadata:
          $ref: '#/components/schemas/Metadata'
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
        closed_at:
          type:
            - string
            - 'null'
          format: date-time
    Message:
      type: object
      properties:
        id:
          type: string
        role:
          type: string
          enum:
            - user
            - agent
            - staff
            - system
        content:
          type: string
        author:
          type:
            - object
            - 'null'
          properties:
            id:
              type: string
            name:
              type: string
        actions_called:
          type: array
          items:
            type: object
            properties:
              name:
                type: string
              status:
                type: string
                enum:
                  - succeeded
                  - failed
                  - timeout
                  - rejected
        created_at:
          type: string
          format: date-time
    TurnResult:
      type: object
      properties:
        user_message:
          $ref: '#/components/schemas/Message'
        agent_message:
          oneOf:
            - $ref: '#/components/schemas/Message'
            - type: 'null'
        conversation_status:
          $ref: '#/components/schemas/ConversationStatus'
    LearningSuggestion:
      type: object
      properties:
        id:
          type: string
        status:
          type: string
          enum:
            - pending
            - approved
            - rejected
        question:
          type: string
        proposed_answer:
          type: string
        final_answer:
          type:
            - string
            - 'null'
        source_conversation_id:
          type:
            - string
            - 'null'
        knowledge_item_id:
          type:
            - string
            - 'null'
        created_at:
          type: string
          format: date-time
    ActionInput:
      type: object
      required:
        - name
        - description
        - url
        - mode
      properties:
        name:
          type: string
          pattern: ^[a-z0-9_]{1,64}$
        description:
          type: string
          maxLength: 1000
        url:
          type: string
          format: uri
          pattern: ^https://
        mode:
          type: string
          enum:
            - read
            - write
        requires_confirmation:
          type: boolean
          description: Forçado true em write
        requires_contact:
          type: boolean
          default: true
        parameters:
          type: object
          description: JSON Schema dos argumentos
        timeout_ms:
          type: integer
          minimum: 1000
          maximum: 15000
          default: 8000
    Action:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        description:
          type: string
        url:
          type: string
        mode:
          type: string
          enum:
            - read
            - write
        requires_confirmation:
          type: boolean
        requires_contact:
          type: boolean
        parameters:
          type: object
        timeout_ms:
          type: integer
        status:
          type: string
          enum:
            - active
            - disabled
        created_at:
          type: string
          format: date-time
    WebhookInput:
      type: object
      required:
        - url
        - events
      properties:
        url:
          type: string
          format: uri
          pattern: ^https://
        events:
          type: array
          minItems: 1
          items:
            $ref: '#/components/schemas/WebhookEventType'
        description:
          type: string
          maxLength: 200
    WebhookEndpoint:
      type: object
      properties:
        id:
          type: string
        url:
          type: string
        events:
          type: array
          items:
            type: string
        description:
          type:
            - string
            - 'null'
        status:
          type: string
          enum:
            - enabled
            - disabled
        created_at:
          type: string
          format: date-time
    WebhookEventType:
      type: string
      enum:
        - '*'
        - conversation.created
        - conversation.handoff
        - conversation.human_assigned
        - conversation.closed
        - message.created
        - contact.created
        - contact.updated
        - visitor.identified
    Period:
      type: object
      properties:
        from:
          type: string
          format: date
        to:
          type: string
          format: date
        timezone:
          type: string
    Metrics:
      type: object
      properties:
        visitors:
          type: integer
        sessions:
          type: integer
        pageviews:
          type: integer
        widget_opens:
          type: integer
        conversations:
          type: integer
        leads:
          type: integer
        appointments_requested:
          type: integer
        handoffs:
          type: integer
        conversions:
          type: integer
        conversion_value:
          type: integer
          description: Centavos
        resolution_rate:
          type: number
        avg_first_response_seconds:
          type: number
        unanswered_questions:
          type: integer
        feedback_incorrect:
          type: integer
    Visitor:
      type: object
      properties:
        id:
          type: string
        identified:
          type: boolean
        contact:
          oneOf:
            - $ref: '#/components/schemas/ContactRef'
            - type: 'null'
        first_seen_at:
          type: string
          format: date-time
        last_seen_at:
          type: string
          format: date-time
        sessions_count:
          type: integer
        pageviews_count:
          type: integer
        first_touch:
          $ref: '#/components/schemas/Touch'
        last_touch:
          $ref: '#/components/schemas/Touch'
        device:
          type: string
        country:
          type: string
        region:
          type: string
        conversations:
          type: array
          items:
            type: string
        is_lead:
          type: boolean
    Touch:
      type: object
      properties:
        source:
          type: string
        utm_source:
          type: string
        utm_medium:
          type: string
        utm_campaign:
          type: string
        landing_page:
          type: string
        referrer_domain:
          type: string
    TimelineItem:
      type: object
      required:
        - at
        - type
      properties:
        at:
          type: string
          format: date-time
        type:
          type: string
          enum:
            - session_started
            - page_view
            - conversation_started
            - lead
            - appointment_requested
            - handoff
            - conversation_closed
            - conversion
            - custom_event
        conversation_id:
          type: string
        channel:
          $ref: '#/components/schemas/Channel'
        name:
          type: string
        value:
          type: integer
        currency:
          $ref: '#/components/schemas/Currency'
        source:
          type: string
        landing_page:
          type: string
    ServerEvent:
      type: object
      required:
        - name
      properties:
        name:
          type: string
          pattern: ^[a-z0-9_]{1,64}$
        contact_external_id:
          type: string
        visitor_id:
          type: string
        occurred_at:
          type: string
          format: date-time
        value:
          type: integer
          description: Centavos
        currency:
          $ref: '#/components/schemas/Currency'
        properties:
          $ref: '#/components/schemas/Metadata'
        dedupe_key:
          type: string
          maxLength: 128
    Export:
      type: object
      properties:
        id:
          type: string
        dataset:
          type: string
        from:
          type: string
          format: date
        to:
          type: string
          format: date
        status:
          type: string
          enum:
            - queued
            - running
            - ready
            - failed
            - expired
        row_count:
          type:
            - integer
            - 'null'
        failure_reason:
          type:
            - string
            - 'null'
        download_url:
          type:
            - string
            - 'null'
        expires_at:
          type:
            - string
            - 'null'
          format: date-time
        created_at:
          type: string
          format: date-time
    UsageItem:
      type: object
      properties:
        used:
          type: integer
        limit:
          type: integer
