Pular para o conteúdo
No ar em produção, em modo shadow: o FingerTrackID recomenda, o seu sistema decide.Status →

POST /v1/assessments — a requisição

No ar · modo shadowAPI v1.1 and v1

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.

Uma tentativa
POST /v1/assessments HTTP/1.1
Host: api.fingertrackid.com
Content-Type: application/json
X-FTID-Timestamp: <second at which you sign this attempt>
X-FTID-Request-Id: <a new lowercase UUIDv7>
X-FTID-External-Event-Id: evt:tag-0001
X-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ç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

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_ref fica vinculado ao subject_ref com que foi enviado pela primeira vez: o mesmo account_ref com outro subject_ref retorna 409 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 do subject_ref mantendo o account_ref: toda conta existente passaria a retornar 409. Uma chave nova para o subject_ref também faz de cada pessoa uma segunda pessoa, nova, nos navegadores que ela já usou: por 30 dias o DEVICE_MULTI_USER conta os dois pseudônimos e, assim, conta pessoas a mais nesses dispositivos (ele fica DETECTED acima 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_ref em todo momento avaliado em que o seu backend conhece o usuário; num login, depois que o seu backend autenticou o usuário. Envie account_ref junto quando o momento disser respeito a uma das contas dessa pessoa; ele sempre vai acompanhado do seu subject_ref. Cada modelo de jornada diz quais referências o momento dele leva: uma recuperação de senha, por exemplo, envia account_ref: null.
  • O que elas mudam. No console, o account_ref alimenta os itens de conta de Contexto do acesso, as contas em Vínculos e a busca por conta. Os 13 indicadores e o evidence_coverage são os mesmos com ou sem ele; trust_score e a recomendação só mudam quando a sua empresa ativou uma regra de contexto sobre um item de conta (regras de risco da empresa). O DEVICE_MULTI_USER conta pessoas pelo subject_ref, por isso o subject_ref muda 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.
  • 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, null e 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.

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.

LOGIN
{
"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
}
WITHDRAWAL
{
"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
}
TRADE
{
"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.