n8n, Make e Zapier#
Ferramentas de automação conversam com o GuruAgenda pelos nós genéricos de HTTP e de webhook. Esta página mostra a configuração no n8n; a mesma ideia vale para Make e Zapier.
Chamar a API no n8n#
- Crie uma credencial Bearer Auth com a chave
ga_live_…(ou Header Auth com o nomeAuthorizatione o valorBearer ga_live_…). - No nó HTTP Request, use a URL
https://api.guruagenda.com.br/v1/…e essa credencial. - Para testar a credencial, chame
GET /v1/me.
Listas com várias páginas: no HTTP Request, em Options → Pagination, escolha o modo Response Contains Next URL, com Next URL {{ $response.body.next }}; em Complete When, escolha Other com a expressão {{ !$response.body.has_more }}. O next já é a URL completa da próxima página.
Repetição segura: em nós que criam algo (POST), mande o header Idempotency-Key com um valor fixo por item, por exemplo {{ $json.id }}-guruagenda. Se o n8n repetir a etapa, nada é criado duas vezes.
Limites: acima de 120 requisições por minuto a API responde 429. Em fluxos com muitos itens, use Batching no HTTP Request (por exemplo, 2 itens por segundo).
Importar a API: a especificação OpenAPI fica em https://api.guruagenda.com.br/v1/openapi.json, para Postman, Insomnia e outras ferramentas que importam OpenAPI.
Receber eventos no n8n#
- Adicione o nó Webhook: método
POST, RespondImmediately. - Copie a Production URL do nó.
- No GuruAgenda, crie um webhook do tipo Genérico com essa URL e escolha os eventos.
- Clique em Testar no GuruAgenda: chega um evento
ping. Para ver um evento de verdade, crie um agendamento de teste.
Enquanto monta o fluxo, você pode usar a Test URL (/webhook-test/…) do n8n, que só recebe com o fluxo em modo de escuta. Depois troque pela Production URL e ative o fluxo.
O evento chega no campo body do item: {{ $json.body.data.object.client.name }} é o nome do cliente; {{ $json.body.type }} é o tipo do evento. Um nó Switch sobre {{ $json.body.type }} separa os caminhos (appointment.created, appointment.cancelled…).
Proteger a URL: o jeito mais simples é o Header Auth do nó Webhook. Cadastre no webhook do GuruAgenda um header, por exemplo X-Webhook-Token: um-valor-longo-e-aleatorio, e crie no n8n uma credencial Header Auth com o mesmo nome e valor. Pedidos sem o header são recusados pelo n8n. Para garantir também que o conteúdo não foi alterado, verifique a assinatura.
Verificar a assinatura no n8n#
- No nó Webhook, abra Options e ligue Raw Body. O corpo chega como arquivo binário
data, byte a byte. - Logo depois, adicione um nó Code (Run Once for All Items, JavaScript) com o código abaixo, trocando o segredo.
- O nó devolve o evento já lido do JSON; se a assinatura não bater, o fluxo para com erro.
const crypto = require('crypto');
const secret = 'whsec_…'; // o segredo do webhook no GuruAgenda
const header = $input.first().json.headers['x-guruagenda-signature'] || '';
const rawBody = await this.helpers.getBinaryDataBuffer(0, 'data');
const parts = {};
for (const item of header.split(',')) {
const i = item.indexOf('=');
if (i > 0) parts[item.slice(0, i)] = item.slice(i + 1);
}
const timestamp = Number(parts.t);
if (!Number.isInteger(timestamp) || Math.abs(Date.now() / 1000 - timestamp) > 300) {
throw new Error('Assinatura vencida ou ausente');
}
const expected = crypto.createHmac('sha256', secret).update(`${timestamp}.`).update(rawBody).digest('hex');
const valid = ['v1', 'v0'].some((key) => parts[key] === expected);
if (!valid) {
throw new Error('Assinatura inválida');
}
return [{ json: JSON.parse(rawBody.toString('utf8')) }];
No n8n instalado no seu servidor, o módulo crypto precisa estar liberado: defina a variável de ambiente NODE_FUNCTION_ALLOW_BUILTIN=crypto. No n8n Cloud ele já vem liberado. Em vez de escrever o segredo no código, você pode guardá-lo numa variável de ambiente e ler com $env.GURUAGENDA_WEBHOOK_SECRET.
Receitas#
Agendamento novo vira tarefa no CRM
Webhook (eventos appointment.created) → nó do CRM (HubSpot, Pipedrive, RD Station…) criando a atividade com {{ $json.body.data.object.start }} e o cliente {{ $json.body.data.object.client.email }}. Para atualizar a mesma atividade depois, grave o id dela de volta no agendamento: PATCH /v1/appointments/{{ $json.body.data.object.id }} com {"metadata": {"crm_activity_id": "…"}}. Nos eventos seguintes (appointment.rescheduled, appointment.cancelled), o id volta em data.object.metadata.crm_activity_id.
Lead do formulário vira cliente
Gatilho do formulário (ou do CRM) → HTTP Request POST /v1/clients com first_name, last_name, email, phone e metadata com o id do lead. Se a pessoa já existir na carteira (mesmo e-mail, telefone ou CPF), a resposta é 200 com o cadastro existente, em vez de 201; com "on_match": "update", os dados enviados atualizam o cadastro.
Agendar a partir de outro sistema
GET /v1/availability/slots?service_ids=3&date=2026-10-20 traz os horários livres (um item por profissional livre); POST /v1/appointments com o horário escolhido, o client_id (ou o client inline) e um Idempotency-Key.
Sincronizar de tempos em tempos, sem webhook
Schedule Trigger a cada 15 minutos → GET /v1/appointments?updated_since={{ $now.minus({minutes: 20}).toISO() }} com paginação. A sobreposição de 5 minutos evita perder alterações entre as execuções.
Make#
- Chamar a API: módulo HTTP → Make a request, com o header
Authorization: Bearer ga_live_…. Para listas, repita a chamada enquantohas_morefor verdadeiro, usando onext. - Receber eventos: módulo Webhooks → Custom webhook. Copie a URL gerada para um webhook Genérico no GuruAgenda e clique em Testar para o Make aprender o formato (o
pingtraz poucos campos; para mapear um agendamento, crie um de teste com o cenário escutando). - Filtros com várias opções aceitam
status=CONFIRMED,PENDING.
Zapier#
- Receber eventos: gatilho Webhooks by Zapier → Catch Hook. Cole a URL num webhook Genérico do GuruAgenda.
- Chamar a API: ação Webhooks by Zapier → Custom Request, com o header
Authorization: Bearer ga_live_…eContent-Type: application/json. - Gatilho por consulta: Webhooks by Zapier → Retrieve Poll sobre
GET /v1/appointments?updated_since=….