Receba pedidos de clientes por um formulário público, por um link ou por um widget no seu site. Cada pedido vira um card no board Helpdesk do projeto. O cliente acompanha o andamento por um link, sem criar conta, e a equipe responde direto pelo card.
Versão em Markdown puro deste guia: https://app.krakendock.com/docs/helpdesk.md?lang=pt-BR. Use-a para colar num assistente de IA ou na documentação interna do seu time.
| Peça | Para quem | Onde |
|---|---|---|
| Formulário | o cliente (solicitante) | https://app.krakendock.com/f/SEU-SLUG, num iframe ou no widget |
| Board Helpdesk | a equipe | um board do projeto, visível só para membros |
| Acompanhamento | o cliente | https://app.krakendock.com/t/…, link enviado por e-mail |
| Configurações | quem administra o projeto | Configurações do projeto → Helpdesk |
O fluxo de um chamado:
Você precisa da permissão de gerenciar o projeto.
Abra o projeto e vá em Configurações → Helpdesk. A opção fica no grupo Integrações.
Clique em Novo formulário. Preencha o Nome (uso interno) e o Título da página (o que o cliente vê).
Mantenha o formulário Ativo e salve. Ao ativar o primeiro formulário, o KrakenDock cria o board Helpdesk com quatro colunas:
| Coluna | Papel | O cliente vê |
|---|---|---|
| Novo | new | Recebido |
| Em atendimento | in_progress | Em atendimento |
| Aguardando solicitante | waiting | Aguardando você |
| Resolvido | resolved (coluna de concluídos) | Resolvido |
Na janela que aparece depois de salvar, copie o link público, o iframe ou o botão flutuante (widget). Veja Divulgar o formulário.
Faça um pedido de teste. Ele aparece em segundos no board Helpdesk.
Pode renomear as colunas à vontade: cada uma guarda o seu papel. Uma coluna sem papel conta como Resolvido se for de concluídos e como Em atendimento nos outros casos. Os cards não passam do board Helpdesk para os outros boards do projeto, nem o contrário.
Cada projeto pode ter vários formulários (por exemplo, "Suporte" e "Financeiro"). Todos entram no mesmo board Helpdesk.
https://app.suaempresa.com (sem caminho). http só é aceito para localhost, e domínios com acento vão em punycode. Sem nenhuma origem, o formulário só funciona pelo link.#rrggbb, usada em botões, links e foco. As configurações avisam quando a cor tem pouco contraste.O jeito mais simples: mande o link por e-mail, coloque num botão do site ou na assinatura.
https://app.krakendock.com/f/SEU-SLUG
Mostra o formulário dentro de uma página do seu site. A origem do site precisa estar em Origens permitidas.
<iframe
id="kraken-form"
src="https://app.krakendock.com/f/SEU-SLUG?embed=1"
title="Fale com o suporte"
style="width:100%;min-height:640px;border:0"
loading="lazy"
></iframe>
Para combinar com o seu site, acrescente à URL do iframe os parâmetros abaixo. Eles só valem junto com embed=1; valores inválidos são ignorados.
| Parâmetro | Valores | Padrão |
|---|---|---|
theme | light, dark ou system | o tema do sistema operacional do visitante |
lang | pt-BR ou en | o idioma do navegador |
Exemplo: https://app.krakendock.com/f/SEU-SLUG?embed=1&theme=light&lang=pt-BR. Sem eles, o formulário não sabe o tema nem o idioma que o visitante escolheu no Kraken: um iframe em outro site não recebe esses cookies.
O formulário avisa a altura do conteúdo por postMessage. Para o iframe crescer junto e não mostrar barra de rolagem, acrescente:
<script>
window.addEventListener('message', function (event) {
var frame = document.getElementById('kraken-form');
if (event.origin !== 'https://app.krakendock.com' || event.source !== frame.contentWindow) return;
if (event.data && event.data.type === 'kraken-intake:resize') {
frame.style.height = event.data.height + 'px';
}
});
</script>
Um botão no canto da página abre o formulário num painel no estilo chat. Em telas de até 639 px, o painel ocupa a tela inteira. O painel não bloqueia a página, e o rascunho continua lá se o cliente fechar e abrir de novo. A origem do site precisa estar em Origens permitidas.
<script
src="https://app.krakendock.com/intake.js"
data-form="SEU-SLUG"
data-label="Suporte"
data-close-label="Fechar"
data-color="#4f46e5"
async
></script>
Os textos padrão dos botões são em português. Num site em outro idioma, defina data-label e data-close-label. Para o formulário combinar com o site, use data-theme e data-lang: o painel não recebe os cookies do Kraken, então sem eles segue o tema do sistema operacional e o idioma do navegador do visitante.
| Atributo | Obrigatório | O que faz |
|---|---|---|
data-form | sim | slug do formulário |
data-label | não | texto do botão (padrão: "Suporte") |
data-close-label | não | nome acessível do botão de fechar (padrão: "Fechar") |
data-position | não | right (padrão) ou left |
data-color | não | cor do botão, #rgb ou #rrggbb (padrão: #4f46e5). A cor do texto é escolhida pelo contraste |
data-identity | não | token de identidade assinada (veja abaixo) |
data-theme | não | tema do formulário: light, dark ou system (padrão: o do sistema operacional do visitante) |
data-lang | não | idioma do formulário: pt-BR ou en (padrão: o do navegador) |
Depois que o intake.js carrega, a página ganha o objeto window.KrakenIntake:
| Função | O que faz |
|---|---|
open(slug?) | abre o painel, opcionalmente com outro formulário |
close() | fecha o painel |
toggle() | abre ou fecha |
identify(token) | informa a identidade assinada do usuário logado; identify(null) esquece só a identidade |
prefill(values) | pré-preenche o formulário; prefill(null) esquece |
onIdentityExpired(handler) | registra a função que busca um token novo quando o atual expira |
reset() | fecha o painel e descarta rascunho, identidade, pré-preenchimento e onIdentityExpired (use no logout) |
Exemplo: abrir o suporte a partir de um link do seu menu.
<a href="#" onclick="window.KrakenIntake.open(); return false;">Precisa de ajuda?</a>
A tecla Esc também fecha o painel.
Sugere valores que o cliente ainda pode editar. Não comprova quem é o usuário (para isso, use a identidade assinada). Funciona em todos os planos.
Pelo widget:
window.KrakenIntake.prefill({
name: 'Ana Souza',
email: 'ana@cliente.com',
phone: '+55 11 91234-5678',
subject: 'Problema no pedido 1234',
description: 'Descreva o que aconteceu…',
fields: { 'ID-DO-CAMPO': 'valor' },
});
fields aceita até 50 campos.fields são os ids dos campos extras, e cada valor segue o tipo do campo:| Tipo do campo | Valor esperado | Exemplo |
|---|---|---|
| texto, URL | texto | 'Pedido 1234' |
| número | número ou texto numérico | 42 ou '42' |
| data | texto no formato AAAA-MM-DD | '2026-10-19' |
| seleção | id da opção (não o rótulo) | '8f0c…' |
| seleção múltipla | lista de ids de opções | ['8f0c…', '1a2b…'] |
| caixa de seleção | booleano | true |
https:// bloqueia o envio até o cliente corrigir, e uma data fora de AAAA-MM-DD faz o envio falhar.data.fields[].field_id e os das opções em data.fields[].options[].id.curl https://app.krakendock.com/api/intake/SEU-SLUG
Pelo link (fragmento #), só os campos fixos:
https://app.krakendock.com/f/SEU-SLUG#name=Ana%20Souza&email=ana%40cliente.com&subject=Pedido%201234
name, email, phone, subject e description.Quando o cliente já está logado no seu sistema, o widget pode abrir com o nome, o e-mail e o telefone dele preenchidos e travados. Nesse caso o envio:
A identidade assinada está disponível nos planos Pro e Business.
Em Configurações → Helpdesk → Integração com seu sistema, clique em Gerar chave.
khd_ e aparece uma única vez. Guarde-a num cofre de segredos do servidor. Ela nunca pode ir para o navegador.O token é um JWT HS256 assinado com a chave inteira, incluindo o prefixo khd_.
| Claim | Obrigatório | Regra |
|---|---|---|
sub | sim | id do usuário no seu sistema, como texto, até 128 caracteres |
name | sim | até 120 caracteres |
email | sim | e-mail válido, até 254 caracteres |
phone | não | de 8 a 15 dígitos; aceita +, espaço, -, ., ( e ) |
exp | sim | no máximo 24 h no futuro (recomendado: 1 h) |
Node (jsonwebtoken):
import jwt from 'jsonwebtoken';
const token = jwt.sign(
{
sub: String(user.id),
name: user.name,
email: user.email,
...(user.phone ? { phone: user.phone } : {}),
},
process.env.KRAKEN_IDENTITY_KEY,
{ algorithm: 'HS256', expiresIn: '1h' },
);
PHP (firebase/php-jwt):
use Firebase\JWT\JWT;
$claims = [
'sub' => (string) $user->id,
'name' => $user->name,
'email' => $user->email,
'exp' => time() + 3600,
];
if ($user->phone) {
$claims['phone'] = $user->phone;
}
$token = JWT::encode($claims, getenv('KRAKEN_IDENTITY_KEY'), 'HS256');
Python (PyJWT):
import os
from datetime import datetime, timedelta, timezone
import jwt
claims = {
"sub": str(user.id),
"name": user.name,
"email": user.email,
"exp": datetime.now(timezone.utc) + timedelta(hours=1),
}
if user.phone:
claims["phone"] = user.phone
token = jwt.encode(claims, os.environ["KRAKEN_IDENTITY_KEY"], algorithm="HS256")
Go (golang-jwt):
import (
"os"
"time"
"github.com/golang-jwt/jwt/v5"
)
claims := jwt.MapClaims{
"sub": userID, // string
"name": user.Name,
"email": user.Email,
"exp": time.Now().Add(time.Hour).Unix(),
}
if user.Phone != "" {
claims["phone"] = user.Phone
}
token, err := jwt.NewWithClaims(jwt.SigningMethodHS256, claims).
SignedString([]byte(os.Getenv("KRAKEN_IDENTITY_KEY")))
Na página do usuário logado:
<script src="https://app.krakendock.com/intake.js" data-form="SEU-SLUG" data-identity="TOKEN" async></script>
Ou depois que o script carregar (por exemplo, numa aplicação de página única):
window.KrakenIntake.identify(token);
// no logout:
window.KrakenIntake.reset();
No logout, prefira reset() a identify(null): além de esquecer a identidade, ele descarta o rascunho do formulário (assunto, descrição, anexos e campos pré-preenchidos), o pré-preenchimento e a função registrada em onIdentityExpired. Uma renovação de token que ainda esteja em andamento vai até o fim (a função do seu site roda e a requisição acontece), mas o token que ela devolver é descartado. Assim, a próxima pessoa que usar a mesma aba começa com o formulário limpo. O reset() vale para todos os widgets da página, mesmo que haja mais de um formulário. O botão continua na página; depois do reset(), chame identify(token) e prefill(values) de novo para o próximo usuário.
Para renovar o token quando ele expira com o widget aberto, registre uma função que busque um token novo no seu backend:
window.KrakenIntake.onIdentityExpired(async () => {
const response = await fetch('/kraken-token'); // rota do seu backend que gera o JWT
if (!response.ok) return null; // sem token: o formulário volta a pedir os dados
return response.text();
});
Regras importantes:
#identity= no link é ignorado, para ninguém conseguir mandar um link que abra chamados no nome de outra pessoa.Uma identidade recusada não trava o formulário: ele volta ao modo normal e registra o motivo no console do navegador, por exemplo [Kraken] Identidade assinada recusada (signature): o formulário segue sem identificação. A API responde 422 INTAKE_IDENTITY_INVALID com o motivo em fields.identity:
| Motivo | Quando acontece |
|---|---|
malformed | não é um JWT, passa de 4 KB ou tem claim com tipo errado (por exemplo, sub numérico) |
signature | outro algoritmo, assinado com outra chave ou sem o prefixo khd_ |
expired | passou do exp (há uma folga de 30 s) |
claims | falta sub, name, email ou exp, exp passa de 24 h, iat está no futuro ou o telefone é inválido |
disabled | o projeto não tem chave |
Num plano sem a identidade assinada, a resposta é 403 PLAN_FEATURE_REQUIRED.
Pelo widget ou por um iframe, disabled e o 403 não chegam a aparecer. Se o projeto não tem chave, ou se o plano não inclui o recurso, o formulário nem consulta a API: ele só registra no console [Kraken] Identidade assinada ignorada: o formulário não aceita identidade (chave do projeto ausente ou plano sem o recurso). Um token com mais de 4.096 caracteres é descartado pelo intake.js sem aviso.
Com a identidade assinada, o widget mostra as abas Novo chamado e Meus chamados. Na segunda, o usuário vê os últimos 50 pedidos verificados dele no projeto (do mesmo sub), do mais novo para o mais antigo, e abre cada conversa sem depender do e-mail. Quando é a mesma pessoa, as respostas enviadas por ali não pedem captcha.
Depois do envio, o cliente vê o número do pedido e o link de acompanhamento, que também chega por e-mail. A página https://app.krakendock.com/t/… mostra:
O link de acompanhamento é pessoal: quem tem o link vê o pedido. Ele não é indexado por buscadores.
| Quando | Assunto |
|---|---|
| O pedido é recebido | Recebemos seu chamado KEY-N |
| A equipe responde ao solicitante | Nova resposta no seu chamado KEY-N |
| O status visível muda (menos para Recebido) | Seu chamado KEY-N foi atualizado |
Abra o card no board Helpdesk.
Solicitante: mostra nome, e-mail, telefone, o id no seu sistema (com identidade assinada), o formulário, a data de abertura, o consentimento e o selo Verificado. Quem gerencia o projeto também vê as ações Bloquear e-mail, Bloquear IP e Anonimizar solicitante.
Conversa: o fio com o cliente. Responda em Responder ao solicitante:
Botões de status, conforme a coluna em que o card está:
| Status atual | Botões |
|---|---|
| Novo | Iniciar atendimento, Resolver |
| Em atendimento | Aguardar solicitante, Resolver |
| Aguardando solicitante | Retomar atendimento, Resolver |
| Resolvido | Reabrir |
Notas internas: os comentários comuns do card são internos (selo Interno) e nunca chegam ao cliente. O Histórico do card mostra as notas internas e a atividade, sem as mensagens da conversa.
Se o cliente responder enquanto o card está em Aguardando solicitante ou Resolvido, o card volta para Em atendimento sozinho.
Um card arquivado, ou com comentários travados, não recebe novas respostas do cliente.
429 RATE_LIMITED.403 INTAKE_BLOCKED).| Free | Pro | Business | |
|---|---|---|---|
| Formulários por projeto | 3 | ilimitados | ilimitados |
| Chamados por mês (soma de todos os projetos da conta) | 50 | ilimitados | ilimitados |
| Tamanho por arquivo | 5 MiB | 25 MiB | 50 MiB |
| Arquivos por pedido | 3 | 10 | 20 |
| Sem a marca KrakenDock | — | sim | sim |
| Identidade assinada e Meus chamados | — | sim | sim |
| Pré-preenchimento, iframe e widget | sim | sim | sim |
Veja os planos em https://app.krakendock.com/pricing.
| Quero… | Use |
|---|---|
| receber pedidos de um site ou app | link, iframe ou widget |
| identificar o usuário logado | identidade assinada |
| sugerir dados que o cliente pode editar | pré-preenchimento |
| avisar outro sistema quando um chamado chega ou muda | webhooks do projeto (card.created, card.moved, comment.created…), nas configurações do projeto, em Webhooks |
| deixar um assistente de IA ler e responder chamados | o servidor MCP do KrakenDock, com um token com permissão de escrita, criado nas configurações da sua conta em Tokens de acesso (MCP): get_card traz a conversa, e add_comment com visibility: requester responde ao cliente por e-mail |
Os webhooks dos cards do Helpdesk não levam nome, e-mail nem IP do solicitante.
O widget e o formulário conversam por postMessage. Se você usar um iframe próprio (?embed=1) em vez do widget, pode usar as mesmas mensagens:
| Direção | Mensagem |
|---|---|
| formulário → página | { type: 'kraken-intake:ready' } a cada carga: a hora de mandar identidade e pré-preenchimento |
| formulário → página | { type: 'kraken-intake:resize', height } quando a altura muda |
| formulário → página | { type: 'kraken-intake:close' } quando o cliente aperta Esc |
| formulário → página | { type: 'kraken-intake:identity-expired', generation } quando a identidade expira |
| página → formulário | { type: 'kraken-intake:identity', token } (null esquece) |
| página → formulário | { type: 'kraken-intake:prefill', values } |
Regras do protocolo:
window.parent) e de uma origem permitida.targetOrigin igual a https://app.krakendock.com.var frame = document.getElementById('kraken-form');
window.addEventListener('message', function (event) {
if (event.origin !== 'https://app.krakendock.com' || event.source !== frame.contentWindow) return;
if (event.data && event.data.type === 'kraken-intake:ready') {
frame.contentWindow.postMessage({ type: 'kraken-intake:identity', token: TOKEN }, 'https://app.krakendock.com');
}
});
| Sintoma | Causa provável |
|---|---|
| O iframe ou o widget aparece em branco, ou o navegador diz que recusou a conexão | a origem do site não está em Origens permitidas (o formato é https://dominio, sem barra no fim) |
| "Formulário não encontrado" | o slug está errado, o formulário está inativo ou o board Helpdesk foi excluído |
| Console: "Identidade assinada ignorada" | o projeto não tem chave (gere em Integração com seu sistema) ou o plano não inclui a identidade assinada |
| A identidade é ignorada | veja o motivo no console do navegador e na tabela Erros da identidade. O mais comum é assinar sem o prefixo khd_ ou mandar sub como número |
| A identidade funciona no widget, mas não no link | é o esperado: o link aceita só pré-preenchimento |
| O cliente não recebeu o e-mail | confira a caixa de spam. O link de acompanhamento também aparece na tela de sucesso |
| "Este pedido não recebe mais respostas." | o card foi arquivado ou teve os comentários travados |
Envio recusado com 429 | limite de envios por IP, e-mail ou link. Espere alguns minutos |
| O limite de 50 chamados acabou | no plano Free, o limite é por conta e por mês. Os planos Pro e Business não têm limite |
Ainda com dúvidas? Fale com a gente em https://app.krakendock.com/help.