GuruAgenda API
menu Guias

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#

  1. Crie uma credencial Bearer Auth com a chave ga_live_… (ou Header Auth com o nome Authorization e o valor Bearer ga_live_…).
  2. No nó HTTP Request, use a URL https://api.guruagenda.com.br/v1/… e essa credencial.
  3. 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#

  1. Adicione o nó Webhook: método POST, Respond Immediately.
  2. Copie a Production URL do nó.
  3. No GuruAgenda, crie um webhook do tipo Genérico com essa URL e escolha os eventos.
  4. 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#

  1. No nó Webhook, abra Options e ligue Raw Body. O corpo chega como arquivo binário data, byte a byte.
  2. Logo depois, adicione um nó Code (Run Once for All Items, JavaScript) com o código abaixo, trocando o segredo.
  3. 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 enquanto has_more for verdadeiro, usando o next.
  • 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 ping traz 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_… e Content-Type: application/json.
  • Gatilho por consulta: Webhooks by Zapier → Retrieve Poll sobre GET /v1/appointments?updated_since=….