Report outcomes
An assessment is a prediction. Weeks later your platform knows the truth: the account ran up a chargeback, your team closed an abuse case, or a flagged signup turned out to be a real customer. POST /v1/assessments/{assessment_id}/outcomes records that truth against the assessment.
Why send outcomes
Section titled “Why send outcomes”Outcomes are the only way NoResponse learns what happened on your platform. A confirmed abuse report links the identifiers in that assessment to abuse, so a later signup that shares them scores higher. A withdrawal clears an earlier report. Over time your outcomes make the scores your platform receives more accurate, and they give you a record of which assessments were right.
The six outcome values
Section titled “The six outcome values”| Outcome | Meaning | Effect |
|---|---|---|
confirmed_abuse |
Your team confirmed the account was abusive. | Reports abuse. |
account_takeover |
The account was taken over by someone other than its owner. | Reports abuse. |
chargeback |
A payment on the account was charged back. | Reports abuse. |
false_positive |
The assessment pointed at abuse and your team found a real customer. | Withdraws your platform’s earlier abuse report for this assessment. |
legitimate |
The account proved to be a real customer. | Withdraws your platform’s earlier abuse report for this assessment. |
unknown |
You closed the case without a finding. | Recorded only. |
Outcomes are append-only, and the latest one recorded for an assessment wins. Send legitimate after confirmed_abuse and the abuse report is withdrawn.
When to send them
Section titled “When to send them”Send an outcome at the moment your platform learns something, from the system that learns it.
- When your payment processor reports a chargeback, send
chargeback. - When your team closes a review as abuse, send
confirmed_abusewith the case id asexternal_ref. - When your team clears a review, or an account that was stepped up or reviewed has been a paying customer for a while, send
legitimate. - When your security team confirms a takeover, send
account_takeover.
You need the assessment_id you stored with the decision. An outcome for an assessment that has expired, or that belongs to another platform, answers 404.
The request
Section titled “The request”const outcome = await nr.assessments.recordOutcome( "asm_01M5FNFQWDRBZZMWBPN0WEC40C", { outcome: "confirmed_abuse", observedAt: "2026-11-04T10:15:00Z", externalRef: "case-4821", notes: "Credits spent on a relay within an hour of signup; closed by trust and safety.", }, { idempotencyKey: "outcome-case-4821-confirmed_abuse" },);console.log(outcome.id, outcome.receivedAt);outcome = client.assessments.record_outcome( "asm_01M5FNFQWDRBZZMWBPN0WEC40C", outcome="confirmed_abuse", observed_at="2026-11-04T10:15:00Z", external_ref="case-4821", notes="Credits spent on a relay within an hour of signup; closed by trust and safety.", idempotency_key="outcome-case-4821-confirmed_abuse",)print(outcome.id, outcome.received_at)res, err := client.Assessments.RecordOutcome(ctx, "asm_01M5FNFQWDRBZZMWBPN0WEC40C", "outcome-case-4821-confirmed_abuse", components.AssessmentOutcomeRequest{ Outcome: components.OutcomeConfirmedAbuse, ObservedAt: noresponse.Pointer("2026-11-04T10:15:00Z"), ExternalRef: noresponse.Pointer("case-4821"), Notes: noresponse.Pointer("Credits spent on a relay within an hour of signup; closed by trust and safety."),})if err != nil { return err}fmt.Println(res.Result.ID, res.Result.ReceivedAt)curl https://api.noresponse.org/v1/assessments/asm_01M5FNFQWDRBZZMWBPN0WEC40C/outcomes \ -H "Authorization: Bearer $NORESPONSE_API_KEY" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: outcome-case-4821-confirmed_abuse" \ -d '{ "outcome": "confirmed_abuse", "observed_at": "2026-11-04T10:15:00Z", "external_ref": "case-4821", "notes": "Credits spent on a relay within an hour of signup; closed by trust and safety." }'| Field | Rules |
|---|---|
outcome |
Required. One of the six values above. |
observed_at |
When your platform observed the outcome, as RFC 3339. Defaults to when NoResponse received it. |
external_ref |
Your own reference, such as a case or ticket id, up to 128 characters of letters, digits, ., _, : and -. |
notes |
Free text for your own records, up to 500 characters. Stored with the outcome and not scored. |
The Idempotency-Key is required, and it works as it does on POST /v1/assessments: the same key and body replays the record with Idempotent-Replayed: true, and the same key with a different body answers 409 idempotency_key_reused. The key stays bound to its first body for as long as the outcome is kept. Derive it from the case and the outcome, as above, rather than from the time. A later outcome for the same case, such as a withdrawal, then uses a new key and does not answer 409.
The answer
Section titled “The answer”The answer is 202 with the recorded outcome.
{ "id": "out_01JA2ZC0Q1R2S3T4V5W6X7Y8Z9", "assessment_id": "asm_01M5FNFQWDRBZZMWBPN0WEC40C", "outcome": "confirmed_abuse", "received_at": "2026-11-04T10:15:02.000Z"}There is nothing to poll afterwards. The outcome follows its assessment’s retention: when the assessment expires, the outcome goes with it.