Skip to main content

Webhooks de Entrada

Roteamento dinâmico de agentes — o Finn chama o seu servidor quando uma chamada recebida chega.

6 min read

Inbound Webhooks

Quando uma chamada de entrada chega, Finn pode perguntar seu servidor em tempo real qual agente responder, quais variáveis injetar, e que base de conhecimento carregar. Isso permite que você roteie dinamicamente — por número de chamada, nível de conta, hora do dia, coorte A/B, ou qualquer lógica que sua infraestrutura se preocupe.

Se um agente fixo é suficiente, ignore isto. Se você quiser Dinâmica per-call roteamento, esta é a página.


Como funciona

caller dials → Finn answers ring → Finn POSTs to your URL → your server returns agent + vars → Finn streams the voice agent

O aperto de mão adiciona ~100–200ms de latência. O seu endpoint deve responder em abaixo de 500ms ou Finn volta para o agente padrão.


Configurar

1. Defina o URL do webhook de entrada

Dashboard → Configurações → Números de telefone → [número] → Inbound Webhook URL.

Colar o endpoint HTTPS. Salvar. Finn pings-lo uma vez com um {"ping": true} corpo para verificar a acessibilidade.

Via API

curl https://api.hirefinn.ai/v1/phone-numbers/ph_1234 \
  -X PATCH \
  -H "Authorization: Bearer $FINN_API_KEY" \
  -d '{ "inbound_webhook_url": "https://your-app.com/finn/inbound" }'

2. Definir um agente de reserva

Configure um Finn padrão para esse número — usado se seu webhook times out, erros ou retorna uma resposta inválida.


Pedido de carga útil

Finn POSTs para o seu URL com:

{
  "session_id": "ws_2H4abc",
  "request_type": "inbound",
  "phone_number_id": "ph_1234",
  "channel": "pstn",
  "from": {
    "phone": "+919876543210",
    "country": "IN",
    "carrier": "Airtel"
  },
  "to": {
    "phone": "+918765432100",
    "country": "IN"
  },
  "received_at": "2026-05-22T14:30:00Z",
  "metadata": {}
}

Para chamadas do WhatsApp, o bloco from usa campos específicos do WhatsApp:

"from": {
  "wa_id": "919876543210",
  "display_name": "Priya M",
  "profile_pic_url": "https://..."
},
"channel": "whatsapp"

Resposta

Devolva um corpo JSON dentro de 500ms descrevendo como encaminhar a chamada:

{
  "finn_id": "fn_def456",
  "language": "hi-IN",
  "variables": {
    "customer_name": "Priya M",
    "account_tier": "premium",
    "last_order_id": "ord_99831",
    "preferred_agent": "Aria"
  },
  "knowledge_base_ids": ["kb_general", "kb_premium_perks"],
  "metadata": {
    "campaign_tag": "premium-support-q2",
    "ab_cohort": "B"
  },
  "recording_enabled": true,
  "max_call_duration_seconds": 600
}

Referência do campo

O campo é obrigatório

Sim Que agente responde. Deve pertencer à sua org □ language □ No □ Substituir o idioma padrão do agente. en-US, hi-IN, es-ES, etc . variables .. Não. Disponível dentro do prompt como {variable_name} Override que KBs são carregados para esta chamada

  • metadata * Não * Anexado ao registro de chamada e webhook pós-call. Use para a sua própria identificação analítica. □ Sobrescrever o padrão do agente Não, não. O padrão é 1800 (30 min)

Rejeitar a chamada

{ "action": "reject", "reason": "blocked_caller" }

Finn termina a chamada com uma mensagem de saída configurada ("Este número não está mais em serviço"). Uso para aplicação DNC, contas bloqueadas, ou desligamentos pós-hora.

Transferir imediatamente

{ "action": "transfer", "to": "+918888888888", "reason": "vip_route" }

Pular o agente de IA inteiramente — rota diretamente para um humano. Útil para níveis VIP / escalada.


Exemplo de implementação (Node)

import express from "express";

const app = express();
app.use(express.json());

