Pular para o conteúdo

Para desenvolvedores

Conecte o Telofia aos sistemas que você já usa

Consulte chamadas, transcrições, agendamentos e contatos por uma API REST, receba webhooks assinados assim que algo acontece, deixe o assistente consultar dados ao vivo no seu sistema durante a chamada e coloque um assistente de voz no seu site com uma linha de código.

A API REST e os webhooks estão incluídos em todos os planos, a partir do Line; planos superiores têm limites maiores. No teste grátis você tem acesso de teste: 1 chave de API, 20 requisições por minuto.

URL base da API
https://telofia.com/api/v1
curl · Testar a chave
curl https://telofia.com/api/v1/me \
  -H "Authorization: Bearer tf_live_…"
200 OK
{
  "object": "account",
  "id": "1f2e3d4c-5b6a-4789-8a7b-6c5d4e3f2a1b",
  "name": "Smile Dental",
  "timezone": "Europe/Warsaw",
  "locale": "en",
  "country": "PL",
  "currency": "PLN",
  "status": "active",
  "plan": {
    "id": "team",
    "billing_cycle": "month",
    "trial_ends_at": null,
    "period_start": "2026-10-01T00:00:00Z",
    "period_end": "2026-11-01T00:00:00Z",
    "recording_history_days": 365
  },
  "minutes": {
    "included": 3000,
    "extra": 100,
    "total": 3100,
    "used": 412.5,
    "remaining": 2687.5
  },
  "api_key_id": "2a3b4c5d-6e7f-4a8b-9c0d-1e2f3a4b5c6d",
  "scopes": [
    "read:calls",
    "read:appointments",
    "read:contacts",
    "read:tasks"
  ],
  "limits": {
    "plan": "team",
    "requests_per_minute": 180,
    "requests_per_day": 50000,
    "max_api_keys": 10,
    "max_webhook_endpoints": 10
  }
}

Início rápido

Sua primeira requisição em dois minutos

  1. 1

    Crie uma chave de API

    No painel, vá em Desenvolvedores → Chaves de API, dê um nome à chave e escolha as permissões. A chave (tf_live_…) aparece só uma vez, então guarde-a logo no seu gerenciador de segredos.

  2. 2

    Teste a conexão

    Chame GET /me. Funciona com qualquer chave válida e retorna sua conta, as permissões da chave e os limites do seu plano.

  3. 3

    Leia dados ou assine eventos

    Liste chamadas, agendamentos e contatos, ou adicione um endpoint em Desenvolvedores → Webhooks para receber eventos na hora.

curl · Testar a chave
curl https://telofia.com/api/v1/me \
  -H "Authorization: Bearer tf_live_…"
JavaScript: todas as chamadas com agendamento, página por página
const API = "https://telofia.com/api/v1";
const headers = { Authorization: `Bearer ${process.env.TELOFIA_API_KEY}` };

// All calls booked since 1 October, page by page
let cursor = null;
while (true) {
  const url = new URL(`${API}/calls`);
  url.searchParams.set("outcome", "booked");
  url.searchParams.set("since", "2026-10-01T00:00:00Z");
  url.searchParams.set("limit", "100");
  if (cursor) url.searchParams.set("cursor", cursor);

  const res = await fetch(url, { headers });
  if (res.status === 429) {
    // rate limited: wait for the number of seconds in Retry-After, then retry the same page
    await new Promise((r) => setTimeout(r, Number(res.headers.get("Retry-After") ?? 1) * 1000));
    continue;
  }
  if (!res.ok) throw new Error((await res.json()).error.message);

  const page = await res.json();
  for (const call of page.data) console.log(call.started_at, call.from, call.summary);
  if (!page.has_more) break;
  cursor = page.next_cursor;
}

API REST v1

Chamadas, agendamentos e contatos via HTTPS

JSON na entrada e na saída. Cada requisição é autenticada com uma chave de API e segue os limites do seu plano. As requisições aparecem no painel (método, caminho, status e tempo — nunca o conteúdo de requisições ou respostas).

Autenticação

Crie uma chave em Chaves de API e envie-a como token Bearer. As chaves começam com tf_live_ e pertencem a uma única conta.

Authorization: Bearer tf_live_…

Paginação

Os endpoints de lista devolvem até limit itens (1–100, padrão 25) em ordem estável. Quando has_more for true, passe next_cursor sem alterações como cursor (com os mesmos filtros) para obter a próxima página. Um cursor inválido devolve 400 invalid_request.

Erros

Os erros usam códigos de status HTTP padrão e um corpo JSON com um tipo e uma mensagem legível.

{ "error": { "type": "…", "message": "…" } }

