Feedback — ação do cliente e desfecho
Depois de uma avaliação, seu backend pode informar o que aconteceu quando a credencial ativa dele tem as capacidades exigidas. O feedback usa o caminho S2S autenticado de forma independente e grava, juntos, um fato, um recibo imutável e a auditoria. Ele nunca executa uma ação no seu produto.
| Rota | Capacidade | Fato |
|---|---|---|
POST /v1/assessments/{assessment_id}/customer-actions |
action:write |
A ação que seu produto de fato executou |
POST /v1/assessments/{assessment_id}/outcomes |
outcome:write |
Verdade/evidência observada depois, ou uma correção do desfecho atual |
Elas são separadas de assessment:write: solicite-as com a permissão
Avaliações, ações e resultados ao criar a credencial de servidor no console e
confirme com o FingerTrackID que estão ativas. Um contrato publicado ou uma credencial de
avaliação, sozinhos, não habilitam o feedback.
Contratos públicos exatos
Seção intitulada “Contratos públicos exatos”- OpenAPI de feedback
- Requisição de ação do cliente
- Recibo de ação do cliente
- Requisição de desfecho do cliente
- Recibo de desfecho do cliente
- Vetor HMAC normativo de ação do cliente
- Vetores de canonicalização sem perda do feedback
Mantenha o assessment.v1.yaml ao lado do OpenAPI de feedback, por causa das referências compartilhadas.
As anotações históricas de implementação e o servidor de exemplo não são configurações de runtime emitidas.
Valide os schemas fechados e as regras normativas de entrada bruta e entre campos; um JSON Schema
sozinho não rejeita chaves duplicadas após a decodificação, NUL nem todas as violações de número sem perda.
Assinatura da chamada de feedback
Seção intitulada “Assinatura da chamada de feedback”Use o mesmo assinador de referência. O caminho canônico inclui o
assessment_id original e exato da avaliação síncrona, sem query string nem barra final. A sexta
linha assinada é assessment_id:<id>, e X-FTID-Assessment-Id precisa corresponder ao caminho.
Não envie, no lugar dele, o cabeçalho de evento externo da rota de avaliação.
secret vem somente do gerenciador de segredos do seu backend. Os corpos de requisição têm no
máximo 16384 bytes; as respostas têm no máximo 65536 bytes. Mantenha exatamente os bytes originais
e a chave de idempotência entre novas tentativas e crie um novo ID de requisição UUIDv7, um novo
timestamp e uma nova assinatura a cada tentativa.
// Validate once, then preserve these exact bytes for the logical feedback operation.const body = Buffer.from(JSON.stringify(customerActionRequest), 'utf8')const path = `/v1/assessments/${assessmentId}/customer-actions`// Each transport attempt receives a new request ID, timestamp and signature.const attempt = prepareAttempt({ secret, keyId, path, body })const result = await postAttempt(apiOrigin, attempt, 2000)// Validate the exact receipt or feedback Problem before accepting the result.Ação do cliente (customer-action.v1)
Seção intitulada “Ação do cliente (customer-action.v1)”Os sete campos são obrigatórios: schema_version, external_action_id, idempotency_key,
action, basis, occurred_at e reason_code.
- Ações:
ALLOWED,CHALLENGED,HELD,REVIEWED,BLOCKED,CANCELLED. - Base:
ASSESSMENT,CLIENT_POLICY,FALLBACK,MANUAL_REVIEW. - O motivo precisa corresponder à sua base no schema.
ASSESSMENTexigeFOLLOWED_FTID_RECOMMENDATIONe uma ação alinhada à recomendação armazenada. occurred_até o horário real da ação no seu backend, não um timestamp escolhido pelo navegador. Ele não pode ser anterior ao evento original nem ultrapassar a janela futura permitida pelo servidor.
O FingerTrackID deriva recommendation_alignment; nunca o inclua na requisição.
CANCELLED é NOT_COMPARABLE. Coincidir com uma recomendação não prova causalidade nem fraude.
O recibo confirma a ação registrada, não um bloqueio recém-executado.
{ "schema_version": "customer-action.v1", "external_action_id": "action:synthetic-001", "idempotency_key": "synthetic-action-001", "action": "ALLOWED", "basis": "ASSESSMENT", "occurred_at": "2026-09-05T12:00:00.123456789+03:00", "reason_code": "FOLLOWED_FTID_RECOMMENDATION"}await ftid?.recordCustomerAction(assessmentId, { action: 'ALLOWED', basis: 'CLIENT_POLICY', reasonCode: 'CLIENT_POLICY_RULE',})O corpo da requisição é um vetor de canonicalização publicado.
Desfecho (customer-outcome.v1)
Seção intitulada “Desfecho (customer-outcome.v1)”Todos os campos, inclusive os anuláveis, são obrigatórios:
schema_version, external_outcome_id, idempotency_key, truth_status, label_maturity,
fraud_type, evidence_source, evidence_reference, evidence_confidence, observed_at,
reason_code e corrects_external_outcome_id.
A verdade é PENDING, INSUFFICIENT_EVIDENCE, LEGITIMATE ou FRAUD_CONFIRMED.
A maturidade é PROVISIONAL ou MATURE; PENDING deve permanecer provisório.
Uma verdade conclusiva exige a tripla de evidência completa, e FRAUD_CONFIRMED exige, além disso,
a entrada ativa do catálogo de tipos de fraude. Nunca coloque PII nem material secreto numa referência de evidência.
A observação inicial tem INITIAL_OBSERVATION e predecessor nulo. Uma correção precisa referenciar
o external_outcome_id da folha atual, usar um novo ID de desfecho e o motivo que corresponde à
mudança real. Um predecessor desatualizado, um sucessor concorrente ou uma segunda raiz é um conflito.
As correções acrescentam fatos; elas não sobrescrevem o registro original nem a recomendação.
A maturidade e a evidência enviadas não qualificam, por si só, o rótulo para a calibração de detectores.
Desfechos de fraude confirmada também alimentam o item do console Contas vizinhas com fraude confirmada pela
empresa em Contexto do acesso; sem desfechos, ele
mostra Sem dado: a empresa não envia resultados.
{ "schema_version": "customer-outcome.v1", "external_outcome_id": "outcome:synthetic-001", "idempotency_key": "synthetic-outcome-001", "truth_status": "PENDING", "label_maturity": "PROVISIONAL", "fraud_type": null, "evidence_source": null, "evidence_reference": null, "evidence_confidence": null, "observed_at": "2026-09-05T12:00Z", "reason_code": "INITIAL_OBSERVATION", "corrects_external_outcome_id": null}await ftid?.recordOutcome(assessmentId, { truthStatus: 'PENDING', labelMaturity: 'PROVISIONAL', reasonCode: 'INITIAL_OBSERVATION',})Recibos, nova tentativa e resultados indisponíveis
Seção intitulada “Recibos, nova tentativa e resultados indisponíveis”201 confirma um novo fato gravado; 200 confirma o mesmo fato lógico sem um segundo efeito.
Uma reutilização divergente retorna 409. Um timeout ou uma confirmação perdida é indeterminado:
reconcilie com o mesmo POST e o mesmo corpo numa nova tentativa assinada, sujeita ao campo
retryable do Problem efetivamente devolvido e a um backoff limitado. 429/503 usam Retry-After.
O catálogo de Problems do feedback pertence ao OpenAPI de feedback; não suponha que todo Problem
de avaliação seja uma resposta de feedback. Alvo inexistente e alvo fora do escopo autenticado
compartilham o 404. Não existe consulta não autenticada de recibo nem GET de avaliação.