Runbook - Horários de atendimento do Sagazchat
Manual operacional para configurar Configurações Horários no Sagazchat. Horários sao configurados por canal (WhatsApp, Instagram, E-mail, Widget), nao por empresa nem por departame
Manual operacional para configurar Configurações > Horários no Sagazchat. Horários sao configurados por canal (WhatsApp, Instagram, E-mail, Widget), nao por empresa nem por departamento.
Status: validado em 2026-05-11 na conta
exemplo. Toggle “Ativar atendimento” e radio Mensagem/Fluxo nao disparam network — sao estado local ate clicar Salvar.
1. Onde fica
- Sidebar: Configurações > Horários
- URL:
https://app.sagazchat.com/office-hours - Endpoint backend: a confirmar (provavelmente
/office-hoursou/business-hours).
2. Estrutura da tela
Layout em duas colunas:
- Esquerda: card Canais com descricao + lista de cards (um por canal conectado).
- Direita: painel de configuracao do canal selecionado (vazio ate clicar num card).

Cada card de canal mostra:
- icone do tipo (WhatsApp, Instagram, etc);
- nome do canal (ex:
exemplo); - badge Atendimento ativo ou Atendimento inativo.
Card selecionado fica com fundo preto destacado.
3. Estado inicial de um canal
Quando o canal nao tem horarios configurados, o painel direito mostra:
- titulo com o nome do canal;
- icone de chat + label Atendimento inativo;
- botao Ativar atendimento (azul).

Clicar Ativar atendimento muda o estado localmente (so persiste no Salvar) e revela os campos de configuracao.
4. Definicao de horarios
Apos ativar, abre a secao Definição de horários com 7 linhas — uma por dia da semana:
| Coluna | O que faz |
|---|---|
| Dia da semana | Label fixo: Segunda-feira a Domingo. |
| Status | Fechado (default) ou Aberto. |
| Switch | Liga o dia. Quando off, o dia fica fechado. |
| Hora inicial | Input hh:mm (placeholder). |
| Hora final | Input hh:mm (placeholder). |

Quirk: cada dia tem apenas UM intervalo (hora inicial + final). Nao existe campo para intervalo de almoco/almocos secundarios. Se o expediente for
08:00–12:00 e 13:00–18:00, e necessario:
- usar
08:00–18:00continuo e tratar o intervalo via IA/fluxo, OU- aceitar que o intervalo de almoco fica “dentro” do horario de atendimento.
5. Acao quando estiver fora do horario
Abaixo de Definição de horários aparece a secao Ação. Define o que fazer quando alguem manda mensagem fora do expediente.
Dois modos exclusivos (radio):
5.1 Mensagem (default)

- Radio Mensagem selecionado.
- Abre textarea para digitar a resposta automatica.
- Mensagem e enviada para o cliente quando ele escreve fora do horario.
5.2 Fluxo