Endpoints

  • GET/mePermissão: qualquer chave

    Obter a conta atual

    Retorna a conta à qual a chave de API pertence. Útil como chamada de “teste de conexão”.

  • GET/assistantsPermissão: qualquer chave

    Listar assistentes

    Seus assistentes com idioma, status e números de telefone atribuídos. Use o id como assistant_id para filtrar chamadas.

  • GET/assistants/{id}Permissão: qualquer chave

    Obter um assistente

    Um assistente com idioma, status e números de telefone. Com o escopo read:assistants (ou write:assistants) retorna também o prompt: instructions, greeting, company_profile e updated_at.

  • PATCH/assistants/{id}Permissão: write:assistants

    Alterar o prompt do assistente

    Altera as instruções, a saudação ou o perfil da empresa. Campos omitidos não mudam. Mesmos limites do painel: instruções até 20.000 caracteres, perfil até 10.000, saudação de 5 a 600 caracteres que deve dizer que a pessoa fala com uma IA (senão 400 com code ai_disclosure). Cada alteração vai para o histórico de versões do assistente (origem API) e vale a partir da próxima chamada. As regras de honestidade da plataforma (aviso de IA e de gravação) sempre se aplicam.

  • GET/phone-numbersPermissão: qualquer chave

    Listar números de telefone

    Os números de telefone da sua conta com país, tipo, status e o assistente que os atende.

  • GET/callsPermissão: read:calls

    Listar chamadas

    Chamadas da mais recente para a mais antiga, sem transcrições. Chamadas de demonstração nunca são incluídas.

  • GET/calls/{id}Permissão: read:calls

    Obter uma chamada

    Uma chamada com a transcrição completa e os agendamentos feitos durante ela.

  • GET/calls/{id}/recordingPermissão: read:calls

    Obter a gravação de uma chamada

    Links assinados (válidos por 1 hora) para ouvir e baixar a gravação MP3 (estéreo: quem liga à esquerda, assistente à direita). Uma gravação mais antiga que o histórico do seu plano devolve 403 plan_required com recording_history_days; uma chamada sem gravação devolve 404.

  • GET/appointmentsPermissão: read:appointments

    Listar agendamentos

    Próximos agendamentos em ordem de início (a partir de agora, por padrão).

  • GET/appointments/{id}Permissão: read:appointments

    Obter uma marcação

    Uma marcação da sua conta.

  • POST/appointments/{id}/cancelPermissão: write:appointments

    Cancelar uma marcação

    Cancela uma marcação futura, remove-a do calendário Google ligado e envia o webhook appointment.canceled. calendar_sync indica se o calendário foi atualizado.

  • POST/appointments/{id}/reschedulePermissão: write:appointments

    Reagendar uma marcação

    Move uma marcação futura para um novo horário. Responde 409 se o horário coincidir com outra marcação ou com um período ocupado no calendário ligado. Sem ends_at a duração mantém-se. Envia o webhook appointment.rescheduled.

  • GET/contactsPermissão: read:contacts

    Listar contatos

    Quem ligou para você, do mais recente para o mais antigo. O assistente se lembra deles entre as chamadas.

  • GET/contacts/{id}Permissão: read:contacts

    Obter um contato

    Um contato com nome, email, tags, notas e a origem do nome e do email (call, system ou manual).

  • POST/contactsPermissão: write:contacts

    Criar um contato

    Adiciona um contato, por exemplo a partir do seu CRM, para que o assistente saiba o nome de quem liga. Nome e email salvos pela API ficam marcados como manual e o assistente nunca os substitui. Devolve 409 com contact_id se o número já existir. Envia o webhook contact.created.

  • PATCH/contacts/{id}Permissão: write:contacts

    Atualizar um contato

    Altera nome, email, notas ou bloqueio. Campos omitidos não mudam e null limpa um campo. Um nome ou email alterado fica marcado como manual, então o assistente não o substituirá. O número de telefone não pode ser alterado.

  • GET/tasksPermissão: read:tasks

    Listar tarefas

    Pedidos de retorno, mensagens e outras tarefas das chamadas, das mais recentes para as mais antigas.

  • GET/tasks/{id}Permissão: read:tasks

    Obter uma tarefa

    Uma tarefa da sua conta.

  • PATCH/tasks/{id}Permissão: write:tasks

    Atualizar uma tarefa

    Define o status da tarefa como open, done ou dismissed, por exemplo depois que sua equipe retornou a ligação ao cliente.

  • POST/calls/outboundPermissão: write:calls

    Criar uma chamada de saída

    Seu assistente liga para uma pessoa a partir do número da sua empresa, com o objetivo que você definir, como uma etapa de uma sequência de onboarding. A chamada é feita agora ou em call_at, sempre dentro do horário de chamadas (seg–sáb, 9h–20h no fuso horário da sua conta; fora dele, é movida para o próximo horário permitido e call_at mostra quando). Se ninguém atender, tenta até 3 vezes, com 2 horas de intervalo. Retorna 202 com a chamada no status scheduled. Erros: 400 consent_missing, invalid_phone, number_not_callable, international ou invalid_call_at; 409 opted_out (a pessoa pediu para não receber ligações), already_scheduled (com existing_id), assistant_not_live, over_quota ou no_outbound_number; 429 daily_outbound_limit com limit (200 chamadas a cada 24 horas por padrão). O resultado chega nos webhooks call.completed e outbound_call.finished com o seu external_id.

  • GET/calls/outbound/{id}Permissão: write:calls

    Obter uma chamada de saída

    Status de uma chamada de saída agendada: scheduled, dialing, done (com call_id da conversa), failed (last_error, ex.: no_answer após todas as tentativas) ou canceled. Também funciona com o callback_id dos webhooks para chamadas de onboarding e de retorno.

  • DELETE/calls/outbound/{id}Permissão: write:calls

    Cancelar uma chamada de saída

    Cancela uma chamada de saída criada pela API que ainda está agendada. Pode ser repetido com segurança (uma chamada já cancelada retorna 200). Retorna 409 not_cancelable quando a chamada está em discagem ou finalizada, ou para chamadas de onboarding (nesse caso, remova a pessoa com POST /api/outreach/unenroll).

  • GET/messagesPermissão: read:messages

    Listar SMS

    SMS enviados pela sua conta e respostas de clientes, dos mais recentes. phone é o número do cliente (destinatário ou remetente de uma resposta). generated_by: template, ai ou manual; charged_from: plan ou credits.

  • POST/messagesPermissão: write:messages

    Enviar um SMS

    Envia um SMS para um dos seus contatos ou pessoas que ligaram: seu próprio texto ou um modelo da sua conta com vars (date, time, name, service, link, amount). Conta no limite de SMS do plano e nos SMS adicionais. Erros: 400 invalid_request (consent_missing, invalid_phone, too_long, missing_vars); 409 conflict (opted_out — o cliente respondeu STOP, over_quota, recipient_not_allowed — crie o contato primeiro, blocked_destination); 429 rate_limited.

