[{"data":1,"prerenderedAt":778},["ShallowReactive",2],{"docs-nav-docs_pt":3,"docs-search-docs_pt":80,"doc-docs_pt-\u002Fdocs\u002Fwebchat":496,"surround-docs_pt-\u002Fdocs\u002Fwebchat":774},[4],{"title":5,"path":6,"stem":7,"children":8,"page":42},"Docs","\u002Fdocs","docs",[9,13,17,21,43,47,68,72,76],{"title":10,"path":11,"stem":12},"Introdução","\u002Fdocs\u002Fintroduction","docs\u002F1.introduction",{"title":14,"path":15,"stem":16},"Início rápido","\u002Fdocs\u002Fquickstart","docs\u002F2.quickstart",{"title":18,"path":19,"stem":20},"Como funciona","\u002Fdocs\u002Fhow-it-works","docs\u002F3.how-it-works",{"title":22,"path":23,"stem":24,"children":25,"page":42},"Conceitos","\u002Fdocs\u002Fconcepts","docs\u002F4.concepts",[26,30,34,38],{"title":27,"path":28,"stem":29},"Workspaces e recursos","\u002Fdocs\u002Fconcepts\u002Fworkspaces-and-resources","docs\u002F4.concepts\u002F1.workspaces-and-resources",{"title":31,"path":32,"stem":33},"Serviços e disponibilidade","\u002Fdocs\u002Fconcepts\u002Fservices-and-availability","docs\u002F4.concepts\u002F2.services-and-availability",{"title":35,"path":36,"stem":37},"Agendamentos e pré-reservas","\u002Fdocs\u002Fconcepts\u002Fbookings-and-holds","docs\u002F4.concepts\u002F3.bookings-and-holds",{"title":39,"path":40,"stem":41},"Automações","\u002Fdocs\u002Fconcepts\u002Fautomations","docs\u002F4.concepts\u002F4.automations",false,{"title":44,"path":45,"stem":46},"WhatsApp e IA","\u002Fdocs\u002Fwhatsapp-and-ai","docs\u002F5.whatsapp-and-ai",{"title":48,"path":49,"stem":50,"children":51,"page":42},"API","\u002Fdocs\u002Fapi","docs\u002F6.api",[52,56,60,64],{"title":53,"path":54,"stem":55},"Autenticação","\u002Fdocs\u002Fapi\u002Fauthentication","docs\u002F6.api\u002F1.authentication",{"title":57,"path":58,"stem":59},"Convenções","\u002Fdocs\u002Fapi\u002Fconventions","docs\u002F6.api\u002F2.conventions",{"title":61,"path":62,"stem":63},"Endpoints","\u002Fdocs\u002Fapi\u002Fendpoints","docs\u002F6.api\u002F3.endpoints",{"title":65,"path":66,"stem":67},"Webhooks","\u002Fdocs\u002Fapi\u002Fwebhooks","docs\u002F6.api\u002F4.webhooks",{"title":69,"path":70,"stem":71},"MCP e agentes de IA","\u002Fdocs\u002Fmcp","docs\u002F7.mcp",{"title":73,"path":74,"stem":75},"Receitas por negócio","\u002Fdocs\u002Frecipes","docs\u002F8.recipes",{"title":77,"path":78,"stem":79},"WebChat no seu site","\u002Fdocs\u002Fwebchat","docs\u002F9.webchat",[81,85,91,96,101,106,109,114,119,124,129,134,139,144,148,151,156,161,166,171,174,179,184,189,194,197,202,207,212,217,222,225,230,235,240,245,250,253,258,263,268,273,278,283,286,291,296,301,306,311,316,319,324,329,334,337,342,347,352,357,362,365,370,375,380,385,390,395,398,403,408,413,418,423,426,431,436,441,446,449,454,459,464,469,474,477,482,487,492],{"id":11,"title":10,"titles":82,"content":83,"level":84},[],"O que é o Wagend, para quem é e os blocos que você vai usar. O Wagend é um motor de agendamento com WhatsApp + IA como canal principal. Seus clientes agendam conversando; o sistema oferece só horários que existem de verdade, faz a pré-reserva, confirma e envia lembretes. O negócio gerencia tudo em um painel, e desenvolvedores integram via API REST e webhooks. O Wagend está em desenvolvimento. Esta documentação descreve o contrato-alvo (rascunho da API v1). Os endpoints ainda podem mudar antes do piloto.",1,{"id":86,"title":87,"titles":88,"content":89,"level":90},"\u002Fdocs\u002Fintroduction#para-quem-é","Para quem é",[10],"Qualquer negócio que vende o tempo de alguém ou de algo: NegócioO que é agendadoBarbeariaUm barbeiro por 30–45 minutosEstéticaUm profissional e uma máquina e uma cabine, ao mesmo tempoClínicaUm médico e um consultórioRestauranteLugares no salão conforme o tamanho do grupoEntregasCapacidade numa janela de 2 horas para uma zonaAulas, quadras, salasUma vaga na aula ou uma quadra por hora",2,{"id":92,"title":93,"titles":94,"content":95,"level":90},"\u002Fdocs\u002Fintroduction#blocos-principais","Blocos principais",[10],"Organização → sua conta. Tem um ou mais workspaces (um negócio ou unidade).Recurso → o que é consumido: um barbeiro, uma mesa, uma máquina de laser, uma sala, uma zona de entrega.Serviço → o que o cliente agenda. Declara seus requisitos: quais recursos precisa, e quantos, ao mesmo tempo.Horário → quando cada recurso está disponível.Agendamento → passa por uma pré-reserva (10 minutos) antes de ser confirmado.Automação → lembretes, confirmações e avisos disparados por eventos do agendamento. Leia Workspaces e recursos para o modelo completo.",{"id":97,"title":98,"titles":99,"content":100,"level":90},"\u002Fdocs\u002Fintroduction#canais","Canais",[10],"Todos os canais usam o mesmo motor: um horário reservado no WhatsApp some na hora do painel e da API. WhatsApp com assistente de IA (texto e áudio).Página pública de reserva, widget para incorporar e MCP para agentes de IA: Em breve.Painel para a equipe (agenda do dia, inbox, calendário, configurações).API REST e webhooks para desenvolvedores.",{"id":102,"title":103,"titles":104,"content":105,"level":90},"\u002Fdocs\u002Fintroduction#próximos-passos","Próximos passos",[10],"Início rápido: faça seu primeiro agendamento pela API em 5 minutos.Como funciona: a arquitetura e a vida de uma mensagem.MCP: a conexão prevista para agentes de IA (em breve).",{"id":15,"title":14,"titles":107,"content":108,"level":84},[],"Crie seu primeiro agendamento pela API em cinco minutos com uma chave de um negócio de teste. Este guia cria um agendamento real, então use uma chave de produção (wg_live_...) de um negócio que você montou para testes. Chaves wg_test_ são somente leitura hoje: um sandbox para escritas está em breve. Para testar o bot sem WhatsApp, use o simulador do painel. URL base: https:\u002F\u002Fapi.wagend.app\u002Fv1. Toda requisição precisa de Authorization: Bearer \u003Cchave>.",{"id":110,"title":111,"titles":112,"content":113,"level":90},"\u002Fdocs\u002Fquickstart#_1-gere-uma-chave","1. Gere uma chave",[14],"No painel, vá em Configurações → Desenvolvedores, crie uma chave de Produção e marque os escopos slots:read, bookings:write e config:read. A chave aparece uma única vez. export WAGEND_KEY=\"wg_live_xxxxxxxx_xxxxxxxxxxxxxxxxxxxx\"",{"id":115,"title":116,"titles":117,"content":118,"level":90},"\u002Fdocs\u002Fquickstart#_2-veja-quem-você-é","2. Veja quem você é",[14],"curl https:\u002F\u002Fapi.wagend.app\u002Fv1\u002Fme -H \"Authorization: Bearer $WAGEND_KEY\" {\n  \"workspace\": { \"id\": \"ws_9f2c\", \"name\": \"Barbearia Centro\", \"timezone\": \"America\u002FSao_Paulo\", \"locale\": \"pt\", \"currency\": \"BRL\" },\n  \"scopes\": [\"slots:read\", \"bookings:write\", \"config:read\"],\n  \"mode\": \"live\"\n} O workspace sempre vem da chave. Você nunca envia um id de workspace.",{"id":120,"title":121,"titles":122,"content":123,"level":90},"\u002Fdocs\u002Fquickstart#_3-liste-os-serviços","3. Liste os serviços",[14],"curl https:\u002F\u002Fapi.wagend.app\u002Fv1\u002Fservices -H \"Authorization: Bearer $WAGEND_KEY\" {\n  \"data\": [\n    { \"id\": \"svc_corte\", \"name\": \"Corte\", \"duration_min\": 30, \"price_cents\": 5000, \"currency\": \"BRL\",\n      \"requirements\": [{ \"resource_group_id\": \"grp_barbers\", \"units\": 1 }] }\n  ]\n}",{"id":125,"title":126,"titles":127,"content":128,"level":90},"\u002Fdocs\u002Fquickstart#_4-busque-horários-disponíveis","4. Busque horários disponíveis",[14],"curl \"https:\u002F\u002Fapi.wagend.app\u002Fv1\u002Fslots?service_id=svc_corte&from=2026-10-15T08:00:00-03:00&to=2026-10-15T13:00:00-03:00\" \\\n  -H \"Authorization: Bearer $WAGEND_KEY\" {\n  \"data\": [\n    { \"start\": \"2026-10-15T09:00:00-03:00\", \"end\": \"2026-10-15T09:30:00-03:00\", \"resource_ids\": [\"res_juan\"] },\n    { \"start\": \"2026-10-15T09:45:00-03:00\", \"end\": \"2026-10-15T10:15:00-03:00\", \"resource_ids\": [\"res_juan\"] }\n  ],\n  \"unavailable_reason\": null\n}",{"id":130,"title":131,"titles":132,"content":133,"level":90},"\u002Fdocs\u002Fquickstart#_5-faça-a-pré-reserva","5. Faça a pré-reserva",[14],"A pré-reserva (hold) segura o horário por 10 minutos enquanto você coleta os dados do cliente. Sempre envie um Idempotency-Key para que reenvios sejam seguros. curl -X POST https:\u002F\u002Fapi.wagend.app\u002Fv1\u002Fholds \\\n  -H \"Authorization: Bearer $WAGEND_KEY\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{ \"service_id\": \"svc_corte\", \"start\": \"2026-10-15T09:45:00-03:00\", \"resource_ids\": [\"res_juan\"] }' { \"id\": \"bkg_7Qx1\", \"status\": \"held\", \"expires_at\": \"2026-10-14T15:30:00-03:00\", \"start\": \"2026-10-15T09:45:00-03:00\" }",{"id":135,"title":136,"titles":137,"content":138,"level":90},"\u002Fdocs\u002Fquickstart#_6-confirme","6. Confirme",[14],"curl -X POST https:\u002F\u002Fapi.wagend.app\u002Fv1\u002Fholds\u002Fbkg_7Qx1\u002Fconfirm \\\n  -H \"Authorization: Bearer $WAGEND_KEY\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{ \"customer\": { \"name\": \"Carlos\", \"phone\": \"+5521999990000\", \"locale\": \"pt\" } }' { \"id\": \"bkg_7Qx1\", \"status\": \"confirmed\", \"start\": \"2026-10-15T09:45:00-03:00\", \"source\": \"api\" } Se o serviço exige sinal, o status fica pending_payment. A cobrança do sinal via Pix está em breve.",{"id":140,"title":141,"titles":142,"content":143,"level":90},"\u002Fdocs\u002Fquickstart#o-mesmo-fluxo-em-javascript","O mesmo fluxo em JavaScript",[14],"const api = (path: string, init: RequestInit = {}) =>\n  fetch(`https:\u002F\u002Fapi.wagend.app\u002Fv1${path}`, {\n    ...init,\n    headers: { Authorization: `Bearer ${process.env.WAGEND_KEY}`, 'Content-Type': 'application\u002Fjson', ...init.headers },\n  }).then((r) => r.json())\n\nconst { data: slots } = await api(`\u002Fslots?service_id=svc_corte&from=${from}&to=${to}`)\nconst hold = await api('\u002Fholds', {\n  method: 'POST',\n  headers: { 'Idempotency-Key': crypto.randomUUID() },\n  body: JSON.stringify({ service_id: 'svc_corte', start: slots[0].start }),\n})\nconst booking = await api(`\u002Fholds\u002F${hold.id}\u002Fconfirm`, {\n  method: 'POST',\n  headers: { 'Idempotency-Key': crypto.randomUUID() },\n  body: JSON.stringify({ customer: { name: 'Carlos', phone: '+5521999990000' } }),\n})",{"id":145,"title":103,"titles":146,"content":147,"level":90},"\u002Fdocs\u002Fquickstart#próximos-passos",[14],"Reaja a agendamentos com webhooks.Veja todos os endpoints na referência. html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}",{"id":19,"title":18,"titles":149,"content":150,"level":84},[],"Arquitetura, princípios e a vida de uma mensagem de WhatsApp dentro do Wagend.",{"id":152,"title":153,"titles":154,"content":155,"level":90},"\u002Fdocs\u002Fhow-it-works#princípios","Princípios",[18],"Núcleo determinístico, IA como intérprete. A IA entende o cliente e chama ferramentas. O motor calcula disponibilidade, faz a pré-reserva, e confirma. A IA nunca inventa horário nem preço.O banco de dados garante as regras. Overbooking é impossível porque o PostgreSQL rejeita alocações sobrepostas, não porque o app \"confere antes\".API primeiro. Painel e bot de WhatsApp usam os mesmos serviços. Se algo não dá para fazer pela API, está faltando na API.A credencial define o negócio. Uma chave ou sessão sempre pertence a um workspace.",{"id":157,"title":158,"titles":159,"content":160,"level":90},"\u002Fdocs\u002Fhow-it-works#arquitetura","Arquitetura",[18],"Canais:     WhatsApp · Painel · REST\n                 │\nGateway:    credencial → workspace · escopos · limites · webhooks assinados\n                 │\nNúcleo:     conversas + IA │ motor de agenda │ automações │ conhecimento\n                 │\nDados:      PostgreSQL (segurança por linha, constraints de exclusão, jobs) · Redis\nExternos:   modelos de IA (OpenRouter) · transcrição de áudio · provedor de WhatsApp",{"id":162,"title":163,"titles":164,"content":165,"level":90},"\u002Fdocs\u002Fhow-it-works#a-vida-de-uma-mensagem","A vida de uma mensagem",[18],"Chega. O provedor de WhatsApp chama nosso webhook. Verificamos a assinatura HMAC, descartamos duplicadas pelo id da mensagem e guardamos. Respondemos em menos de 200 ms.É entendida. Áudios são transcritos. Identificamos cliente e conversa. Se uma pessoa assumiu, o bot fica em silêncio.A IA pede. O modelo recebe o contexto do negócio, data e hora locais, um estado estruturado da conversa e as últimas mensagens. Ele só pode chamar ferramentas como find_slots, hold_slot ou confirm_hold.O motor decide. Cada chamada é validada contra um schema estrito e as regras do negócio, e então executada. Erros voltam como dados estruturados (por exemplo slot_taken com alternativas) para a IA perguntar de novo.Resposta exata. Datas, horários, serviços, preços e endereços saem de modelos de mensagem preenchidos com o resultado real.Eventos. booking.confirmed e companhia disparam automações (lembretes) e seus webhooks.",{"id":167,"title":168,"titles":169,"content":170,"level":90},"\u002Fdocs\u002Fhow-it-works#para-onde-ir","Para onde ir",[18],"Agendamentos e pré-reservas explica as garantias.WhatsApp e IA explica o que a IA pode e não pode fazer.",{"id":28,"title":27,"titles":172,"content":173,"level":84},[],"Organizações, workspaces, papéis, recursos, modos de capacidade e grupos de recursos.",{"id":175,"title":176,"titles":177,"content":178,"level":90},"\u002Fdocs\u002Fconcepts\u002Fworkspaces-and-resources#organização-e-workspaces","Organização e workspaces",[27],"Uma organização é a conta que paga. Ela contém um ou mais workspaces. Um workspace é um negócio ou unidade com seus próprios: fuso horário, idioma e moeda,número(s) de WhatsApp,bot, serviços, recursos e equipe. Uma rede de três barbearias é uma organização com três workspaces.",{"id":180,"title":181,"titles":182,"content":183,"level":90},"\u002Fdocs\u002Fconcepts\u002Fworkspaces-and-resources#papéis","Papéis",[27],"PapelPodeownerTudo, em todos os workspaces da organizaçãomanagerTudo dentro de um workspacestaffVer e gerenciar só os próprios recursos (por exemplo, o barbeiro vê só a sua agenda)viewerSomente leitura A equipe também pode agir pelo WhatsApp depois de vincular o número com um código de uso único. Ações de administrador pelo WhatsApp sempre pedem confirmação SIM\u002FNÃO.",{"id":185,"title":186,"titles":187,"content":188,"level":90},"\u002Fdocs\u002Fconcepts\u002Fworkspaces-and-resources#recursos","Recursos",[27],"Um recurso é qualquer coisa consumida por um agendamento. kindExemplosstaffBarbeiro, médico, esteticista, instrutorspaceSala, consultório, cabine, salãoequipmentMáquina de laser, cadeira, quadratableMesa de restaurante (modo mesas)vehicleVan, equipe de entregazoneÁrea de entrega por CEP Cada recurso tem um modo de capacidade: exclusive — atende um agendamento por vez (um barbeiro, uma sala, uma máquina).pooled — tem capacidade em unidades (40 lugares por turno, 12 vagas numa aula, 10 entregas por janela).",{"id":190,"title":191,"titles":192,"content":193,"level":90},"\u002Fdocs\u002Fconcepts\u002Fworkspaces-and-resources#grupos-de-recursos","Grupos de recursos",[27],"Um grupo de recursos é um conjunto intercambiável (\"qualquer barbeiro\", \"máquinas de laser\"). Serviços exigem grupos, não recursos individuais, para que o motor escolha um. A estratégia de alocação decide qual: assignmentComportamentocustomer_choiceO cliente escolhe (por exemplo \"com o Juan\"); se não tiver preferência, usa outra estratégiaround_robinReveza entre os membrosleast_busyEscolhe o membro com menos agendamentos no diafixedSempre o mesmo membro (máquina única, sala única) {\n  \"name\": \"Barbeiros\",\n  \"assignment\": \"customer_choice\",\n  \"member_ids\": [\"res_juan\", \"res_pedro\", \"res_leo\"]\n} html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"id":32,"title":31,"titles":195,"content":196,"level":84},[],"Serviços, requisitos com vários recursos, horários e como os slots são calculados.",{"id":198,"title":199,"titles":200,"content":201,"level":90},"\u002Fdocs\u002Fconcepts\u002Fservices-and-availability#serviços","Serviços",[31],"Um serviço é o que o cliente agenda. CampoSignificadoduration_minDuração do serviçostep_minGrade de início (a cada 15, 30 minutos…)buffer_before_min \u002F buffer_after_minTempo de preparo ou limpeza bloqueado ao redor do agendamentoprice_cents, currencyPreço que o bot informa (sempre do banco de dados)deposit_centsSinal exigido para confirmar (cobrança via Pix: em breve)lead_time_minAntecedência mínima (por exemplo 60 minutos)max_advance_daysCom quanta antecedência máxima o cliente pode agendarwindow_modeO slot é uma janela fixa (entregas: 14:00–16:00)fulfillment_modescheduled (padrão, com horário) ou queue (despacho por fila, sem horário fixo)intake_formJSON Schema de dados extras a coletar (convênio, endereço…)requirementsQuais recursos o serviço precisa ao mesmo tempo",{"id":203,"title":204,"titles":205,"content":206,"level":90},"\u002Fdocs\u002Fconcepts\u002Fservices-and-availability#janela-ou-despacho-dois-modos-de-cumprimento","Janela ou despacho: dois modos de cumprimento",[31],"Cada serviço define como o agendamento é cumprido (fulfillment_mode): scheduled (o padrão): o agendamento ocupa um intervalo de tempo conhecido — um horário fixo ou, com window_mode, uma janela (entregas das 14:00 às 16:00, com cota por zona).queue (despacho, para água, gás ou delivery sob demanda): o agendamento não tem horário fixo — entra na fila de pendências de um entregador. O motor o atribui ao entregador com menos tarefas ativas e cada entregador tem um limite de tarefas ativas por vez, garantido no banco de dados. A fila usa os mesmos estados de um agendamento: pendente → aceita → iniciada → concluída (ou falhou). Assim, um mesmo negócio de entregas pode oferecer janelas programadas, despacho imediato ou os dois.",{"id":208,"title":209,"titles":210,"content":211,"level":90},"\u002Fdocs\u002Fconcepts\u002Fservices-and-availability#requisitos","Requisitos",[31],"Um requisito diz: deste grupo, preciso de tantas unidades. Um serviço pode ter vários; um slot só existe se todos estiverem livres. {\n  \"name\": \"Depilação a laser\",\n  \"duration_min\": 45,\n  \"buffer_after_min\": 10,\n  \"requirements\": [\n    { \"resource_group_id\": \"grp_professionals\", \"units\": 1 },\n    { \"resource_group_id\": \"grp_lasers\", \"units\": 1 },\n    { \"resource_group_id\": \"grp_rooms\", \"units\": 1 }\n  ]\n} Com duas profissionais e só um laser, o Wagend nunca oferece duas sessões de laser sobrepostas. Opções avançadas: units: \"party_size\" — consome tantas unidades quanto pessoas (restaurantes, aulas).offset_min \u002F duration_min num requisito — usa um recurso só em parte do serviço (por exemplo o lavatório nos últimos 15 minutos de uma coloração).",{"id":213,"title":214,"titles":215,"content":216,"level":90},"\u002Fdocs\u002Fconcepts\u002Fservices-and-availability#horários","Horários",[31],"Cada recurso tem um horário: regras semanais no fuso do recurso mais exceções para datas específicas (fechado ou horário especial). {\n  \"tz\": \"America\u002FSao_Paulo\",\n  \"weekly\": { \"tue\": [[\"09:00\", \"19:00\"]], \"sat\": [[\"08:00\", \"12:00\"], [\"13:00\", \"16:00\"]] },\n  \"overrides\": [{ \"date\": \"2026-12-24\", \"ranges\": [[\"09:00\", \"13:00\"]] }, { \"date\": \"2026-12-25\", \"closed\": true }]\n}",{"id":218,"title":219,"titles":220,"content":221,"level":90},"\u002Fdocs\u002Fconcepts\u002Fservices-and-availability#como-os-slots-são-calculados","Como os slots são calculados",[31],"Expandir os horários para o período pedido, no fuso de cada recurso.Remover agendamentos e pré-reservas ativos (mais os buffers) e bloqueios manuais.Cortar em slots candidatos conforme duração e grade do serviço.Aplicar antecedência mínima e máxima, regras de corte e tamanho do grupo.Cruzar todos os requisitos, testando os membros de cada grupo conforme a estratégia de alocação.Devolver uma lista curta e ordenada. Quando não há nada disponível, a resposta traz unavailable_reason (closed, no_staff, no_equipment, no_space, lead_time, max_advance, cutoff, full) para o bot explicar o motivo. html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"id":36,"title":35,"titles":223,"content":224,"level":84},[],"Estados do agendamento, a pré-reserva de 10 minutos, sinal e a garantia de zero overbooking.",{"id":226,"title":227,"titles":228,"content":229,"level":90},"\u002Fdocs\u002Fconcepts\u002Fbookings-and-holds#por-que-pré-reserva","Por que pré-reserva",[35],"Uma conversa no WhatsApp pode levar minutos: o cliente escolhe o horário, depois você pergunta o nome, talvez um sinal. Enquanto isso, outros clientes e a API disputam o mesmo horário. A pré-reserva (hold) segura o horário por 10 minutos (15 quando há sinal) e expira sozinha.",{"id":231,"title":232,"titles":233,"content":234,"level":90},"\u002Fdocs\u002Fconcepts\u002Fbookings-and-holds#estados","Estados",[35],"StatusSignificadoOcupa o horárioheldPré-reserva temporáriaSimpending_paymentAguardando o sinalSimconfirmedAgendadoSimchecked_inO cliente chegouSimcompletedAtendidoNãocancelledCancelado (ou substituído por reagendamento)Nãono_showFalta marcada por uma pessoaNãoexpiredPré-reserva não confirmada a tempoNão held ──confirm──► confirmed ──check-in──► checked_in ──► completed\n │  └─(sinal)──► pending_payment ──pago──► confirmed\n └─expira──► expired          confirmed ──cancela──► cancelled",{"id":236,"title":237,"titles":238,"content":239,"level":90},"\u002Fdocs\u002Fconcepts\u002Fbookings-and-holds#garantias","Garantias",[35],"Cada recurso ocupado por um agendamento é gravado como uma alocação com intervalo de tempo.Para recursos exclusive, o PostgreSQL rejeita alocações sobrepostas com uma constraint de exclusão.Para recursos pooled, os contadores de capacidade nunca passam do limite (verificação atômica).Um agendamento com vários recursos é gravado numa única transação: se qualquer recurso conflitar, nada é agendado.POST \u002Fholds e POST \u002Fholds\u002F{id}\u002Fconfirm exigem Idempotency-Key: reenviar uma requisição nunca cria um segundo agendamento. Se o horário foi ocupado enquanto o cliente decidia, você recebe 409 com code: \"slot_taken\" e uma lista de alternatives.",{"id":241,"title":242,"titles":243,"content":244,"level":90},"\u002Fdocs\u002Fconcepts\u002Fbookings-and-holds#reagendar-e-cancelar","Reagendar e cancelar",[35],"Reagendar cria um novo agendamento e cancela o anterior (ligados por rescheduled_to). Os lembretes se movem sozinhos.Cancelar libera o horário e cancela lembretes pendentes.Falta nunca é automática: o sistema sugere, uma pessoa confirma.",{"id":246,"title":247,"titles":248,"content":249,"level":90},"\u002Fdocs\u002Fconcepts\u002Fbookings-and-holds#sinal","Sinal",[35],"Se o serviço tem deposit_cents, confirmar a pré-reserva deixa o agendamento em pending_payment e o horário continua bloqueado. A cobrança do sinal via Pix está em breve: até lá o agendamento não vira confirmed sozinho e o evento payment.paid não é emitido.",{"id":40,"title":39,"titles":251,"content":252,"level":84},[],"Lembretes, confirmações e avisos como regras \"quando acontecer isto, faça aquilo\". Automações são regras com um gatilho, condições opcionais e uma ação. Cada negócio cria, ativa e ajusta as suas.",{"id":254,"title":255,"titles":256,"content":257,"level":90},"\u002Fdocs\u002Fconcepts\u002Fautomations#gatilhos","Gatilhos",[39],"GatilhoExemplobooking.confirmedEnviar o resumo do agendamentobooking.starts_in(Δ)Por exemplo 24 h antes: enviar um lembretebooking.ended(+Δ)Depois que o agendamento termina: enviar uma mensagembooking.cancelled, booking.rescheduledAvisar o clientebooking.stage_changedQuando o agendamento muda de etapa",{"id":259,"title":260,"titles":261,"content":262,"level":90},"\u002Fdocs\u002Fconcepts\u002Fautomations#condições","Condições",[39],"Serviço, recurso, número de pessoas acima de N, canal.",{"id":264,"title":265,"titles":266,"content":267,"level":90},"\u002Fdocs\u002Fconcepts\u002Fautomations#ações","Ações",[39],"Enviar uma mensagem ou modelo ao cliente, avisar a equipe, pedir confirmação SIM\u002FNÃO, mudar o status do agendamento.",{"id":269,"title":270,"titles":271,"content":272,"level":90},"\u002Fdocs\u002Fconcepts\u002Fautomations#regras-iniciais","Regras iniciais",[39],"Os modelos de negócio não ativam regras sozinhos: cada negócio cria, ativa e ajusta as suas.",{"id":274,"title":275,"titles":276,"content":277,"level":90},"\u002Fdocs\u002Fconcepts\u002Fautomations#em-breve","Em breve",[39],"Ainda não existem: os gatilhos hold.expired, payment.paid e daily_at(hh:mm) (agenda do dia para a equipe); as condições por etiqueta do cliente e por número de faltas; e as ações de criar uma tarefa interna e chamar um webhook.",{"id":279,"title":280,"titles":281,"content":282,"level":90},"\u002Fdocs\u002Fconcepts\u002Fautomations#garantias-de-execução","Garantias de execução",[39],"Os jobs são criados na mesma transação do evento do agendamento, então nunca se perdem.Antes de rodar, o job confere o agendamento de novo. Se foi reagendado ou cancelado, o job antigo é descartado.Cada job roda uma vez (chave de idempotência) e tenta de novo com espera crescente; depois de 5 falhas aparece no painel.Horário de silêncio: nada é enviado a clientes entre 21:00 e 08:00 no fuso deles.Respostas SIM\u002FNÃO são interpretadas sem IA (sim, sí, ok, 👍, não…), instantâneo e sem custo.",{"id":45,"title":44,"titles":284,"content":285,"level":84},[],"Conectar um número, o que o assistente pode e não pode fazer, ações da equipe e transferência para humano.",{"id":287,"title":288,"titles":289,"content":290,"level":90},"\u002Fdocs\u002Fwhatsapp-and-ai#conectar-um-número","Conectar um número",[44],"No painel, vá em Canais → WhatsApp → Conectar e escaneie o QR com o celular do negócio, como no WhatsApp Web. Um workspace pode conectar vários números (um por unidade, por exemplo). Use um número dedicado ao negócio. Hoje a conexão por QR é a única forma de conectar.",{"id":292,"title":293,"titles":294,"content":295,"level":90},"\u002Fdocs\u002Fwhatsapp-and-ai#clientes-e-equipe","Clientes e equipe",[44],"O papel é decidido no código, nunca pelo que alguém diz no chat: Um número vinculado a alguém da equipe (verificado com código de uso único) recebe ferramentas de equipe.Todos os outros recebem ferramentas de cliente. Ferramentas de clienteFerramentas de equipe (extras)list_services, find_slots, hold_slot, confirm_hold, my_bookings, cancel_my_booking, reschedule_my_booking, get_business_info, search_knowledge, handoff_to_humanlist_today, block_time, mark_no_show, update_catalog_item — sempre com confirmação SIM\u002FNÃO",{"id":297,"title":298,"titles":299,"content":300,"level":90},"\u002Fdocs\u002Fwhatsapp-and-ai#o-que-a-ia-pode-e-não-pode-fazer","O que a IA pode e não pode fazer",[44],"PodeNão podeEntender texto, áudio, erros de digitação e mudanças de ideiaInventar horários, preços ou endereçosBuscar horários e oferecer 2–3 opçõesConfirmar um agendamento sem o motorFazer a pré-reserva e pedir os dados que faltamUsar ferramentas de administrador com um clienteResponder dúvidas com a base de conhecimento do negócioSeguir instruções escondidas em mensagens ou arquivosPassar a conversa para uma pessoaVer dados de outro negócio Ids de workspace, ids de cliente e preços são injetados pelo sistema; o modelo nunca os fornece.",{"id":302,"title":303,"titles":304,"content":305,"level":90},"\u002Fdocs\u002Fwhatsapp-and-ai#transferência-para-humano","Transferência para humano",[44],"A equipe vê todas as conversas ao vivo no Inbox. Assumir uma conversa pausa o bot nela; ele volta sozinho depois de 15 minutos sem atividade do atendente. O assistente também transfere quando o cliente pede (\"quero falar com uma pessoa\").",{"id":307,"title":308,"titles":309,"content":310,"level":90},"\u002Fdocs\u002Fwhatsapp-and-ai#áudios-e-idiomas","Áudios e idiomas",[44],"Áudios são transcritos antes de a IA ler, e a transcrição aparece no inbox. O assistente responde no idioma do cliente (português, espanhol ou inglês).",{"id":312,"title":313,"titles":314,"content":315,"level":90},"\u002Fdocs\u002Fwhatsapp-and-ai#modelos","Modelos",[44],"A camada de IA roda via OpenRouter com uma chave e um limite de gasto próprios por workspace. O padrão é um modelo rápido e barato; um modelo mais forte só é usado nos turnos que falham na validação. Os provedores são fixados entre os que não retêm dados.",{"id":54,"title":53,"titles":317,"content":318,"level":84},[],"Chaves de API, escopos, modos de teste e produção.",{"id":320,"title":321,"titles":322,"content":323,"level":90},"\u002Fdocs\u002Fapi\u002Fauthentication#chaves-de-api","Chaves de API",[53],"Envie sua chave como bearer token: GET \u002Fv1\u002Fme HTTP\u002F1.1\nHost: api.wagend.app\nAuthorization: Bearer wg_live_3fa9c2_Lr8t... PrefixoModowg_live_Dados de produção e mensagens reaiswg_test_Somente leitura: permite listar e ler, não criar nem alterar nada. Um sandbox para escritas está em breve As chaves pertencem a um workspace. O workspace sempre é tirado da chave: não existe id de workspace em paths nem em corpos. As chaves são guardadas com hash; a chave completa aparece só uma vez, na criação.",{"id":325,"title":326,"titles":327,"content":328,"level":90},"\u002Fdocs\u002Fapi\u002Fauthentication#escopos","Escopos",[53],"EscopoPermiteslots:readGET \u002Fslotsbookings:readListar e ler agendamentosbookings:writePré-reservas, confirmar, cancelar, reagendar, check-in, faltacustomers:readLer clientesmessages:readLer conversas e mensagensmessages:writeEnviar mensagens, transferirconfig:read \u002F config:writeServiços, recursos, grupos, horários, automações, conhecimentowebhooks:manageEndpoints de webhook Uma requisição sem o escopo necessário devolve 403 com code: \"insufficient_scope\".",{"id":330,"title":331,"titles":332,"content":333,"level":90},"\u002Fdocs\u002Fapi\u002Fauthentication#rotação","Rotação",[53],"Crie uma chave nova, publique, e depois revogue a antiga em Configurações → Desenvolvedores. Chaves revogadas devolvem 401 na hora. html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"id":58,"title":57,"titles":335,"content":336,"level":84},[],"Formatos, idempotência, paginação, erros e limites de requisição.",{"id":338,"title":339,"titles":340,"content":341,"level":90},"\u002Fdocs\u002Fapi\u002Fconventions#básico","Básico",[57],"URL base https:\u002F\u002Fapi.wagend.app\u002Fv1. Mudanças incompatíveis saem como nova versão.JSON na entrada e na saída (Content-Type: application\u002Fjson).Datas em ISO 8601 com offset (2026-10-15T09:45:00-03:00). Guardadas em UTC.Valores em centavos inteiros mais currency (BRL, ARS, PYG, USD).IDs são strings opacas com prefixo (bkg_, svc_, res_, grp_, cus_).",{"id":343,"title":344,"titles":345,"content":346,"level":90},"\u002Fdocs\u002Fapi\u002Fconventions#idempotência","Idempotência",[57],"POST \u002Fholds, POST \u002Fholds\u002F{id}\u002Fconfirm, POST \u002Fbookings e POST \u002Fbookings\u002F{id}\u002Freschedule exigem o header Idempotency-Key (por exemplo um UUID). Repetir uma requisição com a mesma chave em até 24 horas devolve a resposta original. Reutilizar a chave com outro corpo devolve 422.",{"id":348,"title":349,"titles":350,"content":351,"level":90},"\u002Fdocs\u002Fapi\u002Fconventions#paginação","Paginação",[57],"Os endpoints de lista usam cursores: curl \"https:\u002F\u002Fapi.wagend.app\u002Fv1\u002Fbookings?limit=50\" -H \"Authorization: Bearer $WAGEND_KEY\"\n# → { \"data\": [...], \"next_cursor\": \"eyJpZCI6...\" }\ncurl \"https:\u002F\u002Fapi.wagend.app\u002Fv1\u002Fbookings?limit=50&cursor=eyJpZCI6...\" -H \"Authorization: Bearer $WAGEND_KEY\"",{"id":353,"title":354,"titles":355,"content":356,"level":90},"\u002Fdocs\u002Fapi\u002Fconventions#erros","Erros",[57],"Os erros seguem a RFC 9457 (application\u002Fproblem+json): {\n  \"type\": \"https:\u002F\u002Fwagend.app\u002Fdocs\u002Fapi\u002Fconventions#errors\",\n  \"title\": \"Slot no longer available\",\n  \"status\": 409,\n  \"code\": \"slot_taken\",\n  \"alternatives\": [{ \"start\": \"2026-10-15T10:15:00-03:00\", \"end\": \"2026-10-15T10:45:00-03:00\" }]\n} codeStatusQuandoinvalid_request400 \u002F 422Falha de validaçãounauthorized401Chave ausente, inválida ou revogadainsufficient_scope403A chave não tem o escoponot_found404Id desconhecido (ou de outro workspace)slot_taken409Outra pessoa pegou o horárioinvalid_transition409Por exemplo confirmar um agendamento canceladohold_expired410A pré-reserva expirou antes de confirmaridempotency_mismatch422Mesma chave, corpo diferenterate_limited429Requisições demais",{"id":358,"title":359,"titles":360,"content":361,"level":90},"\u002Fdocs\u002Fapi\u002Fconventions#limites-de-requisição","Limites de requisição",[57],"Os limites valem por chave e por workspace. Toda resposta traz RateLimit-Limit, RateLimit-Remaining e RateLimit-Reset. Em 429, espere Retry-After segundos. html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"id":62,"title":61,"titles":363,"content":364,"level":84},[],"Todos os endpoints da v1 num relance, com os formatos mais comuns de requisição e resposta. O contrato legível por máquina fica no repositório em packages\u002Fopenapi\u002Fopenapi.yaml (OpenAPI 3.1).",{"id":366,"title":367,"titles":368,"content":369,"level":90},"\u002Fdocs\u002Fapi\u002Fendpoints#agenda","Agenda",[61],"MétodoPathEscopoDescriçãoGET\u002Fslotsslots:readHorários disponíveis para um serviçoPOST\u002Fholdsbookings:writeCriar pré-reserva de 10 minutosPOST\u002Fholds\u002F{id}\u002Fconfirmbookings:writeConfirmar (ou pending_payment se exigir sinal)DELETE\u002Fholds\u002F{id}bookings:writeLiberar pré-reservaGET\u002Fbookingsbookings:readListar (filtros: from, to, status, resource_id, customer_id)POST\u002Fbookingsbookings:writePré-reserva + confirmação numa chamadaGET \u002F PATCH\u002Fbookings\u002F{id}bookings:read \u002F writeLer, atualizar notas ou dados de cadastroPOST\u002Fbookings\u002F{id}\u002Fcancelbookings:writeCancelarPOST\u002Fbookings\u002F{id}\u002Freschedulebookings:writeMudar para um novo inícioPOST\u002Fbookings\u002F{id}\u002Fcheck-inbookings:writeMarcar chegadaPOST\u002Fbookings\u002F{id}\u002Fno-showbookings:writeMarcar falta",{"id":371,"title":372,"titles":373,"content":374,"level":90},"\u002Fdocs\u002Fapi\u002Fendpoints#catálogo","Catálogo",[61],"MétodoPathEscopoGET \u002F POST\u002Fservicesconfig:read \u002F config:writeGET \u002F POST\u002Fresourcesconfig:read \u002F config:writeGET\u002Fresource-groupsconfig:readPOST\u002Fschedules\u002F{id}\u002Foverridesconfig:write",{"id":376,"title":377,"titles":378,"content":379,"level":90},"\u002Fdocs\u002Fapi\u002Fendpoints#clientes-e-conversas","Clientes e conversas",[61],"MétodoPathEscopoGET\u002Fcustomerscustomers:readGET\u002Fconversationsmessages:readGET \u002F POST\u002Fconversations\u002F{id}\u002Fmessagesmessages:read \u002F messages:write",{"id":381,"title":382,"titles":383,"content":384,"level":90},"\u002Fdocs\u002Fapi\u002Fendpoints#plataforma","Plataforma",[61],"MétodoPathEscopoGET\u002FmequalquerGET \u002F POST\u002Fwebhook-endpointswebhooks:manage",{"id":386,"title":387,"titles":388,"content":389,"level":90},"\u002Fdocs\u002Fapi\u002Fendpoints#exemplo-slots","Exemplo: slots",[61],"GET \u002Fv1\u002Fslots?service_id=svc_laser&from=2026-10-20T09:00:00-03:00&to=2026-10-20T20:00:00-03:00&around=2026-10-20T18:00:00-03:00 {\n  \"data\": [\n    { \"start\": \"2026-10-20T17:45:00-03:00\", \"end\": \"2026-10-20T18:30:00-03:00\", \"resource_ids\": [\"res_ana\", \"res_laser1\", \"res_room2\"] },\n    { \"start\": \"2026-10-20T18:45:00-03:00\", \"end\": \"2026-10-20T19:30:00-03:00\", \"resource_ids\": [\"res_carla\", \"res_laser1\", \"res_room1\"] }\n  ],\n  \"unavailable_reason\": null\n}",{"id":391,"title":392,"titles":393,"content":394,"level":90},"\u002Fdocs\u002Fapi\u002Fendpoints#exemplo-objeto-de-agendamento","Exemplo: objeto de agendamento",[61],"{\n  \"id\": \"bkg_7Qx1\",\n  \"status\": \"confirmed\",\n  \"service_id\": \"svc_laser\",\n  \"start\": \"2026-10-20T17:45:00-03:00\",\n  \"end\": \"2026-10-20T18:30:00-03:00\",\n  \"party_size\": 1,\n  \"customer\": { \"id\": \"cus_31\", \"name\": \"Marina\", \"phone\": \"+5521988887777\", \"locale\": \"pt\" },\n  \"allocations\": [\n    { \"resource_id\": \"res_ana\", \"start\": \"2026-10-20T17:45:00-03:00\", \"end\": \"2026-10-20T18:40:00-03:00\", \"units\": 1 },\n    { \"resource_id\": \"res_laser1\", \"start\": \"2026-10-20T17:45:00-03:00\", \"end\": \"2026-10-20T18:40:00-03:00\", \"units\": 1 },\n    { \"resource_id\": \"res_room2\", \"start\": \"2026-10-20T17:45:00-03:00\", \"end\": \"2026-10-20T18:40:00-03:00\", \"units\": 1 }\n  ],\n  \"source\": \"whatsapp\",\n  \"created_at\": \"2026-10-19T11:02:13-03:00\"\n} As alocações incluem o buffer (aqui 10 minutos depois do serviço). html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}",{"id":66,"title":65,"titles":396,"content":397,"level":84},[],"Eventos assinados de agendamentos e conversas, com reenvio automático.",{"id":399,"title":400,"titles":401,"content":402,"level":90},"\u002Fdocs\u002Fapi\u002Fwebhooks#eventos","Eventos",[65],"EventoQuandobooking.createdUma pré-reserva ou agendamento foi criadobooking.confirmedUm agendamento foi confirmadobooking.cancelledCancelado ou expiradobooking.rescheduledMudou de horário (o payload traz o id antigo e o novo)booking.no_showMarcado como faltabooking.completedAtendimento concluídopayment.paidReservado: ainda não é emitido (sinal via Pix: em breve)message.receivedChegou uma mensagem de clienteconversation.handoffUma conversa foi passada para uma pessoa Crie endpoints com POST \u002Fv1\u002Fwebhook-endpoints. O segredo de assinatura aparece uma única vez.",{"id":404,"title":405,"titles":406,"content":407,"level":90},"\u002Fdocs\u002Fapi\u002Fwebhooks#payload","Payload",[65],"{\n  \"id\": \"evt_3f6c1d9e0b7a4c2f8e5d1a9b7c3e6f20\",\n  \"type\": \"booking.confirmed\",\n  \"created_at\": \"2026-10-14T15:21:07-03:00\",\n  \"workspace_id\": \"b3a6c8e2-5f1d-4c7a-9e0b-2d8f4a1c6e53\",\n  \"data\": { \"booking\": { \"id\": \"6d1f0c4a-7b2e-4a58-9c3d-0e5f8a2b1c47\", \"status\": \"confirmed\", \"start_at\": \"2026-10-15T12:45:00+00:00\" } }\n} A entrega é pelo menos uma vez: use o id para ignorar duplicados.",{"id":409,"title":410,"titles":411,"content":412,"level":90},"\u002Fdocs\u002Fapi\u002Fwebhooks#verificando-a-assinatura","Verificando a assinatura",[65],"Toda requisição traz o header: Wagend-Signature: t=1791040867,v1=5c2b9f...e81 v1 é HMAC-SHA256(segredo, t + \".\" + corpo_bruto) em hexadecimal. Rejeite requisições com mais de 5 minutos. import crypto from 'node:crypto'\n\nexport function verifyWagend(rawBody: string, header: string, secret: string) {\n  const parts = Object.fromEntries(header.split(',').map((p) => p.split('=') as [string, string]))\n  const age = Math.abs(Date.now() \u002F 1000 - Number(parts.t))\n  if (!parts.t || !parts.v1 || age > 300) return false\n  const expected = crypto.createHmac('sha256', secret).update(`${parts.t}.${rawBody}`).digest('hex')\n  return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1))\n} import hashlib, hmac, time\n\ndef verify_wagend(raw_body: bytes, header: str, secret: str) -> bool:\n    parts = dict(p.split(\"=\", 1) for p in header.split(\",\"))\n    if abs(time.time() - int(parts.get(\"t\", \"0\"))) > 300:\n        return False\n    signed = f\"{parts['t']}.\".encode() + raw_body\n    expected = hmac.new(secret.encode(), signed, hashlib.sha256).hexdigest()\n    return hmac.compare_digest(expected, parts.get(\"v1\", \"\"))",{"id":414,"title":415,"titles":416,"content":417,"level":90},"\u002Fdocs\u002Fapi\u002Fwebhooks#reenvios","Reenvios",[65],"Responda com qualquer 2xx em até 10 segundos. Caso contrário, tentamos de novo após 1 min, 5 min, 30 min, 2 h e 12 h. Cada tentativa aparece no log de entregas, onde você também pode reenviar manualmente.",{"id":419,"title":420,"titles":421,"content":422,"level":90},"\u002Fdocs\u002Fapi\u002Fwebhooks#segurança-e-limites","Segurança e limites",[65],"A URL deve ser https e resolver para um endereço público: rejeitamos localhost, redes privadas, link-local e endereços de metadados de nuvem (ao cadastrar e a cada entrega). Não seguimos redirecionamentos (um 3xx conta como falha).Cabeçalhos extras: Wagend-Event (tipo) e Wagend-Delivery (id da entrega). Cada tentativa é assinada com um timestamp novo.Até 10 endpoints por workspace. Após 10 falhas consecutivas o endpoint é desativado (reative com PATCH \u002Fv1\u002Fwebhook-endpoints\u002F{id} e {\"active\": true}).POST \u002Fv1\u002Fwebhook-endpoints\u002F{id}\u002Fping envia um evento de teste webhook.ping; POST \u002Fv1\u002Fwebhook-endpoints\u002F{id}\u002Frotate-secret gera um novo segredo (mostrado uma única vez; o anterior deixa de valer na hora).Com API key use o escopo webhooks:manage. O log fica em GET \u002Fv1\u002Fwebhook-endpoints\u002F{id}\u002Fdeliveries e o reenvio em POST …\u002Fdeliveries\u002F{delivery_id}\u002Fresend. html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}",{"id":70,"title":69,"titles":424,"content":425,"level":84},[],"Deixe o Claude, o ChatGPT ou seu próprio agente buscar horários, agendar e operar um negócio via Model Context Protocol. Em breve: o servidor MCP ainda não está disponível. Esta página descreve o que está previsto. O Wagend expõe um servidor MCP para que agentes de IA usem o mesmo motor do bot de WhatsApp: mesmas pré-reservas, mesma validação, mesmo registro de auditoria.",{"id":427,"title":428,"titles":429,"content":430,"level":90},"\u002Fdocs\u002Fmcp#conectar","Conectar",[69],"URL: https:\u002F\u002Fmcp.wagend.app (Streamable HTTP)Autenticação: uma chave de API no header Authorization. OAuth virá depois. Exemplo de configuração do cliente: {\n  \"mcpServers\": {\n    \"wagend\": {\n      \"type\": \"http\",\n      \"url\": \"https:\u002F\u002Fmcp.wagend.app\",\n      \"headers\": { \"Authorization\": \"Bearer wg_live_...\" }\n    }\n  }\n}",{"id":432,"title":433,"titles":434,"content":435,"level":90},"\u002Fdocs\u002Fmcp#conjuntos-de-ferramentas","Conjuntos de ferramentas",[69],"As ferramentas que o agente vê dependem dos escopos da chave. Agendamento (slots:read, bookings:write) — para assistentes que agendam em nome de um cliente: FerramentaFazlist_servicesServiços com duração e preçofind_slotsHorários disponíveis para um serviço e períodohold_slotPré-reserva de 10 minutosconfirm_bookingConfirma uma pré-reserva com os dados do clientecancel_booking, reschedule_booking, get_bookingGerencia um agendamento existente Administração (config:write) — para o dono operar o negócio pelo seu assistente de IA: FerramentaFazlist_resources, list_todayEquipe, salas, máquinas e agenda do diablock_timeBloqueia um recurso (férias, manutenção)create_service, update_scheduleAltera catálogo e horáriosget_statsAgendamentos, ocupação e faltas",{"id":437,"title":438,"titles":439,"content":440,"level":90},"\u002Fdocs\u002Fmcp#exemplos-de-pedidos","Exemplos de pedidos",[69],"\"Agenda um corte com o Juan amanhã de manhã, nome Carlos.\"\"Bloqueia a máquina de laser na segunda que vem para manutenção e me diz quais agendamentos são afetados.\"\"Quantas faltas tivemos este mês?\"",{"id":442,"title":443,"titles":444,"content":445,"level":90},"\u002Fdocs\u002Fmcp#docs-para-llms","Docs para LLMs",[69],"\u002Fllms.txt lista todas as páginas da documentação.\u002Fllms-full.txt contém a documentação completa em inglês, em Markdown. html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"id":74,"title":73,"titles":447,"content":448,"level":84},[],"Como modelar uma barbearia, uma clínica de estética, um consultório, um restaurante e entregas. Cada receita corresponde a um modelo pronto que você escolhe no onboarding.",{"id":450,"title":451,"titles":452,"content":453,"level":90},"\u002Fdocs\u002Frecipes#barbearia","Barbearia",[73],"Cada barbeiro é um recurso staff exclusive com seu próprio horário. Um grupo, customer_choice com round_robin como alternativa. {\n  \"name\": \"Corte\",\n  \"duration_min\": 30,\n  \"step_min\": 15,\n  \"buffer_after_min\": 5,\n  \"price_cents\": 5000,\n  \"requirements\": [{ \"resource_group_id\": \"grp_barbers\", \"units\": 1 }]\n}",{"id":455,"title":456,"titles":457,"content":458,"level":90},"\u002Fdocs\u002Frecipes#estética","Estética",[73],"Profissionais, máquinas e cabines são recursos separados. O serviço exige os três ao mesmo tempo, então o mais escasso (geralmente a máquina) limita a agenda. {\n  \"name\": \"Depilação a laser\",\n  \"duration_min\": 45,\n  \"buffer_after_min\": 10,\n  \"price_cents\": 18000,\n  \"deposit_cents\": 5000,\n  \"requirements\": [\n    { \"resource_group_id\": \"grp_professionals\", \"units\": 1 },\n    { \"resource_group_id\": \"grp_lasers\", \"units\": 1 },\n    { \"resource_group_id\": \"grp_rooms\", \"units\": 1 }\n  ]\n}",{"id":460,"title":461,"titles":462,"content":463,"level":90},"\u002Fdocs\u002Frecipes#clínica","Clínica",[73],"Médico mais consultório, por unidade (um workspace por unidade). Dados de saúde são sensíveis: o assistente nunca pergunta sintomas, e o formulário coleta só o necessário para agendar. {\n  \"name\": \"Consulta\",\n  \"duration_min\": 30,\n  \"buffer_after_min\": 10,\n  \"intake_form\": { \"type\": \"object\", \"properties\": { \"convenio\": { \"type\": \"string\" } } },\n  \"requirements\": [\n    { \"resource_group_id\": \"grp_doctors\", \"units\": 1 },\n    { \"resource_group_id\": \"grp_offices\", \"units\": 1 }\n  ]\n}",{"id":465,"title":466,"titles":467,"content":468,"level":90},"\u002Fdocs\u002Frecipes#restaurante","Restaurante",[73],"O salão é um recurso pooled com 40 unidades (lugares) por turno. A duração cresce com o tamanho do grupo, e grupos grandes pagam sinal. {\n  \"name\": \"Mesa\",\n  \"step_min\": 30,\n  \"duration_by_units\": [\n    { \"max_units\": 2, \"duration_min\": 90 },\n    { \"max_units\": 4, \"duration_min\": 120 },\n    { \"max_units\": 20, \"duration_min\": 150 }\n  ],\n  \"requirements\": [{ \"resource_group_id\": \"grp_dining_room\", \"units\": \"party_size\" }]\n} O modo mesas (mesas específicas com tamanho mínimo e máximo, e combinações) está no roadmap.",{"id":470,"title":471,"titles":472,"content":473,"level":90},"\u002Fdocs\u002Frecipes#entregas","Entregas",[73],"Cada zona é um recurso pooled com capacidade por janela de 2 horas. A zona é escolhida pelo CEP, e uma regra de corte fecha as janelas do mesmo dia ao meio-dia. {\n  \"name\": \"Entrega\",\n  \"window_mode\": true,\n  \"duration_min\": 120,\n  \"cutoff_rule\": { \"same_day_until\": \"12:00\" },\n  \"intake_form\": { \"type\": \"object\", \"required\": [\"address\", \"cep\"] },\n  \"requirements\": [{ \"resource_group_id\": \"grp_zones\", \"units\": 1, \"select_by\": \"cep\" }]\n} html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"id":78,"title":77,"titles":475,"content":476,"level":84},[],"Coloque o assistente do Wagend no seu site com uma única linha de script, sem número de WhatsApp. O WebChat é um widget de chat que o seu negócio cola no próprio site. Ele conversa com o mesmo bot do WhatsApp (mesmos horários, preços e reservas), mas sem número nem aprovação de terceiros: ideal para testar e para a vitrine do seu site.",{"id":478,"title":479,"titles":480,"content":481,"level":90},"\u002Fdocs\u002Fwebchat#instalar","Instalar",[77],"No painel, como owner, publique o WebChat e informe os domínios permitidos (por exemplo https:\u002F\u002Fwww.minhaloja.com.br). Você recebe uma chave publicável wg_web_….Cole o snippet antes de \u003C\u002Fbody>: \u003Cscript src=\"https:\u002F\u002Fwagend.app\u002Fwidget.js\" data-key=\"wg_web_…\" defer>\u003C\u002Fscript> Atributos opcionais: data-locale (pt, es ou en; por padrão usa o idioma do navegador) e data-api (origem da API, só para ambientes de teste). Cor, posição e título vêm da configuração do workspace. Há uma página de demonstração em \u002Fdemo\u002Fwebchat onde você cola a chave e vê o widget funcionando.",{"id":483,"title":484,"titles":485,"content":486,"level":90},"\u002Fdocs\u002Fwebchat#o-que-o-visitante-vê","O que o visitante vê",[77],"Um botão flutuante que abre o chat; textos em português, espanhol ou inglês.Nome e telefone são opcionais e não são verificados: não identificam o visitante e não se unem a clientes existentes.A conversa vive na memória da página: ao recarregar, começa uma nova. Nada é gravado no navegador.",{"id":488,"title":489,"titles":490,"content":491,"level":90},"\u002Fdocs\u002Fwebchat#segurança","Segurança",[77],"A chave publicável só abre conversas anônimas: não dá acesso ao painel, à API privada nem a dados de clientes. Ela pode ser revogada a qualquer momento (e rotacionada ao publicar de novo).O workspace vem sempre da chave; o widget nunca envia um workspace_id.Só os domínios permitidos podem usar o chat (CORS por workspace). Sem cookies.A verificação de Origin não é autenticação. Só protege contra outros sites em um navegador; qualquer cliente que não seja um navegador (um script, curl) pode enviar o Origin que quiser. Por isso a chave publicável não é um segredo e a proteção real são os limites de uso, não a origem.Tetos de custo: mensagens por conversa e por hora, mensagens diárias por workspace, conversas novas por hora e conexões ao vivo simultâneas. Ao esgotar, a API responde 429 com Retry-After e o assistente não é chamado. Conversas inativas expiram sozinhas e são apagadas, inclusive o nome declarado do visitante.Limites de uso por IP, por conversa e por workspace; mensagens de até 1000 caracteres.O texto do visitante é tratado como dado não confiável pelo assistente, e o widget mostra todo texto como texto puro (nunca HTML).O chat é apenas reativo: não envia lembretes nem mensagens proativas.",{"id":493,"title":48,"titles":494,"content":495,"level":90},"\u002Fdocs\u002Fwebchat#api",[77],"Gestão (owner, cookie de painel): GET|PUT|DELETE \u002Fv1\u002Fwebchat-site. Públicos: GET \u002Fv1\u002Fpublic\u002Fwebchat\u002Fconfig, POST \u002Fv1\u002Fpublic\u002Fwebchat\u002Fsessions, GET|POST \u002Fv1\u002Fpublic\u002Fwebchat\u002Fsessions\u002F{id}\u002Fmessages e GET \u002Fv1\u002Fpublic\u002Fwebchat\u002Fsessions\u002F{id}\u002Fevents (SSE). Veja o contrato em packages\u002Fopenapi\u002Fopenapi.yaml. Desativado por padrão (PUBLIC_WEBCHAT_ENABLED=false) até a revisão de segurança e a ativação explícita. html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"id":497,"title":77,"badge":498,"body":499,"description":767,"extension":768,"meta":769,"navigation":770,"path":78,"rawbody":771,"seo":772,"stem":79,"__hash__":773},"docs_pt\u002Fdocs\u002F9.webchat.md","Rascunho",{"type":500,"value":501,"toc":760},"minimark",[502,511,515,550,601,624,635,638,658,661,720,723,746,756],[503,504,505,506,510],"p",{},"O WebChat é um widget de chat que o seu negócio cola no próprio site. Ele conversa com o ",[507,508,509],"strong",{},"mesmo bot"," do WhatsApp (mesmos horários, preços e reservas), mas sem número nem aprovação de terceiros: ideal para testar e para a vitrine do seu site.",[512,513,479],"h2",{"id":514},"instalar",[516,517,518,543],"ol",{},[519,520,521,522,525,526,529,530,534,535,538,539,542],"li",{},"No painel, como ",[507,523,524],{},"owner",", publique o WebChat e informe os ",[507,527,528],{},"domínios permitidos"," (por exemplo ",[531,532,533],"code",{},"https:\u002F\u002Fwww.minhaloja.com.br","). Você recebe uma ",[507,536,537],{},"chave publicável"," ",[531,540,541],{},"wg_web_…",".",[519,544,545,546,549],{},"Cole o snippet antes de ",[531,547,548],{},"\u003C\u002Fbody>",":",[551,552,557],"pre",{"className":553,"code":554,"language":555,"meta":556,"style":556},"language-html shiki shiki-themes github-light github-dark","\u003Cscript src=\"https:\u002F\u002Fwagend.app\u002Fwidget.js\" data-key=\"wg_web_…\" defer>\u003C\u002Fscript>\n","html","",[531,558,559],{"__ignoreMap":556},[560,561,563,567,571,575,578,582,585,587,590,593,596,598],"span",{"class":562,"line":84},"line",[560,564,566],{"class":565},"sVt8B","\u003C",[560,568,570],{"class":569},"s9eBZ","script",[560,572,574],{"class":573},"sScJk"," src",[560,576,577],{"class":565},"=",[560,579,581],{"class":580},"sZZnC","\"https:\u002F\u002Fwagend.app\u002Fwidget.js\"",[560,583,584],{"class":573}," data-key",[560,586,577],{"class":565},[560,588,589],{"class":580},"\"wg_web_…\"",[560,591,592],{"class":573}," defer",[560,594,595],{"class":565},">\u003C\u002F",[560,597,570],{"class":569},[560,599,600],{"class":565},">\n",[503,602,603,604,607,608,611,612,615,616,619,620,623],{},"Atributos opcionais: ",[531,605,606],{},"data-locale"," (",[531,609,610],{},"pt",", ",[531,613,614],{},"es"," ou ",[531,617,618],{},"en","; por padrão usa o idioma do navegador) e ",[531,621,622],{},"data-api"," (origem da API, só para ambientes de teste). Cor, posição e título vêm da configuração do workspace.",[625,626,628],"callout",{"type":627},"tip",[503,629,630,631,634],{},"Há uma página de demonstração em ",[531,632,633],{},"\u002Fdemo\u002Fwebchat"," onde você cola a chave e vê o widget funcionando.",[512,636,484],{"id":637},"o-que-o-visitante-vê",[639,640,641,644,655],"ul",{},[519,642,643],{},"Um botão flutuante que abre o chat; textos em português, espanhol ou inglês.",[519,645,646,647,650,651,654],{},"Nome e telefone são ",[507,648,649],{},"opcionais"," e ",[507,652,653],{},"não são verificados",": não identificam o visitante e não se unem a clientes existentes.",[519,656,657],{},"A conversa vive na memória da página: ao recarregar, começa uma nova. Nada é gravado no navegador.",[512,659,489],{"id":660},"segurança",[639,662,663,670,676,679,696,707,710,717],{},[519,664,665,666,669],{},"A chave publicável só abre conversas anônimas: ",[507,667,668],{},"não"," dá acesso ao painel, à API privada nem a dados de clientes. Ela pode ser revogada a qualquer momento (e rotacionada ao publicar de novo).",[519,671,672,673,542],{},"O workspace vem sempre da chave; o widget nunca envia um ",[531,674,675],{},"workspace_id",[519,677,678],{},"Só os domínios permitidos podem usar o chat (CORS por workspace). Sem cookies.",[519,680,681,688,689,692,693,695],{},[507,682,683,684,687],{},"A verificação de ",[531,685,686],{},"Origin"," não é autenticação."," Só protege contra outros sites em um navegador; qualquer cliente que não seja um navegador (um script, ",[531,690,691],{},"curl",") pode enviar o ",[531,694,686],{}," que quiser. Por isso a chave publicável não é um segredo e a proteção real são os limites de uso, não a origem.",[519,697,698,699,702,703,706],{},"Tetos de custo: mensagens por conversa e por hora, mensagens diárias por workspace, conversas novas por hora e conexões ao vivo simultâneas. Ao esgotar, a API responde ",[531,700,701],{},"429"," com ",[531,704,705],{},"Retry-After"," e o assistente não é chamado. Conversas inativas expiram sozinhas e são apagadas, inclusive o nome declarado do visitante.",[519,708,709],{},"Limites de uso por IP, por conversa e por workspace; mensagens de até 1000 caracteres.",[519,711,712,713,716],{},"O texto do visitante é tratado como ",[507,714,715],{},"dado não confiável"," pelo assistente, e o widget mostra todo texto como texto puro (nunca HTML).",[519,718,719],{},"O chat é apenas reativo: não envia lembretes nem mensagens proativas.",[512,721,48],{"id":722},"api",[503,724,725,726,729,730,611,733,611,736,650,739,742,743,542],{},"Gestão (owner, cookie de painel): ",[531,727,728],{},"GET|PUT|DELETE \u002Fv1\u002Fwebchat-site",". Públicos: ",[531,731,732],{},"GET \u002Fv1\u002Fpublic\u002Fwebchat\u002Fconfig",[531,734,735],{},"POST \u002Fv1\u002Fpublic\u002Fwebchat\u002Fsessions",[531,737,738],{},"GET|POST \u002Fv1\u002Fpublic\u002Fwebchat\u002Fsessions\u002F{id}\u002Fmessages",[531,740,741],{},"GET \u002Fv1\u002Fpublic\u002Fwebchat\u002Fsessions\u002F{id}\u002Fevents"," (SSE). Veja o contrato em ",[531,744,745],{},"packages\u002Fopenapi\u002Fopenapi.yaml",[625,747,749],{"type":748},"warning",[503,750,751,752,755],{},"Desativado por padrão (",[531,753,754],{},"PUBLIC_WEBCHAT_ENABLED=false",") até a revisão de segurança e a ativação explícita.",[757,758,759],"style",{},"html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":556,"searchDepth":90,"depth":761,"links":762},3,[763,764,765,766],{"id":514,"depth":90,"text":479},{"id":637,"depth":90,"text":484},{"id":660,"depth":90,"text":489},{"id":722,"depth":90,"text":48},"Coloque o assistente do Wagend no seu site com uma única linha de script, sem número de WhatsApp.","md",{},true,"---\ntitle: WebChat no seu site\ndescription: Coloque o assistente do Wagend no seu site com uma única linha de script, sem número de WhatsApp.\nbadge: Rascunho\n---\n\nO WebChat é um widget de chat que o seu negócio cola no próprio site. Ele conversa com o **mesmo bot** do WhatsApp (mesmos horários, preços e reservas), mas sem número nem aprovação de terceiros: ideal para testar e para a vitrine do seu site.\n\n## Instalar\n\n1. No painel, como **owner**, publique o WebChat e informe os **domínios permitidos** (por exemplo `https:\u002F\u002Fwww.minhaloja.com.br`). Você recebe uma **chave publicável** `wg_web_…`.\n2. Cole o snippet antes de `\u003C\u002Fbody>`:\n\n```html\n\u003Cscript src=\"https:\u002F\u002Fwagend.app\u002Fwidget.js\" data-key=\"wg_web_…\" defer>\u003C\u002Fscript>\n```\n\nAtributos opcionais: `data-locale` (`pt`, `es` ou `en`; por padrão usa o idioma do navegador) e `data-api` (origem da API, só para ambientes de teste). Cor, posição e título vêm da configuração do workspace.\n\n::callout{type=\"tip\"}\nHá uma página de demonstração em `\u002Fdemo\u002Fwebchat` onde você cola a chave e vê o widget funcionando.\n::\n\n## O que o visitante vê\n\n- Um botão flutuante que abre o chat; textos em português, espanhol ou inglês.\n- Nome e telefone são **opcionais** e **não são verificados**: não identificam o visitante e não se unem a clientes existentes.\n- A conversa vive na memória da página: ao recarregar, começa uma nova. Nada é gravado no navegador.\n\n## Segurança\n\n- A chave publicável só abre conversas anônimas: **não** dá acesso ao painel, à API privada nem a dados de clientes. Ela pode ser revogada a qualquer momento (e rotacionada ao publicar de novo).\n- O workspace vem sempre da chave; o widget nunca envia um `workspace_id`.\n- Só os domínios permitidos podem usar o chat (CORS por workspace). Sem cookies.\n- **A verificação de `Origin` não é autenticação.** Só protege contra outros sites em um navegador; qualquer cliente que não seja um navegador (um script, `curl`) pode enviar o `Origin` que quiser. Por isso a chave publicável não é um segredo e a proteção real são os limites de uso, não a origem.\n- Tetos de custo: mensagens por conversa e por hora, mensagens diárias por workspace, conversas novas por hora e conexões ao vivo simultâneas. Ao esgotar, a API responde `429` com `Retry-After` e o assistente não é chamado. Conversas inativas expiram sozinhas e são apagadas, inclusive o nome declarado do visitante.\n- Limites de uso por IP, por conversa e por workspace; mensagens de até 1000 caracteres.\n- O texto do visitante é tratado como **dado não confiável** pelo assistente, e o widget mostra todo texto como texto puro (nunca HTML).\n- O chat é apenas reativo: não envia lembretes nem mensagens proativas.\n\n## API\n\nGestão (owner, cookie de painel): `GET|PUT|DELETE \u002Fv1\u002Fwebchat-site`. Públicos: `GET \u002Fv1\u002Fpublic\u002Fwebchat\u002Fconfig`, `POST \u002Fv1\u002Fpublic\u002Fwebchat\u002Fsessions`, `GET|POST \u002Fv1\u002Fpublic\u002Fwebchat\u002Fsessions\u002F{id}\u002Fmessages` e `GET \u002Fv1\u002Fpublic\u002Fwebchat\u002Fsessions\u002F{id}\u002Fevents` (SSE). Veja o contrato em `packages\u002Fopenapi\u002Fopenapi.yaml`.\n\n::callout{type=\"warning\"}\nDesativado por padrão (`PUBLIC_WEBCHAT_ENABLED=false`) até a revisão de segurança e a ativação explícita.\n::\n",{"title":77,"description":767},"cK-w1QDBjUbFq-NQOjzF9Xy9cqUnpnwl4gfZN-UUFJg",[775,777],{"title":73,"path":74,"stem":75,"description":776,"children":-1},"Como modelar uma barbearia, uma clínica de estética, um consultório, um restaurante e entregas.",null,1790998580361]