# Mapeamento da API Z-PRO — pasta "Agendamentos e Lembretes" > Este documento contém **apenas** informações verificadas diretamente na > coleção pública do Postman em > https://www.postman.com/comunidade-zdg/z-pro/folder/ktt2uon/agendamentos-e-lembretes > (coleção "Z-PRO v4.x.x.x", pasta "📅 Agendamentos e Lembretes"). > Nenhum valor de token, header sensível ou segredo real foi copiado. > > **Status: análise incompleta.** A integração real (`ZProAdapter`) **não foi > implementada** nesta etapa porque partes essenciais do contrato não estão > disponíveis na coleção. Veja a seção "O que não foi possível verificar". ## Itens existentes na pasta A pasta contém 10 requests. Apenas os relacionados ao escopo atual (consultar agendamentos / criar agendamento) foram analisados em detalhe; os demais foram apenas identificados para não serem confundidos com o escopo. | Nome | Método | Path | No escopo atual? | | ---------------------- | ------ | ----------------------------------------------------------- | ------------------------------------------------------------------------------------ | | AppointmentCreate | POST | `/v2/api/external/{{ApiID}}/appointment/create` | ✅ sim | | AppointmentList | GET | `/v2/api/external/{{ApiID}}/appointment/list` | ✅ sim (única consulta existente — ver ressalva abaixo) | | AppointmentShow | GET | `/v2/api/external/{{ApiID}}/appointment/show/{{id}}` | fora do escopo pedido (não é "consultar horários/agendamentos disponíveis" em lista) | | AppointmentUpdate | POST | `/v2/api/external/{{ApiID}}/appointment/update/{{id}}` | ❌ não (remarcação — explicitamente fora do escopo) | | AppointmentDelete | POST | `/v2/api/external/{{ApiID}}/appointment/delete/{{id}}` | ❌ não (cancelamento — explicitamente fora do escopo) | | ScheduleReminderCreate | POST | `/v2/api/external/{{ApiID}}/scheduleReminder/create` | ❌ não (lembretes — explicitamente fora do escopo) | | ScheduleReminderList | GET | `/v2/api/external/{{ApiID}}/scheduleReminder/list` | ❌ não | | ScheduleReminderToggle | POST | `/v2/api/external/{{ApiID}}/scheduleReminder/toggle/{{id}}` | ❌ não | | ScheduleReminderUpdate | POST | `/v2/api/external/{{ApiID}}/scheduleReminder/update/{{id}}` | ❌ não | | ScheduleReminderDelete | POST | `/v2/api/external/{{ApiID}}/scheduleReminder/delete/{{id}}` | ❌ não | **Ressalva importante:** a pasta **não possui nenhum endpoint de "horários disponíveis"** (busca de vagas livres/slots). O único endpoint de consulta relacionado a agendamentos é `AppointmentList`, que **lista agendamentos já existentes** (filtráveis por status `pending | confirmed | cancelled | completed`), não horários livres para agendar. Ver detalhes na seção de ambiguidades. ## Autenticação - Tipo: **Bearer Token** (`auth.type = "bearer"`), definido tanto no nível da coleção quanto em cada request individual. - O token é enviado automaticamente pelo Postman no header `Authorization: Bearer `. - Variável de coleção que armazena o token: `BearerToken` (valor de exemplo na coleção: `your_token_here` — placeholder, não é um token real). - Não há chave de API adicional em header (ex.: `X-API-Key`) documentada nestes requests — apenas o Bearer token. ## Variáveis de coleção relevantes | Variável | Uso verificado | | ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `BaseUrl` | Host base da API (ex.: `https://{{BaseUrl}}/v2/api/external/...`) | | `ApiID` | Segmento obrigatório da URL em **todos** os endpoints desta pasta: `/v2/api/external/{{ApiID}}/...`. Não há descrição do que ele representa (ex.: id da instância/empresa) além do nome da variável. | | `BearerToken` | Token usado na autenticação Bearer | | `SuperAdminToken` | Não utilizado em nenhum request desta pasta | **Achado relevante para configuração:** o `ApiID` é parte obrigatória da URL de todo endpoint. A configuração atual do projeto (`src/config/config.types.ts`, `src/config/env.config.ts`) já prevê `ZPRO_INSTANCE_ID` como **opcional**. Se `ApiID` corresponder a esse campo, ele precisa passar a ser **obrigatório** — mas isso não deve ser alterado sem confirmação, pois não há descrição na coleção que confirme a equivalência semântica entre `ApiID` e "instância". ## AppointmentCreate (criar agendamento) - Método: `POST` - URL: `https://{{BaseUrl}}/v2/api/external/{{ApiID}}/appointment/create` - Auth: Bearer (herdado da coleção) - Headers explícitos no request: nenhum além dos automáticos do Postman (Bearer + `Content-Type: application/json`, implícito pelo modo de body `raw`/`json`) - Query params: nenhum - Corpo da requisição (JSON, `dataMode: raw`, exemplo salvo na coleção): ```json { "title": "Reunião de Vendas", "description": "Reunião sobre proposta comercial", "contactId": "{{contactId}}", "contactName": "João Silva", "contactPhone": "5511999999999", "whatsappId": "{{whatsappId}}", "startAt": "2026-04-15T14:00:00.000Z", "endAt": "2026-04-15T15:00:00.000Z", "status": "pending", "notes": "Levar proposta impressa" } ``` - Campos identificados no exemplo: `title`, `description`, `contactId`, `contactName`, `contactPhone`, `whatsappId`, `startAt`, `endAt`, `status`, `notes`. - **Não há indicação, na coleção, de quais desses campos são obrigatórios versus opcionais** (o Postman não declara isso fora do exemplo). - Formato de sucesso, formato de erro e o campo que identifica o agendamento criado (`id`, `_id`, `appointment.id`, etc.): **não verificados** — não há nenhuma resposta de exemplo salva neste request na coleção (`responses_order: []`). ## AppointmentList (única consulta existente no escopo) - Método: `GET` - URL: `https://{{BaseUrl}}/v2/api/external/{{ApiID}}/appointment/list` - Auth: Bearer (herdado da coleção) - Query params verificados: | Parâmetro | Exemplo | Habilitado por padrão | Descrição na coleção | | ----------- | -------------------------- | --------------------- | --------------------------------------------------- | | `page` | `1` | sim | — | | `limit` | `20` | sim | — | | `status` | `pending` | sim | `pending \| confirmed \| cancelled \| completed` | | `startFrom` | `2026-04-01T00:00:00.000Z` | **não** (disabled) | Filtrar agendamentos a partir desta data (ISO 8601) | | `startTo` | `2026-04-30T23:59:59.000Z` | **não** (disabled) | Filtrar agendamentos até esta data (ISO 8601) | | `search` | `""` | **não** (disabled) | Busca por título ou nome do contato | - Corpo da requisição: nenhum (GET). - Formato de sucesso (envelope, paginação, forma de cada item da lista) e formato de erro: **não verificados** — sem resposta de exemplo salva. ## O que não foi possível verificar 1. **Formato de sucesso de qualquer endpoint** (envelope da resposta, nomes de campos, se há paginação e como ela é representada). 2. **Formato de erro de qualquer endpoint** (estrutura do corpo de erro, nomes de campos como `message`/`error`/`code`). 3. **Identificador retornado após a criação** do agendamento (nome do campo, ex.: `id` vs `_id` vs `appointment.id`). 4. **Conceito de "horário disponível"**: a pasta não expõe nenhum endpoint de disponibilidade/slots livres. `AppointmentList` lista agendamentos já existentes (ocupados), não horários livres. Não é seguro tratar a ausência de um agendamento como "horário disponível" — isso seria inventar uma regra de negócio não documentada. 5. **Relação entre `slotId` (tipo genérico do projeto, `CreateAppointmentInput.slotId`) e a API Z-PRO**: `AppointmentCreate` não recebe um identificador de horário/slot — o agendamento é criado diretamente por `startAt`/`endAt`. Não há, na coleção, nenhum conceito de "slot" com identificador próprio. 6. **Campos obrigatórios vs. opcionais** no corpo de `AppointmentCreate` (a coleção só mostra um exemplo, sem schema declarado). 7. **Semântica exata de `ApiID`** (é o identificador da instância? da empresa? do WhatsApp conectado?) — não há descrição na coleção. ## O que é necessário para prosseguir com a integração real Qualquer um dos itens abaixo destravaria a implementação: - Um **exemplo de resposta salvo** (Postman "Save Response" / "Add Example") para `AppointmentCreate` (sucesso e, se possível, erro) e para `AppointmentList` (sucesso). - Confirmação explícita de que **não existe** endpoint de horários/slots disponíveis na API Z-PRO (para então documentar oficialmente que `consultarHorarios()` não tem correspondência 1:1 e decidir, com o responsável do produto, qual comportamento é aceitável — por exemplo, reinterpretar o escopo, ou aguardar um endpoint futuro). - Documentação (Swagger/OpenAPI, README da API, ou outra coleção) que descreva o schema de resposta dos dois endpoints. - Confirmação do significado e da obrigatoriedade de `ApiID`. ## Decisão tomada nesta etapa Como os contratos de resposta não puderam ser verificados, o `ZProAdapter` **não foi alterado** — permanece lançando `Not implemented`, exatamente como estava antes desta análise, para não implementar por suposição. `npm run build`, `npm run lint` e `npm test` continuam passando sem alterações de código. ## Atualização — resposta real de sucesso capturada (teste manual controlado) Em 09/08/2026, foi executado um teste manual único e controlado de `POST /v2/api/external/{ApiID}/appointment/create`, contra uma instância real do Z-PRO, com dados fictícios (`TESTE-MCP-2026-04-20-001`). O agendamento foi criado de fato (confirmado visualmente na interface do Z-PRO) e a resposta HTTP foi capturada: - **Content-Type**: `application/json; charset=utf-8` - **Corpo bruto** (dados fictícios, sem nenhuma credencial): ```json { "success": true, "data": { "source": "manual", "checkInStatus": "none", "id": 2, "title": "TESTE-MCP-2026-04-20-001", "description": null, "contactId": null, "contactName": "Paciente Teste MCP", "contactPhone": "5511900000000", "whatsappId": null, "tenantId": 4, "startAt": "2026-04-20T14:00:00.000Z", "endAt": "2026-04-20T14:30:00.000Z", "status": "pending", "notes": null, "updatedAt": "2026-08-09T20:32:06.426Z", "createdAt": "2026-08-09T20:32:06.426Z", "bookingPageId": null, "bookingEventTypeId": null, "bookingProfessionalId": null, "userId": null, "location": null, "meetingLink": null, "formAnswers": null, "cancelToken": null, "googleEventId": null, "checkInSentAt": null } } ``` **O que isso confirma:** - Envelope de sucesso: `{ success: boolean, data: {...} }`. - Identificador do agendamento criado: `data.id`, **numérico** (não `_id`, não `appointment.id`). - `data.status` reflete o mesmo valor enviado na requisição (`"pending"`) — **não temos, ainda, um exemplo real de `"confirmed"` ou `"cancelled"` retornados pela API**; o mapeamento desses dois valores no `ZProAdapter` é feito por analogia com o valor documentado no request (`AppointmentList`'s filtro de `status`), não por observação direta. - `data.startAt`/`data.endAt` são ecoados exatamente como enviados. - `data.contactId` continua `null` quando não enviado no request (não inventa um contato). **O que continua não verificado:** o formato de erro (4xx/5xx) do endpoint (esse teste só cobriu o caminho de sucesso), e os valores reais de `data.status` para `"confirmed"`/`"cancelled"`. O `ZProAdapter` continua tratando **qualquer HTTP 2xx** como sucesso mesmo que o corpo não bata com este envelope exato (ver `zpro.mapper.ts`), como proteção contra duplicidade caso a API mude de formato em algum caso não coberto por este teste único.