Permissões

Cada chave tem as permissões escolhidas ao ser criada. As permissões não podem ser alteradas depois — se precisar de mais, crie uma nova chave. Quando falta à chave a permissão necessária, os endpoints respondem 403 insufficient_scope. GET /me, /assistants e /phone-numbers funcionam com qualquer chave válida.

  • read:callsLer chamadas, resumos e transcrições
  • read:appointmentsLer marcações
  • write:appointmentsCancelar e reagendar marcações
  • read:contactsLer contactos
  • write:contactsCriar e editar contatos
  • read:tasksLer tarefas e pedidos de retorno
  • write:tasksAlterar o status das tarefas
  • write:callsIniciar chamadas de saída, consultá-las e cancelá-las
  • read:messagesLer SMS e respostas de clientes
  • write:messagesEnviar SMS para seus contatos
  • read:assistantsLer o prompt do assistente (instruções, saudação, perfil da empresa)
  • write:assistantsAlterar o prompt do assistente

Erros

  • 400invalid_request — um parâmetro está ausente ou é inválido
  • 401unauthorized — chave de API ausente, inválida ou revogada
  • 403insufficient_scope — a chave não tem a permissão do endpoint; plan_required — a conta não tem um plano ativo ou a gravação é mais antiga que o histórico de gravações do plano
  • 404not_found — o objeto não existe na sua conta
  • 409conflict — o horário já está ocupado, a marcação não pode ser alterada, já existe um contato com este número ou uma chamada de saída não pode ser feita (code: opted_out, already_scheduled, assistant_not_live, over_quota, no_outbound_number, not_cancelable)
  • 429rate_limited — demasiados pedidos; tente novamente após o tempo do cabeçalho Retry-After
  • 500server_error — algo deu errado do nosso lado
  • 503service_unavailable — problema temporário; tente novamente após o tempo do cabeçalho Retry-After

A referência completa da API, com parâmetros e exemplos de resposta, está no painel em Desenvolvedores → Referência da API.

Webhooks

Eventos enviados ao seu servidor em tempo real

Adicione um endpoint https no painel, escolha os eventos e enviaremos um envelope JSON assinado (POST) assim que algo acontecer. “Enviar teste” entrega um exemplo do seu primeiro evento, útil para mapear campos no Zapier ou no Make.

Eventos

  • call.completedChamada concluída

    Resumo, resultado, sentimento, transcrição, contato e agendamentos; em chamadas de saída, também a sequência ou a requisição da API (callback_id, external_id, outreach).

  • call.startedChamada iniciada

    Uma chamada foi atendida (de entrada, de saída ou pela web).

  • appointment.bookedAgendamento realizado

    O assistente fez um agendamento.

  • appointment.canceledMarcação cancelada

    Uma marcação foi cancelada por telefone ou através da API.

  • appointment.rescheduledMarcação reagendada

    Uma marcação foi movida para um novo horário (inclui o horário anterior).

  • task.createdRetorno / tarefa criada

    Alguém pediu um retorno ou deixou uma tarefa.

  • contact.createdNovo contato

    Quem ligou pela primeira vez foi salvo como contato.

  • outbound_call.finishedChamada de saída finalizada

    Uma chamada de saída agendada (API, sequência de onboarding ou retorno) foi concluída ou falhou — também quando ninguém atendeu após todas as tentativas.