app.post("/finn/inbound", async (req, res) => {
  const { from, to, channel } = req.body;

  // 1. Look up caller in CRM (must be fast — DB index by phone)
  const phone = from.phone ?? `+${from.wa_id}`;
  const customer = await crm.findByPhone(phone);

  // 2. Block known DNC
  if (customer?.dnc) {
    return res.json({ action: "reject", reason: "dnc" });
  }

  // 3. VIP → straight to human
  if (customer?.tier === "vip") {
    return res.json({
      action: "transfer",
      to: process.env.VIP_DESK_NUMBER!,
      reason: "vip_route",
    });
  }

  // 4. Localized agent based on caller country
  const language = from.country === "IN" ? "hi-IN" : "en-US";

  // 5. Pick agent + load context
  return res.json({
    finn_id: customer?.tier === "premium"
      ? "fn_premium_aria"
      : "fn_standard_aria",
    language,
    variables: {
      customer_name: customer?.name ?? "there",
      account_tier: customer?.tier ?? "standard",
      last_order_id: customer?.last_order_id ?? "",
    },
    knowledge_base_ids:
      customer?.tier === "premium" ? ["kb_general", "kb_premium"] : ["kb_general"],
    metadata: { ab_cohort: customer?.ab_cohort ?? "A" },
  });
});

app.listen(3000);

Verificação da assinatura

O mesmo esquema que os webhooks pós-call — HMAC-SHA256 sobre o corpo bruto, cabeçalho X-Finn-Signature.

const sig = req.headers["x-finn-signature"] as string;
const ok = verifyFinnSignature(rawBody, sig, process.env.FINN_INBOUND_SECRET!);
if (!ok) return res.status(401).send("bad signature");

Ver Post-call Webhooks para a execução integral da verificação.


Requisitos de desempenho

Isto está no caminho hot — o chamador está ouvindo o tom do toque enquanto espera por sua resposta.

□ Meta Metrica Não, não, não Tempo de resposta < 500ms (p99) Tempo limite □ Fallback no timeout □ Agente padrão configurado no número de telefone □ Retalho em 5xx □ Agente por omissão □ Retorno no JSON inválido

Dicas para bater < 500ms

  • Cache CRM buscas por número de telefone durante 5 minutos
  • Use uma base de dados colocalizada — webhook de us-leste, DB em us-west = 80ms de cada forma
  • ** Decisões de encaminhamento pré-computação** — guarde a resposta no registro do cliente, não decida ao vivo
  • ** Saltar enriquecimento não essencial** no salto de entrada — empurrar esse trabalho para o webhook pós-call

Pré- tela de chamadas

A maioria dos aplicativos usam o webhook inbound para um desses padrões:

Padrões de caso de uso Não, não, não Procurar + personalizar** Puxe o registro do cliente, passe o nome + camada como variáveis Rejeitar chamadas de números bloqueados • ** ** ** ** ** Skip agente, transferir diretamente para a mesa humana

  • Detecção de línguas** * Pick hi-IN for India, en-US for US callers Testes A/B** Rota 50% das chamadas para uma nova versão do agente Routing pós-horasRouting de agente diferente (ou voicemail) fora do horário comercial Rastreamento da plataforma** Chamadas de tags de números de rastreamento específicos com um ID de campanha ** Multi-tenant SaaS ** Rota para o inquilino cujo número foi discado

Teste

Use o Finn CLI para simular chamadas de entrada sem um anel PSTN real:

finn inbound simulate \
  --phone-number-id ph_1234 \
  --from +919876543210 \
  --webhook-url https://your-app.com/finn/inbound

A saída mostra sua resposta ao endpoint, latência e as variáveis do agente + resolvido. Amigo da IC.


Gotchas comuns

Corrigir Não, não, não As chamadas sempre caem para o agente padrão. Verifique o log do webhook do Finn para o timing. □ O chamador ouve 2-3s de silêncio antes de o agente falar. Otimizar para < 200ms Variáveis que não aparecem na fala do agente Usar a caixa de serpentes de ambos os lados O seu endpoint devolveu um finn_id que pertence a outra org. Verificar a propriedade

  • action: reject não honrado * Check reason é uma string, resposta JSON é válida. Respostas inválidas → backback

Relacionado

Was this page helpful?

Still stuck or have feedback?

Email [email protected] or use the chat bubble in the bottom-right corner — it's a Finn that knows the Academy cold.