Skip to main content
No modo hosted o UserKit guarda a senha e é dono da conta. Os formulários são seus; estes endpoints são as regras por trás deles. Todo endpoint aqui é superfície pública alcançada com uma chave publicável no corpo da requisição, a partir do seu próprio domínio. A postura é a mais rígida da API: respostas não enumeráveis, caminhos de senha em tempo constante, rate limits estritos e tokens de uso único para tudo que chega por e-mail.
Estes endpoints exigem que o ambiente esteja em modo hosted. Em um ambiente federado, eles respondem 409 environment_not_hosted.

Cadastro

202 — sempre
Sempre 202. A resposta nunca revela se o endereço já tem conta. Três coisas diferentes acontecem por trás dessa única resposta:
1

Um endereço novo

O contato é criado com a senha anexada — não há nada aqui para tomar — e um e-mail de verificação sai. email_verified continua falso até o link ser clicado.
2

Um endereço que já tem senha

Nada é criado. Um aviso de “você já tem uma conta” vai para a caixa de entrada, nunca para quem chamou.
3

Um contato que o seu servidor criou, ainda sem senha

A senha escolhida espera no token de verificação e só se anexa quando o link comprovar o e-mail.
Enquanto o ambiente está em modo lista de espera, esta mesma chamada coloca a pessoa na fila em vez de criar conta, e responde { "waitlist": true }. A senha escolhida fica guardada na entrada até ela ser liberada — o terceiro caso abaixo, uma camada acima.
Esse terceiro caso é o que vale entender. Se a senha se anexasse na hora, qualquer um poderia se cadastrar com o endereço de um contato que você pré-criou e capturar a conta. Fazer a senha esperar no token fecha isso estruturalmente, e não com uma verificação que alguém pode esquecer.
Passar anonymous_id absorve o visitante que essa pessoa já era no novo contato, atribuição incluída. Rate limit de 10 por hora por IP.

Verificar o e-mail

O link do e-mail carrega um token uk_cv_…, válido por 24 horas. Sua página lê da query string e faz o POST:
200
Três coisas acontecem de uma vez: o e-mail é comprovado, qualquer senha esperando no token se anexa, e uma sessão verificada volta — a pessoa clicou a partir da caixa de entrada, não faça ela logar de novo.

Reenviar

202 sempre. Nada sai para endereços desconhecidos ou já verificados. Rate limit de 5 por hora por IP — cada requisição envia e-mail para a caixa de alguém.

Login

200
E-mail desconhecido, contato sem senha e senha errada produzem o mesmo 401 invalid_credentials — e levam aproximadamente o mesmo tempo, porque o caminho sem senha roda uma comparação bcrypt descartável. Sem isso, só contas reais pagariam as dezenas de milissegundos, e a latência sozinha responderia “esse endereço existe?”. Provar a senha prova a conta, então a sessão é verificada. Rate limit de 20 por 5 minutos por IP.

Recuperar a senha

1

Pedir

202 incondicional. Rate limit de 5 por hora por IP.
2

Redefinir

204. Rate limit de 10 por hora por IP.
A redefinição faz três coisas além de trocar a senha:
  • todas as sessões daquele contato são revogadas, na hora — uma redefinição normalmente significa que outra pessoa pode estar com a credencial;
  • o e-mail conta como comprovado, porque o link chegou nele;
  • um contato que nunca havia sido identificado passa a ser.
Este fluxo também funciona para contatos que nunca tiveram senha — os que o seu servidor criou com POST /v1/contacts. Receber o link comprova o e-mail, então “redefinir” faz as vezes de “definir uma senha”.
Login sem senha, e funciona nos dois modos. No modo federado, é também a única coisa capaz de promover um e-mail de atributo a identidade comprovada.
1

Pedir

202 incondicional. Válido por uma hora. Rate limit de 5 por hora por IP.
2

Resgatar

Responde o contato e uma sessão uk_ct_… verificada.
O resgate é atômico em SQL, então o link funciona exatamente uma vez. Usado, expirado e nunca existiu respondem o mesmo 401 — três verdades diferentes, uma resposta, de propósito.

Códigos por e-mail

O mesmo fluxo apresentado como seis dígitos, e também funciona nos dois modos. Prefira o código ao link quando ele vai ser digitado no aparelho que o pediu: um código sobrevive ao cliente de e-mail que abre links no navegador dele, e funciona quando a caixa de entrada está no celular e o login está no notebook.
1

Pedir

202 — sempre
Guarde o desafio na página. Ele não é uma sessão e nunca pode ser usado como uma. Vale por dez minutos. Rate limit de 5 por hora por IP.
2

Verificar

Responde o contato e uma sessão uk_ct_… verificada. O código chegou na caixa de entrada, então ele comprova o endereço exatamente como o link.
O desafio volta para qualquer endereço, tendo conta ou não — do contrário este endpoint seria justamente onde alguém descobre quais endereços têm. A verificação mantém a mesma linha: código errado, expirado, já usado e desafio que nunca teve código atrás dele respondem o mesmo 401 invalid_code.
Duas regras são o que torna seis dígitos seguros de aceitar, e as duas importam:
  • Cada código tem cinco tentativas. Um palpite gasta uma, certo ou errado, e o código morre quando acabam. Seis dígitos são um milhão, o que o rate limit sozinho não fecha.
  • Pedir um código novo gasta o anterior. Senão cada pedido somaria mais cinco palpites contra mais um número.
O código sozinho também não basta: ele só vale contra o desafio para o qual foi emitido, então um código lido por cima do ombro de alguém não abre nada sem o navegador que o pediu.

Política de senha

Pelo menos 8 caracteres, com uma letra minúscula, uma maiúscula e um dígito. Qualquer coisa mais curta ou mais simples responde 400 weak_password. Deliberadamente modesta: comprimento é o que importa, e uma política contra a qual as pessoas brigam produz Password1! em todo lugar. E a senha não pode ser uma senha sabidamente vazada. Toda senha definida aqui — cadastro, redefinição, “definir uma senha” — é conferida contra um corpus público de senhas que apareceram em vazamentos, e um acerto responde 400 breached_password. Essa regra sozinha impede mais tomadas de conta que qualquer exigência de composição, porque credential stuffing é o que de fato acontece com os seus clientes.
A senha não sai do nosso processo, e nada que a identifique sai também. Ela é hasheada localmente e só os cinco primeiros caracteres desse hash vão na rede; o corpus responde com todos os candidatos sob aquele prefixo e a comparação acontece aqui. O serviço aprende que alguém perguntou sobre uma de várias centenas de senhas, e nada além disso.A checagem falha aberta. Se o corpus não puder ser alcançado a senha é aceita e nós registramos: recusar todo cadastro porque um terceiro caiu seria uma indisponibilidade que importamos para dentro do seu produto.

A sessão

Todo fluxo bem-sucedido aqui devolve uma sessão de contato uk_ct_…, válida por 30 dias, com verified: true. Use nas leituras do próprio contato:
Sair deleta a sessão — a próxima busca simplesmente não casa com nada.