Cabeçalhos de cada entrega

  • Telofia-SignatureAssinatura: t=<tempo unix>,v1=<HMAC-SHA256 hex>
  • Telofia-EventTipo de evento, ex.: appointment.booked
  • Telofia-DeliveryID única da entrega
  • User-AgentTelofia-Webhooks/1.0 · Identifica nosso remetente de webhooks

Entrega e novas tentativas

  • Responda com qualquer status 2xx em até 10 segundos. Redirecionamentos não são seguidos.
  • Entregas com falha são repetidas após 1 min, 5 min, 30 min, 2 h, 6 h e 12 h (7 tentativas, cerca de 21 horas).
  • O mesmo evento pode chegar mais de uma vez. Use o id do evento para ignorar duplicados.
  • Só aceitamos endereços https públicos. Após 50 falhas seguidas, o endpoint é pausado e o painel mostra o motivo.
  • O painel mantém um registro de entregas com códigos de status e respostas e permite repetir uma entrega manualmente.
Exemplo de entrega: call.completed
{
  "id": "evt_3f9a1c7e5b2d4f6a8c0e1b3d5f7a9c1e",
  "type": "call.completed",
  "created_at": "2026-10-01T09:17:45Z",
  "account_id": "1f2e3d4c-5b6a-4789-8a7b-6c5d4e3f2a1b",
  "data": {
    "id": "5b1f0c6e-2a8d-4f3e-9d51-7c0a4e2b9f10",
    "object": "call",
    "assistant_id": "0e6f4c8a-3b2d-4a1e-8f7c-5d9b2a1c3e4f",
    "phone_number_id": "4d3c2b1a-0f9e-4d8c-b7a6-958473625140",
    "contact_id": "9a8b7c6d-5e4f-4a3b-2c1d-0e9f8a7b6c5d",
    "direction": "inbound",
    "status": "completed",
    "from": "+48601234567",
    "to": "+48221234567",
    "started_at": "2026-10-01T09:14:03Z",
    "ended_at": "2026-10-01T09:17:41Z",
    "duration_sec": 218,
    "summary": "Anna Kowalska booked a first consultation for Friday 10:00.",
    "outcome": "booked",
    "sentiment": "positive",
    "tags": [
      "new-customer"
    ],
    "has_recording": true,
    "end_reason": "caller_hangup",
    "callback_id": null,
    "external_id": null,
    "outreach": null,
    "caller_spoke": true,
    "caller_words": 6,
    "transcript": [
      {
        "role": "caller",
        "text": "I'd like to book a consultation this week.",
        "at": 4.1
      }
    ],
    "contact": {
      "id": "9a8b7c6d-5e4f-4a3b-2c1d-0e9f8a7b6c5d",
      "object": "contact",
      "phone": "+48601234567",
      "name": "Anna Kowalska",
      "name_source": "call",
      "email": "anna.kowalska@example.com",
      "email_source": "call",
      "notes": null,
      "tags": [
        "customer"
      ],
      "blocked": false,
      "calls_count": 3,
      "last_call_at": "2026-10-01T09:14:03Z",
      "created_at": "2026-08-12T15:02:11Z"
    },
    "appointments": [
      {
        "id": "c3d2e1f0-a9b8-4c7d-8e6f-5a4b3c2d1e0f",
        "object": "appointment",
        "call_id": "5b1f0c6e-2a8d-4f3e-9d51-7c0a4e2b9f10",
        "contact_id": "9a8b7c6d-5e4f-4a3b-2c1d-0e9f8a7b6c5d",
        "customer_name": "Anna Kowalska",
        "customer_phone": "+48601234567",
        "customer_email": "anna.kowalska@example.com",
        "service": "First consultation",
        "starts_at": "2026-10-03T08:00:00Z",
        "ends_at": "2026-10-03T08:30:00Z",
        "status": "booked",
        "external_id": "google:7h3k9s2l1m0n",
        "created_at": "2026-10-01T09:16:20Z"
      }
    ]
  }
}

Verificação de assinaturas. Cada entrega tem um cabeçalho Telofia-Signature no formato t=timestamp,v1=signature. Calcule o HMAC-SHA256 de “timestamp.raw_body” com seu segredo de assinatura e compare com v1. Rejeite timestamps com mais de 5 minutos.

Node.js · Verificar a assinatura
import crypto from "node:crypto";

