POST /v1/assessments — a requisição
Seu backend solicita uma avaliação com uma única chamada síncrona a
POST https://api.fingertrackid.com/v1/assessments, assinada com
HMAC.
A origem da API de produção é https://api.fingertrackid.com; o console também a mostra, com um
botão de copiar, como Endereço da API de risco na etapa Credencial servidor a servidor de
Início. Configure-a exatamente como está escrita, sem barra final nem caminho. O caminho é
exatamente /v1/assessments: sem query string, sem barra final e sem normalização. O corpo é um
único objeto JSON em UTF-8.
POST /v1/assessments HTTP/1.1Host: api.fingertrackid.comContent-Type: application/jsonX-FTID-Timestamp: <second at which you sign this attempt>X-FTID-Request-Id: <a new lowercase UUIDv7>X-FTID-External-Event-Id: evt:tag-0001X-FTID-Signature: v1=<key_id>:<mac>
{"schema_version":"event-assessment-request.v1.1","external_event_id":"evt:tag-0001","idempotency_key":"idem-tag-0001","occurred_at":"2026-10-11T12:00:00.000Z","subject_ref":null,"account_ref":null,"event_context_token":null,"tag":"login","deadline_ms":null}Baixe os arquivos exatos de contrato de cada perfil. Para o v1.1: o
contrato OpenAPI v1.1, o
schema da requisição,
o schema da resposta e os
exemplos sintéticos. Para o
v1: o contrato OpenAPI v1, o
schema da requisição,
o schema da resposta e os
exemplos sintéticos. Os dois
perfis compartilham o schema do Problem,
e o contrato v1.1 também referencia os exemplos v1 para dois Problems.
Mantenha a estrutura relativa de diretórios entre esses arquivos ao usar as referências do
OpenAPI. Eles mantêm o servidor de exemplo original e a anotação de status de implementação;
ignore esse servidor de exemplo e use https://api.fingertrackid.com.
A produção aceita os dois perfis: um corpo v1.1 corretamente assinado com a sua tag é respondido
com event-assessment.v1.1, e a requisição v1 não muda.
Cabeçalhos
Seção intitulada “Cabeçalhos”| Cabeçalho | Valor | Regra |
|---|---|---|
Content-Type |
application/json |
Exatamente este. application/json; charset=utf-8 é recusado com 415 |
X-FTID-Timestamp |
Epoch UTC em segundos, por exemplo 1788523200 |
Só dígitos, sem zero à esquerda, no máximo 253402300799; aceito dentro de ±300 s do relógio do servidor |
X-FTID-Request-Id |
UUIDv7 canônico em minúsculas | Novo a cada tentativa de envio; é o nonce anti-replay |
X-FTID-External-Event-Id |
O external_event_id do corpo |
Igual, byte a byte, ao do corpo e ao da string assinada |
X-FTID-Signature |
v1=<key_id>:<mac> |
Uma única assinatura; mac tem 64 caracteres hexadecimais minúsculos |
Não envie estes cabeçalhos:
| Cabeçalho enviado | Resposta |
|---|---|
Content-Encoding, com qualquer valor, inclusive identity |
415 unsupported-media-type |
Expect ou Trailer; Host, Content-Length, Content-Type ou Transfer-Encoding duplicado |
400 validation-failed |
X-Client-Id, X-Signature, X-Timestamp, X-Nonce |
401 authentication-failed |
X-FTID-Client-Id, X-FTID-Key-Id, X-FTID-Nonce, X-FTID-Event-Id, X-FTID-Business-Event-Id, X-FTID-Delivery-Id |
401 authentication-failed |
X-FTID-Assessment-Id nesta rota |
401 authentication-failed |
Se o seu cliente HTTP acrescentar Expect: 100-continue ou ; charset=... por conta própria,
desligue isso. Não comprima a requisição.
Não existe X-Client-Id, nem client_id no corpo, nem escolha de empresa, aplicação ou ambiente
pelo lado do cliente: tudo isso é derivado do key_id depois que a assinatura é validada.
Nesta rota, o corpo tem dois perfis, escolhidos por schema_version em cada chamada:
o v1.1, que nomeia o momento com a sua própria tag, e o v1, com três jornadas fixas
(jornadas e etiquetas). O v1.1 é o perfil recomendado para integrações
novas e é aceito em produção; o v1 continua suportado, sem mudança.
Todo campo é obrigatório, inclusive os que aceitam null: omitir um campo não é o mesmo que
enviar null. Um campo desconhecido é erro, e um campo do outro perfil também.
| Campo | Formato | Regra |
|---|---|---|
schema_version |
"event-assessment-request.v1.1" ou "event-assessment-request.v1" |
Seleciona o perfil |
external_event_id |
^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$ |
ID do seu evento de negócio; nunca reutilizado |
idempotency_key |
8 a 255 caracteres ASCII visíveis (0x21–0x7E) |
Identifica a operação lógica; nunca reutilizada |
occurred_at |
RFC 3339 com segundos, offset explícito e até 3 casas decimais | Quando o evento aconteceu no seu backend; uma operação nova precisa estar dentro de ±300 s do relógio do servidor |
subject_ref |
Referência opaca (mesma gramática de external_event_id, no máximo 128 caracteres) ou null |
Pseudônimo estável da pessoa no seu sistema (referências) |
account_ref |
Referência opaca (mesma gramática de external_event_id, no máximo 128 caracteres) ou null. Exige um subject_ref não nulo; caso contrário, 400 validation-failed |
Pseudônimo estável da conta. Fica vinculado ao subject_ref com que foi enviado pela primeira vez (referências) |
event_context_token |
1 a 4096 caracteres ASCII visíveis, ou null |
Token do Web SDK para esta ação; null = nenhum contexto do navegador fornecido |
tag |
Só v1.1. ^[a-z0-9][a-z0-9_]{0,63}$, com no máximo 10 dígitos no total |
O nome que você dá ao momento; nunca dado pessoal (a etiqueta) |
journey |
Só v1. LOGIN, WITHDRAWAL ou TRADE |
O perfil v1 |
action |
Só v1. Fixo por jornada | O perfil v1 |
journey_context |
Só v1. Objeto fechado por jornada | O perfil v1 |
deadline_ms |
Inteiro dentro da faixa, ou null |
v1.1: 250–5000 para toda etiqueta; v1: a faixa da jornada. null usa o padrão |
Referências de pessoa e de conta
Seção intitulada “Referências de pessoa e de conta”subject_ref nomeia a pessoa, e account_ref nomeia uma conta dessa pessoa no seu sistema. Uma
pessoa pode ter várias contas; uma conta pertence a exatamente uma pessoa.
- Gere-as como pseudônimos com chave, no seu backend. Por exemplo, HMAC-SHA-256 sobre o seu
ID interno com uma chave secreta que só o seu backend tem, escrito em hexadecimal depois de um
prefixo curto seu (
usr_…,acc_…). Um hash simples de um documento fiscal ou de um e-mail não é pseudônimo: qualquer um consegue recalculá-lo adivinhando a entrada. Hexadecimal sempre cabe na gramática. base64url precisa de prefixo, porque pode começar com-ou_; base64 padrão (+,/,=) é recusado. A referência inteira, prefixo incluído, tem no máximo 128 caracteres. - Mantenha o par estável. Envie o mesmo par para a mesma pessoa e a mesma conta em toda
chamada. Um
account_reffica vinculado aosubject_refcom que foi enviado pela primeira vez: o mesmoaccount_refcom outrosubject_refretorna409 binding-conflict, e nenhum evento ou avaliação é armazenado. Trocar a chave HMAC ou o prefixo cria pessoas novas e contas novas, e por isso o histórico delas recomeça. Nunca troque só a chave dosubject_refmantendo oaccount_ref: toda conta existente passaria a retornar409. Uma chave nova para osubject_reftambém faz de cada pessoa uma segunda pessoa, nova, nos navegadores que ela já usou: por 30 dias oDEVICE_MULTI_USERconta os dois pseudônimos e, assim, conta pessoas a mais nesses dispositivos (ele ficaDETECTEDacima de três pessoas) até que os pseudônimos antigos saiam da janela dele. - Envie-as sempre que o usuário estiver identificado. Envie
subject_refem todo momento avaliado em que o seu backend conhece o usuário; num login, depois que o seu backend autenticou o usuário. Envieaccount_refjunto quando o momento disser respeito a uma das contas dessa pessoa; ele sempre vai acompanhado do seusubject_ref. Cada modelo de jornada diz quais referências o momento dele leva: uma recuperação de senha, por exemplo, enviaaccount_ref: null. - O que elas mudam. No console, o
account_refalimenta os itens de conta de Contexto do acesso, as contas em Vínculos e a busca por conta. Os 13 indicadores e oevidence_coveragesão os mesmos com ou sem ele;trust_scoree a recomendação só mudam quando a sua empresa ativou uma regra de contexto sobre um item de conta (regras de risco da empresa). ODEVICE_MULTI_USERconta pessoas pelosubject_ref, por isso osubject_refmuda as respostas de coletas posteriores (por que um indicador não foi avaliado). - O histórico começa no primeiro evento que traz a referência. Eventos anteriores nunca são ligados a ela depois. O primeiro acesso de cada conta com coleta do navegador concluída mostra Primeira vez: ainda sem histórico nos itens que comparam com o passado da conta; sem coleta do navegador concluída, eles mostram Sem coleta concluída do navegador. Um login posterior avalia Dispositivo novo para esta conta só quando um acesso anterior da mesma conta nos últimos 90 dias também teve uma coleta do navegador cuja instalação do navegador foi vinculada; uma conta parada há mais de 90 dias mostra Primeira vez de novo.
- Uma conta por pessoa. Se o seu produto tem uma única conta por pessoa, envie as duas mesmo assim, com um pseudônimo distinto e estável para a conta.
Regras de bytes do corpo
Seção intitulada “Regras de bytes do corpo”- No máximo 16384 bytes, contados antes de qualquer parsing ou verificação de assinatura.
Acima disso:
413 payload-too-large. - UTF-8 sem BOM, um único documento JSON, nada depois dele e nenhuma chave duplicada em nenhum nível (inclusive chaves que só ficam iguais depois de desfazer os escapes).
- Só objetos, strings,
nulle inteiros; arrays e booleanos são rejeitados. - Números precisam ter um valor inteiro exato e seguro (até 9007199254740991). Envie inteiros simples.
- A assinatura e o servidor leem os mesmos bytes. Serialize uma vez, com uma única chamada a
JSON.stringify, guarde os bytes e assine e envie exatamente esses bytes.
Exemplos de requisição
Seção intitulada “Exemplos de requisição”Um exemplo sintético v1.1. Cada modelo de jornada tem o seu.
{ "schema_version": "event-assessment-request.v1.1", "external_event_id": "evt_login_0001", "idempotency_key": "idem_evt_login_0001", "occurred_at": "2026-11-03T14:05:22.481Z", "subject_ref": "usr_5c0e", "account_ref": "acc_77d2", "event_context_token": "ect_login_0001", "tag": "login", "deadline_ms": null}Exemplos sintéticos v1, um por jornada.
{ "schema_version": "event-assessment-request.v1", "external_event_id": "login_20260904_000001", "idempotency_key": "idem_login_20260904_000001", "occurred_at": "2026-09-04T12:00:00Z", "subject_ref": "subject_123", "account_ref": "account_456", "event_context_token": "ect_login_20260904_000001", "journey": "LOGIN", "action": "LOGIN_ATTEMPT", "journey_context": {}, "deadline_ms": null}{ "schema_version": "event-assessment-request.v1", "external_event_id": "withdrawal_20260904_000001", "idempotency_key": "idem_withdrawal_20260904_000001", "occurred_at": "2026-09-04T12:00:00Z", "subject_ref": "subject_123", "account_ref": "account_456", "event_context_token": "ect_withdrawal_20260904_000001", "journey": "WITHDRAWAL", "action": "WITHDRAWAL_REQUEST", "journey_context": { "amount_minor": 150000, "currency": "BRL", "beneficiary_ref": "beneficiary_789" }, "deadline_ms": 1000}{ "schema_version": "event-assessment-request.v1", "external_event_id": "trade_20260904_000001", "idempotency_key": "idem_trade_20260904_000001", "occurred_at": "2026-09-04T12:00:00Z", "subject_ref": "subject_123", "account_ref": "account_456", "event_context_token": "ect_trade_20260904_000001", "journey": "TRADE", "action": "TRADE_REQUEST", "journey_context": {}, "deadline_ms": 750}Os exemplos estão formatados para leitura. Na chamada real, envie o JSON compacto que
JSON.stringify(object) produz.
Próximo passo: autenticação HMAC.