Contribute evaluation level outcome and product-specific outcome data to RiskOS™ after an evaluation has completed.
Submit an outcome contribution to RiskOS™ after an evaluation completes by calling POST /api/outcome_contribution.
Note:
This endpoint accepts a single contribution per API call. Bulk contributions are planned for a future release.
A contribution has three conceptual sections:
- Envelope (required) — root fields that link the contribution to a prior evaluation:
event_timestamp,eval_id, and optional metadata. - Core outcome (
evaluation_decisions; required except for Watchlist-only contributions) — evaluation-level outcome, such as the final decision and fraud disposition. - Product sections (
account_intelligence,watchlist,docv,kyc; optional) — outcome scoped to a single enrichment. Include a product section only when you have outcome data for that product.
Always include the envelope. Include core outcome unless you submit only Global Watchlist (Watchlist) outcome data. If you include any other product section, core outcome is required, even when you also include watchlist.
Timestamps without a time zone are treated as Coordinated Universal Time (UTC). Include Z or an explicit time zone offset to avoid ambiguity.
Valid and invalid combinations
| Combination | Valid? | Meaning |
|---|---|---|
Envelope + core outcome (evaluation_decisions) | Yes | Evaluation-level outcome only |
| Envelope + core outcome + product sections | Yes | Evaluation-level and product-specific outcome |
| Envelope + Watchlist only | Yes | The only product that you can submit without core outcome |
| Envelope + any other product without core outcome | No | Core outcome is required, including when watchlist is also present |
Missing envelope (event_timestamp or eval_id) | No | Both fields are required for every contribution |
| Envelope only | No | Include core outcome or a Watchlist-only outcome |
Field rules
evaluation_decisions.fraud_type: Required whenfraud_outcomeis"fraud"or"suspected fraud". Optional whenfraud_outcomeis"not fraud". When provided with anyfraud_outcome, it must be"first party fraud","synthetic fraud","third party fraud","account takeover", or"other fraud". Any other value returnsCONTRACT_VALIDATION_FAILED.evaluation_decisions.loss_amount_number: Loss amount. Send as a string. A JSON number (e.g. 250.00) is also accepted and treated as the same value. Accepts US-style ("1,234.56") and European-style ("1.234,56") formats, including negative values such as"-596.23"and"-1.234,56". A leading"+", spaces, and currency symbols are not accepted. The maximum is 13 characters, including the minus sign.account_intelligence.payment_amount: Payment amount. Send as a string. A JSON number (e.g. 250.00) is also accepted and treated as the same value. Accepts US-style ("1,234.56") and European-style ("1.234,56") formats, including negative values such as"-596.23"and"-1.234,56". A leading"+", spaces, and currency symbols are not accepted. The maximum is 13 characters, including the minus sign.
Watchlist feedback changes live screening
Important:
A Watchlist decision of
"no match"suppresses future alerts for that entity. A decision of"match"re-enables future alerts. This feedback changes live screening behavior; it does not only record an analyst decision.
Limits
| Field or payload | Limit | Guidance |
|---|---|---|
| API call body | 160 KiB | Keep the complete body within this limit. |
| Text fields | 255 characters per field | Keep each text value within this limit. |
tags | 255 characters total | Apply the limit across all tag values, not separately to each tag. |
| Amount fields | 13 characters, including the minus sign | Send loss_amount_number and payment_amount as strings. US-style ("1,234.56") and European-style ("1.234,56") formats and negative values ("-596.23", "-1.234,56") are accepted. A leading "+", spaces, and currency symbols are not accepted. A JSON number (e.g. 250.00) is also accepted and treated as the same value. |
additional_fields | 32 KB | Keep the object within this size limit. |
This release does not support client-selected contract versions. Use /api/outcome_contribution without a versioned path, and do not send a version field. Unrecognized fields return INVALID_JSON.
Responses
A successful call returns 202 Accepted once the contribution is validated and accepted for processing. The response includes contribution_id, a UUID that identifies the accepted contribution. You can quote it to Socure support when asking about a specific submission:
{
"status": "accepted",
"contribution_id": "3f6c2a9e-8d41-4b7a-9c2e-1a5f0d7b6e21"
}Validation failures are returned synchronously with field-level detail in message — often a multi-line list of every failing field. Enums are exact strings, including spaces (for example "no match" and "not fraud"):
{
"status": "error",
"code": "CONTRACT_VALIDATION_FAILED",
"message": "validation error:\n - evaluation_decisions.final_decision: must be one of [approve, reject, cancelled]"
}The RiskOS™ edge enforces authentication and rate limiting: a missing or invalid API key returns 401 or 403, and a rate-limited API call returns 429.
Validation error codes
| Code | Meaning | Action |
|---|---|---|
INVALID_JSON | The body contains an unrecognized field, such as version. | Delete unrecognized fields before you resubmit. |
CONTRACT_VALIDATION_FAILED | The contribution fails validation, such as a missing required field, an invalid value, or a product section without the required core outcome. | Correct the fields identified in message before you resubmit. |
End-to-end examples
Accept (envelope + core outcome)
curl -sS -X POST 'https://<riskos-host>/api/outcome_contribution' \
-H 'Authorization: Bearer <RISKOS_API_KEY>' \
-H 'Content-Type: application/json' \
-d '{
"event_timestamp": "2024-01-15T10:30:00Z",
"eval_id": "<your eval id>",
"customer_user_id": "customer_123",
"notes": "Post-review fraud confirmation",
"tags": ["manual-review"],
"evaluation_decisions": {
"initial_decision": "accept",
"final_decision": "approve",
"fraud_outcome": "not fraud",
"label_source": "manual",
"channel": "mobile"
}
}'Response — 202 Accepted:
{
"status": "accepted",
"contribution_id": "3f6c2a9e-8d41-4b7a-9c2e-1a5f0d7b6e21"
}Accept (envelope + core outcome + account_details)
curl -sS -X POST 'https://<riskos-host>/api/outcome_contribution' \
-H 'Authorization: Bearer <RISKOS_API_KEY>' \
-H 'Content-Type: application/json' \
-d '{
"event_timestamp": "2024-01-15T10:30:00Z",
"eval_id": "<your eval id>",
"evaluation_decisions": {
"initial_decision": "reject",
"final_decision": "reject",
"fraud_outcome": "fraud",
"fraud_type": "third party fraud",
"fraud_subtype": "identity theft",
"label_source": "manual",
"loss_amount_number": "596.23",
"loss_amount_currency": "USD",
"account_details": {
"account_type": "checking",
"account_number": "546876945",
"routing_number": "546834213",
"closed_reason": "fraud"
}
}
}'Response — 202 Accepted:
{
"status": "accepted",
"contribution_id": "3f6c2a9e-8d41-4b7a-9c2e-1a5f0d7b6e21"
}Accept (Watchlist only)
This example suppresses future alerts for the specified entity. Use it only when that is your intended screening action.
curl -sS -X POST 'https://<riskos-host>/api/outcome_contribution' \
-H 'Authorization: Bearer <RISKOS_API_KEY>' \
-H 'Content-Type: application/json' \
-d '{
"event_timestamp": "2024-01-15T10:30:00Z",
"eval_id": "<your eval id>",
"watchlist": {
"reference_id": "10c50ad1-8aba-42b4-ab56-8f9ad582777b",
"entity_id": ["ZaP+/U4QdD5dfmJNCjtmwzKDgOyECzc"],
"decision": "no match",
"notes": "Analyst cleared false positive"
}
}'Response — 202 Accepted:
{
"status": "accepted",
"contribution_id": "3f6c2a9e-8d41-4b7a-9c2e-1a5f0d7b6e21"
}Accept (core outcome + Watchlist)
This contribution includes both core outcome and a product section. The Watchlist decision re-enables future alerts for the specified entity.
curl -sS -X POST 'https://<riskos-host>/api/outcome_contribution' \
-H 'Authorization: Bearer <RISKOS_API_KEY>' \
-H 'Content-Type: application/json' \
-d '{
"event_timestamp": "2024-01-15T10:30:00Z",
"eval_id": "<your eval id>",
"evaluation_decisions": {
"initial_decision": "reject",
"final_decision": "reject",
"fraud_outcome": "fraud",
"fraud_type": "third party fraud",
"label_source": "manual"
},
"watchlist": {
"reference_id": "10c50ad1-8aba-42b4-ab56-8f9ad582777b",
"entity_id": ["ZaP+/U4QdD5dfmJNCjtmwzKDgOyECzc"],
"decision": "match"
}
}'Response — 202 Accepted:
{
"status": "accepted",
"contribution_id": "3f6c2a9e-8d41-4b7a-9c2e-1a5f0d7b6e21"
}Validation failure (missing fraud type)
This example intentionally sets fraud_outcome to "fraud" without fraud_type. Include an allowed fraud_type when fraud_outcome is "fraud" or "suspected fraud".
curl -sS -X POST 'https://<riskos-host>/api/outcome_contribution' \
-H 'Authorization: Bearer <RISKOS_API_KEY>' \
-H 'Content-Type: application/json' \
-d '{
"event_timestamp": "2024-01-15T10:30:00Z",
"eval_id": "<your eval id>",
"evaluation_decisions": {
"initial_decision": "reject",
"final_decision": "reject",
"fraud_outcome": "fraud",
"label_source": "manual"
}
}'Expected result: 400 Bad Request with status set to "error" and code set to "CONTRACT_VALIDATION_FAILED". Read message for the field-level validation details.
Validation failure (product without core outcome)
This example intentionally omits core outcome. The API rejects it because kyc cannot be submitted without evaluation_decisions.
curl -sS -X POST 'https://<riskos-host>/api/outcome_contribution' \
-H 'Authorization: Bearer <RISKOS_API_KEY>' \
-H 'Content-Type: application/json' \
-d '{
"event_timestamp": "2024-01-15T10:30:00Z",
"eval_id": "<your eval id>",
"kyc": {
"deceased_flag": false
}
}'Expected result: 400 Bad Request with status set to "error" and code set to "CONTRACT_VALIDATION_FAILED". Read message for the field-level validation details. Include valid core outcome before you resubmit.
Validation failure (unknown field)
This example intentionally sends an unrecognized field (version). Unrecognized fields return INVALID_JSON.
curl -sS -X POST 'https://<riskos-host>/api/outcome_contribution' \
-H 'Authorization: Bearer <RISKOS_API_KEY>' \
-H 'Content-Type: application/json' \
-d '{
"version": "v1",
"event_timestamp": "2024-01-15T10:30:00Z",
"eval_id": "<your eval id>",
"evaluation_decisions": {
"initial_decision": "reject",
"final_decision": "reject",
"fraud_outcome": "fraud",
"fraud_type": "third party fraud",
"label_source": "manual"
}
}'Expected result: an error response with status set to "error" and code set to "INVALID_JSON". Delete version before you resubmit.
Validation failure (bad enum)
curl -sS -X POST 'https://<riskos-host>/api/outcome_contribution' \
-H 'Authorization: Bearer <RISKOS_API_KEY>' \
-H 'Content-Type: application/json' \
-d '{
"event_timestamp": "2024-01-15T10:30:00Z",
"eval_id": "<your eval id>",
"evaluation_decisions": {
"initial_decision": "accept",
"final_decision": "accept",
"fraud_outcome": "not fraud",
"fraud_type": "other fraud",
"label_source": "manual"
}
}'Response — 400 Bad Request (final_decision does not allow "accept"; use approve, reject, or cancelled):
{
"status": "error",
"code": "CONTRACT_VALIDATION_FAILED",
"message": "validation error:\n - evaluation_decisions.final_decision: must be one of [approve, reject, cancelled]"
}Validation failure (missing envelope field)
curl -sS -X POST 'https://<riskos-host>/api/outcome_contribution' \
-H 'Authorization: Bearer <RISKOS_API_KEY>' \
-H 'Content-Type: application/json' \
-d '{
"eval_id": "<your eval id>",
"evaluation_decisions": {
"initial_decision": "accept",
"final_decision": "approve",
"fraud_outcome": "not fraud",
"fraud_type": "other fraud",
"label_source": "manual"
}
}'Response — 400 Bad Request:
{
"status": "error",
"code": "CONTRACT_VALIDATION_FAILED",
"message": "validation error:\n - event_timestamp: is required"
}Validation failure (Watchlist section incomplete)
curl -sS -X POST 'https://<riskos-host>/api/outcome_contribution' \
-H 'Authorization: Bearer <RISKOS_API_KEY>' \
-H 'Content-Type: application/json' \
-d '{
"event_timestamp": "2024-01-15T10:30:00Z",
"eval_id": "<your eval id>",
"watchlist": {
"reference_id": "10c50ad1-8aba-42b4-ab56-8f9ad582777b",
"decision": "maybe"
}
}'Response — 400 Bad Request:
{
"status": "error",
"code": "CONTRACT_VALIDATION_FAILED",
"message": "validation error:\n - watchlist.entity_id: is required\n - watchlist.decision: must be one of [match, no match]"
}Best practices
- Always send
event_timestampandeval_idfrom the evaluation you are labeling. - Submit core outcome alone, core outcome with product sections, or Watchlist alone. Watchlist is the only product you can submit without core outcome. Do not send empty product sections.
- Include
account_detailsonly when you have account data. Do not send an empty object. - Treat
202as "accepted for processing." - Do not resend an accepted contribution. Each contribution is stored separately.
- On
CONTRACT_VALIDATION_FAILED, fix the listed fields before you resubmit. - On
INVALID_JSON, delete unrecognized fields before you resubmit.
401Unauthorized - A missing or invalid API key was provided.
403Forbidden - The API key is not permitted to perform this action.
413Payload Too Large - The request body exceeds 160 KiB (PAYLOAD_TOO_LARGE).
429Too Many Requests - The rate limit for this API has been exceeded.
500Internal Server Error - An unexpected condition occurred on the server (INTERNAL_ERROR).