// Express: app.post("/webhook", express.raw({ type: "application/json" }), handler)
export function verify(rawBody, signatureHeader, secret) {
  // Telofia-Signature: t=1727774265,v1=5f2c…
  const parts = Object.fromEntries(signatureHeader.split(",").map((p) => p.split("=")));
  const expected = crypto.createHmac("sha256", secret).update(`${parts.t}.${rawBody}`).digest("hex");
  const fresh = Math.abs(Date.now() / 1000 - Number(parts.t)) < 300;
  const given = Buffer.from(parts.v1 ?? "");
  // timingSafeEqual needs buffers of the same length
  return fresh && given.length === expected.length && crypto.timingSafeEqual(Buffer.from(expected), given);
}
Python · Verificar a assinatura
import hmac, hashlib, time

def verify(raw_body: bytes, signature_header: str, secret: str) -> bool:
    parts = dict(p.split("=", 1) for p in signature_header.split(","))
    expected = hmac.new(secret.encode(), f"{parts['t']}.".encode() + raw_body, hashlib.sha256).hexdigest()
    fresh = abs(time.time() - int(parts["t"])) < 300
    return fresh and hmac.compare_digest(expected, parts.get("v1", ""))
Receptor de exemplo (Express)
import express from "express";
import { verify } from "./verify.js";

const app = express();
const seen = new Set(); // use your database in production

app.post("/telofia/webhook", express.raw({ type: "application/json" }), (req, res) => {
  const raw = req.body.toString("utf8");
  if (!verify(raw, req.get("Telofia-Signature") ?? "", process.env.TELOFIA_WEBHOOK_SECRET)) return res.sendStatus(401);

  const event = JSON.parse(raw);
  if (seen.has(event.id)) return res.sendStatus(200); // retried delivery, already handled
  seen.add(event.id);

  if (event.type === "appointment.booked") {
    const a = event.data;
    console.log("New booking:", a.customer_name, a.service, a.starts_at);
  }
  res.sendStatus(200); // answer with 2xx within 10 seconds
});

app.listen(3000);

Valores estáveis

Estes valores em chamadas (API e webhooks call.*) e em chamadas de saída (outbound_call.finished, /calls/outbound) são um contrato estável: podemos adicionar novos valores, mas não vamos alterar nem remover estes. Tentativas de saída sem resposta, ocupadas ou rejeitadas nunca criam uma chamada, então não há call.completed para elas: você recebe outbound_call.finished com last_error no_answer após a última tentativa. Uma chamada atendida pela caixa postal conta como atendida (normalmente uma chamada curta com outcome other).

Status da chamada

in_progress
A chamada está em andamento.
completed
A pessoa falou com o assistente.
missed
Ninguém falou, ou o assistente não pôde atender a chamada (veja end_reason).
failed
A chamada não pôde ser tratada por causa de um erro.

Resultado da chamada

booked
Foi feito um agendamento.
transferred
A chamada foi transferida para uma pessoa.
message
Foi registrada uma mensagem, pedido de retorno, encomenda ou acompanhamento.
info
A pessoa recebeu informações; nada mais foi necessário.
spam
Spam, telemarketing ou um número bloqueado.
other
Qualquer outra coisa, ex.: uma chamada muito curta ou caixa postal.

Motivo de encerramento da chamada (end_reason)

caller_hangup
A outra pessoa desligou.
caller_hangup_greeting
Chamada de saída: a pessoa desligou durante a saudação ou logo a seguir, sem dizer nada (chamada até 45 s). Nesse caso caller_spoke é false.
agent_hangup
O assistente encerrou a chamada após se despedir.
transferred
A chamada foi transferida para uma pessoa.
silence
Encerrada após um longo silêncio.
max_duration
A duração máxima da chamada foi atingida.
spam
Encerrada como spam.
blocked
O número está bloqueado nos contatos.
busy
Todas as linhas da conta estavam ocupadas.
over_quota
Sem minutos de chamada restantes.
trial_expired
O teste gratuito terminou.
inactive
Sem plano ativo.
assistant_not_live
O assistente está pausado.
no_assistant
Nenhum assistente atende este número.
ai_budget
Tratada sem IA por causa de um limite temporário; a equipe foi avisada para retornar a ligação.
error
Um erro técnico encerrou a chamada.

Status da chamada de saída

scheduled
Aguardando o seu horário (ou a próxima tentativa).
dialing
Ligando agora.
done
Atendida; call_id é a conversa.
failed
Não atendida após todas as tentativas, ou não pôde ser feita (veja last_error).
canceled
Cancelada (API, pessoa removida da sequência ou sequência desativada).

last_error da chamada de saída

no_answer
Ninguém atendeu (também ocupado ou rejeitada).
failed
O assistente não estava disponível no horário da chamada (plano, minutos ou pausa).
no_result
Nenhum resultado da chamada em 15 minutos.
expired
A chamada estava mais de 2 horas atrasada, então não foi feita.
outside_window
Movida para o próximo horário de chamadas (o status continua scheduled).
dial_error
A rede telefônica recusou a chamada (enviado como dial_<reason>).
over_quota
Sem minutos de chamada restantes.
inactive
Sem plano ativo.
assistant_not_live
O assistente está pausado.
no_outbound_number
Nenhum número da empresa para fazer a ligação.
canceled_by_api
Cancelada com DELETE /calls/outbound/{id}.
unenrolled
A pessoa foi removida da sequência (POST /api/outreach/unenroll).
opt_out
A pessoa pediu para não receber ligações.
replaced
Substituída por um retorno mais recente para o mesmo número.

