YAML
openapi: 3.1.0
info:
  title: Encantra API
  version: "1.0"
  summary: API REST v1 da plataforma Encantra (suporte com IA e customer success).
  description: |
    Autenticação por chave de API (Bearer `enc_live_...`) com escopos. Limite: 600 req/min por chave.
    Respostas `{data, meta}`; erros `{error:{status,message,fields?}}`.
  contact:
    name: Encantra
    email: master@inspire4u.com.br
servers:
  - url: https://suporte.inspire4u.com.br/api/v1
security:
  - apiKey: []
tags:
  - name: conta
  - name: contas
  - name: contatos
  - name: eventos
  - name: conhecimento
  - name: tickets
paths:
  /me:
    get:
      tags: [conta]
      summary: Workspace e chave em uso
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tenant: { type: object, properties: { uuid: { type: string }, name: { type: string }, slug: { type: string }, plan: { type: string }, status: { type: string } } }
                      key: { type: object, properties: { name: { type: string }, prefix: { type: string }, scopes: { type: array, items: { type: string } } } }
                      api_version: { type: string, const: v1 }
        "401": { $ref: "#/components/responses/Error" }
  /accounts:
    get:
      tags: [contas]
      summary: Lista contas
      parameters:
        - { name: external_id, in: query, schema: { type: string } }
        - { name: domain, in: query, schema: { type: string } }
        - { name: lifecycle_stage, in: query, schema: { $ref: "#/components/schemas/LifecycleStage" } }
        - { name: updated_since, in: query, schema: { type: string, format: date-time } }
        - $ref: "#/components/parameters/page"
        - $ref: "#/components/parameters/perPage"
      responses:
        "200":
          description: Página de contas
          content:
            application/json:
              schema:
                type: object
                properties:
                  data: { type: array, items: { $ref: "#/components/schemas/Account" } }
                  meta: { $ref: "#/components/schemas/PageMeta" }
        "403": { $ref: "#/components/responses/Error" }
    post:
      tags: [contas]
      summary: Cria ou atualiza conta (upsert por external_id)
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: "#/components/schemas/AccountInput" }
      responses:
        "200": { $ref: "#/components/responses/AccountSaved" }
        "201": { $ref: "#/components/responses/AccountSaved" }
        "402": { $ref: "#/components/responses/Error" }
        "422": { $ref: "#/components/responses/Error" }
  /accounts/{id}:
    parameters:
      - { name: id, in: path, required: true, schema: { type: integer } }
    get:
      tags: [contas]
      summary: Detalhe da conta
      responses:
        "200":
          description: Conta
          content:
            application/json:
              schema: { type: object, properties: { data: { $ref: "#/components/schemas/Account" } } }
        "404": { $ref: "#/components/responses/Error" }
    patch:
      tags: [contas]
      summary: Atualização parcial
      requestBody:
        content:
          application/json:
            schema: { $ref: "#/components/schemas/AccountInput" }
      responses:
        "200":
          description: Conta atualizada
          content:
            application/json:
              schema: { type: object, properties: { data: { $ref: "#/components/schemas/Account" } } }
        "404": { $ref: "#/components/responses/Error" }
  /contacts:
    get:
      tags: [contatos]
      summary: Lista contatos
      parameters:
        - { name: email, in: query, schema: { type: string, format: email } }
        - { name: external_id, in: query, schema: { type: string } }
        - { name: account_id, in: query, schema: { type: integer } }
        - $ref: "#/components/parameters/page"
        - $ref: "#/components/parameters/perPage"
      responses:
        "200":
          description: Página de contatos
          content:
            application/json:
              schema:
                type: object
                properties:
                  data: { type: array, items: { $ref: "#/components/schemas/Contact" } }
                  meta: { $ref: "#/components/schemas/PageMeta" }
    post:
      tags: [contatos]
      summary: Cria ou atualiza contato (upsert por external_id ou email)
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: "#/components/schemas/ContactInput" }
      responses:
        "200": { $ref: "#/components/responses/ContactSaved" }
        "201": { $ref: "#/components/responses/ContactSaved" }
        "422": { $ref: "#/components/responses/Error" }
  /events:
    post:
      tags: [eventos]
      summary: Registra eventos de uso (lote até 1000)
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [events]
              properties:
                events: { type: array, maxItems: 1000, items: { $ref: "#/components/schemas/UsageEvent" } }
      responses:
        "202":
          description: Aceito
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      inserted: { type: integer }
                      skipped: { type: integer }
                      errors: { type: array, items: { type: object, properties: { index: { type: integer }, message: { type: string } } } }
        "413": { $ref: "#/components/responses/Error" }
        "422": { $ref: "#/components/responses/Error" }
  /knowledge:
    post:
      tags: [conhecimento]
      summary: Publica ou atualiza um documento no conhecimento da Lumi
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [source_id, title, body_markdown]
              properties:
                source_id: { type: string, maxLength: 190 }
                title: { type: string, maxLength: 255 }
                body_markdown: { type: string, maxLength: 500000 }
                url: { type: [string, "null"] }
                visibility: { type: string, enum: [public, internal], default: public }
                locale: { type: string, default: pt-BR }
                type: { type: string, default: article }
                tags: { type: array, items: { type: string } }
      responses:
        "201":
          description: Indexado
          content:
            application/json:
              schema: { type: object, properties: { data: { type: object, properties: { id: { type: integer }, source_id: { type: string }, chunks: { type: integer } } } } }
        "422": { $ref: "#/components/responses/Error" }
  /knowledge/{source_id}:
    delete:
      tags: [conhecimento]
      summary: Remove um documento publicado pela API
      parameters:
        - { name: source_id, in: path, required: true, schema: { type: string } }
      responses:
        "200": { description: Removido }
        "404": { $ref: "#/components/responses/Error" }
  /tickets:
    get:
      tags: [tickets]
      summary: Lista tickets
      parameters:
        - { name: status, in: query, schema: { $ref: "#/components/schemas/TicketStatus" } }
        - { name: priority, in: query, schema: { $ref: "#/components/schemas/Priority" } }
        - { name: channel, in: query, schema: { type: string } }
        - { name: contact_email, in: query, schema: { type: string, format: email } }
        - $ref: "#/components/parameters/page"
        - $ref: "#/components/parameters/perPage"
      responses:
        "200":
          description: Página de tickets
          content:
            application/json:
              schema:
                type: object
                properties:
                  data: { type: array, items: { $ref: "#/components/schemas/Ticket" } }
                  meta: { $ref: "#/components/schemas/PageMeta" }
    post:
      tags: [tickets]
      summary: Abre um ticket
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [subject, body, contact_email]
              properties:
                subject: { type: string }
                body: { type: string, description: Texto ou Markdown }
                contact_email: { type: string, format: email }
                contact_name: { type: string }
                priority: { $ref: "#/components/schemas/Priority" }
                type: { type: string, enum: [question, incident, problem, task, feature_request] }
                channel: { type: string, default: api }
                tags: { type: array, items: { type: string } }
                custom: { type: object }
      responses:
        "201":
          description: Ticket criado
          content:
            application/json:
              schema: { type: object, properties: { data: { $ref: "#/components/schemas/Ticket" } } }
        "409": { $ref: "#/components/responses/Error" }
        "422": { $ref: "#/components/responses/Error" }
  /tickets/{id}:
    parameters:
      - { name: id, in: path, required: true, schema: { type: integer } }
    get:
      tags: [tickets]
      summary: Detalhe do ticket com mensagens públicas
      responses:
        "200":
          description: Ticket
          content:
            application/json:
              schema: { type: object, properties: { data: { $ref: "#/components/schemas/Ticket" } } }
        "404": { $ref: "#/components/responses/Error" }
    patch:
      tags: [tickets]
      summary: Atualiza status, prioridade, tipo, categoria, tags ou responsável
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                status: { $ref: "#/components/schemas/TicketStatus" }
                priority: { $ref: "#/components/schemas/Priority" }
                type: { type: string }
                category: { type: string }
                tags: { type: array, items: { type: string } }
                assignee_email: { type: [string, "null"], format: email }
      responses:
        "200":
          description: Atualizado
          content:
            application/json:
              schema: { type: object, properties: { data: { $ref: "#/components/schemas/Ticket" } } }
        "422": { $ref: "#/components/responses/Error" }
  /tickets/{id}/messages:
    post:
      tags: [tickets]
      summary: Adiciona resposta ao ticket
      parameters:
        - { name: id, in: path, required: true, schema: { type: integer } }
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [body]
              properties:
                body: { type: string }
                author_type: { type: string, enum: [contact, agent], default: contact }
                user_email: { type: string, format: email, description: Obrigatório quando author_type=agent }
      responses:
        "201": { description: Mensagem registrada }
        "422": { $ref: "#/components/responses/Error" }
