Trilambdas Connect · contrato v1
Documentação para desenvolvedores
Tudo o que o seu app precisa para mostrar ao usuário as pendências do próprio CPF, com consentimento, e ajudar a planejar o pagamento. A negociação continua no canal oficial de cada birô.
Visão geral
A integração tem três elos:
| Seu app | Trilambdas | Birô |
|---|---|---|
| Identifica o usuário e abre a conexão | Verifica a identidade e coleta o consentimento | Autoriza o titular, quando tem fluxo próprio |
| Exibe as dívidas e ajuda a planejar | Consulta, normaliza e junta duplicidades | Fornece as pendências e negocia |
A Trilambdas não guarda renda nem gastos, não negocia, não recebe pagamentos e não faz análise de crédito.
Início rápido
Com a chave de sandbox (tlk_test_…) que enviamos depois do pedido de acesso:
1. Crie a sessão de conexão (no seu backend)
curl https://api.trilambdas.com.br/v1/connect/sessions \
-H "Authorization: Bearer $TRILAMBDAS_KEY" \
-H "Content-Type: application/json" \
-d '{
"user": { "externalRef": "usr_123", "cpf": "529.982.247-25" },
"providers": ["SANDBOX"],
"redirectUrl": "https://seuapp.com.br/conexoes/retorno"
}'{
"connectionId": "cmwfp2k3x0001abcd",
"connectToken": "ctk_1f9c…",
"connectUrl": "https://api.trilambdas.com.br/connect?token=ctk_1f9c…",
"expiresAt": "2026-11-14T15:30:00.000Z"
}2. Abra o widget para o usuário
Na web, entregue o connectToken ao front e abra com o connect-js. No app móvel, abra o connectUrl numa webview ou aba segura. O usuário confirma a identidade e autoriza. Veja Widget.
3. Consulte o estado da conexão
curl https://api.trilambdas.com.br/v1/connections/cmwfp2k3x0001abcd \
-H "Authorization: Bearer $TRILAMBDAS_KEY"4. Leia as dívidas e o resumo
curl https://api.trilambdas.com.br/v1/users/usr_123/debts -H "Authorization: Bearer $TRILAMBDAS_KEY"
curl https://api.trilambdas.com.br/v1/users/usr_123/debt-summary -H "Authorization: Bearer $TRILAMBDAS_KEY"Testes automatizados podem pular o widget: POST /v1/connections/{id}/sandbox-authorize simula o titular autorizando e já faz a primeira consulta.
Autenticação e ambientes
| Ambiente | Prefixo da chave | Fontes | Dados |
|---|---|---|---|
| Sandbox | tlk_test_ | SANDBOX | fictícios, sempre iguais para o mesmo CPF |
| Produção | tlk_live_ | birôs com contrato ativo | reais |
- Envie
Authorization: Bearer tlk_…só do seu backend. A chave nunca vai para o app, o navegador ou o repositório. - A chave aparece uma única vez. Se vazar, peça a revogação.
- Base:
https://api.trilambdas.com.br/v1. Limite: 120 requisições por minuto por chave.
SDK para Node.js disponível
O @trilambdas/node cobre todas as rotas, com tipos, sem dependências (Node 20 ou mais novo). Repete sozinho leituras que falharam por rede, limite ou erro do servidor, e nunca repete um POST.
import { Trilambdas, constructEvent } from '@trilambdas/node';
const trilambdas = new Trilambdas({ apiKey: process.env.TRILAMBDAS_KEY! });
const { connectionId, connectToken } = await trilambdas.connect.createSession({
user: { externalRef: 'usr_123', cpf: '529.982.247-25' },
providers: ['SANDBOX'],
redirectUrl: 'https://seuapp.com.br/conexoes/retorno',
});
const dividas = await trilambdas.debts.list('usr_123');
const resumo = await trilambdas.debts.summary('usr_123');Até a publicação no npm, o SDK é entregue junto com a chave de sandbox: instale pelo repositório ou copie a pasta src para o seu projeto.
Conexões
A conexão é a autorização de um titular para um conjunto de fontes. Guarde o connectionId: é o identificador estável dela.
| Rota | Para quê | |
|---|---|---|
POST /v1/connect/sessions | Cria a conexão pendente e o token de uso único do widget (vale 30 min) | disponível |
GET /v1/connections/:id | Estado e resultado da última consulta, fonte por fonte | disponível |
GET /v1/users/:externalRef/connections | Conexões de um usuário | disponível |
DELETE /v1/connections/:id | Revoga; repetir não causa erro | disponível |
POST /v1/debt-discoveries | Consulta de novo as fontes autorizadas | disponível |
O externalRef é o id do usuário no seu app: estável e opaco, nunca CPF, e-mail ou telefone. Um externalRef fica preso a um CPF.
Widget
O widget é uma página da Trilambdas em três passos:
- Confirmar que é você. Em produção, com uma selfie no app Datavalid (Serpro): o titular informa um código de 9 caracteres no app e a foto é comparada à da CNH. No sandbox, também digitando o CPF da conta (5 tentativas; depois o link é bloqueado e a conexão fica
ERROR). - Autorizar, vendo o nome do seu app, as fontes, a validade e o que não acontece com os dados.
- Concluir e voltar para o seu app.
| Como você abriu | Ao terminar |
|---|---|
Janela aberta pelo seu site (window.open) | postMessage para a origem do seu redirectUrl, e a janela fecha |
| Webview, aba segura ou navegação direta | Redireciona para o redirectUrl com connectionId e status=authorized|cancelled|error |
Na web, com o connect-js
<script src="https://api.trilambdas.com.br/connect/connect.js"></script>
<script>
botao.addEventListener('click', () => {
TrilambdasConnect.open({
token: connectToken, // da sessão criada no seu backend
onSuccess: ({ connectionId }) => avisarBackend(connectionId),
onExit: ({ reason }) => registrar(reason), // 'user_cancelled' | 'user_closed' | 'error'
});
});
</script>- Chame
open()direto no clique do usuário, semawaitantes: senão o navegador bloqueia a janela. - A página que chama
open()precisa estar na mesma origem doredirectUrlda sessão: é só para ela que o widget envia o resultado. - Se a janela for bloqueada, o widget abre na mesma aba e volta ao
redirectUrl; lá,TrilambdasConnect.readRedirect()devolve{ connectionId, status }. - Se o seu site usa
Cross-Origin-Opener-Policy: same-origin, troque parasame-origin-allow-popups.
Confirme sempre o estado pelo seu backend (webhook ou GET): o retorno do navegador é só um aviso. O widget não abre dentro de iframe (proteção contra clique enganoso na tela de consentimento).
Ciclo de vida da conexão
| Estado | Quando | O que o app faz |
|---|---|---|
PENDING | Sessão criada; titular ainda não concluiu | Nada. Expira em 30 min |
AUTHORIZED | Titular autorizou; primeira consulta em andamento | Mostrar "Buscando suas pendências" |
ACTIVE | Primeira consulta concluída | Exibir as dívidas |
EXPIRED | Fim da validade (90 dias) | Apagar os dados importados e oferecer reconectar |
REVOKED | Titular desconectou | Apagar os dados importados |
ERROR | Nenhuma fonte respondeu ou identidade não confirmada | Ver lastErrorCode e oferecer nova sessão |
Dívidas e resumo
{
"id": "cm0debt001",
"creditor": { "name": "Banco Exemplo S.A.", "document": "00000000000191" },
"category": "CREDIT_CARD",
"status": "NEGATIVATED",
"currency": "BRL",
"registeredAmount": 4250.9,
"settlementOffer": { "amount": 2550.54, "validTo": "2026-11-28T00:00:00.000Z" },
"lastVerifiedAt": "2026-11-13T22:41:00.000Z",
"matchConfidence": "HIGH",
"negotiationUrl": "https://…",
"sources": ["SERASA", "BOA_VISTA"]
}registeredAmounté o valor da anotação no birô. Não é o valor para quitar.settlementOfferé o valor para quitar, com validade. Pode virnull.matchConfidence:HIGH(uma fonte ou fontes casadas pelo CNPJ) ouMEDIUM(casadas pelo nome do credor).
{
"userRef": "usr_123",
"currency": "BRL",
"identifiedDebt": 7241.66,
"settlementOffersTotal": 4344.99,
"uniqueDebts": 3,
"openDebts": 3,
"overdueDebts": 3,
"debtsWithOffer": 3,
"coverage": "complete"
}Com coverage: "partial", avise o usuário que a lista pode estar incompleta.
Webhooks disponível
Cadastre um destino HTTPS público com POST /v1/webhooks e os eventos que quer receber. A resposta traz o secret uma única vez: guarde num cofre. Cada destino pertence ao ambiente da chave que o cadastrou: com tlk_test_ recebe só eventos do sandbox; com tlk_live_, só de produção.
| Evento | Quando | Em data |
|---|---|---|
connection.authorized | O titular concluiu a autorização | connectionId, userRef, providers, expiresAt |
connection.revoked | A conexão foi revogada | connectionId, userRef |
connection.expired | A validade acabou | connectionId, userRef |
debts.updated | Uma consulta terminou | discoveryId, userRef, added, updated, removed, coverage |
O evento só avisa: nenhum CPF ou dado de dívida viaja nele. Os dados vêm do GET.
POST /webhooks/trilambdas
Content-Type: application/json
Trilambdas-Event-Id: evt_3f1a…
Trilambdas-Signature: t=1763073660,v1=5f2b0c…
{
"id": "evt_3f1a…",
"type": "debts.updated",
"environment": "SANDBOX",
"createdAt": "2026-11-14T04:41:00.000Z",
"data": { "connectionId": "cmwfp2k3x…", "discoveryId": "cmwfq9a1b…", "userRef": "usr_123",
"added": 3, "updated": 0, "removed": 0, "coverage": "complete" }
}Validar a assinatura
// Use o corpo bruto, exatamente como chegou, antes do JSON.parse
const evento = constructEvent(corpoBruto, req.headers['trilambdas-signature'], process.env.TRILAMBDAS_WEBHOOK_SECRET!);Sem o SDK:
- Separe
tev1do cabeçalhoTrilambdas-Signature. - Calcule
HMAC-SHA256(secret, "{t}.{corpo bruto}")e compare comv1em tempo constante. - Recuse se
ttiver mais de 5 minutos de diferença. - Ignore
Trilambdas-Event-Idjá processado. - Responda 2xx em até 10 s e processe em fila.
Novas tentativas e testes
- Sem 2xx, reenviamos com o mesmo
Trilambdas-Event-Id: depois de 30 s, 2 min, 10 min, 30 min, 1 h, 2 h, 4 h e então a cada 6 h, até 24 horas do evento. Redirecionamentos não são seguidos. POST /v1/webhooks/{id}/pingenvia agora umwebhook.pingassinado e devolve o resultado.GET /v1/webhooks/{id}/deliveriesmostra as últimas 50 entregas, com tentativas e código HTTP.
removed vem sempre 0 por enquanto: dívidas que somem passam a ser detectadas com a reconsulta periódica.
Erros
Todos seguem a RFC 9457 (application/problem+json).
{
"type": "https://docs.trilambdas.com.br/errors/422",
"title": "UNPROCESSABLE_ENTITY",
"status": 422,
"detail": "No ambiente de testes, use apenas a fonte SANDBOX",
"instance": "/v1/connect/sessions"
}400 | Corpo inválido (errors lista os campos) ou CPF inválido |
401 | Chave ausente, inválida ou revogada |
403 | Operação não permitida no ambiente da chave |
404 | Recurso não existe para o seu app (dados de outros apps nunca aparecem) |
409 | externalRef já vinculado a outro CPF |
422 | Regra de negócio (fonte de outro ambiente, sessão expirada, sem fonte autorizada) |
429 | Limite de requisições |
Sandbox e CPFs de teste
O 9º dígito do CPF define quantas dívidas voltam (9º dígito % 4). Os credores e os links de negociação são fictícios.
| CPF de teste | Dívidas |
|---|---|
100.000.000-19 | 0 |
100.000.001-08 | 1 |
100.000.002-80 | 2 |
529.982.247-25 | 3 |
Regras para o seu app
Obrigatórias em produção. Elas protegem o titular e fazem parte do que acordamos com os birôs.
- Mostre um selo de origem em cada dívida importada: "via Trilambdas · Serasa".
- Não deixe o usuário editar o que vem da fonte: credor, valores, datas, situação e link de negociação.
- Guarde o id da dívida e atualize por ele. Dívidas manuais continuam existindo.
- Planeje pela oferta de acordo, mostrando a validade. Nunca apresente o valor registrado como valor para quitar.
- O botão de negociar leva sempre ao
negotiationUrl. - Ofereça "Desconectar" com o mesmo destaque de "Conectar". Na revogação ou expiração, apague as dívidas importadas em até 24 horas.
- Não use os dados para análise ou oferta de crédito, marketing ou repasse a terceiros.
Antes de abrir o widget, mostre:
Conectar suas pendências. Vamos consultar, com a sua autorização, as pendências registradas no seu CPF nos birôs de crédito. Você pode desconectar quando quiser. A consulta é feita pela Trilambdas. A negociação acontece no canal oficial de cada birô.
Homologação
Antes da chave de produção, o seu app precisa:
- Criar a sessão e abrir o widget no fluxo real do app
- Tratar os retornos do widget e confirmar o estado pelo backend
- Exibir as dívidas com selo de origem e campos da fonte travados
- Planejar pela oferta, com validade visível
- Levar ao
negotiationUrlno botão de negociar - Desconectar e apagar os dados importados em até 24 horas
- Tratar
coverage: partiale os erros401,409,422e429 - Mostrar os textos obrigatórios
Referência da API
Todos os campos, parâmetros e respostas, gerados a partir do código, estão na referência interativa (OpenAPI).
Ainda não tem acesso? Peça a chave do sandbox.