{
  "components": {
    "schemas": {
      "AgentOut": {
        "properties": {
          "active": {
            "title": "Active",
            "type": "boolean"
          },
          "avatar_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Avatar Url"
          },
          "created_at": {
            "anyOf": [
              {
                "format": "date-time",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Created At"
          },
          "id": {
            "format": "uuid",
            "title": "Id",
            "type": "string"
          },
          "name": {
            "title": "Name",
            "type": "string"
          },
          "persona": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Persona"
          },
          "product": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ProductRef"
              },
              {
                "type": "null"
              }
            ],
            "description": "Primeiro produto que o agente atende (ordem do catálogo). `null` quando não atende nenhum produto (ex.: só o padrão da empresa, sem produto usando)."
          },
          "scope": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "O que o agente atende e o que não atende.",
            "title": "Scope"
          },
          "updated_at": {
            "anyOf": [
              {
                "format": "date-time",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Updated At"
          }
        },
        "required": [
          "id",
          "name",
          "product",
          "active",
          "persona",
          "scope",
          "avatar_url",
          "created_at",
          "updated_at"
        ],
        "title": "AgentOut",
        "type": "object"
      },
      "AgentPreviewIn": {
        "properties": {
          "history": {
            "items": {
              "$ref": "#/components/schemas/AgentPreviewTurn"
            },
            "maxItems": 20,
            "title": "History",
            "type": "array"
          },
          "message": {
            "maxLength": 4000,
            "minLength": 1,
            "title": "Message",
            "type": "string"
          }
        },
        "required": [
          "message"
        ],
        "title": "AgentPreviewIn",
        "type": "object"
      },
      "AgentPreviewOut": {
        "additionalProperties": true,
        "properties": {
          "action": {
            "description": "`answer`, `handoff` (transferiria a um humano) ou `refuse`.",
            "title": "Action",
            "type": "string"
          },
          "answer_html": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Answer Html"
          },
          "citations": {
            "description": "Fontes citadas na resposta.",
            "items": {},
            "title": "Citations",
            "type": "array"
          },
          "collected": {
            "description": "Dados já coletados do cliente.",
            "title": "Collected",
            "type": "object"
          },
          "confidence": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Confidence"
          },
          "escalated": {
            "default": false,
            "title": "Escalated",
            "type": "boolean"
          },
          "guards": {
            "description": "Salvaguardas acionadas.",
            "items": {
              "type": "string"
            },
            "title": "Guards",
            "type": "array"
          },
          "handoff_reason": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Handoff Reason"
          },
          "missing": {
            "description": "Dados que o agente ainda pediria.",
            "items": {},
            "title": "Missing",
            "type": "array"
          },
          "refused": {
            "default": false,
            "title": "Refused",
            "type": "boolean"
          },
          "sources": {
            "items": {
              "type": "object"
            },
            "title": "Sources",
            "type": "array"
          },
          "topic": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Assunto identificado na mensagem.",
            "title": "Topic"
          }
        },
        "required": [
          "action",
          "answer_html",
          "escalated",
          "refused",
          "handoff_reason",
          "confidence",
          "topic",
          "guards",
          "citations",
          "sources",
          "collected",
          "missing"
        ],
        "title": "AgentPreviewOut",
        "type": "object"
      },
      "AgentPreviewTurn": {
        "properties": {
          "content": {
            "maxLength": 4000,
            "title": "Content",
            "type": "string"
          },
          "role": {
            "enum": [
              "customer",
              "bot"
            ],
            "title": "Role",
            "type": "string"
          }
        },
        "required": [
          "role",
          "content"
        ],
        "title": "AgentPreviewTurn",
        "type": "object"
      },
      "BatchItemResult": {
        "properties": {
          "code": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "Status HTTP que o item teria sozinho (só em erro).",
            "title": "Code"
          },
          "error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Código estável do erro do item (`status = error`).",
            "title": "Error"
          },
          "external_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Identificador do item DEPOIS do upsert — o principal do cadastro. Pode voltar DIFERENTE do que você enviou: quando o e-mail ou o telefone enviado já pertence a outra pessoa da empresa, o cadastro é unificado e aqui volta o identificador que ficou.",
            "title": "External Id"
          },
          "index": {
            "description": "Posição do item no lote (0 = primeiro). **Case o resultado com o que você enviou por `index`, nunca por `external_id`** — na unificação o `external_id` volta diferente, e casar por ele credita o item errado.",
            "title": "Index",
            "type": "integer"
          },
          "linked": {
            "default": false,
            "description": "`true` = o item LIGOU a pessoa a mais um cliente (ela já existia em outro). Diferente de `merged_into`, que é absorção por contato.",
            "title": "Linked",
            "type": "boolean"
          },
          "merged_into": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Preenchido quando houve unificação: o identificador que você enviou virou extra e este é o principal do cadastro único. Nulo quando não houve.",
            "title": "Merged Into"
          },
          "status": {
            "enum": [
              "created",
              "updated",
              "unchanged",
              "error"
            ],
            "title": "Status",
            "type": "string"
          }
        },
        "required": [
          "index",
          "status",
          "external_id",
          "merged_into",
          "linked",
          "error",
          "code"
        ],
        "title": "BatchItemResult",
        "type": "object"
      },
      "BatchOut": {
        "properties": {
          "results": {
            "description": "Um resultado por item, na ordem enviada.",
            "items": {
              "$ref": "#/components/schemas/BatchItemResult"
            },
            "title": "Results",
            "type": "array"
          },
          "summary": {
            "$ref": "#/components/schemas/BatchSummary"
          }
        },
        "required": [
          "results",
          "summary"
        ],
        "title": "BatchOut",
        "type": "object"
      },
      "BatchSummary": {
        "properties": {
          "created": {
            "title": "Created",
            "type": "integer"
          },
          "error": {
            "title": "Error",
            "type": "integer"
          },
          "unchanged": {
            "title": "Unchanged",
            "type": "integer"
          },
          "updated": {
            "title": "Updated",
            "type": "integer"
          }
        },
        "required": [
          "created",
          "updated",
          "unchanged",
          "error"
        ],
        "title": "BatchSummary",
        "type": "object"
      },
      "ContactOut": {
        "properties": {
          "created_at": {
            "anyOf": [
              {
                "format": "date-time",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Created At"
          },
          "email": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Email"
          },
          "external_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "External Id"
          },
          "id": {
            "format": "uuid",
            "title": "Id",
            "type": "string"
          },
          "is_primary": {
            "title": "Is Primary",
            "type": "boolean"
          },
          "name": {
            "title": "Name",
            "type": "string"
          },
          "notes": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Notes"
          },
          "phone": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Phone"
          },
          "role": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Role"
          },
          "updated_at": {
            "anyOf": [
              {
                "format": "date-time",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Updated At"
          }
        },
        "required": [
          "id",
          "external_id",
          "name",
          "role",
          "email",
          "phone",
          "notes",
          "is_primary",
          "created_at",
          "updated_at"
        ],
        "title": "ContactOut",
        "type": "object"
      },
      "ContactUpsert": {
        "properties": {
          "email": {
            "anyOf": [
              {
                "format": "email",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Email"
          },
          "is_primary": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Is Primary"
          },
          "name": {
            "anyOf": [
              {
                "maxLength": 255,
                "minLength": 1,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Obrigatório ao criar.",
            "title": "Name"
          },
          "notes": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Notes"
          },
          "phone": {
            "anyOf": [
              {
                "maxLength": 50,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Phone"
          },
          "role": {
            "anyOf": [
              {
                "maxLength": 120,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Role"
          }
        },
        "title": "ContactUpsert",
        "type": "object"
      },
      "CustomFieldOut": {
        "additionalProperties": true,
        "properties": {
          "key": {
            "title": "Key",
            "type": "string"
          },
          "label": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Label"
          },
          "type": {
            "default": "text",
            "title": "Type",
            "type": "string"
          },
          "value": {
            "title": "Value"
          },
          "visibility": {
            "default": "interno",
            "description": "Quem vê o campo no bFocus (definido no painel).",
            "title": "Visibility",
            "type": "string"
          }
        },
        "required": [
          "key"
        ],
        "title": "CustomFieldOut",
        "type": "object"
      },
      "CustomerBatchIn": {
        "examples": [
          {
            "items": [
              {
                "document": "12.345.678/0001-90",
                "external_id": "erp-1042",
                "name": "Padaria Estrela"
              },
              {
                "email": "contato@mercadosol.example",
                "external_id": "erp-1043",
                "name": "Mercado Sol"
              }
            ]
          }
        ],
        "properties": {
          "items": {
            "description": "Até 500 clientes, no mesmo formato do upsert (com `external_id` em cada item).",
            "items": {
              "$ref": "#/components/schemas/IntegrationCustomerPayload"
            },
            "maxItems": 500,
            "title": "Items",
            "type": "array"
          }
        },
        "required": [
          "items"
        ],
        "title": "CustomerBatchIn",
        "type": "object"
      },
      "CustomerIdentifiersOut": {
        "properties": {
          "created_at": {
            "anyOf": [
              {
                "format": "date-time",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Created At"
          },
          "custom_fields": {
            "items": {
              "$ref": "#/components/schemas/CustomFieldOut"
            },
            "title": "Custom Fields",
            "type": "array"
          },
          "document": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "CNPJ (PJ) ou CPF (PF), sem máscara.",
            "title": "Document"
          },
          "email": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Email"
          },
          "external_id": {
            "title": "External Id",
            "type": "string"
          },
          "extra_emails": {
            "description": "E-mails adicionais do cliente (o principal é `email`).",
            "items": {
              "type": "string"
            },
            "title": "Extra Emails",
            "type": "array"
          },
          "extra_phones": {
            "description": "Telefones adicionais do cliente (o principal é `phone`).",
            "items": {
              "type": "string"
            },
            "title": "Extra Phones",
            "type": "array"
          },
          "id": {
            "format": "uuid",
            "title": "Id",
            "type": "string"
          },
          "id_document": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Só PF: RG e órgão emissor (texto livre — varia por estado).",
            "title": "Id Document"
          },
          "identifiers": {
            "description": "Identificadores extras (o principal é `external_id`).",
            "items": {
              "$ref": "#/components/schemas/IdentifierOut"
            },
            "title": "Identifiers",
            "type": "array"
          },
          "is_active": {
            "title": "Is Active",
            "type": "boolean"
          },
          "kind": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Tipo do CONTRATANTE: `pj` (empresa) ou `pf` (pessoa física). `null` = ninguém declarou, e aí vale o que o documento indica. Cliente é a conta, não a pessoa: uma conta PF pode ter várias pessoas dentro (o titular e o cônjuge, por exemplo).",
            "title": "Kind"
          },
          "legal_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Só PJ: razão social, quando difere do nome fantasia.",
            "title": "Legal Name"
          },
          "logo_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Logotipo do cliente, como a equipe subiu no bFocus. Serve para o seu sistema mostrar a mesma marca que o atendimento mostra. `null` = sem logotipo.",
            "title": "Logo Url"
          },
          "municipal_registration": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Só PJ: inscrição municipal.",
            "title": "Municipal Registration"
          },
          "name": {
            "description": "O nome usado em tudo (listas, chamados, e-mail). Na PJ, o nome fantasia.",
            "title": "Name",
            "type": "string"
          },
          "notes": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Notes"
          },
          "phone": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Phone"
          },
          "state_registration": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Só PJ: inscrição estadual (aceita `ISENTO`).",
            "title": "State Registration"
          },
          "updated_at": {
            "anyOf": [
              {
                "format": "date-time",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Updated At"
          },
          "website": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Website"
          }
        },
        "required": [
          "id",
          "external_id",
          "name",
          "kind",
          "legal_name",
          "state_registration",
          "municipal_registration",
          "id_document",
          "document",
          "email",
          "phone",
          "website",
          "notes",
          "custom_fields",
          "is_active",
          "logo_url",
          "extra_emails",
          "extra_phones",
          "created_at",
          "updated_at",
          "identifiers"
        ],
        "title": "CustomerIdentifiersOut",
        "type": "object"
      },
      "CustomerInteractionCreate": {
        "properties": {
          "author_email": {
            "anyOf": [
              {
                "maxLength": 255,
                "pattern": "^[^@\\s]+@[^@\\s]+$",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "E-mail de um usuário do bFocus que assina o registro. Omitido = 'sistema'.",
            "title": "Author Email"
          },
          "content": {
            "description": "HTML ou texto puro (vira parágrafos).",
            "maxLength": 50000,
            "minLength": 1,
            "title": "Content",
            "type": "string"
          },
          "is_internal": {
            "default": true,
            "description": "Nota interna (padrão) ou registro visível ao cliente.",
            "title": "Is Internal",
            "type": "boolean"
          }
        },
        "required": [
          "content"
        ],
        "title": "CustomerInteractionCreate",
        "type": "object"
      },
      "CustomerOut": {
        "properties": {
          "created_at": {
            "anyOf": [
              {
                "format": "date-time",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Created At"
          },
          "custom_fields": {
            "items": {
              "$ref": "#/components/schemas/CustomFieldOut"
            },
            "title": "Custom Fields",
            "type": "array"
          },
          "document": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "CNPJ (PJ) ou CPF (PF), sem máscara.",
            "title": "Document"
          },
          "email": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Email"
          },
          "external_id": {
            "title": "External Id",
            "type": "string"
          },
          "extra_emails": {
            "description": "E-mails adicionais do cliente (o principal é `email`).",
            "items": {
              "type": "string"
            },
            "title": "Extra Emails",
            "type": "array"
          },
          "extra_phones": {
            "description": "Telefones adicionais do cliente (o principal é `phone`).",
            "items": {
              "type": "string"
            },
            "title": "Extra Phones",
            "type": "array"
          },
          "id": {
            "format": "uuid",
            "title": "Id",
            "type": "string"
          },
          "id_document": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Só PF: RG e órgão emissor (texto livre — varia por estado).",
            "title": "Id Document"
          },
          "is_active": {
            "title": "Is Active",
            "type": "boolean"
          },
          "kind": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Tipo do CONTRATANTE: `pj` (empresa) ou `pf` (pessoa física). `null` = ninguém declarou, e aí vale o que o documento indica. Cliente é a conta, não a pessoa: uma conta PF pode ter várias pessoas dentro (o titular e o cônjuge, por exemplo).",
            "title": "Kind"
          },
          "legal_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Só PJ: razão social, quando difere do nome fantasia.",
            "title": "Legal Name"
          },
          "logo_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Logotipo do cliente, como a equipe subiu no bFocus. Serve para o seu sistema mostrar a mesma marca que o atendimento mostra. `null` = sem logotipo.",
            "title": "Logo Url"
          },
          "municipal_registration": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Só PJ: inscrição municipal.",
            "title": "Municipal Registration"
          },
          "name": {
            "description": "O nome usado em tudo (listas, chamados, e-mail). Na PJ, o nome fantasia.",
            "title": "Name",
            "type": "string"
          },
          "notes": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Notes"
          },
          "phone": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Phone"
          },
          "state_registration": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Só PJ: inscrição estadual (aceita `ISENTO`).",
            "title": "State Registration"
          },
          "updated_at": {
            "anyOf": [
              {
                "format": "date-time",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Updated At"
          },
          "website": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Website"
          }
        },
        "required": [
          "id",
          "external_id",
          "name",
          "kind",
          "legal_name",
          "state_registration",
          "municipal_registration",
          "id_document",
          "document",
          "email",
          "phone",
          "website",
          "notes",
          "custom_fields",
          "is_active",
          "logo_url",
          "extra_emails",
          "extra_phones",
          "created_at",
          "updated_at"
        ],
        "title": "CustomerOut",
        "type": "object"
      },
      "Deleted": {
        "properties": {
          "deleted": {
            "default": true,
            "title": "Deleted",
            "type": "boolean"
          }
        },
        "required": [
          "deleted"
        ],
        "title": "Deleted",
        "type": "object"
      },
      "Envelope_AgentOut_": {
        "properties": {
          "code": {
            "description": "Status HTTP, repetido no corpo.",
            "title": "Code",
            "type": "integer"
          },
          "data": {
            "$ref": "#/components/schemas/AgentOut"
          },
          "message": {
            "title": "Message",
            "type": "string"
          }
        },
        "required": [
          "code",
          "data",
          "message"
        ],
        "title": "Envelope[AgentOut]",
        "type": "object"
      },
      "Envelope_AgentPreviewOut_": {
        "properties": {
          "code": {
            "description": "Status HTTP, repetido no corpo.",
            "title": "Code",
            "type": "integer"
          },
          "data": {
            "$ref": "#/components/schemas/AgentPreviewOut"
          },
          "message": {
            "title": "Message",
            "type": "string"
          }
        },
        "required": [
          "code",
          "data",
          "message"
        ],
        "title": "Envelope[AgentPreviewOut]",
        "type": "object"
      },
      "Envelope_BatchOut_": {
        "properties": {
          "code": {
            "description": "Status HTTP, repetido no corpo.",
            "title": "Code",
            "type": "integer"
          },
          "data": {
            "$ref": "#/components/schemas/BatchOut"
          },
          "message": {
            "title": "Message",
            "type": "string"
          }
        },
        "required": [
          "code",
          "data",
          "message"
        ],
        "title": "Envelope[BatchOut]",
        "type": "object"
      },
      "Envelope_ContactOut_": {
        "properties": {
          "code": {
            "description": "Status HTTP, repetido no corpo.",
            "title": "Code",
            "type": "integer"
          },
          "data": {
            "$ref": "#/components/schemas/ContactOut"
          },
          "message": {
            "title": "Message",
            "type": "string"
          }
        },
        "required": [
          "code",
          "data",
          "message"
        ],
        "title": "Envelope[ContactOut]",
        "type": "object"
      },
      "Envelope_CustomerIdentifiersOut_": {
        "properties": {
          "code": {
            "description": "Status HTTP, repetido no corpo.",
            "title": "Code",
            "type": "integer"
          },
          "data": {
            "$ref": "#/components/schemas/CustomerIdentifiersOut"
          },
          "message": {
            "title": "Message",
            "type": "string"
          }
        },
        "required": [
          "code",
          "data",
          "message"
        ],
        "title": "Envelope[CustomerIdentifiersOut]",
        "type": "object"
      },
      "Envelope_CustomerOut_": {
        "properties": {
          "code": {
            "description": "Status HTTP, repetido no corpo.",
            "title": "Code",
            "type": "integer"
          },
          "data": {
            "$ref": "#/components/schemas/CustomerOut"
          },
          "message": {
            "title": "Message",
            "type": "string"
          }
        },
        "required": [
          "code",
          "data",
          "message"
        ],
        "title": "Envelope[CustomerOut]",
        "type": "object"
      },
      "Envelope_Deleted_": {
        "properties": {
          "code": {
            "description": "Status HTTP, repetido no corpo.",
            "title": "Code",
            "type": "integer"
          },
          "data": {
            "$ref": "#/components/schemas/Deleted"
          },
          "message": {
            "title": "Message",
            "type": "string"
          }
        },
        "required": [
          "code",
          "data",
          "message"
        ],
        "title": "Envelope[Deleted]",
        "type": "object"
      },
      "Envelope_InteractionOut_": {
        "properties": {
          "code": {
            "description": "Status HTTP, repetido no corpo.",
            "title": "Code",
            "type": "integer"
          },
          "data": {
            "$ref": "#/components/schemas/InteractionOut"
          },
          "message": {
            "title": "Message",
            "type": "string"
          }
        },
        "required": [
          "code",
          "data",
          "message"
        ],
        "title": "Envelope[InteractionOut]",
        "type": "object"
      },
      "Envelope_KBArticleOut_": {
        "properties": {
          "code": {
            "description": "Status HTTP, repetido no corpo.",
            "title": "Code",
            "type": "integer"
          },
          "data": {
            "$ref": "#/components/schemas/KBArticleOut"
          },
          "message": {
            "title": "Message",
            "type": "string"
          }
        },
        "required": [
          "code",
          "data",
          "message"
        ],
        "title": "Envelope[KBArticleOut]",
        "type": "object"
      },
      "Envelope_KBBatchOut_": {
        "properties": {
          "code": {
            "description": "Status HTTP, repetido no corpo.",
            "title": "Code",
            "type": "integer"
          },
          "data": {
            "$ref": "#/components/schemas/KBBatchOut"
          },
          "message": {
            "title": "Message",
            "type": "string"
          }
        },
        "required": [
          "code",
          "data",
          "message"
        ],
        "title": "Envelope[KBBatchOut]",
        "type": "object"
      },
      "Envelope_PersonIdentifiersOut_": {
        "properties": {
          "code": {
            "description": "Status HTTP, repetido no corpo.",
            "title": "Code",
            "type": "integer"
          },
          "data": {
            "$ref": "#/components/schemas/PersonIdentifiersOut"
          },
          "message": {
            "title": "Message",
            "type": "string"
          }
        },
        "required": [
          "code",
          "data",
          "message"
        ],
        "title": "Envelope[PersonIdentifiersOut]",
        "type": "object"
      },
      "Envelope_PersonRevokeOut_": {
        "properties": {
          "code": {
            "description": "Status HTTP, repetido no corpo.",
            "title": "Code",
            "type": "integer"
          },
          "data": {
            "$ref": "#/components/schemas/PersonRevokeOut"
          },
          "message": {
            "title": "Message",
            "type": "string"
          }
        },
        "required": [
          "code",
          "data",
          "message"
        ],
        "title": "Envelope[PersonRevokeOut]",
        "type": "object"
      },
      "Envelope_PersonUpsertOut_": {
        "properties": {
          "code": {
            "description": "Status HTTP, repetido no corpo.",
            "title": "Code",
            "type": "integer"
          },
          "data": {
            "$ref": "#/components/schemas/PersonUpsertOut"
          },
          "message": {
            "title": "Message",
            "type": "string"
          }
        },
        "required": [
          "code",
          "data",
          "message"
        ],
        "title": "Envelope[PersonUpsertOut]",
        "type": "object"
      },
      "Envelope_ProductOut_": {
        "properties": {
          "code": {
            "description": "Status HTTP, repetido no corpo.",
            "title": "Code",
            "type": "integer"
          },
          "data": {
            "$ref": "#/components/schemas/ProductOut"
          },
          "message": {
            "title": "Message",
            "type": "string"
          }
        },
        "required": [
          "code",
          "data",
          "message"
        ],
        "title": "Envelope[ProductOut]",
        "type": "object"
      },
      "Envelope_ProductRef_": {
        "properties": {
          "code": {
            "description": "Status HTTP, repetido no corpo.",
            "title": "Code",
            "type": "integer"
          },
          "data": {
            "$ref": "#/components/schemas/ProductRef"
          },
          "message": {
            "title": "Message",
            "type": "string"
          }
        },
        "required": [
          "code",
          "data",
          "message"
        ],
        "title": "Envelope[ProductRef]",
        "type": "object"
      },
      "Envelope_ProductRoleOut_": {
        "properties": {
          "code": {
            "description": "Status HTTP, repetido no corpo.",
            "title": "Code",
            "type": "integer"
          },
          "data": {
            "$ref": "#/components/schemas/ProductRoleOut"
          },
          "message": {
            "title": "Message",
            "type": "string"
          }
        },
        "required": [
          "code",
          "data",
          "message"
        ],
        "title": "Envelope[ProductRoleOut]",
        "type": "object"
      },
      "Envelope_ReleaseNoteOut_": {
        "properties": {
          "code": {
            "description": "Status HTTP, repetido no corpo.",
            "title": "Code",
            "type": "integer"
          },
          "data": {
            "$ref": "#/components/schemas/ReleaseNoteOut"
          },
          "message": {
            "title": "Message",
            "type": "string"
          }
        },
        "required": [
          "code",
          "data",
          "message"
        ],
        "title": "Envelope[ReleaseNoteOut]",
        "type": "object"
      },
      "Envelope_list_AgentOut__": {
        "properties": {
          "code": {
            "description": "Status HTTP, repetido no corpo.",
            "title": "Code",
            "type": "integer"
          },
          "data": {
            "items": {
              "$ref": "#/components/schemas/AgentOut"
            },
            "title": "Data",
            "type": "array"
          },
          "message": {
            "title": "Message",
            "type": "string"
          }
        },
        "required": [
          "code",
          "data",
          "message"
        ],
        "title": "Envelope[list[AgentOut]]",
        "type": "object"
      },
      "Envelope_list_ContactOut__": {
        "properties": {
          "code": {
            "description": "Status HTTP, repetido no corpo.",
            "title": "Code",
            "type": "integer"
          },
          "data": {
            "items": {
              "$ref": "#/components/schemas/ContactOut"
            },
            "title": "Data",
            "type": "array"
          },
          "message": {
            "title": "Message",
            "type": "string"
          }
        },
        "required": [
          "code",
          "data",
          "message"
        ],
        "title": "Envelope[list[ContactOut]]",
        "type": "object"
      },
      "Envelope_list_KBSearchHit__": {
        "properties": {
          "code": {
            "description": "Status HTTP, repetido no corpo.",
            "title": "Code",
            "type": "integer"
          },
          "data": {
            "items": {
              "$ref": "#/components/schemas/KBSearchHit"
            },
            "title": "Data",
            "type": "array"
          },
          "message": {
            "title": "Message",
            "type": "string"
          }
        },
        "required": [
          "code",
          "data",
          "message"
        ],
        "title": "Envelope[list[KBSearchHit]]",
        "type": "object"
      },
      "Envelope_list_PersonOut__": {
        "properties": {
          "code": {
            "description": "Status HTTP, repetido no corpo.",
            "title": "Code",
            "type": "integer"
          },
          "data": {
            "items": {
              "$ref": "#/components/schemas/PersonOut"
            },
            "title": "Data",
            "type": "array"
          },
          "message": {
            "title": "Message",
            "type": "string"
          }
        },
        "required": [
          "code",
          "data",
          "message"
        ],
        "title": "Envelope[list[PersonOut]]",
        "type": "object"
      },
      "Envelope_list_ProductOut__": {
        "properties": {
          "code": {
            "description": "Status HTTP, repetido no corpo.",
            "title": "Code",
            "type": "integer"
          },
          "data": {
            "items": {
              "$ref": "#/components/schemas/ProductOut"
            },
            "title": "Data",
            "type": "array"
          },
          "message": {
            "title": "Message",
            "type": "string"
          }
        },
        "required": [
          "code",
          "data",
          "message"
        ],
        "title": "Envelope[list[ProductOut]]",
        "type": "object"
      },
      "Envelope_list_ProductRef__": {
        "properties": {
          "code": {
            "description": "Status HTTP, repetido no corpo.",
            "title": "Code",
            "type": "integer"
          },
          "data": {
            "items": {
              "$ref": "#/components/schemas/ProductRef"
            },
            "title": "Data",
            "type": "array"
          },
          "message": {
            "title": "Message",
            "type": "string"
          }
        },
        "required": [
          "code",
          "data",
          "message"
        ],
        "title": "Envelope[list[ProductRef]]",
        "type": "object"
      },
      "Envelope_list_ProductRoleOut__": {
        "properties": {
          "code": {
            "description": "Status HTTP, repetido no corpo.",
            "title": "Code",
            "type": "integer"
          },
          "data": {
            "items": {
              "$ref": "#/components/schemas/ProductRoleOut"
            },
            "title": "Data",
            "type": "array"
          },
          "message": {
            "title": "Message",
            "type": "string"
          }
        },
        "required": [
          "code",
          "data",
          "message"
        ],
        "title": "Envelope[list[ProductRoleOut]]",
        "type": "object"
      },
      "ErrorBody": {
        "properties": {
          "code": {
            "description": "Status HTTP, repetido no corpo.",
            "title": "Code",
            "type": "integer"
          },
          "data": {
            "anyOf": [
              {
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "Quase sempre `null`. Detalhe de alguns erros (ex.: `owner` em `IDENTIFIER_IN_USE`).",
            "title": "Data"
          },
          "error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Código estável do erro. Use SEMPRE este campo na sua lógica.",
            "title": "Error"
          },
          "message": {
            "description": "Igual a `error` (compatibilidade com integrações antigas).",
            "title": "Message",
            "type": "string"
          },
          "request_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Id da requisição (também no header `X-Request-Id`).",
            "title": "Request Id"
          },
          "validation": {
            "additionalProperties": {
              "type": "string"
            },
            "description": "Campo → motivo, em erros 422.",
            "title": "Validation",
            "type": "object"
          }
        },
        "required": [
          "code",
          "data",
          "message",
          "error",
          "validation",
          "request_id"
        ],
        "title": "ErrorBody",
        "type": "object"
      },
      "IdentifierLabelIn": {
        "properties": {
          "label": {
            "anyOf": [
              {
                "maxLength": 120,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Rótulo livre (ex.: nome do sistema).",
            "title": "Label"
          }
        },
        "title": "IdentifierLabelIn",
        "type": "object"
      },
      "IdentifierOut": {
        "properties": {
          "external_id": {
            "title": "External Id",
            "type": "string"
          },
          "label": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Label"
          },
          "source": {
            "description": "Quem ligou: `api`, `panel`, `import`…",
            "title": "Source",
            "type": "string"
          }
        },
        "required": [
          "external_id",
          "label",
          "source"
        ],
        "title": "IdentifierOut",
        "type": "object"
      },
      "IntegrationCustomerPayload": {
        "description": "Corpo do upsert de cliente. Três formatos, que podem conviver:\n\n**Recomendado para ERPs** — só muda o que foi enviado:\n    {\"customer\": {campos fixos...}, \"fields\": {\"chave\": valor | {label,type,value} | null}}\n  - `customer`: external_id, name, document, email, phone, website, logo, is_active, notes,\n    extra_emails, extra_phones. Chave ausente não muda; `null` limpa (exceto `name`).\n  - `fields` (objeto): campos livres. Chave existente é atualizada, nova é criada, `null`\n    remove; as que não vieram ficam como estão.\n\n**Campos planos** — o que as SDKs mandam: `name`, `email`, …, `custom_fields`. Só o que vier\nno corpo muda (`null` explícito limpa); `custom_fields` só é substituído quando vier.\n\n**Legado** — `{\"fields\": [{key,label,type,value}, ...]}`: as chaves reservadas vão para as\ncolunas e a lista de campos livres SUBSTITUI a anterior (o que não veio é removido).\nMantido para as integrações que já usam.\n\nCampo plano vence o mesmo campo dentro de `customer`/`fields`.",
        "properties": {
          "custom_fields": {
            "anyOf": [
              {
                "items": {
                  "$ref": "#/components/schemas/IntegrationField"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "Substitui a lista de campos customizados. Omitido = mantém.",
            "title": "Custom Fields"
          },
          "customer": {
            "anyOf": [
              {
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "Campos fixos do cliente (formato recomendado para ERPs). Ausente = não muda.",
            "title": "Customer"
          },
          "document": {
            "anyOf": [
              {
                "maxLength": 50,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Document"
          },
          "email": {
            "anyOf": [
              {
                "maxLength": 255,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Email"
          },
          "external_id": {
            "anyOf": [
              {
                "maxLength": 255,
                "minLength": 1,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "External Id"
          },
          "fields": {
            "anyOf": [
              {
                "items": {
                  "$ref": "#/components/schemas/IntegrationField"
                },
                "type": "array"
              },
              {
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "Objeto `{chave: valor | null}` (muda só as chaves enviadas) ou, no formato legado, lista `[{key,label,type,value}]` que substitui os campos customizados.",
            "title": "Fields"
          },
          "name": {
            "anyOf": [
              {
                "maxLength": 500,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          },
          "notes": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Notes"
          },
          "phone": {
            "anyOf": [
              {
                "maxLength": 50,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Phone"
          },
          "website": {
            "anyOf": [
              {
                "maxLength": 500,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Website"
          }
        },
        "title": "IntegrationCustomerPayload",
        "type": "object"
      },
      "IntegrationField": {
        "properties": {
          "key": {
            "maxLength": 80,
            "minLength": 1,
            "title": "Key",
            "type": "string"
          },
          "label": {
            "default": "",
            "maxLength": 200,
            "title": "Label",
            "type": "string"
          },
          "options": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Options"
          },
          "type": {
            "default": "text",
            "enum": [
              "text",
              "textarea",
              "email",
              "phone",
              "url",
              "number",
              "date",
              "datetime",
              "bool",
              "select",
              "file"
            ],
            "title": "Type",
            "type": "string"
          },
          "value": {
            "title": "Value"
          }
        },
        "required": [
          "key"
        ],
        "title": "IntegrationField",
        "type": "object"
      },
      "InteractionOut": {
        "properties": {
          "author_kind": {
            "description": "`human` (assinado por `author_email`) ou `system`.",
            "title": "Author Kind",
            "type": "string"
          },
          "author_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Author Name"
          },
          "content": {
            "title": "Content",
            "type": "string"
          },
          "created_at": {
            "anyOf": [
              {
                "format": "date-time",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Created At"
          },
          "id": {
            "format": "uuid",
            "title": "Id",
            "type": "string"
          },
          "is_internal": {
            "title": "Is Internal",
            "type": "boolean"
          }
        },
        "required": [
          "id",
          "content",
          "is_internal",
          "author_kind",
          "author_name",
          "created_at"
        ],
        "title": "InteractionOut",
        "type": "object"
      },
      "KBArticleOut": {
        "properties": {
          "body_html": {
            "title": "Body Html",
            "type": "string"
          },
          "created_at": {
            "anyOf": [
              {
                "format": "date-time",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Created At"
          },
          "excerpt": {
            "title": "Excerpt",
            "type": "string"
          },
          "external_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "External Id"
          },
          "id": {
            "format": "uuid",
            "title": "Id",
            "type": "string"
          },
          "origin": {
            "title": "Origin",
            "type": "string"
          },
          "product": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Slug do produto; `null` = todos.",
            "title": "Product"
          },
          "published_at": {
            "anyOf": [
              {
                "format": "date-time",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Published At"
          },
          "status": {
            "title": "Status",
            "type": "string"
          },
          "title": {
            "title": "Title",
            "type": "string"
          },
          "updated_at": {
            "anyOf": [
              {
                "format": "date-time",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Updated At"
          }
        },
        "required": [
          "id",
          "external_id",
          "product",
          "title",
          "excerpt",
          "status",
          "origin",
          "published_at",
          "created_at",
          "updated_at",
          "body_html"
        ],
        "title": "KBArticleOut",
        "type": "object"
      },
      "KBArticleSummary": {
        "description": "Artigo sem o corpo — listagem e resultado do lote.",
        "properties": {
          "created_at": {
            "anyOf": [
              {
                "format": "date-time",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Created At"
          },
          "excerpt": {
            "title": "Excerpt",
            "type": "string"
          },
          "external_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "External Id"
          },
          "id": {
            "format": "uuid",
            "title": "Id",
            "type": "string"
          },
          "origin": {
            "title": "Origin",
            "type": "string"
          },
          "product": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Slug do produto; `null` = todos.",
            "title": "Product"
          },
          "published_at": {
            "anyOf": [
              {
                "format": "date-time",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Published At"
          },
          "status": {
            "title": "Status",
            "type": "string"
          },
          "title": {
            "title": "Title",
            "type": "string"
          },
          "updated_at": {
            "anyOf": [
              {
                "format": "date-time",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Updated At"
          }
        },
        "required": [
          "id",
          "external_id",
          "product",
          "title",
          "excerpt",
          "status",
          "origin",
          "published_at",
          "created_at",
          "updated_at"
        ],
        "title": "KBArticleSummary",
        "type": "object"
      },
      "KBArticleUpsert": {
        "properties": {
          "body_html": {
            "anyOf": [
              {
                "maxLength": 200000,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Corpo em HTML (sanitizado).",
            "title": "Body Html"
          },
          "body_markdown": {
            "anyOf": [
              {
                "maxLength": 200000,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Corpo em Markdown. Use este OU o HTML.",
            "title": "Body Markdown"
          },
          "product": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Slug do produto. `null` = vale para todos os produtos. Omitido = mantém.",
            "title": "Product"
          },
          "status": {
            "anyOf": [
              {
                "enum": [
                  "draft",
                  "published"
                ],
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Omitido = mantém (rascunho ao criar). Só publicado alimenta o agente de IA.",
            "title": "Status"
          },
          "title": {
            "anyOf": [
              {
                "maxLength": 200,
                "minLength": 1,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Obrigatório ao criar.",
            "title": "Title"
          }
        },
        "title": "KBArticleUpsert",
        "type": "object"
      },
      "KBBatchIn": {
        "properties": {
          "articles": {
            "items": {
              "$ref": "#/components/schemas/KBBatchItem"
            },
            "maxItems": 100,
            "minItems": 1,
            "title": "Articles",
            "type": "array"
          }
        },
        "required": [
          "articles"
        ],
        "title": "KBBatchIn",
        "type": "object"
      },
      "KBBatchItem": {
        "properties": {
          "body_html": {
            "anyOf": [
              {
                "maxLength": 200000,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Corpo em HTML (sanitizado).",
            "title": "Body Html"
          },
          "body_markdown": {
            "anyOf": [
              {
                "maxLength": 200000,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Corpo em Markdown. Use este OU o HTML.",
            "title": "Body Markdown"
          },
          "external_id": {
            "pattern": "^[A-Za-z0-9][A-Za-z0-9._:~@+=-]{0,199}$",
            "title": "External Id",
            "type": "string"
          },
          "product": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Slug do produto. `null` = vale para todos os produtos. Omitido = mantém.",
            "title": "Product"
          },
          "status": {
            "anyOf": [
              {
                "enum": [
                  "draft",
                  "published"
                ],
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Omitido = mantém (rascunho ao criar). Só publicado alimenta o agente de IA.",
            "title": "Status"
          },
          "title": {
            "anyOf": [
              {
                "maxLength": 200,
                "minLength": 1,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Obrigatório ao criar.",
            "title": "Title"
          }
        },
        "required": [
          "external_id"
        ],
        "title": "KBBatchItem",
        "type": "object"
      },
      "KBBatchOut": {
        "properties": {
          "created": {
            "title": "Created",
            "type": "integer"
          },
          "failed": {
            "title": "Failed",
            "type": "integer"
          },
          "results": {
            "items": {
              "$ref": "#/components/schemas/KBBatchResult"
            },
            "title": "Results",
            "type": "array"
          },
          "unchanged": {
            "title": "Unchanged",
            "type": "integer"
          },
          "updated": {
            "title": "Updated",
            "type": "integer"
          }
        },
        "required": [
          "results",
          "created",
          "updated",
          "unchanged",
          "failed"
        ],
        "title": "KBBatchOut",
        "type": "object"
      },
      "KBBatchResult": {
        "properties": {
          "action": {
            "anyOf": [
              {
                "enum": [
                  "created",
                  "updated",
                  "unchanged"
                ],
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Action"
          },
          "article": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/KBArticleSummary"
              },
              {
                "type": "null"
              }
            ]
          },
          "error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Código do erro quando `ok` é falso.",
            "title": "Error"
          },
          "external_id": {
            "title": "External Id",
            "type": "string"
          },
          "ok": {
            "title": "Ok",
            "type": "boolean"
          }
        },
        "required": [
          "external_id",
          "ok",
          "action",
          "error",
          "article"
        ],
        "title": "KBBatchResult",
        "type": "object"
      },
      "KBSearchHit": {
        "properties": {
          "excerpt": {
            "title": "Excerpt",
            "type": "string"
          },
          "external_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "External Id"
          },
          "id": {
            "format": "uuid",
            "title": "Id",
            "type": "string"
          },
          "title": {
            "title": "Title",
            "type": "string"
          }
        },
        "required": [
          "id",
          "external_id",
          "title",
          "excerpt"
        ],
        "title": "KBSearchHit",
        "type": "object"
      },
      "PageEnvelope_CustomerOut_": {
        "properties": {
          "code": {
            "description": "Status HTTP, repetido no corpo.",
            "title": "Code",
            "type": "integer"
          },
          "data": {
            "items": {
              "$ref": "#/components/schemas/CustomerOut"
            },
            "title": "Data",
            "type": "array"
          },
          "message": {
            "title": "Message",
            "type": "string"
          },
          "pagination": {
            "$ref": "#/components/schemas/Pagination"
          }
        },
        "required": [
          "code",
          "data",
          "message",
          "pagination"
        ],
        "title": "PageEnvelope[CustomerOut]",
        "type": "object"
      },
      "PageEnvelope_InteractionOut_": {
        "properties": {
          "code": {
            "description": "Status HTTP, repetido no corpo.",
            "title": "Code",
            "type": "integer"
          },
          "data": {
            "items": {
              "$ref": "#/components/schemas/InteractionOut"
            },
            "title": "Data",
            "type": "array"
          },
          "message": {
            "title": "Message",
            "type": "string"
          },
          "pagination": {
            "$ref": "#/components/schemas/Pagination"
          }
        },
        "required": [
          "code",
          "data",
          "message",
          "pagination"
        ],
        "title": "PageEnvelope[InteractionOut]",
        "type": "object"
      },
      "PageEnvelope_KBArticleSummary_": {
        "properties": {
          "code": {
            "description": "Status HTTP, repetido no corpo.",
            "title": "Code",
            "type": "integer"
          },
          "data": {
            "items": {
              "$ref": "#/components/schemas/KBArticleSummary"
            },
            "title": "Data",
            "type": "array"
          },
          "message": {
            "title": "Message",
            "type": "string"
          },
          "pagination": {
            "$ref": "#/components/schemas/Pagination"
          }
        },
        "required": [
          "code",
          "data",
          "message",
          "pagination"
        ],
        "title": "PageEnvelope[KBArticleSummary]",
        "type": "object"
      },
      "PageEnvelope_ReleaseNoteOut_": {
        "properties": {
          "code": {
            "description": "Status HTTP, repetido no corpo.",
            "title": "Code",
            "type": "integer"
          },
          "data": {
            "items": {
              "$ref": "#/components/schemas/ReleaseNoteOut"
            },
            "title": "Data",
            "type": "array"
          },
          "message": {
            "title": "Message",
            "type": "string"
          },
          "pagination": {
            "$ref": "#/components/schemas/Pagination"
          }
        },
        "required": [
          "code",
          "data",
          "message",
          "pagination"
        ],
        "title": "PageEnvelope[ReleaseNoteOut]",
        "type": "object"
      },
      "Pagination": {
        "properties": {
          "page": {
            "title": "Page",
            "type": "integer"
          },
          "page_size": {
            "title": "Page Size",
            "type": "integer"
          },
          "pages": {
            "title": "Pages",
            "type": "integer"
          },
          "total": {
            "title": "Total",
            "type": "integer"
          }
        },
        "required": [
          "page",
          "page_size",
          "total",
          "pages"
        ],
        "title": "Pagination",
        "type": "object"
      },
      "PeopleBatchIn": {
        "examples": [
          {
            "items": [
              {
                "customer_external_id": "erp-1042",
                "person": {
                  "email": "paula@padaria.example",
                  "external_id": "app-77",
                  "name": "Paula Reis"
                }
              }
            ]
          }
        ],
        "properties": {
          "items": {
            "description": "Até 500 pessoas.",
            "items": {
              "$ref": "#/components/schemas/PeopleBatchItem"
            },
            "maxItems": 500,
            "title": "Items",
            "type": "array"
          }
        },
        "required": [
          "items"
        ],
        "title": "PeopleBatchIn",
        "type": "object"
      },
      "PeopleBatchItem": {
        "properties": {
          "customer_external_id": {
            "maxLength": 255,
            "minLength": 1,
            "title": "Customer External Id",
            "type": "string"
          },
          "person": {
            "$ref": "#/components/schemas/PersonFields",
            "description": "Campos da pessoa, com `external_id`."
          }
        },
        "required": [
          "customer_external_id",
          "person"
        ],
        "title": "PeopleBatchItem",
        "type": "object"
      },
      "PersonFields": {
        "additionalProperties": false,
        "description": "Campos da pessoa. Só o que vier muda; `null` (ou ausente) não altera o que já está gravado.",
        "properties": {
          "access": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "description": "Acesso ao widget/portal. Padrão ao criar: `true`.",
            "title": "Access"
          },
          "clear": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "Campos a APAGAR nesta pessoa: `[\"email\"]`, `[\"phone\"]` ou os dois. Apagar é explícito — mandar `null`, vazio ou omitir o campo continua significando \"não mexe\". Só vale na ficha alcançada pelo identificador dela; por um identificador extra, recusa.",
            "title": "Clear"
          },
          "custom_fields": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "Campos personalizados da pessoa: lista de `{key, label, value}`. Mande a lista INTEIRA do seu sistema — campo omitido é removido. A visibilidade é decidida no bFocus e não muda por aqui.",
            "title": "Custom Fields"
          },
          "document": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "CPF da pessoa (com ou sem máscara). A PESSOA É ÚNICA: o mesmo CPF é sempre o mesmo cadastro, em qualquer produto e cliente. Chegando com um identificador desconhecido, o CPF acha a pessoa que já existe (o seu id vira identificador extra dela, `merged_into` na resposta); se o seu id e o CPF apontarem para duas fichas, elas são mescladas na hora. CPF inválido → `PERSON_DOCUMENT_INVALID`; CPF diferente do que a ficha já tem → `PERSON_DOCUMENT_CONFLICT` (nunca troca sozinho). `null`/vazio não apaga.",
            "title": "Document"
          },
          "email": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Identifica a pessoa já cadastrada (sem duplicar).",
            "title": "Email"
          },
          "external_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Só no lote: identificador da pessoa no seu sistema.",
            "title": "External Id"
          },
          "extra_emails": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "E-mails adicionais (somam aos que já existem).",
            "title": "Extra Emails"
          },
          "extra_phones": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "Telefones adicionais (somam aos que já existem).",
            "title": "Extra Phones"
          },
          "is_primary": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "description": "Contato principal do cliente.",
            "title": "Is Primary"
          },
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Obrigatório ao criar.",
            "title": "Name"
          },
          "phone": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Phone"
          },
          "role": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Cargo/função no cliente (ex.: Financeiro).",
            "title": "Role"
          }
        },
        "title": "PersonFields",
        "type": "object"
      },
      "PersonIdentifiersOut": {
        "properties": {
          "external_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Identificador principal da pessoa.",
            "title": "External Id"
          },
          "identifiers": {
            "description": "Identificadores extras.",
            "items": {
              "$ref": "#/components/schemas/IdentifierOut"
            },
            "title": "Identifiers",
            "type": "array"
          }
        },
        "required": [
          "external_id",
          "identifiers"
        ],
        "title": "PersonIdentifiersOut",
        "type": "object"
      },
      "PersonOut": {
        "properties": {
          "access": {
            "description": "Pode abrir o widget/portal do cliente.",
            "title": "Access",
            "type": "boolean"
          },
          "custom_fields": {
            "description": "Campos personalizados da pessoa, como `{key, label, value, visibility}`.",
            "items": {},
            "title": "Custom Fields",
            "type": "array"
          },
          "customer_external_id": {
            "description": "`external_id` principal do cliente a que a pessoa pertence.",
            "title": "Customer External Id",
            "type": "string"
          },
          "document": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "CPF da pessoa, só os dígitos.",
            "title": "Document"
          },
          "email": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Email"
          },
          "external_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "`null` = contato do cliente sem acesso (sem identificador).",
            "title": "External Id"
          },
          "identifiers": {
            "description": "Identificadores EXTRAS desta pessoa, como `{external_id, label, source}` — os outros ids pelos quais ela também é encontrada (o principal é o `external_id` acima). Lista vazia = só o principal. É por aqui que você descobre que o id que o SEU sistema usa virou um apelido do cadastro de outro sistema.",
            "items": {},
            "title": "Identifiers",
            "type": "array"
          },
          "is_primary": {
            "title": "Is Primary",
            "type": "boolean"
          },
          "name": {
            "title": "Name",
            "type": "string"
          },
          "phone": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Phone"
          },
          "role": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Role"
          }
        },
        "required": [
          "external_id",
          "name",
          "email",
          "phone",
          "document",
          "role",
          "access",
          "is_primary",
          "customer_external_id",
          "custom_fields",
          "identifiers"
        ],
        "title": "PersonOut",
        "type": "object"
      },
      "PersonRevokeOut": {
        "properties": {
          "access": {
            "description": "Pode abrir o widget/portal do cliente.",
            "title": "Access",
            "type": "boolean"
          },
          "custom_fields": {
            "description": "Campos personalizados da pessoa, como `{key, label, value, visibility}`.",
            "items": {},
            "title": "Custom Fields",
            "type": "array"
          },
          "customer_external_id": {
            "description": "`external_id` principal do cliente a que a pessoa pertence.",
            "title": "Customer External Id",
            "type": "string"
          },
          "document": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "CPF da pessoa, só os dígitos.",
            "title": "Document"
          },
          "email": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Email"
          },
          "external_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "`null` = contato do cliente sem acesso (sem identificador).",
            "title": "External Id"
          },
          "identifiers": {
            "description": "Identificadores EXTRAS desta pessoa, como `{external_id, label, source}` — os outros ids pelos quais ela também é encontrada (o principal é o `external_id` acima). Lista vazia = só o principal. É por aqui que você descobre que o id que o SEU sistema usa virou um apelido do cadastro de outro sistema.",
            "items": {},
            "title": "Identifiers",
            "type": "array"
          },
          "is_primary": {
            "title": "Is Primary",
            "type": "boolean"
          },
          "name": {
            "title": "Name",
            "type": "string"
          },
          "phone": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Phone"
          },
          "role": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Role"
          },
          "unlinked": {
            "default": false,
            "description": "`true` = a pessoa foi apenas DESLIGADA deste cliente e continua com acesso, porque ela também é de outros (cadastro único em N clientes). `false` = ela era só deste cliente e perdeu o acesso (`access: false`), como sempre. Em nenhum dos casos algo é apagado: o histórico de chamados e conversas fica.",
            "title": "Unlinked",
            "type": "boolean"
          }
        },
        "required": [
          "external_id",
          "name",
          "email",
          "phone",
          "document",
          "role",
          "access",
          "is_primary",
          "customer_external_id",
          "custom_fields",
          "identifiers",
          "unlinked"
        ],
        "title": "PersonRevokeOut",
        "type": "object"
      },
      "PersonUpsertIn": {
        "examples": [
          {
            "person": {
              "email": "paula@padaria.example",
              "is_primary": true,
              "name": "Paula Reis",
              "role": "Financeiro"
            }
          }
        ],
        "properties": {
          "person": {
            "$ref": "#/components/schemas/PersonFields"
          }
        },
        "required": [
          "person"
        ],
        "title": "PersonUpsertIn",
        "type": "object"
      },
      "PersonUpsertOut": {
        "properties": {
          "access": {
            "description": "Pode abrir o widget/portal do cliente.",
            "title": "Access",
            "type": "boolean"
          },
          "custom_fields": {
            "description": "Campos personalizados da pessoa, como `{key, label, value, visibility}`.",
            "items": {},
            "title": "Custom Fields",
            "type": "array"
          },
          "customer_external_id": {
            "description": "`external_id` principal do cliente a que a pessoa pertence.",
            "title": "Customer External Id",
            "type": "string"
          },
          "document": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "CPF da pessoa, só os dígitos.",
            "title": "Document"
          },
          "email": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Email"
          },
          "external_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "`null` = contato do cliente sem acesso (sem identificador).",
            "title": "External Id"
          },
          "identifiers": {
            "description": "Identificadores EXTRAS desta pessoa, como `{external_id, label, source}` — os outros ids pelos quais ela também é encontrada (o principal é o `external_id` acima). Lista vazia = só o principal. É por aqui que você descobre que o id que o SEU sistema usa virou um apelido do cadastro de outro sistema.",
            "items": {},
            "title": "Identifiers",
            "type": "array"
          },
          "is_primary": {
            "title": "Is Primary",
            "type": "boolean"
          },
          "linked": {
            "default": false,
            "description": "`true` = esta chamada LIGOU a pessoa a mais um cliente: ela já existia em outro e agora pertence aos dois. Não confunda com absorção, em que o `external_id` devolvido é DIFERENTE do enviado (o seu identificador virou extra de outra ficha). São coisas distintas e pedem reações distintas: ligar é o resultado desejado quando a mesma pessoa circula entre clientes; absorver é um casamento por contato, que pode estar errado.",
            "title": "Linked",
            "type": "boolean"
          },
          "merged_into": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Preenchido quando o identificador que você enviou é um APELIDO: este é o `external_id` principal do cadastro único, e é ele que vale daqui em diante. `null` = o id que você mandou é o principal. Mesmo campo que o lote já devolvia — agora também no PUT único.",
            "title": "Merged Into"
          },
          "name": {
            "title": "Name",
            "type": "string"
          },
          "phone": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Phone"
          },
          "role": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Role"
          },
          "status": {
            "enum": [
              "created",
              "updated",
              "unchanged"
            ],
            "title": "Status",
            "type": "string"
          }
        },
        "required": [
          "external_id",
          "name",
          "email",
          "phone",
          "document",
          "role",
          "access",
          "is_primary",
          "customer_external_id",
          "custom_fields",
          "identifiers",
          "status",
          "merged_into",
          "linked"
        ],
        "title": "PersonUpsertOut",
        "type": "object"
      },
      "ProductOut": {
        "properties": {
          "ai_level": {
            "description": "`none`, `assisted` ou `autonomous` (definido no painel).",
            "title": "Ai Level",
            "type": "string"
          },
          "color": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Color"
          },
          "created_at": {
            "anyOf": [
              {
                "format": "date-time",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Created At"
          },
          "current_version": {
            "description": "Maior versão publicada em release notes.",
            "title": "Current Version",
            "type": "string"
          },
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "icon": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Icon"
          },
          "id": {
            "format": "uuid",
            "title": "Id",
            "type": "string"
          },
          "is_active": {
            "title": "Is Active",
            "type": "boolean"
          },
          "name": {
            "title": "Name",
            "type": "string"
          },
          "slug": {
            "title": "Slug",
            "type": "string"
          },
          "sort_order": {
            "title": "Sort Order",
            "type": "integer"
          },
          "updated_at": {
            "anyOf": [
              {
                "format": "date-time",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Updated At"
          }
        },
        "required": [
          "id",
          "slug",
          "name",
          "description",
          "color",
          "icon",
          "is_active",
          "sort_order",
          "current_version",
          "ai_level",
          "created_at",
          "updated_at"
        ],
        "title": "ProductOut",
        "type": "object"
      },
      "ProductRef": {
        "properties": {
          "id": {
            "format": "uuid",
            "title": "Id",
            "type": "string"
          },
          "is_active": {
            "title": "Is Active",
            "type": "boolean"
          },
          "name": {
            "title": "Name",
            "type": "string"
          },
          "slug": {
            "title": "Slug",
            "type": "string"
          }
        },
        "required": [
          "id",
          "slug",
          "name",
          "is_active"
        ],
        "title": "ProductRef",
        "type": "object"
      },
      "ProductRoleOut": {
        "properties": {
          "access_limits": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Access Limits"
          },
          "agent_instructions": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Agent Instructions"
          },
          "id": {
            "format": "uuid",
            "title": "Id",
            "type": "string"
          },
          "key": {
            "title": "Key",
            "type": "string"
          },
          "label": {
            "title": "Label",
            "type": "string"
          },
          "people_count": {
            "description": "Quantas pessoas estão neste papel hoje.",
            "title": "People Count",
            "type": "integer"
          },
          "product": {
            "title": "Product",
            "type": "string"
          }
        },
        "required": [
          "id",
          "product",
          "key",
          "label",
          "agent_instructions",
          "access_limits",
          "people_count"
        ],
        "title": "ProductRoleOut",
        "type": "object"
      },
      "ProductRoleUpsert": {
        "properties": {
          "access_limits": {
            "anyOf": [
              {
                "maxLength": 4000,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "O que este papel NÃO acessa. **Instrução para o agente, não permissão**: o papel é declarado pela sua página e não é prova de nada (ver a seção de papéis no guia).",
            "title": "Access Limits"
          },
          "agent_instructions": {
            "anyOf": [
              {
                "maxLength": 4000,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Como o agente de IA deve tratar quem é deste papel. String vazia limpa.",
            "title": "Agent Instructions"
          },
          "label": {
            "anyOf": [
              {
                "maxLength": 120,
                "minLength": 1,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Nome na tela. Ausente ao criar = a própria `key`.",
            "title": "Label"
          }
        },
        "title": "ProductRoleUpsert",
        "type": "object"
      },
      "ProductUpsert": {
        "properties": {
          "color": {
            "anyOf": [
              {
                "maxLength": 16,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Color"
          },
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "icon": {
            "anyOf": [
              {
                "maxLength": 64,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Icon"
          },
          "is_active": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Is Active"
          },
          "name": {
            "anyOf": [
              {
                "maxLength": 255,
                "minLength": 1,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Obrigatório ao criar.",
            "title": "Name"
          },
          "sort_order": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Sort Order"
          }
        },
        "title": "ProductUpsert",
        "type": "object"
      },
      "ReleaseNoteOut": {
        "properties": {
          "audience": {
            "title": "Audience",
            "type": "string"
          },
          "created_at": {
            "anyOf": [
              {
                "format": "date-time",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Created At"
          },
          "description_html": {
            "title": "Description Html",
            "type": "string"
          },
          "id": {
            "format": "uuid",
            "title": "Id",
            "type": "string"
          },
          "is_published": {
            "title": "Is Published",
            "type": "boolean"
          },
          "product": {
            "description": "Slug do produto.",
            "title": "Product",
            "type": "string"
          },
          "published_at": {
            "anyOf": [
              {
                "format": "date-time",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Published At"
          },
          "require_ack_external": {
            "title": "Require Ack External",
            "type": "boolean"
          },
          "require_ack_internal": {
            "title": "Require Ack Internal",
            "type": "boolean"
          },
          "title": {
            "title": "Title",
            "type": "string"
          },
          "updated_at": {
            "anyOf": [
              {
                "format": "date-time",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Updated At"
          },
          "version": {
            "title": "Version",
            "type": "string"
          }
        },
        "required": [
          "id",
          "product",
          "version",
          "title",
          "description_html",
          "audience",
          "is_published",
          "require_ack_internal",
          "require_ack_external",
          "published_at",
          "created_at",
          "updated_at"
        ],
        "title": "ReleaseNoteOut",
        "type": "object"
      },
      "ReleaseNoteUpsert": {
        "properties": {
          "audience": {
            "anyOf": [
              {
                "enum": [
                  "internal",
                  "external",
                  "both"
                ],
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Quem vê: equipe (`internal`), clientes no widget (`external`) ou os dois. Padrão ao criar: `both`.",
            "title": "Audience"
          },
          "description_html": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Corpo em HTML (sanitizado).",
            "title": "Description Html"
          },
          "description_markdown": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Corpo em Markdown. Use este OU o HTML.",
            "title": "Description Markdown"
          },
          "publish": {
            "default": false,
            "description": "Publica depois de salvar. Já publicada = nada muda.",
            "title": "Publish",
            "type": "boolean"
          },
          "require_ack_external": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Require Ack External"
          },
          "require_ack_internal": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Require Ack Internal"
          },
          "title": {
            "anyOf": [
              {
                "maxLength": 255,
                "minLength": 1,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Obrigatório ao criar.",
            "title": "Title"
          }
        },
        "title": "ReleaseNoteUpsert",
        "type": "object"
      }
    },
    "securitySchemes": {
      "bearerAuth": {
        "description": "Chave de API (`bf_live_…`).",
        "scheme": "bearer",
        "type": "http"
      }
    }
  },
  "info": {
    "contact": {
      "name": "Berni Software",
      "url": "https://bfocus.com.br"
    },
    "description": "API pública do bFocus. Use as SDKs oficiais (Python, Node/TS, PHP, .NET, Java, Go, Ruby) ou HTTP direto.\n\n## Autenticação\n`Authorization: Bearer <chave>`. Crie chaves em **Integrações → Chaves de API**, cada uma com os\nescopos que precisa. A chave legada (`bf_sk_…`) só alcança clientes (`customers:*`).\n\n## Escopos\n- `customers:read` — Ler clientes, contatos, pessoas, produtos vinculados e interações\n- `customers:write` — Cadastrar, atualizar e excluir clientes, contatos, pessoas, identificadores extras e interações\n- `products:read` — Ler o catálogo de produtos\n- `products:write` — Cadastrar, atualizar e arquivar produtos\n- `kb:read` — Ler e buscar artigos da base de conhecimento\n- `kb:write` — Criar, atualizar, publicar e excluir artigos da base de conhecimento\n- `ai_agents:read` — Ler os agentes de IA\n- `ai_agents:preview` — Testar a resposta de um agente de IA (consome IA do tenant)\n- `widget:sign` — Assinar a identidade do usuário do widget (sem guardar segredo no seu servidor)\n- `tickets:read` — Ler chamados e a conversa deles\n- `tickets:write` — Comentar em chamados e mudar status, prioridade e responsável\n- `tasks:read` — Ler tarefas e a conversa delas\n- `tasks:write` — Comentar em tarefas e mudar status, prioridade, responsável e prazo\n- `release_notes:read` — Ler release notes\n- `release_notes:write` — Criar, atualizar e publicar release notes\n- `projects:read` — Ler projetos, a situação deles e a leitura do radar de risco\n- `monitor:read` — Ler os erros capturados pelo Monitoramento (resumo, lista e detalhe com ocorrências)\n- `monitor:write` — Agir nos erros do Monitoramento: resolver, ignorar, juntar, investigar e abrir demanda\n\n## Respostas\nSucesso: `{\"code\": <status>, \"data\": …, \"message\": \"…\"}` (listas paginadas trazem `pagination`).\nErro: `{\"code\": <status>, \"data\": null, \"message\": \"<CÓDIGO>\", \"error\": \"<CÓDIGO>\", \"validation\": {}, \"request_id\": \"…\"}`.\n**Use sempre `error`** na sua lógica — é estável. Toda resposta traz `X-Request-Id`.\n\n## Erros comuns a todas as operações\n- `INTEGRATION_KEY_MISSING` — 401 — faltou `Authorization: Bearer <chave>`\n- `INTEGRATION_KEY_INVALID` — 401 — chave desconhecida\n- `INTEGRATION_KEY_REVOKED` — 401 — chave revogada\n- `INTEGRATION_DISABLED` — 403 — chave desligada no painel\n- `INTEGRATION_HOST_FORBIDDEN` — 403 — o IP de origem não está na lista de IPs liberados da chave\n- `INTEGRATION_SCOPE_MISSING` — 403 — a chave não tem o escopo da operação (header `X-Required-Scope`)\n- `MODULE_NOT_CONTRACTED` — 403 — a empresa não contratou o módulo da operação (header `X-Required-Module`; ver `x-module`)\n- `TENANT_NOT_FOUND` — 404 — conta inativa\n- `VALIDATION_ERROR` — 422 — corpo ou parâmetro inválido (detalhe em `validation`)\n- `RATE_LIMITED` — 429 — limite de requisições da chave (header `Retry-After`)\n- `IDEMPOTENCY_KEY_INVALID` — 422 — `Idempotency-Key` vazia ou com mais de 255 caracteres\n- `IDEMPOTENCY_KEY_REUSED` — 422 — a mesma `Idempotency-Key` com outra requisição\n- `IDEMPOTENCY_IN_PROGRESS` — 409 — a requisição original com esta chave ainda está rodando\n- `INTERNAL_ERROR` — 500 — erro interno (informe o `request_id`)\n\n## Idempotência\nEnvie `Idempotency-Key: <uuid>` em POST/PUT/PATCH/DELETE: repetir a chamada com a mesma chave\n(e a mesma requisição) devolve a resposta original com `Idempotent-Replayed: true`, sem executar\nde novo. As SDKs fazem isso sozinhas em toda nova tentativa.\n\n## SDK em uso\nAs SDKs enviam `X-Bfocus-Client: bfocus-<linguagem>/<versão>`. É assim que avisamos você quando\numa correção exigir atualizar a SDK.\n",
    "title": "bFocus API pública",
    "version": "1.0.0"
  },
  "openapi": "3.1.0",
  "paths": {
    "/api/v1/integration/ai-agents": {
      "get": {
        "operationId": "ai_agents.list",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope_list_AgentOut__"
                }
              }
            },
            "description": "Successful Response"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "Erro. Use o campo `error` (código estável) na sua lógica."
          }
        },
        "summary": "Lista os agentes de IA da empresa (o padrão primeiro)",
        "tags": [
          "ai_agents"
        ],
        "x-errors": [],
        "x-module": "atendimento",
        "x-scopes": [
          "ai_agents:read"
        ]
      }
    },
    "/api/v1/integration/ai-agents/{agent_id}": {
      "get": {
        "operationId": "ai_agents.get",
        "parameters": [
          {
            "in": "path",
            "name": "agent_id",
            "required": true,
            "schema": {
              "format": "uuid",
              "title": "Agent Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope_AgentOut_"
                }
              }
            },
            "description": "Successful Response"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "Erro. Use o campo `error` (código estável) na sua lógica."
          }
        },
        "summary": "Lê um agente de IA",
        "tags": [
          "ai_agents"
        ],
        "x-errors": [
          "AI_AGENT_NOT_FOUND"
        ],
        "x-module": "atendimento",
        "x-scopes": [
          "ai_agents:read"
        ]
      }
    },
    "/api/v1/integration/ai-agents/{agent_id}/preview": {
      "post": {
        "description": "Resposta simulada, sem conversa real — para conferir o que o agente responde depois de enriquecer a base. Funciona com o agente inativo. Consome IA do tenant; limite de 30 por minuto por chave.",
        "operationId": "ai_agents.preview",
        "parameters": [
          {
            "in": "path",
            "name": "agent_id",
            "required": true,
            "schema": {
              "format": "uuid",
              "title": "Agent Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AgentPreviewIn"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope_AgentPreviewOut_"
                }
              }
            },
            "description": "Successful Response"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "Erro. Use o campo `error` (código estável) na sua lógica."
          }
        },
        "summary": "Testa a resposta do agente para uma mensagem",
        "tags": [
          "ai_agents"
        ],
        "x-errors": [
          "AI_AGENT_NOT_FOUND",
          "AI_DISABLED",
          "AI_KEY_INVALID",
          "AI_NO_KEY"
        ],
        "x-module": "atendimento",
        "x-scopes": [
          "ai_agents:preview"
        ]
      }
    },
    "/api/v1/integration/customers": {
      "get": {
        "description": "`q` busca em nome, external_id (inclusive os extras) e documento (com ou sem máscara). `updated_since` serve para sincronização incremental.",
        "operationId": "customers.list",
        "parameters": [
          {
            "in": "query",
            "name": "q",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "maxLength": 200,
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Q"
            }
          },
          {
            "description": "Só clientes alterados a partir deste instante (ISO 8601).",
            "in": "query",
            "name": "updated_since",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "format": "date-time",
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Só clientes alterados a partir deste instante (ISO 8601).",
              "title": "Updated Since"
            }
          },
          {
            "in": "query",
            "name": "page",
            "required": false,
            "schema": {
              "default": 1,
              "minimum": 1,
              "title": "Page",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "page_size",
            "required": false,
            "schema": {
              "default": 50,
              "maximum": 200,
              "minimum": 1,
              "title": "Page Size",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PageEnvelope_CustomerOut_"
                }
              }
            },
            "description": "Successful Response"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "Erro. Use o campo `error` (código estável) na sua lógica."
          }
        },
        "summary": "Lista clientes (mais recentes primeiro)",
        "tags": [
          "customers"
        ],
        "x-errors": [],
        "x-scopes": [
          "customers:read"
        ]
      },
      "post": {
        "description": "Mesma semântica do PUT. Use quando não sabe se o cliente existe. 201 ao criar, 200 ao atualizar.",
        "operationId": "customers.create",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IntegrationCustomerPayload"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope_CustomerOut_"
                }
              }
            },
            "description": "Successful Response"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "Erro. Use o campo `error` (código estável) na sua lógica."
          }
        },
        "summary": "Cadastra ou atualiza um cliente (external_id no corpo)",
        "tags": [
          "customers"
        ],
        "x-errors": [
          "CUSTOMER_DOCUMENT_DUPLICATE",
          "CUSTOMER_UPSERT_CONFLICT",
          "EXTERNAL_ID_REQUIRED",
          "FIELDS_MUST_BE_OBJECT",
          "FIELD_KEY_INVALID",
          "FIELD_LABEL_INVALID",
          "FIELD_TYPE_INVALID",
          "FIXED_FIELD_IN_FIELDS",
          "IS_ACTIVE_INVALID",
          "NAME_REQUIRED",
          "RESOURCE_LIMIT_REACHED",
          "UNKNOWN_CUSTOMER_FIELD"
        ],
        "x-scopes": [
          "customers:write"
        ]
      }
    },
    "/api/v1/integration/customers/batch": {
      "post": {
        "description": "Para a carga inicial e volumes grandes: até 500 itens por chamada (acima disso, 422 `VALIDATION_ERROR` e nada é gravado). Cada item é independente — um erro não desfaz os outros — e volta em `results` (mesma ordem, com `index`) com `status` `created`, `updated`, `unchanged` ou `error` (código estável em `error`). `summary` conta cada status. Cada item tem o formato do upsert, com `external_id`. Erros por item: `EXTERNAL_ID_REQUIRED`, `NAME_REQUIRED`, `CUSTOMER_DOCUMENT_DUPLICATE`, `CUSTOMER_UPSERT_CONFLICT`, `RESOURCE_LIMIT_REACHED`, `UNKNOWN_CUSTOMER_FIELD`, `FIELDS_MUST_BE_OBJECT`, `FIELD_KEY_INVALID`, `FIXED_FIELD_IN_FIELDS`, `FIELD_LABEL_INVALID`, `FIELD_TYPE_INVALID`, `IS_ACTIVE_INVALID`.",
        "operationId": "customers.batch",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CustomerBatchIn"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope_BatchOut_"
                }
              }
            },
            "description": "Successful Response"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "Erro. Use o campo `error` (código estável) na sua lógica."
          }
        },
        "summary": "Cadastra ou atualiza até 500 clientes de uma vez",
        "tags": [
          "customers"
        ],
        "x-errors": [],
        "x-scopes": [
          "customers:write"
        ]
      }
    },
    "/api/v1/integration/customers/{external_id}": {
      "delete": {
        "operationId": "customers.delete",
        "parameters": [
          {
            "description": "`external_id` do cliente no seu sistema.",
            "in": "path",
            "name": "external_id",
            "required": true,
            "schema": {
              "description": "`external_id` do cliente no seu sistema.",
              "maxLength": 255,
              "minLength": 1,
              "title": "External Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope_Deleted_"
                }
              }
            },
            "description": "Successful Response"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "Erro. Use o campo `error` (código estável) na sua lógica."
          }
        },
        "summary": "Exclui um cliente",
        "tags": [
          "customers"
        ],
        "x-errors": [
          "CUSTOMER_NOT_FOUND"
        ],
        "x-scopes": [
          "customers:write"
        ]
      },
      "get": {
        "operationId": "customers.get",
        "parameters": [
          {
            "description": "`external_id` do cliente no seu sistema.",
            "in": "path",
            "name": "external_id",
            "required": true,
            "schema": {
              "description": "`external_id` do cliente no seu sistema.",
              "maxLength": 255,
              "minLength": 1,
              "title": "External Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope_CustomerOut_"
                }
              }
            },
            "description": "Successful Response"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "Erro. Use o campo `error` (código estável) na sua lógica."
          }
        },
        "summary": "Lê um cliente",
        "tags": [
          "customers"
        ],
        "x-errors": [
          "CUSTOMER_NOT_FOUND"
        ],
        "x-scopes": [
          "customers:read"
        ]
      },
      "put": {
        "description": "Só o que vier no corpo muda. `name` é obrigatório ao criar. 201 ao criar, 200 ao atualizar.",
        "operationId": "customers.upsert",
        "parameters": [
          {
            "description": "`external_id` do cliente no seu sistema.",
            "in": "path",
            "name": "external_id",
            "required": true,
            "schema": {
              "description": "`external_id` do cliente no seu sistema.",
              "maxLength": 255,
              "minLength": 1,
              "title": "External Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IntegrationCustomerPayload"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope_CustomerOut_"
                }
              }
            },
            "description": "Successful Response"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "Erro. Use o campo `error` (código estável) na sua lógica."
          }
        },
        "summary": "Cadastra ou atualiza um cliente",
        "tags": [
          "customers"
        ],
        "x-errors": [
          "CUSTOMER_DOCUMENT_DUPLICATE",
          "CUSTOMER_UPSERT_CONFLICT",
          "EXTERNAL_ID_MISMATCH",
          "FIELDS_MUST_BE_OBJECT",
          "FIELD_KEY_INVALID",
          "FIELD_LABEL_INVALID",
          "FIELD_TYPE_INVALID",
          "FIXED_FIELD_IN_FIELDS",
          "IS_ACTIVE_INVALID",
          "NAME_REQUIRED",
          "RESOURCE_LIMIT_REACHED",
          "UNKNOWN_CUSTOMER_FIELD"
        ],
        "x-scopes": [
          "customers:write"
        ]
      }
    },
    "/api/v1/integration/customers/{external_id}/contacts": {
      "get": {
        "operationId": "customers.contacts.list",
        "parameters": [
          {
            "description": "`external_id` do cliente no seu sistema.",
            "in": "path",
            "name": "external_id",
            "required": true,
            "schema": {
              "description": "`external_id` do cliente no seu sistema.",
              "maxLength": 255,
              "minLength": 1,
              "title": "External Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope_list_ContactOut__"
                }
              }
            },
            "description": "Successful Response"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "Erro. Use o campo `error` (código estável) na sua lógica."
          }
        },
        "summary": "Lista os contatos do cliente",
        "tags": [
          "customers"
        ],
        "x-errors": [
          "CUSTOMER_NOT_FOUND"
        ],
        "x-scopes": [
          "customers:read"
        ]
      }
    },
    "/api/v1/integration/customers/{external_id}/contacts/{contact_external_id}": {
      "delete": {
        "operationId": "customers.contacts.delete",
        "parameters": [
          {
            "description": "`external_id` do cliente no seu sistema.",
            "in": "path",
            "name": "external_id",
            "required": true,
            "schema": {
              "description": "`external_id` do cliente no seu sistema.",
              "maxLength": 255,
              "minLength": 1,
              "title": "External Id",
              "type": "string"
            }
          },
          {
            "description": "`external_id` do contato no seu sistema.",
            "in": "path",
            "name": "contact_external_id",
            "required": true,
            "schema": {
              "description": "`external_id` do contato no seu sistema.",
              "maxLength": 255,
              "minLength": 1,
              "title": "Contact External Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope_Deleted_"
                }
              }
            },
            "description": "Successful Response"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "Erro. Use o campo `error` (código estável) na sua lógica."
          }
        },
        "summary": "Exclui um contato do cliente",
        "tags": [
          "customers"
        ],
        "x-errors": [
          "CONTACT_NOT_FOUND",
          "CUSTOMER_NOT_FOUND"
        ],
        "x-scopes": [
          "customers:write"
        ]
      },
      "put": {
        "description": "Só o que vier no corpo muda. `name` é obrigatório ao criar. 201 ao criar, 200 ao atualizar.",
        "operationId": "customers.contacts.upsert",
        "parameters": [
          {
            "description": "`external_id` do cliente no seu sistema.",
            "in": "path",
            "name": "external_id",
            "required": true,
            "schema": {
              "description": "`external_id` do cliente no seu sistema.",
              "maxLength": 255,
              "minLength": 1,
              "title": "External Id",
              "type": "string"
            }
          },
          {
            "description": "`external_id` do contato no seu sistema.",
            "in": "path",
            "name": "contact_external_id",
            "required": true,
            "schema": {
              "description": "`external_id` do contato no seu sistema.",
              "maxLength": 255,
              "minLength": 1,
              "title": "Contact External Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ContactUpsert"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope_ContactOut_"
                }
              }
            },
            "description": "Successful Response"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "Erro. Use o campo `error` (código estável) na sua lógica."
          }
        },
        "summary": "Cadastra ou atualiza um contato do cliente",
        "tags": [
          "customers"
        ],
        "x-errors": [
          "CONTACT_NAME_REQUIRED",
          "CUSTOMER_NOT_FOUND"
        ],
        "x-scopes": [
          "customers:write"
        ]
      }
    },
    "/api/v1/integration/customers/{external_id}/identifiers/{extra_id}": {
      "delete": {
        "description": "O identificador deixa de apontar para o cadastro. O principal (`external_id`) não sai por aqui.",
        "operationId": "customers.identifiers.remove",
        "parameters": [
          {
            "description": "`external_id` do cliente no seu sistema.",
            "in": "path",
            "name": "external_id",
            "required": true,
            "schema": {
              "description": "`external_id` do cliente no seu sistema.",
              "maxLength": 255,
              "minLength": 1,
              "title": "External Id",
              "type": "string"
            }
          },
          {
            "description": "Identificador extra (de outro sistema seu).",
            "in": "path",
            "name": "extra_id",
            "required": true,
            "schema": {
              "description": "Identificador extra (de outro sistema seu).",
              "maxLength": 255,
              "minLength": 1,
              "title": "Extra Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope_CustomerIdentifiersOut_"
                }
              }
            },
            "description": "Successful Response"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "Erro. Use o campo `error` (código estável) na sua lógica."
          }
        },
        "summary": "Desliga um identificador extra do cliente",
        "tags": [
          "customers"
        ],
        "x-errors": [
          "CUSTOMER_NOT_FOUND",
          "IDENTIFIER_NOT_FOUND"
        ],
        "x-scopes": [
          "customers:write"
        ]
      },
      "put": {
        "description": "Liga um identificador de outro sistema seu ao mesmo cadastro: depois disso, qualquer rota (e o widget) aceita os dois. Idempotente — já ligado a este cadastro, nada muda (200). Ligado a OUTRO cadastro: 409 `IDENTIFIER_IN_USE`, com o dono em `data.owner`.",
        "operationId": "customers.identifiers.add",
        "parameters": [
          {
            "description": "`external_id` do cliente no seu sistema.",
            "in": "path",
            "name": "external_id",
            "required": true,
            "schema": {
              "description": "`external_id` do cliente no seu sistema.",
              "maxLength": 255,
              "minLength": 1,
              "title": "External Id",
              "type": "string"
            }
          },
          {
            "description": "Identificador extra (de outro sistema seu).",
            "in": "path",
            "name": "extra_id",
            "required": true,
            "schema": {
              "description": "Identificador extra (de outro sistema seu).",
              "maxLength": 255,
              "minLength": 1,
              "title": "Extra Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/IdentifierLabelIn"
                  },
                  {
                    "type": "null"
                  }
                ],
                "title": "Body"
              }
            }
          }
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope_CustomerIdentifiersOut_"
                }
              }
            },
            "description": "Successful Response"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "Erro. Use o campo `error` (código estável) na sua lógica."
          }
        },
        "summary": "Liga um identificador extra ao cliente",
        "tags": [
          "customers"
        ],
        "x-errors": [
          "CUSTOMER_NOT_FOUND",
          "IDENTIFIER_IN_USE"
        ],
        "x-scopes": [
          "customers:write"
        ]
      }
    },
    "/api/v1/integration/customers/{external_id}/interactions": {
      "get": {
        "operationId": "customers.interactions.list",
        "parameters": [
          {
            "description": "`external_id` do cliente no seu sistema.",
            "in": "path",
            "name": "external_id",
            "required": true,
            "schema": {
              "description": "`external_id` do cliente no seu sistema.",
              "maxLength": 255,
              "minLength": 1,
              "title": "External Id",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "page",
            "required": false,
            "schema": {
              "default": 1,
              "minimum": 1,
              "title": "Page",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "page_size",
            "required": false,
            "schema": {
              "default": 50,
              "maximum": 200,
              "minimum": 1,
              "title": "Page Size",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PageEnvelope_InteractionOut_"
                }
              }
            },
            "description": "Successful Response"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "Erro. Use o campo `error` (código estável) na sua lógica."
          }
        },
        "summary": "Lista o histórico de interações do cliente (mais recentes primeiro)",
        "tags": [
          "customers"
        ],
        "x-errors": [
          "CUSTOMER_NOT_FOUND"
        ],
        "x-scopes": [
          "customers:read"
        ]
      },
      "post": {
        "description": "Ligação, visita, venda… Alimenta o dossiê do cliente e o resumo da IA.",
        "operationId": "customers.interactions.create",
        "parameters": [
          {
            "description": "`external_id` do cliente no seu sistema.",
            "in": "path",
            "name": "external_id",
            "required": true,
            "schema": {
              "description": "`external_id` do cliente no seu sistema.",
              "maxLength": 255,
              "minLength": 1,
              "title": "External Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CustomerInteractionCreate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope_InteractionOut_"
                }
              }
            },
            "description": "Successful Response"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "Erro. Use o campo `error` (código estável) na sua lógica."
          }
        },
        "summary": "Registra uma interação no histórico do cliente",
        "tags": [
          "customers"
        ],
        "x-errors": [
          "AUTHOR_NOT_FOUND",
          "CUSTOMER_NOT_FOUND",
          "INTERACTION_CONTENT_REQUIRED"
        ],
        "x-scopes": [
          "customers:write"
        ]
      }
    },
    "/api/v1/integration/customers/{external_id}/people": {
      "get": {
        "description": "Principal primeiro, depois quem tem acesso, por nome. Contato sem acesso vem com `external_id: null`.",
        "operationId": "people.list",
        "parameters": [
          {
            "description": "`external_id` do cliente no seu sistema.",
            "in": "path",
            "name": "external_id",
            "required": true,
            "schema": {
              "description": "`external_id` do cliente no seu sistema.",
              "maxLength": 255,
              "minLength": 1,
              "title": "External Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope_list_PersonOut__"
                }
              }
            },
            "description": "Successful Response"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "Erro. Use o campo `error` (código estável) na sua lógica."
          }
        },
        "summary": "Lista as pessoas do cliente",
        "tags": [
          "people"
        ],
        "x-errors": [
          "CUSTOMER_NOT_FOUND"
        ],
        "x-scopes": [
          "customers:read"
        ]
      }
    },
    "/api/v1/integration/customers/{external_id}/people/{person_external_id}": {
      "delete": {
        "description": "Use quando o usuário é excluído ou desativado no seu sistema. A pessoa perde o acesso (`access: false`) mas continua no histórico de chamados e conversas — nada é apagado. Um upsert com `access: true` devolve o acesso. O acesso é DO VÍNCULO com este cliente: a mesma pessoa circula por vários clientes e produtos, e tirar o acesso aqui não tira o dela nos outros — quando sobra algum, a resposta volta com `unlinked: true` e a pessoa segue ativa lá. Sem nenhum outro, ela é desligada, como sempre foi.",
        "operationId": "people.delete",
        "parameters": [
          {
            "description": "`external_id` do cliente no seu sistema.",
            "in": "path",
            "name": "external_id",
            "required": true,
            "schema": {
              "description": "`external_id` do cliente no seu sistema.",
              "maxLength": 255,
              "minLength": 1,
              "title": "External Id",
              "type": "string"
            }
          },
          {
            "description": "`external_id` da pessoa no seu sistema (o mesmo `user.externalId` do widget).",
            "in": "path",
            "name": "person_external_id",
            "required": true,
            "schema": {
              "description": "`external_id` da pessoa no seu sistema (o mesmo `user.externalId` do widget).",
              "maxLength": 255,
              "minLength": 1,
              "title": "Person External Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope_PersonRevokeOut_"
                }
              }
            },
            "description": "Successful Response"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "Erro. Use o campo `error` (código estável) na sua lógica."
          }
        },
        "summary": "Retira o acesso de uma pessoa NESTE cliente",
        "tags": [
          "people"
        ],
        "x-errors": [
          "CUSTOMER_NOT_FOUND",
          "PERSON_NOT_FOUND"
        ],
        "x-scopes": [
          "customers:write"
        ]
      },
      "put": {
        "description": "Pessoa = quem usa o seu sistema do lado do cliente (e abre chamados/conversas no widget). O identificador é o do seu sistema — o mesmo `user.externalId` do widget. Só o que vier em `person` muda. Sem cadastro com esse identificador, o e-mail (ou, sem e-mail, o telefone) encontra a pessoa que já chegou por e-mail ou por outro sistema: ela é adotada, nunca duplicada. A mesma pessoa informada com outro cliente NÃO é transferida: ela é LIGADA também a esse cliente (fica registrado) e a resposta volta com `linked: true` — o cadastro é único e a mesma pessoa circula por vários clientes e vários produtos. `status`: `created` (201), `updated` ou `unchanged` (200). Conta da equipe nunca é adotada nem alterada: e-mail (ou telefone) que já é de alguém da equipe simplesmente não entra na pessoa — o cadastro é feito sem ele, com o `status` normal, e a equipe vê a pista no app. Só o próprio identificador apontando para uma conta da equipe ainda recusa (`PERSON_EMAIL_STAFF`).",
        "operationId": "people.upsert",
        "parameters": [
          {
            "description": "`external_id` do cliente no seu sistema.",
            "in": "path",
            "name": "external_id",
            "required": true,
            "schema": {
              "description": "`external_id` do cliente no seu sistema.",
              "maxLength": 255,
              "minLength": 1,
              "title": "External Id",
              "type": "string"
            }
          },
          {
            "description": "`external_id` da pessoa no seu sistema (o mesmo `user.externalId` do widget).",
            "in": "path",
            "name": "person_external_id",
            "required": true,
            "schema": {
              "description": "`external_id` da pessoa no seu sistema (o mesmo `user.externalId` do widget).",
              "maxLength": 255,
              "minLength": 1,
              "title": "Person External Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PersonUpsertIn"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope_PersonUpsertOut_"
                }
              }
            },
            "description": "Successful Response"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "Erro. Use o campo `error` (código estável) na sua lógica."
          }
        },
        "summary": "Cadastra ou atualiza uma pessoa do cliente",
        "tags": [
          "people"
        ],
        "x-errors": [
          "ACCESS_INVALID",
          "CUSTOMER_NOT_FOUND",
          "EXTERNAL_ID_REQUIRED",
          "NAME_REQUIRED",
          "PERSON_CLEAR_FIELD_INVALID",
          "PERSON_CLEAR_NOT_OWN_RECORD",
          "PERSON_CONTACT_OTHER_CUSTOMER",
          "PERSON_DOCUMENT_CONFLICT",
          "PERSON_DOCUMENT_INVALID",
          "PERSON_EMAIL_STAFF",
          "PERSON_EMAIL_TAKEN",
          "PERSON_FIELD_INVALID",
          "PERSON_PHONE_TAKEN",
          "UNKNOWN_PERSON_FIELD"
        ],
        "x-scopes": [
          "customers:write"
        ]
      }
    },
    "/api/v1/integration/customers/{external_id}/products": {
      "get": {
        "operationId": "customers.products.list",
        "parameters": [
          {
            "description": "`external_id` do cliente no seu sistema.",
            "in": "path",
            "name": "external_id",
            "required": true,
            "schema": {
              "description": "`external_id` do cliente no seu sistema.",
              "maxLength": 255,
              "minLength": 1,
              "title": "External Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope_list_ProductRef__"
                }
              }
            },
            "description": "Successful Response"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "Erro. Use o campo `error` (código estável) na sua lógica."
          }
        },
        "summary": "Lista os produtos que o cliente usa",
        "tags": [
          "customers"
        ],
        "x-errors": [
          "CUSTOMER_NOT_FOUND"
        ],
        "x-scopes": [
          "customers:read"
        ]
      }
    },
    "/api/v1/integration/customers/{external_id}/products/{slug}": {
      "delete": {
        "operationId": "customers.products.detach",
        "parameters": [
          {
            "description": "`external_id` do cliente no seu sistema.",
            "in": "path",
            "name": "external_id",
            "required": true,
            "schema": {
              "description": "`external_id` do cliente no seu sistema.",
              "maxLength": 255,
              "minLength": 1,
              "title": "External Id",
              "type": "string"
            }
          },
          {
            "description": "Slug do produto.",
            "in": "path",
            "name": "slug",
            "required": true,
            "schema": {
              "description": "Slug do produto.",
              "pattern": "^[a-z0-9][a-z0-9_-]{1,63}$",
              "title": "Slug",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope_Deleted_"
                }
              }
            },
            "description": "Successful Response"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "Erro. Use o campo `error` (código estável) na sua lógica."
          }
        },
        "summary": "Desvincula um produto do cliente",
        "tags": [
          "customers"
        ],
        "x-errors": [
          "CUSTOMER_NOT_FOUND",
          "PRODUCT_NOT_FOUND",
          "PRODUCT_NOT_LINKED"
        ],
        "x-scopes": [
          "customers:write"
        ]
      },
      "put": {
        "description": "Idempotente: 201 ao vincular, 200 se já estava vinculado. Produto arquivado recusa com `PRODUCT_ARCHIVED` — arquivar encerra o produto e ele não recebe vínculo novo.",
        "operationId": "customers.products.attach",
        "parameters": [
          {
            "description": "`external_id` do cliente no seu sistema.",
            "in": "path",
            "name": "external_id",
            "required": true,
            "schema": {
              "description": "`external_id` do cliente no seu sistema.",
              "maxLength": 255,
              "minLength": 1,
              "title": "External Id",
              "type": "string"
            }
          },
          {
            "description": "Slug do produto.",
            "in": "path",
            "name": "slug",
            "required": true,
            "schema": {
              "description": "Slug do produto.",
              "pattern": "^[a-z0-9][a-z0-9_-]{1,63}$",
              "title": "Slug",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope_ProductRef_"
                }
              }
            },
            "description": "Successful Response"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "Erro. Use o campo `error` (código estável) na sua lógica."
          }
        },
        "summary": "Vincula um produto ao cliente",
        "tags": [
          "customers"
        ],
        "x-errors": [
          "CUSTOMER_NOT_FOUND",
          "PRODUCT_ARCHIVED",
          "PRODUCT_NOT_FOUND"
        ],
        "x-scopes": [
          "customers:write"
        ]
      }
    },
    "/api/v1/integration/kb/articles": {
      "get": {
        "description": "`updated_since` serve para sincronização incremental. Artigos do painel vêm com `external_id` nulo.",
        "operationId": "kb.articles.list",
        "parameters": [
          {
            "description": "Só os artigos deste produto.",
            "in": "query",
            "name": "product",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "pattern": "^[a-z0-9][a-z0-9_-]{1,63}$",
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Só os artigos deste produto.",
              "title": "Product"
            }
          },
          {
            "in": "query",
            "name": "status",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "pattern": "^(draft|published)$",
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Status"
            }
          },
          {
            "description": "Busca no título e no texto.",
            "in": "query",
            "name": "q",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "maxLength": 200,
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Busca no título e no texto.",
              "title": "Q"
            }
          },
          {
            "in": "query",
            "name": "updated_since",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "format": "date-time",
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Updated Since"
            }
          },
          {
            "in": "query",
            "name": "page",
            "required": false,
            "schema": {
              "default": 1,
              "minimum": 1,
              "title": "Page",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "page_size",
            "required": false,
            "schema": {
              "default": 50,
              "maximum": 100,
              "minimum": 1,
              "title": "Page Size",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PageEnvelope_KBArticleSummary_"
                }
              }
            },
            "description": "Successful Response"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "Erro. Use o campo `error` (código estável) na sua lógica."
          }
        },
        "summary": "Lista artigos da base de conhecimento (sem o corpo)",
        "tags": [
          "kb"
        ],
        "x-errors": [
          "PRODUCT_NOT_FOUND"
        ],
        "x-module": "atendimento",
        "x-scopes": [
          "kb:read"
        ]
      }
    },
    "/api/v1/integration/kb/articles/batch": {
      "post": {
        "description": "Cada artigo é processado e salvo por conta própria: um erro não desfaz os outros. Veja `results[].ok` / `results[].error`. Artigo idêntico ao que já existe volta como `unchanged` (não reindexa).",
        "operationId": "kb.articles.batch_upsert",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/KBBatchIn"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope_KBBatchOut_"
                }
              }
            },
            "description": "Successful Response"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "Erro. Use o campo `error` (código estável) na sua lógica."
          }
        },
        "summary": "Cria ou atualiza até 100 artigos de uma vez",
        "tags": [
          "kb"
        ],
        "x-errors": [],
        "x-module": "atendimento",
        "x-scopes": [
          "kb:write"
        ]
      }
    },
    "/api/v1/integration/kb/articles/{external_id}": {
      "delete": {
        "operationId": "kb.articles.delete",
        "parameters": [
          {
            "description": "`external_id` do artigo no seu sistema. Sem `/` — use `:` para hierarquia.",
            "in": "path",
            "name": "external_id",
            "required": true,
            "schema": {
              "description": "`external_id` do artigo no seu sistema. Sem `/` — use `:` para hierarquia.",
              "pattern": "^[A-Za-z0-9][A-Za-z0-9._:~@+=-]{0,199}$",
              "title": "External Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope_Deleted_"
                }
              }
            },
            "description": "Successful Response"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "Erro. Use o campo `error` (código estável) na sua lógica."
          }
        },
        "summary": "Exclui um artigo",
        "tags": [
          "kb"
        ],
        "x-errors": [
          "KB_ARTICLE_NOT_FOUND"
        ],
        "x-module": "atendimento",
        "x-scopes": [
          "kb:write"
        ]
      },
      "get": {
        "operationId": "kb.articles.get",
        "parameters": [
          {
            "description": "`external_id` do artigo no seu sistema. Sem `/` — use `:` para hierarquia.",
            "in": "path",
            "name": "external_id",
            "required": true,
            "schema": {
              "description": "`external_id` do artigo no seu sistema. Sem `/` — use `:` para hierarquia.",
              "pattern": "^[A-Za-z0-9][A-Za-z0-9._:~@+=-]{0,199}$",
              "title": "External Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope_KBArticleOut_"
                }
              }
            },
            "description": "Successful Response"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "Erro. Use o campo `error` (código estável) na sua lógica."
          }
        },
        "summary": "Lê um artigo",
        "tags": [
          "kb"
        ],
        "x-errors": [
          "KB_ARTICLE_NOT_FOUND"
        ],
        "x-module": "atendimento",
        "x-scopes": [
          "kb:read"
        ]
      },
      "put": {
        "description": "Corpo em `body_html` OU `body_markdown`. Só o que vier no corpo muda. `title` é obrigatório ao criar. Com `status: published`, o artigo passa a alimentar o agente de IA. 201 ao criar, 200 ao atualizar.",
        "operationId": "kb.articles.upsert",
        "parameters": [
          {
            "description": "`external_id` do artigo no seu sistema. Sem `/` — use `:` para hierarquia.",
            "in": "path",
            "name": "external_id",
            "required": true,
            "schema": {
              "description": "`external_id` do artigo no seu sistema. Sem `/` — use `:` para hierarquia.",
              "pattern": "^[A-Za-z0-9][A-Za-z0-9._:~@+=-]{0,199}$",
              "title": "External Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/KBArticleUpsert"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope_KBArticleOut_"
                }
              }
            },
            "description": "Successful Response"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "Erro. Use o campo `error` (código estável) na sua lógica."
          }
        },
        "summary": "Cria ou atualiza um artigo",
        "tags": [
          "kb"
        ],
        "x-errors": [
          "BODY_FORMAT_CONFLICT",
          "KB_ARTICLE_CONFLICT",
          "KB_ARTICLE_EMPTY",
          "KB_ARTICLE_TITLE_REQUIRED",
          "PRODUCT_NOT_FOUND"
        ],
        "x-module": "atendimento",
        "x-scopes": [
          "kb:write"
        ]
      }
    },
    "/api/v1/integration/kb/articles/{external_id}/publish": {
      "post": {
        "description": "Idempotente.",
        "operationId": "kb.articles.publish",
        "parameters": [
          {
            "description": "`external_id` do artigo no seu sistema. Sem `/` — use `:` para hierarquia.",
            "in": "path",
            "name": "external_id",
            "required": true,
            "schema": {
              "description": "`external_id` do artigo no seu sistema. Sem `/` — use `:` para hierarquia.",
              "pattern": "^[A-Za-z0-9][A-Za-z0-9._:~@+=-]{0,199}$",
              "title": "External Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope_KBArticleOut_"
                }
              }
            },
            "description": "Successful Response"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "Erro. Use o campo `error` (código estável) na sua lógica."
          }
        },
        "summary": "Publica um artigo (passa a alimentar o agente de IA)",
        "tags": [
          "kb"
        ],
        "x-errors": [
          "KB_ARTICLE_EMPTY",
          "KB_ARTICLE_NOT_FOUND"
        ],
        "x-module": "atendimento",
        "x-scopes": [
          "kb:write"
        ]
      }
    },
    "/api/v1/integration/kb/articles/{external_id}/unpublish": {
      "post": {
        "description": "Idempotente.",
        "operationId": "kb.articles.unpublish",
        "parameters": [
          {
            "description": "`external_id` do artigo no seu sistema. Sem `/` — use `:` para hierarquia.",
            "in": "path",
            "name": "external_id",
            "required": true,
            "schema": {
              "description": "`external_id` do artigo no seu sistema. Sem `/` — use `:` para hierarquia.",
              "pattern": "^[A-Za-z0-9][A-Za-z0-9._:~@+=-]{0,199}$",
              "title": "External Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope_KBArticleOut_"
                }
              }
            },
            "description": "Successful Response"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "Erro. Use o campo `error` (código estável) na sua lógica."
          }
        },
        "summary": "Volta um artigo para rascunho (sai do agente de IA na hora)",
        "tags": [
          "kb"
        ],
        "x-errors": [
          "KB_ARTICLE_NOT_FOUND"
        ],
        "x-module": "atendimento",
        "x-scopes": [
          "kb:write"
        ]
      }
    },
    "/api/v1/integration/kb/search": {
      "get": {
        "description": "Só artigos publicados. Com `product`, os do produto e os que valem para todos.",
        "operationId": "kb.search",
        "parameters": [
          {
            "in": "query",
            "name": "q",
            "required": true,
            "schema": {
              "maxLength": 500,
              "minLength": 1,
              "title": "Q",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "product",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "pattern": "^[a-z0-9][a-z0-9_-]{1,63}$",
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Product"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 5,
              "maximum": 20,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope_list_KBSearchHit__"
                }
              }
            },
            "description": "Successful Response"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "Erro. Use o campo `error` (código estável) na sua lógica."
          }
        },
        "summary": "Busca na base de conhecimento como o agente de IA busca",
        "tags": [
          "kb"
        ],
        "x-errors": [
          "PRODUCT_NOT_FOUND"
        ],
        "x-module": "atendimento",
        "x-scopes": [
          "kb:read"
        ]
      }
    },
    "/api/v1/integration/people/batch": {
      "post": {
        "description": "Para a carga inicial e volumes grandes: até 500 itens por chamada (acima disso, 422 `VALIDATION_ERROR` e nada é gravado). Cada item é independente — um erro não desfaz os outros — e volta em `results` (mesma ordem, com `index`) com `status` `created`, `updated`, `unchanged` ou `error` (código estável em `error`). `summary` conta cada status. Cada item: `customer_external_id` + `person` (com `external_id`). Erros por item: `CUSTOMER_NOT_FOUND`, `EXTERNAL_ID_REQUIRED`, `NAME_REQUIRED`, `UNKNOWN_PERSON_FIELD`, `PERSON_FIELD_INVALID`, `ACCESS_INVALID`, `PERSON_EMAIL_STAFF`, `PERSON_EMAIL_TAKEN`, `PERSON_PHONE_TAKEN`, `PERSON_CONTACT_OTHER_CUSTOMER`, `PERSON_CLEAR_FIELD_INVALID`, `PERSON_CLEAR_NOT_OWN_RECORD`, `PERSON_DOCUMENT_INVALID`, `PERSON_DOCUMENT_CONFLICT`.",
        "operationId": "people.batch",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PeopleBatchIn"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope_BatchOut_"
                }
              }
            },
            "description": "Successful Response"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "Erro. Use o campo `error` (código estável) na sua lógica."
          }
        },
        "summary": "Cadastra ou atualiza até 500 pessoas de uma vez",
        "tags": [
          "people"
        ],
        "x-errors": [],
        "x-scopes": [
          "customers:write"
        ]
      }
    },
    "/api/v1/integration/people/{person_external_id}/identifiers": {
      "get": {
        "description": "Todos os identificadores que apontam para a pessoa: o principal (`external_id`) e os extras. **É a fonte de verdade para reconciliar**: a listagem de pessoas do cliente mostra só o principal, então um identificador que virou extra some de lá sem ter sumido do cadastro. Aceita o principal ou qualquer um dos extras no caminho.",
        "operationId": "people.identifiers.list",
        "parameters": [
          {
            "description": "`external_id` da pessoa no seu sistema (o mesmo `user.externalId` do widget).",
            "in": "path",
            "name": "person_external_id",
            "required": true,
            "schema": {
              "description": "`external_id` da pessoa no seu sistema (o mesmo `user.externalId` do widget).",
              "maxLength": 255,
              "minLength": 1,
              "title": "Person External Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope_PersonIdentifiersOut_"
                }
              }
            },
            "description": "Successful Response"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "Erro. Use o campo `error` (código estável) na sua lógica."
          }
        },
        "summary": "Lista os identificadores da pessoa",
        "tags": [
          "people"
        ],
        "x-errors": [
          "PERSON_NOT_FOUND"
        ],
        "x-scopes": [
          "customers:read"
        ]
      }
    },
    "/api/v1/integration/people/{person_external_id}/identifiers/{extra_id}": {
      "delete": {
        "description": "O identificador deixa de apontar para a pessoa. O principal (`external_id`) não sai por aqui.",
        "operationId": "people.identifiers.remove",
        "parameters": [
          {
            "description": "`external_id` da pessoa no seu sistema (o mesmo `user.externalId` do widget).",
            "in": "path",
            "name": "person_external_id",
            "required": true,
            "schema": {
              "description": "`external_id` da pessoa no seu sistema (o mesmo `user.externalId` do widget).",
              "maxLength": 255,
              "minLength": 1,
              "title": "Person External Id",
              "type": "string"
            }
          },
          {
            "description": "Identificador extra (de outro sistema seu).",
            "in": "path",
            "name": "extra_id",
            "required": true,
            "schema": {
              "description": "Identificador extra (de outro sistema seu).",
              "maxLength": 255,
              "minLength": 1,
              "title": "Extra Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope_PersonIdentifiersOut_"
                }
              }
            },
            "description": "Successful Response"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "Erro. Use o campo `error` (código estável) na sua lógica."
          }
        },
        "summary": "Desliga um identificador extra da pessoa",
        "tags": [
          "people"
        ],
        "x-errors": [
          "IDENTIFIER_NOT_FOUND",
          "PERSON_NOT_FOUND"
        ],
        "x-scopes": [
          "customers:write"
        ]
      },
      "put": {
        "description": "Liga um identificador de outro sistema seu ao mesmo cadastro: depois disso, qualquer rota (e o widget) aceita os dois. Idempotente — já ligado a este cadastro, nada muda (200). Ligado a OUTRO cadastro: 409 `IDENTIFIER_IN_USE`, com o dono em `data.owner`.",
        "operationId": "people.identifiers.add",
        "parameters": [
          {
            "description": "`external_id` da pessoa no seu sistema (o mesmo `user.externalId` do widget).",
            "in": "path",
            "name": "person_external_id",
            "required": true,
            "schema": {
              "description": "`external_id` da pessoa no seu sistema (o mesmo `user.externalId` do widget).",
              "maxLength": 255,
              "minLength": 1,
              "title": "Person External Id",
              "type": "string"
            }
          },
          {
            "description": "Identificador extra (de outro sistema seu).",
            "in": "path",
            "name": "extra_id",
            "required": true,
            "schema": {
              "description": "Identificador extra (de outro sistema seu).",
              "maxLength": 255,
              "minLength": 1,
              "title": "Extra Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/IdentifierLabelIn"
                  },
                  {
                    "type": "null"
                  }
                ],
                "title": "Body"
              }
            }
          }
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope_PersonIdentifiersOut_"
                }
              }
            },
            "description": "Successful Response"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "Erro. Use o campo `error` (código estável) na sua lógica."
          }
        },
        "summary": "Liga um identificador extra à pessoa",
        "tags": [
          "people"
        ],
        "x-errors": [
          "IDENTIFIER_IN_USE",
          "PERSON_NOT_FOUND"
        ],
        "x-scopes": [
          "customers:write"
        ]
      }
    },
    "/api/v1/integration/products": {
      "get": {
        "operationId": "products.list",
        "parameters": [
          {
            "description": "Inclui os arquivados.",
            "in": "query",
            "name": "include_inactive",
            "required": false,
            "schema": {
              "default": false,
              "description": "Inclui os arquivados.",
              "title": "Include Inactive",
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope_list_ProductOut__"
                }
              }
            },
            "description": "Successful Response"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "Erro. Use o campo `error` (código estável) na sua lógica."
          }
        },
        "summary": "Lista o catálogo de produtos",
        "tags": [
          "products"
        ],
        "x-errors": [],
        "x-scopes": [
          "products:read"
        ]
      }
    },
    "/api/v1/integration/products/{slug}": {
      "delete": {
        "description": "Não apaga: marca `is_active=false` e mantém as referências (chamados, clientes, release notes). **Encerra o produto**: ele deixa de aceitar vínculo novo de cliente, nota de novidade e agente de monitoramento, é desvinculado dos atendentes, tem as conversas abertas fechadas e sai do changelog público.",
        "operationId": "products.archive",
        "parameters": [
          {
            "description": "Slug do produto (minúsculas, números, `-` e `_`).",
            "in": "path",
            "name": "slug",
            "required": true,
            "schema": {
              "description": "Slug do produto (minúsculas, números, `-` e `_`).",
              "pattern": "^[a-z0-9][a-z0-9_-]{1,63}$",
              "title": "Slug",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope_ProductOut_"
                }
              }
            },
            "description": "Successful Response"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "Erro. Use o campo `error` (código estável) na sua lógica."
          }
        },
        "summary": "Arquiva um produto",
        "tags": [
          "products"
        ],
        "x-errors": [
          "PRODUCT_NOT_FOUND"
        ],
        "x-scopes": [
          "products:write"
        ]
      },
      "get": {
        "operationId": "products.get",
        "parameters": [
          {
            "description": "Slug do produto (minúsculas, números, `-` e `_`).",
            "in": "path",
            "name": "slug",
            "required": true,
            "schema": {
              "description": "Slug do produto (minúsculas, números, `-` e `_`).",
              "pattern": "^[a-z0-9][a-z0-9_-]{1,63}$",
              "title": "Slug",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope_ProductOut_"
                }
              }
            },
            "description": "Successful Response"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "Erro. Use o campo `error` (código estável) na sua lógica."
          }
        },
        "summary": "Lê um produto",
        "tags": [
          "products"
        ],
        "x-errors": [
          "PRODUCT_NOT_FOUND"
        ],
        "x-scopes": [
          "products:read"
        ]
      },
      "put": {
        "description": "Só o que vier no corpo muda. `name` é obrigatório ao criar. 201 ao criar, 200 ao atualizar.",
        "operationId": "products.upsert",
        "parameters": [
          {
            "description": "Slug do produto (minúsculas, números, `-` e `_`).",
            "in": "path",
            "name": "slug",
            "required": true,
            "schema": {
              "description": "Slug do produto (minúsculas, números, `-` e `_`).",
              "pattern": "^[a-z0-9][a-z0-9_-]{1,63}$",
              "title": "Slug",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProductUpsert"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope_ProductOut_"
                }
              }
            },
            "description": "Successful Response"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "Erro. Use o campo `error` (código estável) na sua lógica."
          }
        },
        "summary": "Cadastra ou atualiza um produto",
        "tags": [
          "products"
        ],
        "x-errors": [
          "PRODUCT_NAME_REQUIRED",
          "PRODUCT_SLUG_TAKEN"
        ],
        "x-scopes": [
          "products:write"
        ]
      }
    },
    "/api/v1/integration/products/{slug}/release-notes": {
      "get": {
        "operationId": "release_notes.list",
        "parameters": [
          {
            "description": "Slug do produto (minúsculas, números, `-` e `_`).",
            "in": "path",
            "name": "slug",
            "required": true,
            "schema": {
              "description": "Slug do produto (minúsculas, números, `-` e `_`).",
              "pattern": "^[a-z0-9][a-z0-9_-]{1,63}$",
              "title": "Slug",
              "type": "string"
            }
          },
          {
            "description": "Filtra publicadas (`true`) ou rascunhos (`false`).",
            "in": "query",
            "name": "published",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "boolean"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Filtra publicadas (`true`) ou rascunhos (`false`).",
              "title": "Published"
            }
          },
          {
            "in": "query",
            "name": "page",
            "required": false,
            "schema": {
              "default": 1,
              "minimum": 1,
              "title": "Page",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "page_size",
            "required": false,
            "schema": {
              "default": 50,
              "maximum": 200,
              "minimum": 1,
              "title": "Page Size",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PageEnvelope_ReleaseNoteOut_"
                }
              }
            },
            "description": "Successful Response"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "Erro. Use o campo `error` (código estável) na sua lógica."
          }
        },
        "summary": "Lista as release notes do produto (mais recentes primeiro)",
        "tags": [
          "release_notes"
        ],
        "x-errors": [
          "PRODUCT_NOT_FOUND"
        ],
        "x-scopes": [
          "release_notes:read"
        ]
      }
    },
    "/api/v1/integration/products/{slug}/release-notes/{version}": {
      "get": {
        "operationId": "release_notes.get",
        "parameters": [
          {
            "description": "Slug do produto (minúsculas, números, `-` e `_`).",
            "in": "path",
            "name": "slug",
            "required": true,
            "schema": {
              "description": "Slug do produto (minúsculas, números, `-` e `_`).",
              "pattern": "^[a-z0-9][a-z0-9_-]{1,63}$",
              "title": "Slug",
              "type": "string"
            }
          },
          {
            "description": "Versão SemVer `X.Y.Z` (aceita `v` na frente).",
            "in": "path",
            "name": "version",
            "required": true,
            "schema": {
              "description": "Versão SemVer `X.Y.Z` (aceita `v` na frente).",
              "pattern": "^[vV]?\\d+\\.\\d+\\.\\d+$",
              "title": "Version",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope_ReleaseNoteOut_"
                }
              }
            },
            "description": "Successful Response"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "Erro. Use o campo `error` (código estável) na sua lógica."
          }
        },
        "summary": "Lê uma release note",
        "tags": [
          "release_notes"
        ],
        "x-errors": [
          "PRODUCT_NOT_FOUND",
          "RELEASE_NOTE_NOT_FOUND"
        ],
        "x-scopes": [
          "release_notes:read"
        ]
      },
      "put": {
        "description": "Idempotente por produto + versão — feito para rodar no CI a cada deploy. `title` e a descrição são obrigatórios ao criar. Com `publish: true`, publica (atualiza a versão do produto e notifica). 201 ao criar, 200 ao atualizar.",
        "operationId": "release_notes.upsert",
        "parameters": [
          {
            "description": "Slug do produto (minúsculas, números, `-` e `_`).",
            "in": "path",
            "name": "slug",
            "required": true,
            "schema": {
              "description": "Slug do produto (minúsculas, números, `-` e `_`).",
              "pattern": "^[a-z0-9][a-z0-9_-]{1,63}$",
              "title": "Slug",
              "type": "string"
            }
          },
          {
            "description": "Versão SemVer `X.Y.Z` (aceita `v` na frente).",
            "in": "path",
            "name": "version",
            "required": true,
            "schema": {
              "description": "Versão SemVer `X.Y.Z` (aceita `v` na frente).",
              "pattern": "^[vV]?\\d+\\.\\d+\\.\\d+$",
              "title": "Version",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReleaseNoteUpsert"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope_ReleaseNoteOut_"
                }
              }
            },
            "description": "Successful Response"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "Erro. Use o campo `error` (código estável) na sua lógica."
          }
        },
        "summary": "Cria ou atualiza a release note de uma versão",
        "tags": [
          "release_notes"
        ],
        "x-errors": [
          "BODY_FORMAT_CONFLICT",
          "PRODUCT_NOT_FOUND",
          "RELEASE_NOTE_DESCRIPTION_REQUIRED",
          "RELEASE_NOTE_TITLE_REQUIRED"
        ],
        "x-scopes": [
          "release_notes:write"
        ]
      }
    },
    "/api/v1/integration/products/{slug}/release-notes/{version}/publish": {
      "post": {
        "description": "Idempotente: já publicada devolve 200 sem notificar de novo.",
        "operationId": "release_notes.publish",
        "parameters": [
          {
            "description": "Slug do produto (minúsculas, números, `-` e `_`).",
            "in": "path",
            "name": "slug",
            "required": true,
            "schema": {
              "description": "Slug do produto (minúsculas, números, `-` e `_`).",
              "pattern": "^[a-z0-9][a-z0-9_-]{1,63}$",
              "title": "Slug",
              "type": "string"
            }
          },
          {
            "description": "Versão SemVer `X.Y.Z` (aceita `v` na frente).",
            "in": "path",
            "name": "version",
            "required": true,
            "schema": {
              "description": "Versão SemVer `X.Y.Z` (aceita `v` na frente).",
              "pattern": "^[vV]?\\d+\\.\\d+\\.\\d+$",
              "title": "Version",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope_ReleaseNoteOut_"
                }
              }
            },
            "description": "Successful Response"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "Erro. Use o campo `error` (código estável) na sua lógica."
          }
        },
        "summary": "Publica uma release note",
        "tags": [
          "release_notes"
        ],
        "x-errors": [
          "PRODUCT_NOT_FOUND",
          "RELEASE_NOTE_NOT_FOUND"
        ],
        "x-scopes": [
          "release_notes:write"
        ]
      }
    },
    "/api/v1/integration/products/{slug}/roles": {
      "get": {
        "operationId": "products.roles.list",
        "parameters": [
          {
            "description": "Slug do produto (minúsculas, números, `-` e `_`).",
            "in": "path",
            "name": "slug",
            "required": true,
            "schema": {
              "description": "Slug do produto (minúsculas, números, `-` e `_`).",
              "pattern": "^[a-z0-9][a-z0-9_-]{1,63}$",
              "title": "Slug",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope_list_ProductRoleOut__"
                }
              }
            },
            "description": "Successful Response"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "Erro. Use o campo `error` (código estável) na sua lógica."
          }
        },
        "summary": "Lista os papéis de um produto",
        "tags": [
          "products"
        ],
        "x-errors": [
          "PRODUCT_NOT_FOUND"
        ],
        "x-scopes": [
          "products:read"
        ]
      }
    },
    "/api/v1/integration/products/{slug}/roles/{key}": {
      "delete": {
        "description": "As pessoas vinculadas perdem o papel e as novidades dirigidas a ele voltam a valer para todos. Se a sua página continuar declarando esta `key`, o papel é cadastrado de novo na próxima sessão do widget.",
        "operationId": "products.roles.delete",
        "parameters": [
          {
            "description": "Slug do produto (minúsculas, números, `-` e `_`).",
            "in": "path",
            "name": "slug",
            "required": true,
            "schema": {
              "description": "Slug do produto (minúsculas, números, `-` e `_`).",
              "pattern": "^[a-z0-9][a-z0-9_-]{1,63}$",
              "title": "Slug",
              "type": "string"
            }
          },
          {
            "description": "Identificador do papel (minúsculas, números, `-` e `_`).",
            "in": "path",
            "name": "key",
            "required": true,
            "schema": {
              "description": "Identificador do papel (minúsculas, números, `-` e `_`).",
              "pattern": "^[a-z0-9][a-z0-9_-]{1,63}$",
              "title": "Key",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope_ProductRoleOut_"
                }
              }
            },
            "description": "Successful Response"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "Erro. Use o campo `error` (código estável) na sua lógica."
          }
        },
        "summary": "Apaga um papel do produto",
        "tags": [
          "products"
        ],
        "x-errors": [
          "PRODUCT_ROLE_NOT_FOUND"
        ],
        "x-scopes": [
          "products:write"
        ]
      },
      "put": {
        "description": "Idempotente: pode rodar a cada deploy. Só o que vier no corpo muda; string vazia limpa uma instrução. 201 ao criar, 200 ao atualizar.",
        "operationId": "products.roles.upsert",
        "parameters": [
          {
            "description": "Slug do produto (minúsculas, números, `-` e `_`).",
            "in": "path",
            "name": "slug",
            "required": true,
            "schema": {
              "description": "Slug do produto (minúsculas, números, `-` e `_`).",
              "pattern": "^[a-z0-9][a-z0-9_-]{1,63}$",
              "title": "Slug",
              "type": "string"
            }
          },
          {
            "description": "Identificador do papel (minúsculas, números, `-` e `_`).",
            "in": "path",
            "name": "key",
            "required": true,
            "schema": {
              "description": "Identificador do papel (minúsculas, números, `-` e `_`).",
              "pattern": "^[a-z0-9][a-z0-9_-]{1,63}$",
              "title": "Key",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProductRoleUpsert"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope_ProductRoleOut_"
                }
              }
            },
            "description": "Successful Response"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            },
            "description": "Erro. Use o campo `error` (código estável) na sua lógica."
          }
        },
        "summary": "Cadastra ou atualiza um papel do produto",
        "tags": [
          "products"
        ],
        "x-errors": [
          "PRODUCT_NOT_FOUND"
        ],
        "x-scopes": [
          "products:write"
        ]
      }
    }
  },
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "servers": [
    {
      "description": "Produção",
      "url": "https://api.bfocus.com.br"
    }
  ],
  "tags": [
    {
      "description": "Agentes de IA de atendimento (leitura e teste de resposta).",
      "name": "ai_agents"
    },
    {
      "description": "Clientes do seu sistema (ERP), identificados pelo seu `external_id`, com contatos, produtos e interações.",
      "name": "customers"
    },
    {
      "description": "Base de conhecimento que alimenta os agentes de IA.",
      "name": "kb"
    },
    {
      "description": "Pessoas dos clientes (quem usa o seu sistema e abre chamados/conversas), identificadas pelo seu `external_id`.",
      "name": "people"
    },
    {
      "description": "Catálogo de produtos, identificados pelo `slug`.",
      "name": "products"
    },
    {
      "description": "Release notes por produto e versão — idempotentes para rodar no CI.",
      "name": "release_notes"
    }
  ],
  "x-common-errors": {
    "IDEMPOTENCY_IN_PROGRESS": "409 — a requisição original com esta chave ainda está rodando",
    "IDEMPOTENCY_KEY_INVALID": "422 — `Idempotency-Key` vazia ou com mais de 255 caracteres",
    "IDEMPOTENCY_KEY_REUSED": "422 — a mesma `Idempotency-Key` com outra requisição",
    "INTEGRATION_DISABLED": "403 — chave desligada no painel",
    "INTEGRATION_HOST_FORBIDDEN": "403 — o IP de origem não está na lista de IPs liberados da chave",
    "INTEGRATION_KEY_INVALID": "401 — chave desconhecida",
    "INTEGRATION_KEY_MISSING": "401 — faltou `Authorization: Bearer <chave>`",
    "INTEGRATION_KEY_REVOKED": "401 — chave revogada",
    "INTEGRATION_SCOPE_MISSING": "403 — a chave não tem o escopo da operação (header `X-Required-Scope`)",
    "INTERNAL_ERROR": "500 — erro interno (informe o `request_id`)",
    "MODULE_NOT_CONTRACTED": "403 — a empresa não contratou o módulo da operação (header `X-Required-Module`; ver `x-module`)",
    "RATE_LIMITED": "429 — limite de requisições da chave (header `Retry-After`)",
    "TENANT_NOT_FOUND": "404 — conta inativa",
    "VALIDATION_ERROR": "422 — corpo ou parâmetro inválido (detalhe em `validation`)"
  },
  "x-scopes": {
    "ai_agents:preview": "Testar a resposta de um agente de IA (consome IA do tenant)",
    "ai_agents:read": "Ler os agentes de IA",
    "customers:read": "Ler clientes, contatos, pessoas, produtos vinculados e interações",
    "customers:write": "Cadastrar, atualizar e excluir clientes, contatos, pessoas, identificadores extras e interações",
    "kb:read": "Ler e buscar artigos da base de conhecimento",
    "kb:write": "Criar, atualizar, publicar e excluir artigos da base de conhecimento",
    "monitor:read": "Ler os erros capturados pelo Monitoramento (resumo, lista e detalhe com ocorrências)",
    "monitor:write": "Agir nos erros do Monitoramento: resolver, ignorar, juntar, investigar e abrir demanda",
    "products:read": "Ler o catálogo de produtos",
    "products:write": "Cadastrar, atualizar e arquivar produtos",
    "projects:read": "Ler projetos, a situação deles e a leitura do radar de risco",
    "release_notes:read": "Ler release notes",
    "release_notes:write": "Criar, atualizar e publicar release notes",
    "tasks:read": "Ler tarefas e a conversa delas",
    "tasks:write": "Comentar em tarefas e mudar status, prioridade, responsável e prazo",
    "tickets:read": "Ler chamados e a conversa deles",
    "tickets:write": "Comentar em chamados e mudar status, prioridade e responsável",
    "widget:sign": "Assinar a identidade do usuário do widget (sem guardar segredo no seu servidor)"
  }
}
