API do chat do website
Ligue um formulário próprio ao widget de chat ou crie uma interface de chat própria com o SDK do widget, REST, tipos, SSE e atividade do visitante.
Última atualização em
O widget oficial instala-se na aplicação: consulte Colocar o chat no seu website. As opções do snippet estão em Definições do chat do website. Esta página é para programadores: o SDK do widget para um formulário próprio e a camada REST para uma interface de chat própria. Consulte o OpenAPI, etiqueta inbox.
SDK do widget
Depois de carregar o script do widget, window.TillorInbox fica disponível. Com ele passa dados de contacto a partir do seu próprio formulário (página de contacto, detalhe de venda, pedido de orçamento). Todos os métodos esperam até a configuração do widget estar carregada.
| Método | Descrição |
|---|---|
ready() | Promise que fica pronta assim que o widget estiver carregado |
getVisitor() | Lê os dados de contacto guardados em localStorage e os campos do widget preenchidos; síncrono, sem rede |
setVisitor({ name?, firstName?, lastName?, email?, phone?, message?, customFields? }, options?) | Preenche os campos do chat sem enviar |
open() | Abre a janela de chat |
close() | Fecha a janela de chat |
toggle() | Abre ou fecha a janela de chat |
send({ body, name?, firstName?, lastName?, email?, phone?, message?, customFields?, open?, silent?, markSubmitted?, metadata? }) | Envia uma mensagem com dados de contacto |
getVisitor() devolve este objeto:
| Campo | Descrição |
|---|---|
visitorId | ID deste visitante neste navegador (localStorage) |
name | Nome completo (um único campo no widget) |
firstName / lastName | Derivados de name (primeira palavra / resto) |
email, phone | Dados de contacto |
customFields | Campos adicionais das definições do widget |
message | Rascunho no campo da mensagem |
detailsSubmitted | Se o formulário do visitante conta como preenchido |
Utilize getVisitor() para preencher previamente um formulário próprio a partir de localStorage (mesmo navegador, também após atualizar a página).
Opções para setVisitor (segundo argumento):
| Opção | Por defeito | Explicação |
|---|---|---|
open | false | Abrir logo a janela de chat |
markSubmitted | false | Ocultar o formulário do visitante se todos os campos obrigatórios estiverem preenchidos |
onlyEmpty | false | Substituir apenas campos vazios |
persist | false | Guardar os dados em localStorage (mesmo navegador, também num novo separador) |
Opções para send:
| Opção | Por defeito | Explicação |
|---|---|---|
open | false | Abrir a janela de chat antes de enviar |
silent | true se open for false | Sem som, sem mensagem de erro no widget; use a Promise para sucesso ou erro |
markSubmitted | true | Os dados de contacto já não têm de ser indicados de novo no widget |
metadata | - | Sugestões opcionais para a Tillie (não visíveis na janela de chat); consulte metadata |
Com open: false (por defeito), o botão do chat permanece fechado. A mensagem chega mesmo assim ao Tillor; o seu formulário pode agradecer ou mostrar um erro. Com open: true, a janela de chat abre e o visitante vê o comportamento normal de envio (som, vistos, eventuais erros do widget).
Quer usar um botão seu em vez do botão de chat flutuante? Defina data-launcher="false" no snippet e chame TillorInbox.open().
metadata (formulário de reserva)
Utilize metadata quando tiver um formulário próprio no website e a Tillie deva enviar apenas uma confirmação, sem perguntas de seguimento (por exemplo, porque o separador se fecha depois).
| Chave | Tipo | Explicação |
|---|---|---|
forceHandover | boolean | Mensagem de confirmação e passagem a um colega, sem perguntas de admissão. Ignora também a pausa da IA após uma mensagem da equipa (consulte ignoreAiPause) |
ignoreAiPause | boolean | A Tillie responde também quando está em pausa no modo Automático após uma mensagem da equipa (30 minutos). Útil para envio silencioso de formulários; combine com forceHandover ou deixe a Tillie fazer a admissão normalmente |
handoverIntent | "reservation" | "caravan_rental" | "sale" | "other" | Opcional: fluxo da passagem (por defeito: deduzido automaticamente da mensagem) |
source | string | Etiqueta de integração opcional para a sua equipa (letras minúsculas, números, -, _; máx. 64 carateres) |
await TillorInbox.send({
name: "Jan Janssens",
email: "jan@voorbeeld.be",
phone: "+32 3 779 81 64",
body: structuredBookingMessage,
silent: true,
metadata: {
forceHandover: true,
handoverIntent: "reservation",
source: "website_booking_form",
},
});Substituir o formulário de contacto (envio silencioso)
Utilize isto quando quiser manter o formulário de contacto existente, mas fazer as mensagens passar pelo Tillor sem abrir a janela de chat.
<form id="site-contact-form">
<input name="name" type="text" required />
<input name="email" type="email" required />
<input name="phone" type="tel" />
<textarea name="message" required></textarea>
<button type="submit">Enviar</button>
<p id="contact-status" hidden></p>
</form>
<script>
document.getElementById("site-contact-form").addEventListener("submit", async (event) => {
event.preventDefault();
const form = event.currentTarget;
const status = document.getElementById("contact-status");
const data = new FormData(form);
try {
await TillorInbox.send({
name: String(data.get("name") ?? ""),
email: String(data.get("email") ?? ""),
phone: String(data.get("phone") ?? ""),
body: String(data.get("message") ?? ""),
});
status.textContent = "Obrigado, entraremos em contacto em breve.";
status.hidden = false;
form.reset();
} catch (error) {
status.textContent = error instanceof Error ? error.message : "Falha ao enviar.";
status.hidden = false;
}
});
</script>Não precisa de definir open e silent: sem open: true, a janela permanece fechada e o Tillor trata a chamada como envio silencioso.
Ligar o formulário de contacto (abrir o chat)
Passar os campos e abrir a janela de chat, para que o visitante veja a conversa:
<form id="site-contact-form">
<input name="name" type="text" required />
<input name="email" type="email" required />
<input name="phone" type="tel" />
<textarea name="message" required></textarea>
<button type="submit">Enviar</button>
</form>
<script>
document.getElementById("site-contact-form").addEventListener("submit", (event) => {
event.preventDefault();
const form = event.currentTarget;
const data = new FormData(form);
void TillorInbox.send({
name: String(data.get("name") ?? ""),
email: String(data.get("email") ?? ""),
phone: String(data.get("phone") ?? ""),
body: String(data.get("message") ?? ""),
open: true,
});
});
</script>Ou apenas preencher os campos e abrir a janela, sem enviar logo:
void TillorInbox.setVisitor(
{
name: "Jan Janssens",
email: "jan@voorbeeld.be",
phone: "+32 3 779 81 64",
message: "Ik heb een vraag over de stacaravan te koop.",
},
{ markSubmitted: true, open: true },
);Uma página de vendas com envio direto e abertura do chat:
void TillorInbox.send({
name: "Jan Janssens",
email: "jan@voorbeeld.be",
phone: "+32 3 779 81 64",
body: "Ik heb interesse in deze stacaravan.",
open: true,
});Sincronizar em direto enquanto alguém escreve:
const form = document.getElementById("site-contact-form");
form.addEventListener("input", () => {
void TillorInbox.setVisitor({
name: form.name.value,
email: form.email.value,
phone: form.phone.value,
message: form.message.value,
});
});Chamar cedo (antes do script do widget)
Se chamar um método antes de o script estar carregado, coloque a chamada na fila:
<script>
window.TillorInbox = window.TillorInbox || { q: [] };
window.TillorInbox.q.push([
"setVisitor",
{ name: "Jan", email: "jan@voorbeeld.be" },
{ open: true },
]);
</script>
<script src="https://tillor.eu/inbox-widget.js" data-org-id="org_abc123" data-widget-key="iwk_xxx" async defer></script>Interface de chat própria
Se criar uma interface de chat própria em vez do widget, utilize a camada REST abaixo.
Autenticação: cabeçalho X-Tillor-Inbox-Widget-Key (valor em Definições > Integrações > Chat do website).
Escrita
POST /api/orgs/{orgId}/inbox/website/typing
X-Tillor-Inbox-Widget-Key: iwk_xxx
Content-Type: application/json
{
"visitorId": "vis_…",
"active": true,
"visitorName": "Jan",
"visitorEmail": "jan@voorbeeld.nl",
"visitorPhone": "+32470123456"
}active: truequando o visitante escreve;falsequando o campo fica vazio ou o visitante pára (o widget enviafalseapós cerca de 4 segundos sem entrada)visitorName/visitorEmail/visitorPhonesão opcionais- Utilize o mesmo
visitorIdque emPOST …/inbox/website/messageseGET …/inbox/website/messages
Tempo real (SSE)
GET /api/orgs/{orgId}/inbox/website/subscribe?visitorId=vis_…
X-Tillor-Inbox-Widget-Key: iwk_xxx
Accept: text/event-stream| Evento | Quando |
|---|---|
inbox:website:message-created | Nova mensagem da equipa ou da IA |
inbox:website:message-updated | Mensagem da equipa ou da IA alterada ou eliminada |
inbox:website:typing-changed | data.staffTyping ou data.staffOutboundSenderType muda |
O formato do payload é o mesmo do SSE da organização (event, data, timestamp). Volte a ligar após uma interrupção; não há retoma.
O widget oficial usa o SSE como camada principal e volta a obter GET …/messages a cada 5 segundos como alternativa (a cada 1 segundo com o painel aberto quando o SSE cai por momentos). Assim, as respostas são marcadas como entregues enquanto o visitante estiver na página.
Atividade do visitante
POST /api/orgs/{orgId}/inbox/website/events
X-Tillor-Inbox-Widget-Key: iwk_xxx
Content-Type: application/jsonevent: chat_closed, tab_hidden ou navigation (na navegação também url). A sua equipa vê estes eventos como texto informativo cinzento na conversa, consulte Conversas através do chat do website.
Limites
POST …/inbox/website/messages e POST …/inbox/website/attachments/upload respondem 429 quando um visitante ou uma rede envia demasiado. O corpo traz data.reason = INBOX_WIDGET_RATE_LIMITED e data.retryAfterSeconds. Limites por organização:
| Rota | Por visitante (visitorId) | Por rede (endereço IP) |
|---|---|---|
messages | 10 por minuto, 200 por dia | 30 por minuto, 600 por dia |
attachments/upload | 10 por hora | 50 por hora |
Espera retryAfterSeconds antes de tentar de novo e mostra um aviso ao visitante em vez de repetir automaticamente.