Dados ao vivo via MCP

O assistente consulta o seu sistema durante a chamada

Conecte um servidor MCP remoto (Model Context Protocol), como o catálogo da sua loja, o estoque ou o sistema de agendamentos ou pedidos. Você escolhe exatamente quais ferramentas e recursos (somente leitura) o assistente pode usar.

Aprender com antecedência

Para conteúdos que mudam pouco, como tabelas de preços, descrições de produtos ou políticas. Os recursos e ferramentas de leitura escolhidos são importados para o conhecimento do assistente a cada 1 a 168 horas ou quando você quiser. Sem atraso na chamada.

Consultar ao vivo na chamada

Para o que muda: estoque, disponibilidade, status do pedido. O assistente usa a ferramenta durante a conversa com um rápido “um momento, vou verificar”. Se o seu servidor não responder em cerca de 2,5 segundos, ele diz que não consegue confirmar agora e oferece um retorno da sua equipe.

O que você precisa

  • Um servidor MCP acessível por https (Streamable HTTP, ex.: https://mcp.example.com/mcp; servidores HTTP+SSE antigos são detectados automaticamente).
  • Autenticação: nenhuma, um token Bearer ou um cabeçalho próprio como X-API-Key. Os segredos são criptografados (AES-256-GCM) e nunca vão para o navegador.
  • Ferramentas somente leitura. As marcadas como destrutivas são bloqueadas; para as que não estão marcadas como somente leitura, você confirma que elas apenas leem dados.
  • Até 5 fontes e 50 ferramentas ao vivo por assistente. As consultas ao vivo devem responder em cerca de 2 segundos.
  • Opcional para o widget do site: numa ferramenta «No início da chamada», escolha o argumento que recebe o token de identidade do visitante com sessão iniciada (ver Widget de voz para o site).

Os argumentos são validados pelo esquema da ferramenta, os resultados são encurtados e tratados estritamente como dados (nunca como instruções), e cada consulta é registrada sem dados de quem liga. Endereços privados e internos são recusados.

Widget de voz para o site

Seu assistente no seu site, com uma linha de código

Os visitantes clicam em um botão e falam, no navegador, com o mesmo assistente que atende o seu telefone. As chamadas web usam os minutos do seu plano, sem custos de telefonia.

A partir do Office

  • Cerca de 14 KB, sem dependências, isolado em Shadow DOM para que os estilos do seu site não o quebrem.
  • Fala o idioma da sua página (<html lang>) ou o definido com data-lang="de".
  • Legendas ao vivo; se o microfone estiver bloqueado, o visitante pode digitar e o assistente responde por voz.
  • Limite o widget aos seus domínios e ele só vai iniciar nesses sites.
Código de incorporação (sua chave está no painel)
<script src="https://telofia.com/widget.js" data-key="tfw_…" async></script>
API JavaScript
// optional: open the widget from your own button
document.querySelector("#talk-to-us").addEventListener("click", () => window.TelofiaWidget?.open());

window.TelofiaWidget?.close();   // close the panel
window.TelofiaWidget?.destroy(); // remove the widget from the page

Tem uma Content Security Policy rígida? Permita script-src https://telofia.com https://cdn.jsdelivr.net, connect-src https://telofia.com wss://*.livekit.cloud https://*.livekit.cloud e media-src blob:.

Utilizadores com sessão iniciada (token de identidade)

Quando os visitantes têm sessão iniciada no seu site, o assistente pode saber quem está a falar sem pedir o e-mail.

  • O seu servidor emite um token assinado e de curta duração para o utilizador com sessão iniciada (p. ex. HMAC, válido 15 minutos). Nunca coloque um e-mail nem um ID de utilizador no navegador: qualquer pessoa poderia escrever o de outra na consola.
  • Chame TelofiaWidget.identify({ token }) a qualquer momento; uma chamada posterior substitui o token e identify(null) apaga-o. Antes de o widget.js carregar, defina window.TelofiaIdentity = { token, expires_at }: é lido quando a conversa começa e um token expirado é ignorado.
  • No painel, escolha o argumento do token de identidade na sua ferramenta MCP «No início da chamada». A Telofia passa o token sem alterações apenas para esse argumento, nunca o guarda nem o mostra e mantém-no fora de transcrições, resumos, webhooks e registos; o assistente nunca o vê.
  • De 8 a 400 caracteres: letras, dígitos e . _ ~ + / = - (p. ex. base64url). Renove-o antes de expirar, por exemplo a cada 10 minutos. O seu servidor MCP verifica-o; um token inválido ou expirado deve dar o mesmo resultado que não ter token. As chamadas telefónicas e as conversas sem token funcionam como até agora.
Token de identidade
// signed-in user: a short-lived, signed token issued by YOUR server (never an e-mail or user ID)
const { token, expires_at } = await fetch("/api/telofia-identity").then((r) => r.json());

window.TelofiaIdentity = { token, expires_at };       // read when the conversation starts, also before widget.js loads
window.TelofiaWidget?.identify({ token, expires_at }); // replaces the token at any time

// refresh before it expires (e.g. every 10 minutes); on sign-out:
window.TelofiaIdentity = null;
window.TelofiaWidget?.identify(null);

Onboarding por telefone

Seus novos clientes recebem uma ligação de boas-vindas automaticamente

Quando alguém se cadastra no seu sistema, envie essa pessoa para uma sequência de ligações. O assistente liga do número da sua empresa, ajuda a começar e volta a ligar alguns dias depois. As ligações acontecem dentro do horário de ligações da sequência: por padrão de segunda a sábado, das 9h às 20h no seu fuso horário, ou nos dias e horários que você definir.

POST/api/outreach/enroll

Autentique-se com a chave da sequência (tlo_…) do painel, como token Bearer ou no cabeçalho X-Telofia-Key. Cada sequência tem sua própria chave.

Corpo da requisição

  • phonestringobrigatório
    Número de telefone, de preferência no formato E.164. Números nacionais são lidos com o código do país da sua conta.
  • consenttrueobrigatório
    Deve ser true: a pessoa concordou em ser contatada por telefone, ex.: no seu formulário de cadastro.
  • namestringopcional
    Nome, até 120 caracteres.
  • emailstringopcional
    Endereço de e-mail.
  • contextstringopcional
    O que o assistente deve saber sobre essa pessoa, até 1.000 caracteres (ex.: o plano escolhido).
  • external_idstring | numberopcional
    A ID da pessoa no seu sistema (texto ou número). A mesma ID é inscrita só uma vez.
curl
curl -X POST "https://telofia.com/api/outreach/enroll" \
  -H "Authorization: Bearer tlo_…" \
  -H "Content-Type: application/json" \
  -d '{"phone":"+48601234567","name":"Anna Kowalska","email":"anna@example.com","context":"Signed up today, Start plan","external_id":"user_123","consent":true}'
201 Created
{
  "ok": true,
  "enrollment_id": "8f7e6d5c-4b3a-4c2d-9e1f-0a9b8c7d6e5f",
  "external_id": "user_123",
  "status": "active",
  "next_call_at": "2026-10-09T10:20:00Z",
  "limits": {
    "per_day": 500,
    "remaining_today": 499
  }
}

Respostas

  • 201: inscrita. enrollment_id, external_id, status, next_call_at (horário da primeira ligação), intro_sms_at (quando sai o SMS antes da primeira chamada, ou null) e limits { per_day, remaining_today }
  • 200: já inscrita (mesmo external_id, ou este número já está em andamento na sequência), com duplicate: true
  • 400: invalid_request, invalid_phone ou consent_required
  • 401: invalid_key
  • 409: sequence_disabled, consent_missing ou opted_out (a pessoa não quer ligações)
  • 429: limit, o limite diário de inscrições da sequência foi atingido (500 novas pessoas a cada 24 horas; o corpo contém limit). rate_limited: mais de 120 requisições por minuto com esta chave (cabeçalho Retry-After)

Horário de ligações: defina no painel os dias e um intervalo entre 7h e 21h para cada sequência. Se ninguém atender, o assistente tenta até 3 vezes, com 2 horas de intervalo, dentro desse horário.

SMS antes da chamada: quando está ativo na sequência (painel), a pessoa recebe uma mensagem curta do número de onde o assistente vai ligar, por predefinição 20 minutos antes da primeira chamada (5–120 min). Se a primeira chamada fosse mais cedo, é adiada para que o SMS saia sempre primeiro, dentro do horário de chamadas. Um SMS que falhe (a pessoa respondeu STOP, os SMS do plano esgotaram-se) nunca impede a chamada. Cada SMS conta para os SMS do seu plano e aparece no painel, em SMS.

Saudação: no painel define a primeira frase da chamada para cada passo (ou por omissão para toda a sequência) — um texto fixo com as variáveis {first_name}, {first_name_vocative} (vocativo polaco, p. ex. Krystianie), {assistant_name}, Telofia (nome da empresa nas chamadas, das definições do assistente) e {name}, com uma variante própria para inscrições sem nome — ou um modo em que o assistente escreve a primeira frase a partir de name, context, do objetivo do passo e do resultado das ferramentas «No início da chamada». Que liga um assistente de IA e que a chamada é gravada é sempre acrescentado à primeira frase se o texto não o disser.

Remover uma pessoa da sequência

POST/api/outreach/unenroll

Quando alguém não precisa mais das ligações (por exemplo, após a primeira venda ou se cancelou), interrompa a sequência dessa pessoa com a mesma chave. As ligações agendadas são canceladas imediatamente. Uma ligação já em andamento não é interrompida, mas nenhuma outra ligação será feita depois dela.

  • external_id | enrollment_id | phoneobrigatório
    Exatamente um destes: external_id (como enviado na inscrição), enrollment_id (da resposta da inscrição) ou phone.
  • reasonopcional
    Motivo opcional, até 200 caracteres, guardado no registro de auditoria da sua conta.
  • 200: interrompida (changed: true) ou já encerrada: status stopped, completed ou failed (changed: false). Pode ser repetido com segurança.
  • 400: invalid_request (nenhum identificador ou mais de um) ou invalid_phone
  • 401: invalid_key
  • 404: not_found, não existe essa inscrição nesta sequência
  • 429: rate_limited
curl
curl -X POST "https://telofia.com/api/outreach/unenroll" \
  -H "Authorization: Bearer tlo_…" \
  -H "Content-Type: application/json" \
  -d '{"external_id":"user_123","reason":"first_sale"}'
200 OK
{
  "ok": true,
  "enrollment_id": "8f7e6d5c-4b3a-4c2d-9e1f-0a9b8c7d6e5f",
  "external_id": "user_123",
  "status": "stopped",
  "changed": true
}

Resultados das ligações nos webhooks

call.started e call.completed de ligações de uma sequência trazem callback_id, external_id e outreach { sequence_id, enrollment_id, external_id, step } (todos null em ligações recebidas). Tentativas sem resposta não criam uma ligação, então não há call.completed para elas: após a última tentativa você recebe outbound_call.finished com status failed e last_error no_answer. As novas tentativas de uma etapa contam como um único resultado. call.completed inclui também caller_spoke e caller_words (quantas palavras a pessoa disse). Se alguém atendeu e desligou durante a saudação ou logo a seguir sem dizer nada, end_reason é caller_hangup_greeting.

call.completed de uma ligação da sequência
{
  "id": "5b1f0c6e-2a8d-4f3e-9d51-7c0a4e2b9f10",
  "object": "call",
  "assistant_id": "0e6f4c8a-3b2d-4a1e-8f7c-5d9b2a1c3e4f",
  "phone_number_id": "4d3c2b1a-0f9e-4d8c-b7a6-958473625140",
  "contact_id": "9a8b7c6d-5e4f-4a3b-2c1d-0e9f8a7b6c5d",
  "direction": "outbound",
  "status": "completed",
  "from": "+48732127980",
  "to": "+48601234567",
  "started_at": "2026-10-01T09:14:03Z",
  "ended_at": "2026-10-01T09:17:41Z",
  "duration_sec": 218,
  "summary": "Jan added the company name and tax ID; asked for a call tomorrow at 10:00 about payments.",
  "outcome": "message",
  "sentiment": "positive",
  "tags": [],
  "has_recording": true,
  "end_reason": "agent_hangup",
  "callback_id": "0f1e2d3c-4b5a-4968-8776-655443322110",
  "external_id": "gapli-evt-1842",
  "outreach": {
    "sequence_id": "11111111-1111-4111-8111-111111111111",
    "enrollment_id": "8f7e6d5c-4b3a-4c2d-9e1f-0a9b8c7d6e5f",
    "external_id": "gapli-evt-1842",
    "step": 1
  },
  "caller_spoke": true,
  "caller_words": 112
}

Agenda, CRM e automação

Integrações prontas, sem código

  • Google Agenda

    O assistente verifica a disponibilidade real e marca, remarca e cancela agendamentos na sua agenda. Lê apenas os horários ocupados, nunca os títulos dos eventos.

  • HubSpot

    Cada chamada é registrada no contato, agendamentos viram reuniões e pedidos de retorno viram tarefas. Opcionalmente cria contatos e negócios.

  • Pipedrive

    Chamadas como atividades ou notas, agendamentos como reuniões, retornos como atividades. Opcionalmente cria pessoas, negócios ou leads.

  • Zapier, Make e n8n

    Guias passo a passo no painel. Funcionam com webhooks e a API, incluídos em todos os planos.

Planos e limites

De qual plano você precisa

Limites por conta: requisições por minuto (também por chave, janela deslizante) e por dia (UTC). Acima do limite você recebe 429 rate_limited com o cabeçalho Retry-After.

PlanoPedidos / minPedidos / diaChaves APIWebhooks
Teste grátis (acesso de teste)201.00011
Line302.00022
Desk6010.00055
Office18050.0001010
Network600200.0002520

Widget de voz para o site: a partir do plano Office.

Precisa de limites maiores? Fale com a gente e podemos aumentá-los para a sua conta.

Acesso antecipado: seja uma das primeiras empresas a deixar a IA atender o telefone.

Pronto para conectar?

Comece o teste grátis, crie uma chave de API de teste e envie sua primeira requisição em minutos. A API está incluída em todos os planos, a partir do Line.