# Agenda

> Agendas, horários livres, compromissos e bloqueios.

Leitura usa `agenda:ler` e escrita usa `agenda:escrever`. A API segue as mesmas regras do app e do agente de IA: horário de trabalho, bloqueios, intervalo e antecedência mínima. O módulo Agenda precisa estar no plano; se o plano perder o módulo, a chave deixa de funcionar na hora.

- Datas e horas sempre com o fuso, como `2026-10-12T14:00:00-03:00` (ou `Z`). Sem o deslocamento a API recusa, nunca chuta o fuso. As respostas trazem `inicio` e `fim` em UTC e `inicio_local` e `fim_local` no fuso da agenda.
- Veja os horários livres em [`GET /disponibilidade`](https://docs.forsi.com.br/api/agenda/disponibilidade) (janela de até 62 dias) e marque em [`POST /compromissos`](https://docs.forsi.com.br/api/agenda/criar-compromisso). Duas chamadas ao mesmo tempo para o mesmo horário: uma marca e a outra recebe `409 horario_ocupado`, mesmo com muitas chamadas em paralelo.
- Sem `agenda_id`, o compromisso vai para a primeira agenda com o horário livre. O contato vem de `contato_id`, `conversa_id` ou `telefone` (só um deles). Pelo telefone, o contato é criado se ainda não existir.
- Duração: mande `fim` ou `duracao_min`; sem nenhum, vale a duração padrão da agenda.
- Remarcar, cancelar e confirmar têm rota própria. Compromisso cancelado não volta: marque um novo. Cancelar duas vezes é seguro. `PATCH` marca presença (`estado`: `concluido` ou `faltou`) e edita título, local, link e notas.
- Eventos de webhook: `agendamento.criado`, `agendamento.remarcado` (traz também `anterior`), `agendamento.cancelado` e `agendamento.confirmado`. Disparam para qualquer origem: app, agente de IA ou API.
- Fora da API de propósito: apagar agenda, apagar compromisso (só cancelar), encaixe fora do horário, operações em massa e trocar o profissional de uma agenda. Apagar bloqueio existe, um por chamada.
- Não existe cadastro de serviços: cada agenda tem a sua duração padrão (`duracao_min`).

```json title="Com contato que já existe e fim explícito"
{
  "agenda_id": "f7233bb7-10b6-49d2-aa3b-8c2e7d88064d",
  "inicio": "2026-10-12T14:00:00-03:00",
  "fim": "2026-10-12T14:45:00-03:00",
  "contato_id": "08054a7f-a752-481e-9915-cf4cf944df39",
  "titulo": "Avaliação",
  "local": "Rua das Flores, 120 - sala 4"
}
```

**Códigos de erro comuns aqui**: `horario_invalido`, `janela_grande`, `duracao_invalida`, `campo_longo`, `campo_invalido`, `link_invalido`, `contato_ambiguo`, `conversa_de_outro_contato`, `evento_cancelado`, `evento_finalizado`, `horario_ocupado`, `horario_bloqueado`, `fora_do_horario`, `antecedencia`, `compromisso_estado_invalido`, `nada_para_atualizar`, `fuso_invalido`, `cor_invalida`, `lembretes_invalidos`, `usuario_inexistente`, `agenda_inexistente`, `evento_inexistente`, `bloqueio_inexistente`, `agenda_repetida`, `limite_agendas`, `limite_bloqueios`, `bloqueio_tipo_invalido`, `repeticao_invalida` (todos em [Erros](https://docs.forsi.com.br/erros)).

## GET /agendas — Listar agendas

- URL: `GET https://chat.forsi.com.br/api/v1/agendas`
- Acesso: escopo `agenda:ler` · módulos do plano: API + Agenda
- Sucesso: `200`, `{"dados": ...}` com lista de `Agenda` (paginada por cursor)
- Página: https://docs.forsi.com.br/api/agenda/listar-agendas (Markdown: https://docs.forsi.com.br/api/agenda/listar-agendas.md)

As agendas (uma por profissional ou sala), com horário de trabalho, duração padrão e fuso.

**Parâmetros de consulta (query string)**

| Campo | Tipo | Obrigatório | Notas |
| --- | --- | --- | --- |
| `limite` | integer | não | Itens por página (1 a 100, padrão 50). |
| `cursor` | string | não | O valor de `proximo` da página anterior. até 80 caracteres |
| `ativa` | "true" \| "false" | não | Só as ativas (`true`) ou só as inativas (`false`). |

**Exemplo (curl)**

```bash
curl "https://chat.forsi.com.br/api/v1/agendas?ativa=true" \
  -H "Authorization: Bearer $FORSI_CHAVE"
```

**Resposta `200` (exemplo)**

```json
{
  "dados": [
    {
      "id": "f7233bb7-10b6-49d2-aa3b-8c2e7d88064d",
      "nome": "Dra. Ana Lima",
      "cor": "blue",
      "fuso": "America/Sao_Paulo",
      "ativa": true,
      "duracao_min": 30,
      "intervalo_min": 10,
      "antecedencia_min": 120,
      "horario": {"1":[["09:00","12:00"],["14:00","18:00"]]},
      "lembretes": [{"antes_min":1440}],
      "mensagem_lembrete": "Oi {nome}, lembrando da sua consulta {data} às {hora}.",
      "profissional": {"id":"27a50fb4-0f76-4c9a-92d0-c2d984d356b9","nome":"Maria Souza"},
      "criado_em": "2026-10-04T13:05:12.481Z",
      "atualizado_em": "2026-10-04T13:05:12.481Z"
    }
  ],
  "proximo": "1791205512481_3791c08d-72dd-4002-89ff-1e14a11c07e5"
}
```

**Erros**: `401`, `403`, `422`, `429` (formato e códigos em "Erros"; códigos desta seção no início dela).

## POST /agendas — Criar agenda

- URL: `POST https://chat.forsi.com.br/api/v1/agendas`
- Acesso: escopo `agenda:escrever` · módulos do plano: API + Agenda · aceita `Idempotency-Key`
- Sucesso: `201`, `{"dados": ...}` com `Agenda`
- Página: https://docs.forsi.com.br/api/agenda/criar-agenda (Markdown: https://docs.forsi.com.br/api/agenda/criar-agenda.md)

Até 100 agendas por organização. Mande `Idempotency-Key` para poder repetir com segurança. Apagar agenda não existe na API.

**Corpo (JSON)**

| Campo | Tipo | Obrigatório | Notas |
| --- | --- | --- | --- |
| `nome` | string | sim | até 80 caracteres |
| `cor` | "slate" \| "blue" \| "violet" \| "amber" \| "emerald" \| "green" \| "rose" \| "cyan" \| "orange" | não |  |
| `fuso` | string | não | Fuso IANA, ex.: America/Sao_Paulo. Padrão: o da organização. até 64 caracteres |
| `horario` | objeto livre | não | Horário de trabalho: dia da semana (0 domingo a 6 sábado) para faixas [início, fim], ex.: {"1": [["09:00","12:00"],["14:00","18:00"]]}. |
| `duracao_min` | integer | não | Duração padrão de cada compromisso, em minutos (5 a 720). |
| `intervalo_min` | integer | não | Folga entre compromissos, em minutos (0 a 240). |
| `antecedencia_min` | integer | não | Antecedência mínima para marcar, em minutos. mín. 0 máx. 43200 |
| `lembretes` | lista de object | não | Lembretes ao contato: até 5, cada um com `antes_min` (minutos antes do compromisso). |
| `lembretes[].antes_min` | integer | sim | mín. 1 máx. 43200 |
| `mensagem_lembrete` | string | não | até 1000 caracteres |
| `ativa` | boolean | não |  |
| `usuario_id` | uuid | não | Profissional dono da agenda (precisa ser da equipe). Só na criação; não dá para trocar depois pela API. |

**Exemplo (curl)**

```bash
curl -X POST "https://chat.forsi.com.br/api/v1/agendas" \
  -H "Authorization: Bearer $FORSI_CHAVE" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: pedido-4821" \
  -d '{
    "nome": "Dra. Ana Lima",
    "cor": "blue",
    "fuso": "America/Sao_Paulo",
    "duracao_min": 30,
    "intervalo_min": 10,
    "antecedencia_min": 120,
    "horario": {
      "1": [["09:00","12:00"],["14:00","18:00"]],
      "3": [["09:00","12:00"],["14:00","18:00"]],
      "5": [["09:00","13:00"]]
    },
    "lembretes": [{"antes_min":1440},{"antes_min":120}]
  }'
```

**Resposta `201` (exemplo)**

```json
{
  "dados": {
    "id": "f7233bb7-10b6-49d2-aa3b-8c2e7d88064d",
    "nome": "Dra. Ana Lima",
    "cor": "blue",
    "fuso": "America/Sao_Paulo",
    "ativa": true,
    "duracao_min": 30,
    "intervalo_min": 10,
    "antecedencia_min": 120,
    "horario": {"1":[["09:00","12:00"],["14:00","18:00"]]},
    "lembretes": [{"antes_min":1440}],
    "mensagem_lembrete": "Oi {nome}, lembrando da sua consulta {data} às {hora}.",
    "profissional": {"id":"27a50fb4-0f76-4c9a-92d0-c2d984d356b9","nome":"Maria Souza"},
    "criado_em": "2026-10-04T13:05:12.481Z",
    "atualizado_em": "2026-10-04T13:05:12.481Z"
  }
}
```

**Erros**: `401`, `403`, `409`, `422`, `429` (formato e códigos em "Erros"; códigos desta seção no início dela).

## GET /agendas/{id} — Ver uma agenda

- URL: `GET https://chat.forsi.com.br/api/v1/agendas/{id}`
- Acesso: escopo `agenda:ler` · módulos do plano: API + Agenda
- Sucesso: `200`, `{"dados": ...}` com `Agenda`
- Página: https://docs.forsi.com.br/api/agenda/ver-agenda (Markdown: https://docs.forsi.com.br/api/agenda/ver-agenda.md)

**Parâmetros no caminho**

| Campo | Tipo | Obrigatório | Notas |
| --- | --- | --- | --- |
| `id` | uuid | sim | No caminho da URL. |

**Exemplo (curl)**

```bash
curl "https://chat.forsi.com.br/api/v1/agendas/f7233bb7-10b6-49d2-aa3b-8c2e7d88064d" \
  -H "Authorization: Bearer $FORSI_CHAVE"
```

**Resposta `200`**: mesmo formato do exemplo de `Agenda` acima (campos em "Objetos das respostas").

**Erros**: `401`, `403`, `404`, `422`, `429` (formato e códigos em "Erros"; códigos desta seção no início dela).

## PATCH /agendas/{id} — Atualizar agenda

- URL: `PATCH https://chat.forsi.com.br/api/v1/agendas/{id}`
- Acesso: escopo `agenda:escrever` · módulos do plano: API + Agenda
- Sucesso: `200`, `{"dados": ...}` com `Agenda`
- Página: https://docs.forsi.com.br/api/agenda/atualizar-agenda (Markdown: https://docs.forsi.com.br/api/agenda/atualizar-agenda.md)

Horário, duração, intervalo, antecedência, fuso, lembretes, cor, nome e `ativa`. Para tirar uma agenda do ar, use `ativa: false`. Trocar o profissional só pela tela.

**Parâmetros no caminho**

| Campo | Tipo | Obrigatório | Notas |
| --- | --- | --- | --- |
| `id` | uuid | sim | No caminho da URL. |

**Corpo (JSON)**

| Campo | Tipo | Obrigatório | Notas |
| --- | --- | --- | --- |
| `nome` | string | não | até 80 caracteres |
| `cor` | "slate" \| "blue" \| "violet" \| "amber" \| "emerald" \| "green" \| "rose" \| "cyan" \| "orange" | não |  |
| `fuso` | string | não | Fuso IANA, ex.: America/Sao_Paulo. Padrão: o da organização. até 64 caracteres |
| `horario` | objeto livre | não | Horário de trabalho: dia da semana (0 domingo a 6 sábado) para faixas [início, fim], ex.: {"1": [["09:00","12:00"],["14:00","18:00"]]}. |
| `duracao_min` | integer | não | Duração padrão de cada compromisso, em minutos (5 a 720). |
| `intervalo_min` | integer | não | Folga entre compromissos, em minutos (0 a 240). |
| `antecedencia_min` | integer | não | Antecedência mínima para marcar, em minutos. mín. 0 máx. 43200 |
| `lembretes` | lista de object | não | Lembretes ao contato: até 5, cada um com `antes_min` (minutos antes do compromisso). |
| `lembretes[].antes_min` | integer | sim | mín. 1 máx. 43200 |
| `mensagem_lembrete` | string | não | até 1000 caracteres |
| `ativa` | boolean | não |  |

**Exemplo (curl)**

```bash
curl -X PATCH "https://chat.forsi.com.br/api/v1/agendas/f7233bb7-10b6-49d2-aa3b-8c2e7d88064d" \
  -H "Authorization: Bearer $FORSI_CHAVE" \
  -H "Content-Type: application/json" \
  -d '{"duracao_min":45,"antecedencia_min":60}'
```

**Resposta `200`**: mesmo formato do exemplo de `Agenda` acima (campos em "Objetos das respostas").

**Erros**: `401`, `403`, `404`, `409`, `422`, `429` (formato e códigos em "Erros"; códigos desta seção no início dela).

## GET /disponibilidade — Horários livres

- URL: `GET https://chat.forsi.com.br/api/v1/disponibilidade`
- Acesso: escopo `agenda:ler` · módulos do plano: API + Agenda
- Sucesso: `200`, `{"dados": ...}` com `Disponibilidade`
- Página: https://docs.forsi.com.br/api/agenda/disponibilidade (Markdown: https://docs.forsi.com.br/api/agenda/disponibilidade.md)

Os mesmos horários que o agente de IA oferece: respeita o horário de trabalho, bloqueios, compromissos, intervalo e antecedência mínima. Cada horário traz `inicio`/`fim` em UTC e `inicio_local`/`fim_local` no fuso da agenda. Até 400 horários por consulta.

**Parâmetros de consulta (query string)**

| Campo | Tipo | Obrigatório | Notas |
| --- | --- | --- | --- |
| `de` | data e hora ISO 8601 | não | Começo da janela (com fuso). |
| `ate` | data e hora ISO 8601 | não | Fim da janela (com fuso). A janela vai até 62 dias. |
| `agenda_id` | uuid | não | Só esta agenda. Sem ela, todas as agendas ativas. |
| `duracao_min` | integer | não | Duração do compromisso, em minutos. Padrão: a da agenda. mín. 5 máx. 720 |

**Exemplo (curl)**

```bash
curl "https://chat.forsi.com.br/api/v1/disponibilidade?agenda_id=f7233bb7-10b6-49d2-aa3b-8c2e7d88064d&de=2026-10-12T00:00:00-03:00&ate=2026-10-17T00:00:00-03:00&duracao_min=30" \
  -H "Authorization: Bearer $FORSI_CHAVE"
```

**Resposta `200` (exemplo)**

```json
{"dados":{"fuso":"America/Sao_Paulo","duracao_min":30,"slots":[{}],"truncado":false}}
```

**Erros**: `401`, `403`, `422`, `429` (formato e códigos em "Erros"; códigos desta seção no início dela).

## GET /compromissos — Listar compromissos

- URL: `GET https://chat.forsi.com.br/api/v1/compromissos`
- Acesso: escopo `agenda:ler` · módulos do plano: API + Agenda
- Sucesso: `200`, `{"dados": ...}` com lista de `Compromisso` (paginada por cursor)
- Página: https://docs.forsi.com.br/api/agenda/listar-compromissos (Markdown: https://docs.forsi.com.br/api/agenda/listar-compromissos.md)

Em ordem de horário, paginado por cursor. Filtre por agenda, contato, estado e período.

**Parâmetros de consulta (query string)**

| Campo | Tipo | Obrigatório | Notas |
| --- | --- | --- | --- |
| `limite` | integer | não | Itens por página (1 a 100, padrão 50). |
| `cursor` | string | não | O valor de `proximo` da página anterior. até 80 caracteres |
| `agenda_id` | uuid | não |  |
| `contato_id` | uuid | não |  |
| `estado` | "marcado" \| "confirmado" \| "concluido" \| "faltou" \| "cancelado" | não |  |
| `de` | data e hora ISO 8601 | não | Só compromissos que terminam depois disto. |
| `ate` | data e hora ISO 8601 | não | Só compromissos que começam antes disto. |

**Exemplo (curl)**

```bash
curl "https://chat.forsi.com.br/api/v1/compromissos?de=2026-10-12T00:00:00-03:00&ate=2026-10-19T00:00:00-03:00&estado=marcado" \
  -H "Authorization: Bearer $FORSI_CHAVE"
```

**Resposta `200` (exemplo)**

```json
{
  "dados": [
    {
      "id": "e0c6d7e8-baef-444c-acaf-8ea96e737165",
      "agenda_id": "f7233bb7-10b6-49d2-aa3b-8c2e7d88064d",
      "agenda": "Dra. Ana Lima",
      "cor": "blue",
      "titulo": "Consulta de retorno",
      "inicio": "2026-10-12T17:00:00.000Z",
      "fim": "2026-10-12T17:30:00.000Z",
      "fuso": "America/Sao_Paulo",
      "inicio_local": "2026-10-12T14:00:00-03:00",
      "fim_local": "2026-10-12T14:30:00-03:00",
      "duracao_min": 30,
      "estado": "marcado",
      "local": "Rua das Flores, 120 - sala 4",
      "link": "https://meet.google.com/abc-defg-hij",
      "notas": "Trazer os exames.",
      "contato_id": "08054a7f-a752-481e-9915-cf4cf944df39",
      "conversa_id": "495a7cae-128c-4b66-adbc-807b3959c129",
      "contato": {
        "id": "08054a7f-a752-481e-9915-cf4cf944df39",
        "nome": "Maria Souza",
        "telefone": "+5531988887777",
        "avatar_url": "https://chat.forsi.com.br/avatar.png"
      },
      "lembretes": [
        {
          "antes_min": 1440,
          "estado": "texto",
          "enviar_em": "2026-10-04T13:05:12.481Z",
          "enviado_em": "2026-10-04T13:05:12.481Z"
        }
      ],
      "criado_por_tipo": "texto",
      "criado_em": "2026-10-04T13:05:12.481Z",
      "confirmado_em": "2026-10-04T13:05:12.481Z",
      "cancelado_em": "2026-10-04T13:05:12.481Z"
    }
  ],
  "proximo": "1791205512481_3791c08d-72dd-4002-89ff-1e14a11c07e5"
}
```

**Erros**: `401`, `403`, `422`, `429` (formato e códigos em "Erros"; códigos desta seção no início dela).

## POST /compromissos — Marcar compromisso

- URL: `POST https://chat.forsi.com.br/api/v1/compromissos`
- Acesso: escopo `agenda:escrever` · módulos do plano: API + Agenda · aceita `Idempotency-Key`
- Sucesso: `201`, `{"dados": ...}` com `Compromisso`
- Página: https://docs.forsi.com.br/api/agenda/criar-compromisso (Markdown: https://docs.forsi.com.br/api/agenda/criar-compromisso.md)

Mesmas regras do app e do agente: horário de trabalho, bloqueios, intervalo e antecedência mínima. Horário ocupado devolve 409, mesmo com várias chamadas ao mesmo tempo. O contato vem de `contato_id`, `conversa_id` ou `telefone` (um só). Não existe `forcar`: encaixe fora das regras só pela tela. Mande `Idempotency-Key` para poder repetir com segurança.

**Corpo (JSON)**

| Campo | Tipo | Obrigatório | Notas |
| --- | --- | --- | --- |
| `inicio` | data e hora ISO 8601 | sim | Começo do compromisso (com fuso). |
| `fim` | data e hora ISO 8601 | não | Fim do compromisso (com fuso, até 12 horas depois do início). |
| `duracao_min` | integer | não | Duração em minutos (5 a 720). |
| `agenda_id` | uuid | não | Sem ela, vale a primeira agenda com o horário livre (como o agente faz). |
| `titulo` | string | não | até 160 caracteres |
| `local` | string | não | até 200 caracteres |
| `link` | string | não | Link da chamada ou reunião (https). até 500 caracteres |
| `notas` | string | não | até 2000 caracteres |
| `contato_id` | uuid | não |  |
| `conversa_id` | uuid | não |  |
| `telefone` | string | não | Acha o contato pelo telefone (ou cria um). Não combine com `contato_id` nem `conversa_id`. mín. 8 caracteres até 30 caracteres |
| `nome` | string | não | Nome do contato novo, quando criado pelo `telefone`. até 120 caracteres |

**Exemplo (curl)**

```bash
curl -X POST "https://chat.forsi.com.br/api/v1/compromissos" \
  -H "Authorization: Bearer $FORSI_CHAVE" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: pedido-4821" \
  -d '{
    "agenda_id": "f7233bb7-10b6-49d2-aa3b-8c2e7d88064d",
    "inicio": "2026-10-12T14:00:00-03:00",
    "duracao_min": 30,
    "telefone": "+55 31 98888-7777",
    "nome": "Maria Souza",
    "titulo": "Consulta de retorno"
  }'
```

**Resposta `201` (exemplo)**

```json
{
  "dados": {
    "id": "e0c6d7e8-baef-444c-acaf-8ea96e737165",
    "agenda_id": "f7233bb7-10b6-49d2-aa3b-8c2e7d88064d",
    "agenda": "Dra. Ana Lima",
    "cor": "blue",
    "titulo": "Consulta de retorno",
    "inicio": "2026-10-12T17:00:00.000Z",
    "fim": "2026-10-12T17:30:00.000Z",
    "fuso": "America/Sao_Paulo",
    "inicio_local": "2026-10-12T14:00:00-03:00",
    "fim_local": "2026-10-12T14:30:00-03:00",
    "duracao_min": 30,
    "estado": "marcado",
    "local": "Rua das Flores, 120 - sala 4",
    "link": "https://meet.google.com/abc-defg-hij",
    "notas": "Trazer os exames.",
    "contato_id": "08054a7f-a752-481e-9915-cf4cf944df39",
    "conversa_id": "495a7cae-128c-4b66-adbc-807b3959c129",
    "contato": {
      "id": "08054a7f-a752-481e-9915-cf4cf944df39",
      "nome": "Maria Souza",
      "telefone": "+5531988887777",
      "avatar_url": "https://chat.forsi.com.br/avatar.png"
    },
    "lembretes": [
      {
        "antes_min": 1440,
        "estado": "texto",
        "enviar_em": "2026-10-04T13:05:12.481Z",
        "enviado_em": "2026-10-04T13:05:12.481Z"
      }
    ],
    "criado_por_tipo": "texto",
    "criado_em": "2026-10-04T13:05:12.481Z",
    "confirmado_em": "2026-10-04T13:05:12.481Z",
    "cancelado_em": "2026-10-04T13:05:12.481Z"
  }
}
```

**Erros**: `401`, `403`, `409`, `422`, `429` (formato e códigos em "Erros"; códigos desta seção no início dela).

## GET /compromissos/{id} — Ver um compromisso

- URL: `GET https://chat.forsi.com.br/api/v1/compromissos/{id}`
- Acesso: escopo `agenda:ler` · módulos do plano: API + Agenda
- Sucesso: `200`, `{"dados": ...}` com `Compromisso`
- Página: https://docs.forsi.com.br/api/agenda/ver-compromisso (Markdown: https://docs.forsi.com.br/api/agenda/ver-compromisso.md)

**Parâmetros no caminho**

| Campo | Tipo | Obrigatório | Notas |
| --- | --- | --- | --- |
| `id` | uuid | sim | No caminho da URL. |

**Exemplo (curl)**

```bash
curl "https://chat.forsi.com.br/api/v1/compromissos/e0c6d7e8-baef-444c-acaf-8ea96e737165" \
  -H "Authorization: Bearer $FORSI_CHAVE"
```

**Resposta `200`**: mesmo formato do exemplo de `Compromisso` acima (campos em "Objetos das respostas").

**Erros**: `401`, `403`, `404`, `422`, `429` (formato e códigos em "Erros"; códigos desta seção no início dela).

## PATCH /compromissos/{id} — Atualizar compromisso

- URL: `PATCH https://chat.forsi.com.br/api/v1/compromissos/{id}`
- Acesso: escopo `agenda:escrever` · módulos do plano: API + Agenda
- Sucesso: `200`, `{"dados": ...}` com `Compromisso`
- Página: https://docs.forsi.com.br/api/agenda/atualizar-compromisso (Markdown: https://docs.forsi.com.br/api/agenda/atualizar-compromisso.md)

Título, notas, local, link, contato e `estado` (só `concluido` ou `faltou`, para marcar comparecimento). Horário: use remarcar.

**Parâmetros no caminho**

| Campo | Tipo | Obrigatório | Notas |
| --- | --- | --- | --- |
| `id` | uuid | sim | No caminho da URL. |

**Corpo (JSON)**

| Campo | Tipo | Obrigatório | Notas |
| --- | --- | --- | --- |
| `titulo` | string ou null | não |  |
| `local` | string ou null | não |  |
| `link` | string ou null | não |  |
| `notas` | string ou null | não |  |
| `contato_id` | uuid ou null | não |  |
| `estado` | "concluido" \| "faltou" | não | Só para encerrar: `concluido` (compareceu) ou `faltou`. Confirmar e cancelar têm rota própria. |

**Exemplo (curl)**

```bash
curl -X PATCH "https://chat.forsi.com.br/api/v1/compromissos/e0c6d7e8-baef-444c-acaf-8ea96e737165" \
  -H "Authorization: Bearer $FORSI_CHAVE" \
  -H "Content-Type: application/json" \
  -d '{"notas":"Trazer os exames de sangue."}'
```

**Resposta `200`**: mesmo formato do exemplo de `Compromisso` acima (campos em "Objetos das respostas").

**Erros**: `401`, `403`, `404`, `409`, `422`, `429` (formato e códigos em "Erros"; códigos desta seção no início dela).

## POST /compromissos/{id}/remarcar — Remarcar compromisso

- URL: `POST https://chat.forsi.com.br/api/v1/compromissos/{id}/remarcar`
- Acesso: escopo `agenda:escrever` · módulos do plano: API + Agenda · aceita `Idempotency-Key`
- Sucesso: `200`, `{"dados": ...}` com `Compromisso`
- Página: https://docs.forsi.com.br/api/agenda/remarcar-compromisso (Markdown: https://docs.forsi.com.br/api/agenda/remarcar-compromisso.md)

Só compromissos marcados ou confirmados. Volta para `marcado` e dispara `agendamento.remarcado`. Cancelado ou encerrado devolve 409.

**Parâmetros no caminho**

| Campo | Tipo | Obrigatório | Notas |
| --- | --- | --- | --- |
| `id` | uuid | sim | No caminho da URL. |

**Corpo (JSON)**

| Campo | Tipo | Obrigatório | Notas |
| --- | --- | --- | --- |
| `inicio` | data e hora ISO 8601 | sim | Novo começo (com fuso). |
| `fim` | data e hora ISO 8601 | não | Novo fim (com fuso). |
| `duracao_min` | integer | não | Duração em minutos (5 a 720). |
| `agenda_id` | uuid | não | Mudar de agenda junto com o horário. |

**Exemplo (curl)**

```bash
curl -X POST "https://chat.forsi.com.br/api/v1/compromissos/e0c6d7e8-baef-444c-acaf-8ea96e737165/remarcar" \
  -H "Authorization: Bearer $FORSI_CHAVE" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: pedido-4821" \
  -d '{"inicio":"2026-10-13T09:30:00-03:00"}'
```

**Resposta `200`**: mesmo formato do exemplo de `Compromisso` acima (campos em "Objetos das respostas").

**Erros**: `401`, `403`, `404`, `409`, `422`, `429` (formato e códigos em "Erros"; códigos desta seção no início dela).

## POST /compromissos/{id}/cancelar — Cancelar compromisso

- URL: `POST https://chat.forsi.com.br/api/v1/compromissos/{id}/cancelar`
- Acesso: escopo `agenda:escrever` · módulos do plano: API + Agenda
- Sucesso: `200`, `{"dados": ...}` com `Compromisso`
- Página: https://docs.forsi.com.br/api/agenda/cancelar-compromisso (Markdown: https://docs.forsi.com.br/api/agenda/cancelar-compromisso.md)

Libera o horário. Repetir o cancelamento é seguro. Não apaga o registro.

**Parâmetros no caminho**

| Campo | Tipo | Obrigatório | Notas |
| --- | --- | --- | --- |
| `id` | uuid | sim | No caminho da URL. |

**Corpo (JSON, opcional)**

Sem campos: mande `{}` ou nenhum corpo.

**Exemplo (curl)**

```bash
curl -X POST "https://chat.forsi.com.br/api/v1/compromissos/e0c6d7e8-baef-444c-acaf-8ea96e737165/cancelar" \
  -H "Authorization: Bearer $FORSI_CHAVE" \
  -H "Content-Type: application/json" \
  -d '{}'
```

**Resposta `200`**: mesmo formato do exemplo de `Compromisso` acima (campos em "Objetos das respostas").

**Erros**: `401`, `403`, `404`, `409`, `422`, `429` (formato e códigos em "Erros"; códigos desta seção no início dela).

## POST /compromissos/{id}/confirmar — Confirmar compromisso

- URL: `POST https://chat.forsi.com.br/api/v1/compromissos/{id}/confirmar`
- Acesso: escopo `agenda:escrever` · módulos do plano: API + Agenda
- Sucesso: `200`, `{"dados": ...}` com `Compromisso`
- Página: https://docs.forsi.com.br/api/agenda/confirmar-compromisso (Markdown: https://docs.forsi.com.br/api/agenda/confirmar-compromisso.md)

O contato confirmou presença.

**Parâmetros no caminho**

| Campo | Tipo | Obrigatório | Notas |
| --- | --- | --- | --- |
| `id` | uuid | sim | No caminho da URL. |

**Corpo (JSON, opcional)**

Sem campos: mande `{}` ou nenhum corpo.

**Exemplo (curl)**

```bash
curl -X POST "https://chat.forsi.com.br/api/v1/compromissos/e0c6d7e8-baef-444c-acaf-8ea96e737165/confirmar" \
  -H "Authorization: Bearer $FORSI_CHAVE" \
  -H "Content-Type: application/json" \
  -d '{}'
```

**Resposta `200`**: mesmo formato do exemplo de `Compromisso` acima (campos em "Objetos das respostas").

**Erros**: `401`, `403`, `404`, `409`, `422`, `429` (formato e códigos em "Erros"; códigos desta seção no início dela).

## GET /bloqueios — Listar bloqueios

- URL: `GET https://chat.forsi.com.br/api/v1/bloqueios`
- Acesso: escopo `agenda:ler` · módulos do plano: API + Agenda
- Sucesso: `200`, `{"dados": ...}` com lista de `Bloqueio` (paginada por cursor)
- Página: https://docs.forsi.com.br/api/agenda/listar-bloqueios (Markdown: https://docs.forsi.com.br/api/agenda/listar-bloqueios.md)

Folgas, almoços e feriados que fecham a agenda. Os que repetem aparecem uma vez, com a regra de repetição.

**Parâmetros de consulta (query string)**

| Campo | Tipo | Obrigatório | Notas |
| --- | --- | --- | --- |
| `limite` | integer | não | Itens por página (1 a 100, padrão 50). |
| `cursor` | string | não | O valor de `proximo` da página anterior. até 80 caracteres |
| `agenda_id` | uuid | não |  |
| `de` | data e hora ISO 8601 | não | Só bloqueios que ainda valem a partir daqui. |
| `ate` | data e hora ISO 8601 | não | Só bloqueios que começam antes disto. |

**Exemplo (curl)**

```bash
curl "https://chat.forsi.com.br/api/v1/bloqueios?agenda_id=f7233bb7-10b6-49d2-aa3b-8c2e7d88064d" \
  -H "Authorization: Bearer $FORSI_CHAVE"
```

**Resposta `200` (exemplo)**

```json
{
  "dados": [
    {
      "id": "a27653af-7bd5-4506-af22-674660419819",
      "agenda_id": "f7233bb7-10b6-49d2-aa3b-8c2e7d88064d",
      "titulo": "Almoço",
      "tipo": "folga",
      "inicio": "2026-10-12T17:00:00.000Z",
      "fim": "2026-10-12T17:30:00.000Z",
      "fuso": "America/Sao_Paulo",
      "inicio_local": "2026-10-12T14:00:00-03:00",
      "fim_local": "2026-10-12T14:30:00-03:00",
      "repetir": "nunca",
      "repetir_ate": "2026-10-12",
      "criado_em": "2026-10-04T13:05:12.481Z"
    }
  ],
  "proximo": "1791205512481_3791c08d-72dd-4002-89ff-1e14a11c07e5"
}
```

**Erros**: `401`, `403`, `422`, `429` (formato e códigos em "Erros"; códigos desta seção no início dela).

## POST /bloqueios — Criar bloqueio

- URL: `POST https://chat.forsi.com.br/api/v1/bloqueios`
- Acesso: escopo `agenda:escrever` · módulos do plano: API + Agenda · aceita `Idempotency-Key`
- Sucesso: `201`, `{"dados": ...}` com `Bloqueio`
- Página: https://docs.forsi.com.br/api/agenda/criar-bloqueio (Markdown: https://docs.forsi.com.br/api/agenda/criar-bloqueio.md)

Até 500 bloqueios por organização. Não cancela compromissos que já estão marcados nesse horário. Mande `Idempotency-Key` para poder repetir com segurança.

**Corpo (JSON)**

| Campo | Tipo | Obrigatório | Notas |
| --- | --- | --- | --- |
| `inicio` | data e hora ISO 8601 | sim | Começo do bloqueio (com fuso). |
| `fim` | data e hora ISO 8601 | sim | Fim do bloqueio (com fuso, até 366 dias depois do início). |
| `agenda_id` | uuid ou null | não | Agenda do bloqueio. Vazio = vale para todas as agendas. |
| `titulo` | string | não | até 120 caracteres |
| `tipo` | "folga" \| "almoco" \| "feriado" \| "outro" | não |  |
| `repetir` | "nunca" \| "diario" \| "semanal" \| "anual" | não |  |
| `repetir_ate` | data AAAA-MM-DD ou null | não | Último dia da repetição (AAAA-MM-DD). Só com `repetir` diferente de `nunca`. |

**Exemplo (curl)**

```bash
curl -X POST "https://chat.forsi.com.br/api/v1/bloqueios" \
  -H "Authorization: Bearer $FORSI_CHAVE" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: pedido-4821" \
  -d '{
    "agenda_id": "f7233bb7-10b6-49d2-aa3b-8c2e7d88064d",
    "inicio": "2026-10-12T12:00:00-03:00",
    "fim": "2026-10-12T13:00:00-03:00",
    "titulo": "Almoço",
    "tipo": "almoco",
    "repetir": "diario"
  }'
```

**Resposta `201` (exemplo)**

```json
{
  "dados": {
    "id": "a27653af-7bd5-4506-af22-674660419819",
    "agenda_id": "f7233bb7-10b6-49d2-aa3b-8c2e7d88064d",
    "titulo": "Almoço",
    "tipo": "folga",
    "inicio": "2026-10-12T17:00:00.000Z",
    "fim": "2026-10-12T17:30:00.000Z",
    "fuso": "America/Sao_Paulo",
    "inicio_local": "2026-10-12T14:00:00-03:00",
    "fim_local": "2026-10-12T14:30:00-03:00",
    "repetir": "nunca",
    "repetir_ate": "2026-10-12",
    "criado_em": "2026-10-04T13:05:12.481Z"
  }
}
```

**Erros**: `401`, `403`, `409`, `422`, `429` (formato e códigos em "Erros"; códigos desta seção no início dela).

## GET /bloqueios/{id} — Ver um bloqueio

- URL: `GET https://chat.forsi.com.br/api/v1/bloqueios/{id}`
- Acesso: escopo `agenda:ler` · módulos do plano: API + Agenda
- Sucesso: `200`, `{"dados": ...}` com `Bloqueio`
- Página: https://docs.forsi.com.br/api/agenda/ver-bloqueio (Markdown: https://docs.forsi.com.br/api/agenda/ver-bloqueio.md)

**Parâmetros no caminho**

| Campo | Tipo | Obrigatório | Notas |
| --- | --- | --- | --- |
| `id` | uuid | sim | No caminho da URL. |

**Exemplo (curl)**

```bash
curl "https://chat.forsi.com.br/api/v1/bloqueios/a27653af-7bd5-4506-af22-674660419819" \
  -H "Authorization: Bearer $FORSI_CHAVE"
```

**Resposta `200`**: mesmo formato do exemplo de `Bloqueio` acima (campos em "Objetos das respostas").

**Erros**: `401`, `403`, `404`, `422`, `429` (formato e códigos em "Erros"; códigos desta seção no início dela).

## PATCH /bloqueios/{id} — Atualizar bloqueio

- URL: `PATCH https://chat.forsi.com.br/api/v1/bloqueios/{id}`
- Acesso: escopo `agenda:escrever` · módulos do plano: API + Agenda
- Sucesso: `200`, `{"dados": ...}` com `Bloqueio`
- Página: https://docs.forsi.com.br/api/agenda/atualizar-bloqueio (Markdown: https://docs.forsi.com.br/api/agenda/atualizar-bloqueio.md)

**Parâmetros no caminho**

| Campo | Tipo | Obrigatório | Notas |
| --- | --- | --- | --- |
| `id` | uuid | sim | No caminho da URL. |

**Corpo (JSON)**

| Campo | Tipo | Obrigatório | Notas |
| --- | --- | --- | --- |
| `inicio` | data e hora ISO 8601 | não | Começo do bloqueio (com fuso). |
| `fim` | data e hora ISO 8601 | não | Fim do bloqueio (com fuso, até 366 dias depois do início). |
| `agenda_id` | uuid ou null | não | Agenda do bloqueio. Vazio = vale para todas as agendas. |
| `titulo` | string | não | até 120 caracteres |
| `tipo` | "folga" \| "almoco" \| "feriado" \| "outro" | não |  |
| `repetir` | "nunca" \| "diario" \| "semanal" \| "anual" | não |  |
| `repetir_ate` | data AAAA-MM-DD ou null | não | Último dia da repetição (AAAA-MM-DD). Só com `repetir` diferente de `nunca`. |

**Exemplo (curl)**

```bash
curl -X PATCH "https://chat.forsi.com.br/api/v1/bloqueios/a27653af-7bd5-4506-af22-674660419819" \
  -H "Authorization: Bearer $FORSI_CHAVE" \
  -H "Content-Type: application/json" \
  -d '{"fim":"2026-10-12T13:30:00-03:00"}'
```

**Resposta `200`**: mesmo formato do exemplo de `Bloqueio` acima (campos em "Objetos das respostas").

**Erros**: `401`, `403`, `404`, `409`, `422`, `429` (formato e códigos em "Erros"; códigos desta seção no início dela).

## DELETE /bloqueios/{id} — Apagar bloqueio

- URL: `DELETE https://chat.forsi.com.br/api/v1/bloqueios/{id}`
- Acesso: escopo `agenda:escrever` · módulos do plano: API + Agenda
- Sucesso: `200`, `{"dados": ...}` com `Apagado`
- Página: https://docs.forsi.com.br/api/agenda/apagar-bloqueio (Markdown: https://docs.forsi.com.br/api/agenda/apagar-bloqueio.md)

Apaga um bloqueio (um por chamada). Só o bloqueio: agendas e compromissos não se apagam pela API.

**Parâmetros no caminho**

| Campo | Tipo | Obrigatório | Notas |
| --- | --- | --- | --- |
| `id` | uuid | sim | No caminho da URL. |

**Exemplo (curl)**

```bash
curl -X DELETE "https://chat.forsi.com.br/api/v1/bloqueios/a27653af-7bd5-4506-af22-674660419819" \
  -H "Authorization: Bearer $FORSI_CHAVE"
```

**Resposta `200` (exemplo)**

```json
{"dados":{"apagado":false,"conversas_apagadas":1}}
```

**Erros**: `401`, `403`, `404`, `409`, `422`, `429` (formato e códigos em "Erros"; códigos desta seção no início dela).

## Objetos das respostas

Campos de cada objeto devolvido em `dados`. Campos novos podem aparecer: ignore os que não conhecer.

### Agenda

| Campo | Tipo | Obrigatório | Notas |
| --- | --- | --- | --- |
| `id` | uuid | não |  |
| `nome` | string | não |  |
| `cor` | string | não |  |
| `fuso` | string | não | ex.: America/Sao_Paulo |
| `ativa` | boolean | não |  |
| `duracao_min` | integer | não |  |
| `intervalo_min` | integer | não |  |
| `antecedencia_min` | integer | não |  |
| `horario` | objeto livre | não | Dia da semana (0 domingo a 6 sábado) para faixas [início, fim]. |
| `lembretes` | lista de object | não |  |
| `lembretes[].antes_min` | integer | não |  |
| `mensagem_lembrete` | string | não |  |
| `profissional` | object | não | Quando a agenda é de uma pessoa da equipe. |
| `profissional.id` | uuid | não |  |
| `profissional.nome` | string | não |  |
| `criado_em` | data e hora ISO 8601 | não |  |
| `atualizado_em` | data e hora ISO 8601 | não |  |

### Disponibilidade

| Campo | Tipo | Obrigatório | Notas |
| --- | --- | --- | --- |
| `fuso` | string | não |  |
| `duracao_min` | integer | não |  |
| `slots` | lista de Slot | não |  |
| `truncado` | boolean | não | Verdadeiro quando passou de 400 horários: estreite a janela. |

### Compromisso

| Campo | Tipo | Obrigatório | Notas |
| --- | --- | --- | --- |
| `id` | uuid | não |  |
| `agenda_id` | uuid | não |  |
| `agenda` | string | não |  |
| `cor` | string | não |  |
| `titulo` | string | não |  |
| `inicio` | data e hora ISO 8601 | não |  |
| `fim` | data e hora ISO 8601 | não |  |
| `fuso` | string | não |  |
| `inicio_local` | string | não | Começo no fuso da agenda, com deslocamento. ex.: 2026-10-12T14:00:00-03:00 |
| `fim_local` | string | não | Fim no fuso da agenda, com deslocamento. ex.: 2026-10-12T14:00:00-03:00 |
| `duracao_min` | integer | não |  |
| `estado` | "marcado" \| "confirmado" \| "concluido" \| "faltou" \| "cancelado" | não |  |
| `local` | string | não |  |
| `link` | string | não |  |
| `notas` | string | não |  |
| `contato_id` | uuid | não |  |
| `conversa_id` | uuid | não |  |
| `contato` | object | não |  |
| `contato.id` | uuid | não |  |
| `contato.nome` | string | não |  |
| `contato.telefone` | string | não |  |
| `contato.avatar_url` | string | não |  |
| `lembretes` | lista de object | não |  |
| `lembretes[].antes_min` | integer | não |  |
| `lembretes[].estado` | string | não |  |
| `lembretes[].enviar_em` | data e hora ISO 8601 | não |  |
| `lembretes[].enviado_em` | data e hora ISO 8601 | não |  |
| `criado_por_tipo` | string | não |  |
| `criado_em` | data e hora ISO 8601 | não |  |
| `confirmado_em` | data e hora ISO 8601 | não |  |
| `cancelado_em` | data e hora ISO 8601 | não |  |

### Bloqueio

| Campo | Tipo | Obrigatório | Notas |
| --- | --- | --- | --- |
| `id` | uuid | não |  |
| `agenda_id` | uuid ou null | não |  |
| `titulo` | string | não |  |
| `tipo` | "folga" \| "almoco" \| "feriado" \| "outro" | não |  |
| `inicio` | data e hora ISO 8601 | não |  |
| `fim` | data e hora ISO 8601 | não |  |
| `fuso` | string | não |  |
| `inicio_local` | string | não | Começo no fuso da agenda, com deslocamento. ex.: 2026-10-12T14:00:00-03:00 |
| `fim_local` | string | não | Fim no fuso da agenda, com deslocamento. ex.: 2026-10-12T14:00:00-03:00 |
| `repetir` | "nunca" \| "diario" \| "semanal" \| "anual" | não |  |
| `repetir_ate` | data AAAA-MM-DD | não |  |
| `criado_em` | data e hora ISO 8601 | não |  |

### Apagado

| Campo | Tipo | Obrigatório | Notas |
| --- | --- | --- | --- |
| `apagado` | boolean | não |  |
| `conversas_apagadas` | integer | não |  |

---

Página: https://docs.forsi.com.br/api/agenda · Índice: https://docs.forsi.com.br/llms.txt · Tudo num arquivo: https://docs.forsi.com.br/llms-full.txt
