Serviços
Catálogo de serviços agendáveis. Cada serviço define duração, preço padrão e templates de lembrete automático que são materializados no momento do agendamento.
Licença e permissão
Serviços está incluído em toda licença NooviChat válida. Qualquer membro autenticado da conta pode listar e consultar. Criar, atualizar e remover exige administrador ou a permissão customizada appointment_manage.
Sem autenticação a API responde 401; um membro sem permissão de gerenciamento recebe 403; um ID inexistente ou de outra conta recebe 404.
Templates de Lembrete
Cada serviço pode ter N templates de lembrete configurados (ex: "1 dia antes", "3 horas antes"). Ao criar um atendimento, somente templates ativos, configurados para WhatsApp e com send_at ainda no futuro são materializados como lembretes pendentes. O despacho posterior exige que o contato tenha um vínculo contact_inbox com canal Channel::Whatsapp da mesma conta ou Channel::Api da mesma conta respaldado por uma configuração WAHA, Uazapi ou NooviConnect; uma falha pode manter o lembrete pendente para nova tentativa ou marcá-lo como falho. Não existe filtro por uma flag active do inbox nessa seleção.
Ao materializar o lembrete, o corpo faz uma única passagem de substituição literal apenas pelos tokens exatos: {{paciente}}, {{cliente}}, {{profissional}}, {{servico}}, {{data}}, {{hora}}, {{duracao}}, {{valor}} e {{empresa}}. Um token desconhecido permanece literal. Um texto com aparência de token que venha dentro de um valor inserido não passa por uma segunda renderização.
Data, hora e valor usam as configurações da conta
{{data}} e {{valor}} são formatados com o locale da conta; {{data}} e {{hora}} usam o fuso efetivo de agendamento: primeiro account.reporting_timezone, depois account.custom_attributes.timezone gravado pelo onboarding e, sem uma configuração válida, America/Sao_Paulo. Se o locale não estiver disponível, o backend usa o locale padrão da instalação quando ele estiver disponível e, por fim, inglês.
{{valor}} usa primeiro o preço e a moeda gravados no atendimento. Quando um deles não foi gravado, somente esse campo recorre ao preço ou à moeda padrão do serviço. O resultado tem duas casas decimais; sem preço ou sem moeda, o token vira texto vazio.
/api/v1/accounts/{account_id}/servicesLista todos os serviços ativos do catálogo da conta (não-descartados), ordenados por nome, com reminder_templates embutidos. Qualquer membro da conta pode visualizar.
Sem filtros nem paginação
Esta listagem retorna sempre todos os serviços ativos da conta — não aceita parâmetros de query de filtro ou paginação.
curl -s "https://chat.seudominio.com/api/v1/accounts/1/services" \
-H "api_access_token: YOUR_TOKEN" | jq .{
"data": [
{
"id": 7,
"name": "Limpeza Dental",
"description": "Profilaxia e polimento dental completo.",
"duration_minutes": 60,
"default_price_cents": 20000,
"currency": "BRL",
"color": "#10B981",
"online_available": true,
"active": true,
"custom_attributes": {
"external_code": "PROC-001"
},
"reminder_templates": [
{
"id": 5,
"label": "1 dia antes",
"days_before": 1,
"hours_before": 0,
"minutes_before": 0,
"body_template": "Ola {{paciente}}, lembrando do seu {{servico}} amanha as {{hora}}.",
"active": true,
"send_via": "whatsapp",
"whatsapp_template_id": null
}
]
}
]
}/api/v1/accounts/{account_id}/servicesCria novo serviço no catálogo. Exige administrador ou a permissão appointment_manage.
Body (service)
| Nome | Tipo | Obrigatorio | Descricao |
|---|---|---|---|
name | string | Sim | Nome do serviço |
duration_minutes | integer | Sim | Duração em minutos (mínimo 1) |
description | string | Nao | Descrição do serviço |
default_price_cents | integer | Nao | Preço padrão em centavos (padrão 0) |
currency | string | Nao | Moeda (3 letras, padrão BRL) |
color | string | Nao | Cor hex para o calendário |
online_available | boolean | Nao | Disponível no widget público (padrão true) |
active | boolean | Nao | Inclui o serviço nas listagens ativas (padrão true) |
custom_attributes | object | Nao | Metadados livres persistidos no serviço (padrão {}) |
curl -X POST "https://chat.seudominio.com/api/v1/accounts/1/services" \
-H "api_access_token: YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"service": {
"name": "Clareamento Dental",
"duration_minutes": 90,
"default_price_cents": 45000,
"currency": "BRL",
"online_available": true
}
}'{ "data": { "id": 8, "name": "Clareamento Dental", "duration_minutes": 90 } }/api/v1/accounts/{account_id}/services/{id}Retorna detalhes de um serviço incluindo templates de lembrete.
curl -s "https://chat.seudominio.com/api/v1/accounts/1/services/7" \
-H "api_access_token: YOUR_TOKEN" | jq ./api/v1/accounts/{account_id}/services/{id}Atualiza dados do serviço. Exige administrador ou a permissão appointment_manage.
Body (service; todos opcionais no PATCH)
| Nome | Tipo | Obrigatorio | Descricao |
|---|---|---|---|
name | string | Nao | Novo nome do serviço |
description | string | null | Nao | Nova descrição |
duration_minutes | integer | Nao | Duração em minutos (mínimo 1) |
default_price_cents | integer | Nao | Preço padrão em centavos (mínimo 0) |
currency | string | Nao | Código de moeda com 3 letras |
color | string | Nao | Cor hex para o calendário |
online_available | boolean | Nao | Disponibilidade no widget público |
active | boolean | Nao | Ativa ou desativa o serviço sem fazer soft-delete |
custom_attributes | object | Nao | Substitui o objeto de metadados livres enviado para o serviço |
curl -X PATCH "https://chat.seudominio.com/api/v1/accounts/1/services/7" \
-H "api_access_token: YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "service": { "duration_minutes": 75, "default_price_cents": 22000 } }'/api/v1/accounts/{account_id}/services/{id}Remove o serviço por soft-delete. Exige administrador ou appointment_manage; o histórico de atendimentos é preservado.
curl -X DELETE "https://chat.seudominio.com/api/v1/accounts/1/services/7" \
-H "api_access_token: YOUR_TOKEN"Templates de Lembrete
Não há endpoints REST dedicados para reminder_templates
Os templates de lembrete não têm rotas próprias (/services/{id}/reminder_templates não existe). Eles são gerenciados como um campo aninhado no próprio recurso de serviço: envie o array reminder_templates no body do POST ou PATCH de /services. O backend faz replace-all — a lista enviada substitui integralmente os templates atuais do serviço.
O GET /services/{id} já retorna os reminder_templatesembutidos. Para criar, atualizar ou remover, envie o array completo no body do serviço. Omitir o campo preserva os templates existentes; enviar [] remove todos.
Somente WhatsApp e campo Meta legado
O único canal de entrega implementado é whatsapp. Lembretes legados com outro canal falham de forma fechada antes de qualquer requisição externa. O campo whatsapp_template_id permanece temporariamente no contrato apenas para compatibilidade com clientes antigos: o backend aceita e ignora o valor, não o utiliza para selecionar um template Meta e sempre o retorna como null.
Novas gravações aceitam corpos de até 4096 caracteres. Uma resposta de leitura ainda pode conter um body_template legado maior enquanto ele não for editado. Se a substituição dos tokens gerar um corpo acima desse limite, o lembrete materializado fica com status de falha e não é enviado.
Campos de cada item de reminder_templates
| Nome | Tipo | Obrigatorio | Descricao |
|---|---|---|---|
body_template | string | Sim | Corpo de até 4096 caracteres, com uma única passagem de substituição literal dos nove tokens exatos documentados acima |
label | string | null | Nao | Label descritivo (ex: 1 dia antes) |
days_before | integer | Nao | Dias antes do atendimento, de 0 a 1491308 (padrão 0) |
hours_before | integer | Nao | Horas antes do atendimento, de 0 a 35791394 (padrão 0) |
minutes_before | integer | Nao | Minutos antes do atendimento, de 0 a 2147483647 (padrão 0) |
active | boolean | Nao | Se o lembrete está ativo (padrão true) |
send_via | string | Nao | Use whatsapp, único canal de entrega implementado (padrão whatsapp) |
whatsapp_template_id | integer | null | Nao | Deprecated: compatibilidade de rollout. O valor é ignorado e a resposta sempre retorna null; não seleciona template Meta |
Limites da antecedência
Os offsets devem ser inteiros: days_before entre 0 e 1491308, hours_before entre 0 e 35791394, e minutes_before entre 0 e 2147483647. Pelo menos um deles deve ser maior que zero. A antecedência normalizada, calculada como days_before * 1440 + hours_before * 60 + minutes_before, também deve ser menor ou igual a 2147483647 minutos.
# Definir os lembretes de um servico via PATCH (replace-all):
curl -X PATCH "https://chat.seudominio.com/api/v1/accounts/1/services/7" \
-H "api_access_token: YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"service": {
"reminder_templates": [
{
"label": "1 dia antes",
"days_before": 1,
"body_template": "Ola {{paciente}}, lembrando do seu {{servico}} amanha as {{hora}}.",
"send_via": "whatsapp",
"active": true
},
{
"label": "3 horas antes",
"hours_before": 3,
"body_template": "Ola {{paciente}}! Seu {{servico}} e hoje as {{hora}}.",
"send_via": "whatsapp"
}
]
}
}'Lembretes já materializados
Alterar ou remover um template via replace-all não reescreve nem cancela imediatamente os lembretes já materializados. Ao destruir um template, o backend preserva esses registros e apenas define seu service_reminder_template_id como null. No próximo reagendamento do atendimento, os lembretes pendentes órfãos ou que deixaram de ser entregáveis são cancelados, e os templates entregáveis da configuração atual são reconciliados ou materializados para o novo horário.