﻿# Contrato genérico da API

## Descoberta para agentes

Agentes e automacoes podem descobrir este contrato em:

```http
GET /api/agents/manifest
Authorization: Bearer SUA_API_KEY
```

O manifesto retorna o endpoint recomendado, campos obrigatorios, exemplos e status de erro esperados.

## Endpoint

```http
POST /api/messages
Authorization: Bearer SUA_API_KEY
Content-Type: application/json
```

## Estrutura do request

```json
{
  "actor": {
    "id": "lead-42",
    "type": "lead",
    "name": "Maria"
  },
  "conversation": {
    "id": "site-chat:lead-42",
    "channel": "web"
  },
  "message": {
    "text": "Quero um orçamento",
    "direction": "inbound"
  },
  "metadata": {
    "source": "landing-widget",
    "locale": "pt-BR"
  },
  "context": [
    "Página: /precos",
    "Campanha: ads-maio"
  ]
}
```

## Campos obrigatórios

- `actor.id`
- `conversation.id`
- `message.text`

## Campos opcionais

- `actor.type`
- `actor.name`
- `conversation.channel`
- `message.direction`
- `metadata`
- `context`
- `provider` — escolhe o cerebro de IA: `chatgpt` (padrao) ou `deepseek`. Use
  `deepseek` para rotear esta conversa para o DeepSeek web. Se o DeepSeek nao
  estiver habilitado no servidor, a chamada retorna `503`.

## Selecao de provider (ChatGPT x DeepSeek)

O campo opcional `provider` no topo do body define qual IA responde:

```json
{
  "actor": { "id": "lead-42", "type": "lead", "name": "Maria" },
  "conversation": { "id": "site-chat:lead-42", "channel": "web" },
  "message": { "text": "Quero um orçamento" },
  "provider": "deepseek"
}
```

- `provider` ausente ou `"chatgpt"` → ChatGPT (comportamento padrao, via openai-oauth — sem scraping de navegador).
- `provider: "deepseek"` → DeepSeek web (texto-only).

A memoria por conversa continua valendo igual nos dois: mantenha `actor.id` e
`conversation.id` estaveis. O `provider` pode variar por mensagem, mas trocar de
provider no meio de uma conversa reinicia o contexto do lado do provedor (o
historico montado no prompt e preservado).

## Como pensar no contrato

- `actor` identifica quem está falando
- `conversation` identifica onde essa mensagem pertence
- `message` contém o texto atual

O `conversation_id` é o identificador público da conversa.

O `thread_id` continua existindo para log, rastreio e compatibilidade interna.

## Exemplo de resposta

```json
{
  "reply": "Posso te ajudar com isso.",
  "conversation_id": "site-chat:lead-42",
  "thread_id": "conversation:web:site-chat:lead-42",
  "channel": "web",
  "actor_id": "lead-42",
  "credits_remaining": 123,
  "elapsed": 1.2,
  "status": "answered"
}
```

## Boas práticas

- mantenha `actor.id` estável para a mesma pessoa
- mantenha `conversation.id` estável para a mesma conversa
- envie apenas texto limpo em `message.text`
- use `metadata` para dados auxiliares do canal
- use `reply` como texto final devolvido ao usuário

## Compatibilidade

Se o seu fluxo ainda é explicitamente WhatsApp, você pode continuar usando:

```http
POST /api/whatsapp/message
```

Mas o contrato genérico novo em `/api/messages` deve ser a base para novas integrações.