webhooks:
  evento:
    post:
      summary: Entrega de webhook da Encantra para o seu sistema
      parameters:
        - { name: X-Encantra-Event, in: header, schema: { type: string } }
        - { name: X-Encantra-Signature, in: header, description: "t=<unix>,v1=<hex(hmac_sha256(segredo, t + '.' + corpo))>", schema: { type: string } }
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                id: { type: string }
                event: { type: string }
                created_at: { type: string, format: date-time }
                data: { type: object }
      responses:
        "200": { description: Recebido (qualquer 2xx) }
components:
  securitySchemes:
    apiKey:
      type: http
      scheme: bearer
      description: "Chave de API do workspace: enc_live_<prefixo>_<segredo>"
  parameters:
    page: { name: page, in: query, schema: { type: integer, minimum: 1, default: 1 } }
    perPage: { name: per_page, in: query, schema: { type: integer, minimum: 1, maximum: 100, default: 25 } }
  responses:
    Error:
      description: Erro
      content:
        application/json:
          schema:
            type: object
            properties:
              error:
                type: object
                properties:
                  status: { type: integer }
                  message: { type: string }
                  fields: { type: object }
    AccountSaved:
      description: Conta criada (201) ou atualizada (200)
      content:
        application/json:
          schema: { type: object, properties: { data: { $ref: "#/components/schemas/Account" }, meta: { type: object, properties: { created: { type: boolean } } } } }
    ContactSaved:
      description: Contato criado (201) ou atualizado (200)
      content:
        application/json:
          schema: { type: object, properties: { data: { $ref: "#/components/schemas/Contact" }, meta: { type: object, properties: { created: { type: boolean } } } } }
  schemas:
    PageMeta:
      type: object
      properties: { page: { type: integer }, per_page: { type: integer }, total: { type: integer }, pages: { type: integer } }
    LifecycleStage: { type: string, enum: [lead, onboarding, adoption, expansion, renewal, advocacy, at_risk, churned] }
    TicketStatus: { type: string, enum: [new, open, pending, on_hold, solved, closed] }
    Priority: { type: string, enum: [low, normal, high, urgent] }
    Account:
      type: object
      properties:
        id: { type: integer }
        external_id: { type: [string, "null"] }
        name: { type: string }
        domain: { type: [string, "null"] }
        industry: { type: [string, "null"] }
        size: { type: [string, "null"] }
        plan_name: { type: [string, "null"] }
        mrr_cents: { type: integer }
        lifecycle_stage: { $ref: "#/components/schemas/LifecycleStage" }
        health_score: { type: [integer, "null"] }
        health_status: { type: [string, "null"], enum: [healthy, neutral, at_risk, critical, null] }
        nps_last: { type: [integer, "null"] }
        segment: { type: [string, "null"] }
        tier: { type: string, enum: [low_touch, mid_touch, high_touch] }
        customer_since: { type: [string, "null"], format: date }
        renewal_date: { type: [string, "null"], format: date }
        tags: { type: array, items: { type: string } }
        custom: { type: object }
        created_at: { type: string }
        updated_at: { type: string }
    AccountInput:
      type: object
      properties:
        external_id: { type: string, maxLength: 120 }
        name: { type: string }
        domain: { type: string }
        industry: { type: string }
        size: { type: string }
        segment: { type: string }
        plan: { type: string }
        mrr_cents: { type: integer, minimum: 0 }
        customer_since: { type: string, format: date }
        renewal_date: { type: string, format: date }
        lifecycle_stage: { $ref: "#/components/schemas/LifecycleStage" }
        status: { type: string, enum: [active, trialing, past_due, paused, canceled, churned] }
        tags: { type: array, items: { type: string } }
        custom: { type: object }
        contacts: { type: array, items: { $ref: "#/components/schemas/ContactInput" } }
    Contact:
      type: object
      properties:
        id: { type: integer }
        account_id: { type: [integer, "null"] }
        external_id: { type: [string, "null"] }
        name: { type: string }
        email: { type: [string, "null"] }
        phone: { type: [string, "null"] }
        title: { type: [string, "null"] }
        role_in_account: { type: string, enum: [champion, decision_maker, user, billing, other] }
        language: { type: string }
        tags: { type: array, items: { type: string } }
        custom: { type: object }
        last_seen_at: { type: [string, "null"] }
    ContactInput:
      type: object
      properties:
        external_id: { type: string }
        email: { type: string, format: email }
        name: { type: string }
        phone: { type: string }
        title: { type: string }
        role: { type: string, enum: [champion, decision_maker, user, billing, other] }
        account_id: { type: integer }
        account_external_id: { type: string }
        custom: { type: object }
    UsageEvent:
      type: object
      required: [event]
      properties:
        id: { type: string, description: Usado para deduplicação }
        customer_external_id: { type: string }
        account_id: { type: integer }
        user_external_id: { type: string }
        contact_email: { type: string, format: email }
        contact_id: { type: integer }
        event: { type: string, maxLength: 120 }
        quantity: { type: number, default: 1 }
        properties: { type: object }
        occurred_at: { type: string, format: date-time }
    Ticket:
      type: object
      properties:
        id: { type: integer }
        number: { type: integer }
        subject: { type: string }
        status: { $ref: "#/components/schemas/TicketStatus" }
        priority: { $ref: "#/components/schemas/Priority" }
        type: { type: [string, "null"] }
        channel: { type: string }
        category: { type: [string, "null"] }
        tags: { type: array, items: { type: string } }
        sentiment: { type: [string, "null"] }
        language: { type: [string, "null"] }
        summary: { type: [string, "null"], description: Resumo gerado pela IA }
        contact: { type: object, properties: { email: { type: string }, name: { type: string } } }
        account_external_id: { type: [string, "null"] }
        assignee_email: { type: [string, "null"] }
        messages:
          type: array
          items:
            type: object
            properties:
              id: { type: integer }
              author_type: { type: string }
              visibility: { type: string }
              body: { type: string }
              created_at: { type: string }

Encontrou algo para melhorar? Escreva para master@inspire4u.com.br.