Customer Metadata Pass-Through
Attach opaque, caller-owned context to RiskOS™ evaluation requests with customer_metadata and receive it unchanged in API responses and webhooks.
What customer_metadata is
customer_metadata iscustomer_metadata is an optional, top-level field on the evaluation request. It holds an opaque JSON object that you define and own. RiskOS™ stores the object, forwards it to the workflow engine, and echoes it back unchanged on every outbound surface:
- The synchronous response from
POST /api/evaluation - Asynchronous webhook callbacks (for example,
evaluation_completed,case_status_updated)
RiskOS™ doesn't transform or interpret the contents as decisioning data. Use it to carry your own context — such as the internal service, product, or business flow that started a request — so you can identify, route, and handle responses without adding custom fields per customer.
Note:
For the complete evaluation request schema, including all standard fields available alongside
customer_metadata, see the Evaluation API reference.
When to use customer_metadata instead of custom
customer_metadata instead of customBoth fields accept caller-defined JSON, but they serve different purposes:
Use customer_metadata when… | Use custom when… |
|---|---|
| You want context returned to you untouched, for routing or correlation. | You need the data as a decisioning input for enrichments or integrations. |
| The data is for your systems, not for Socure to evaluate. | The data feeds workflow rules, case tiles, or reporting exports. |
How to include customer_metadata in a request
customer_metadata in a requestAdd customer_metadata as a top-level sibling of id, timestamp, workflow, and data. The value must be a JSON object of your own keys and values.
curl -X POST https://riskos.sandbox.socure.com/api/evaluation \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"id": "onb-12345",
"timestamp": "2026-06-26T08:15:30.456Z",
"workflow": "consumer_onboarding",
"customer_metadata": {
"service": "checkout-api",
"business_unit": "consumer-lending",
"internal_ref": "order-998877"
},
"data": {
"individual": {
"given_name": "Jane",
"family_name": "Smith",
"email": "[email protected]"
}
}
}'You can reference the values in workflow conditions using the $request.customer_metadata.* path:
$request.customer_metadata.business_unit == "consumer-lending"
How to expect it back
In the synchronous response
When you send customer_metadata, the response echoes the same object at the top level, unchanged:
{
"id": "onb-12345",
"eval_id": "6dc8f39c-ecc3-4fe0-9283-fc8e5f99e816",
"workflow": "consumer_onboarding",
"eval_status": "evaluation_completed",
"decision": "ACCEPT",
"status": "CLOSED",
"customer_metadata": {
"service": "checkout-api",
"business_unit": "consumer-lending",
"internal_ref": "order-998877"
},
"environment_name": "Sandbox"
}In a webhook callback
For asynchronous workflows, customer_metadata appears at the top level of the webhook envelope — a sibling of event_id, event_at, event_type, and data. It is not nested inside data.
{
"event_id": "336ccd2a-b3a8-49a8-b2cc-89a4ae90feeb",
"event_at": "2026-06-26T16:16:23.104744158Z",
"event_type": "evaluation_completed",
"customer_metadata": {
"service": "checkout-api",
"business_unit": "consumer-lending",
"internal_ref": "order-998877"
},
"data": {
"id": "onb-12345",
"eval_id": "8770e076-f568-48a9-8201-dca13087e592",
"workflow": "consumer_onboarding",
"decision": "ACCEPT",
"status": "CLOSED"
}
}To learn how to subscribe to and verify webhook events, see Webhook events.
Field constraints
| Constraint | Rule |
|---|---|
| Type | A JSON object ({ ... }). Arrays, strings, numbers, and booleans at the top level are rejected. |
| Keys and values | Any valid JSON: string, number, boolean, array, or nested object. Designed for string-valued tags and IDs. |
| Nesting | Nested objects and arrays are allowed. All nested content counts toward the size limit. |
| Size | Up to 200 characters total, measured across the entire serialized JSON (keys, values, braces, and quotes). |
| Numbers | JSON numbers are preserved as numbers. For exact-fidelity identifiers, send them as strings. |
Do not include sensitive data:
customer_metadatais stored and echoed verbatim. Do not place personally identifiable information (PII), secrets, or regulated data in it. Send identity data in the standard request fields underdatainstead.
Validation errors
| Condition | HTTP status | Error code |
|---|---|---|
| Value is not valid JSON | 400 | INVALID_REQUEST |
| Value is valid JSON but not an object | 400 | INVALID_REQUEST |
| Serialized object exceeds the character limit | 413 | CUSTOMER_METADATA_TOO_LARGE |
A size violation returns a message describing the limit and the size received:
{
"code": "CUSTOMER_METADATA_TOO_LARGE",
"error": "customer_metadata exceeds maximum allowed size of 200 characters (received 412)"
}Backward compatibility
customer_metadata is optional. Existing integrations are unaffected:
- Omit the field and requests behave exactly as before.
- Send
nulland RiskOS™ treats it as absent — no value is stored or echoed. - When the field is absent, it does not appear in the response or webhook payload.
Common use cases
- Route webhook callbacks. Tag each request with the originating service (for example,
"service": "checkout-api") and route the callback to the right internal consumer when it arrives. - Correlate asynchronous results. Carry your own
internal_refor order ID so you can match a paused-then-completed evaluation back to its originating transaction without server-side state management. - Segment by business context. Attach a
business_unit,product, orenvironmenttag so multiple teams can share one RiskOS™ integration and filter responses by their own context. - Standardize across products. Use one consistent context object across every internal product that calls RiskOS™, instead of requesting a custom field per customer or per team.
Related
Updated 16 days ago