- Radio Fluxo selecionado.
- Substitui o textarea por combobox Escolha um fluxo (alimentado por
/flowbuilder/all/get). - Quando alguem escreve fora do horario, o fluxo dispara automaticamente (pode coletar dados, dar opcoes, marcar etiquetas etc).
O radio
config.typetem valores"msg"(Mensagem) e"flow"(Fluxo).
6. Salvar
Botao Salvar verde no final da pagina. So depois de clicar nele a configuracao e persistida no backend. Antes disso, mudancas sao apenas locais — recarregar a pagina volta tudo ao estado anterior.
6.1 Endpoint validado
POST https://backend.sagazchat.com/outOfHours
Authorization: Bearer <jwt>
Content-Type: application/json
Resposta: 200 + corpo "APPLY" (string literal entre aspas, nao objeto).
6.2 Payload completo (validado 2026-05-11)
{
"config": {
"whatsappId": 216,
"waOficialId": 0,
"type": "msg",
"flowId": 0,
"msg": "Estamos fechados, voltamos amanha as 9h",
"active": true
},
"monday": { "open": true, "openTime": "2026-05-11T12:00:00.000Z", "closeTime": "2026-05-11T21:00:00.000Z" },
"tuesday": { "open": false, "openTime": null, "closeTime": null },
"wednsday": { "open": false, "openTime": null, "closeTime": null },
"thursday": { "open": false, "openTime": null, "closeTime": null },
"friday": { "open": false, "openTime": null, "closeTime": null },
"saturday": { "open": false, "openTime": null, "closeTime": null },
"sunday": { "open": false, "openTime": null, "closeTime": null }
}
6.3 Quirks do payload (importantes!)
| Quirk | Detalhe |
|---|---|
| Nome do endpoint | /outOfHours (camelCase, sem hifen). NAO e /office-hours como a rota UI sugere. |
TYPO wednsday | A chave de quarta-feira no payload e wednsday (faltando o e antes do s). Quem chamar a API via codigo precisa enviar exatamente como o backend espera, com o typo. As outras chaves estao corretas: monday, tuesday, thursday, friday, saturday, sunday. |
| Horarios em ISO UTC | openTime/closeTime sao ISO 8601 UTC. O frontend converte o hh:mm local para UTC ao enviar (ex: 09:00 BRT → 2026-05-11T12:00:00.000Z). Quem chamar a API direta precisa fazer a mesma conversao. |
| Data no horario | A data da string ISO e o “dia atual” — o backend ignora a data e usa so o time. Mas o frontend sempre envia uma data valida. |
config.type | Strings literais: "msg" (Mensagem) ou "flow" (Fluxo). |
config.active | Toggle “Ativar atendimento” / “Desativar atendimento”. false mantem o resto do payload salvo mas inativa a regra. |
config.whatsappId | ID do canal — vem de /whatsapp ou similar. No teste lab: 216. |
config.waOficialId | Para canais WA Oficial; senao 0. |
config.flowId | ID do fluxo selecionado quando type=flow. 0 quando type=msg. |
Resposta "APPLY" | String literal entre aspas, nao um objeto JSON. Frontend nao usa nada do corpo, so o status 200. |
6.4 Payload com Fluxo (type=flow)
Quando config.type === "flow", os campos mudam:
"config": {
"whatsappId": 216,
"waOficialId": 0,
"type": "flow",
"flowId": 540,
"msg": "",
"active": true
}
| Campo | Comportamento |
|---|---|
type | "flow" em vez de "msg". |
flowId | ID inteiro do fluxo selecionado no combobox. Quando type=msg, fica 0. |
msg | String vazia (frontend nao envia o texto da textarea quando o radio esta em Fluxo). |
Lista de fluxos vem de GET /flowbuilder/all/get (o mesmo endpoint usado pelo combobox em Remarketing e Acao do Flowbuilder).
6.5 Comportamento ao desativar
Quando o usuario clica Desativar atendimento + Salvar, o payload ainda inclui toda a configuracao previa — apenas config.active vai a false. Significa que a config fica memorizada e e reativada se clicar Ativar de novo (sem precisar reconfigurar dias/horarios/mensagem).
Para “esquecer” config previa, e preciso ativar, desligar todos os dias, limpar mensagem, e so depois desativar + salvar.
7. Acoes seguras e perigosas
| Acao | Impacto | Regra |
|---|---|---|
Abrir /office-hours | Leitura | Seguro. |
| Selecionar canal | Carrega painel | Seguro. |
| Toggle Ativar atendimento | Apenas local | Seguro (so persiste no Salvar). |
| Toggle dia da semana | Apenas local | Seguro. |
| Trocar radio Mensagem ↔ Fluxo | Apenas local | Seguro. |
| Clicar Salvar | Persiste no backend | Cuidado: afeta atendimento real imediatamente — clientes fora do horario passam a receber a mensagem/fluxo configurado. |
| Clicar Desativar atendimento + Salvar | Tira horario do canal | Destrutivo: clientes fora do horario voltam a nao receber ausencia. |
8. Quirks descobertos
- Endpoint
/outOfHours(camelCase) — nome diverge da rota UI/office-hours. - TYPO
wednsdayno payload — semeentrewednesday. Outras chaves de dias estao corretas. - Horarios em ISO UTC: o frontend converte
hh:mmlocal pra UTC ao enviar. API direta precisa fazer o mesmo. - Resposta
"APPLY"(string literal, nao JSON object). - Desativar nao limpa a config — apenas marca
active: false. Reativar traz tudo de volta. - Horarios sao por canal, nao por departamento. Departamentos tem
schedulesno payload do POST/queue(ver runbookdepartamentos) com defaults Seg-Sex 08-18, mas nao foi achada UI para edita-los. Hipoteses: ou e configurado via API, ou ha uma area secundaria nao mapeada. - Toggle “Ativar atendimento” e estado local; so persiste com Salvar.
- Cada dia tem 1 intervalo apenas (sem horarios partidos para almoco).
- Card do canal selecionado fica com fundo preto (nao laranja/azul como em outros modulos MUI).
- Sem botao Cancelar: para descartar mudancas, sair da pagina antes de Salvar. Recarregar volta ao estado salvo.
9. Snippets
9.1 Listar canais e estado
// /office-hours alimenta a UI a partir de /whatsapp, /waoficial, /instagram, /email etc.
// O estado "Atendimento ativo/inativo" provavelmente vem de um campo `officeHoursActive`
// ou similar dentro de cada canal. Verificar com:
const v = localStorage.getItem('token');
const token = v?.startsWith('"') ? JSON.parse(v) : v;
const res = await fetch('https://backend.sagazchat.com/whatsapp', {
headers: { Authorization: `Bearer ${token}` },
});
console.log(await res.json());
[a validar] endpoint exato e nome dos campos.
9.2 Salvar horarios via API
[a validar] — capturar quando rodar Salvar uma vez.
10. Pendencias
- Endpoint exato do Salvar e payload.
- Onde ficam os
schedulesde departamento (visiveis no POST/queuemas sem UI obvia). - Comportamento se canal tem multiplos numeros vinculados.
- Validar diferenca entre WhatsApp QR e WhatsApp Oficial.
11. Imagens
public/media/nova-ui/horarios-lista-canais.pngpublic/media/nova-ui/horarios-canal-inativo.pngpublic/media/nova-ui/horarios-canal-ativo.pngpublic/media/nova-ui/horarios-acao-mensagem.pngpublic/media/nova-ui/horarios-acao-fluxo.png
12. Scripts validados
node scripts/sagaz-horarios-mapear.mjs # lista de canais
node scripts/sagaz-horarios-canal-v3.mjs # abrir canal inativo
node scripts/sagaz-horarios-ativar.mjs # ativar atendimento (local)
node scripts/sagaz-horarios-acao-fluxo.mjs # toggle radio Mensagem/Fluxo