Evaluation payload reference
Field-by-field reference for the object passed to txnShield.evaluate and the result your app must enforce.
Evaluate request shape
The evaluate payload describes one protected transaction. Keep values stable, compact, and security-relevant. Do not send full protected records, raw secrets, or large request bodies when ids, counts, and field names are enough.
Nested fields are listed in the order they are normally written in code: operationKey, actor, resource, requestData, session, metadata, challengeResult, and rawSignals.
| Field | Type | Required | Description | Example |
|---|---|---|---|---|
| operationKey | string | Yes | Stable key for the concrete protected operation. It must match a Protected Operation configured in the TxnShield environment, such as customer.create, invoice.export, bank_account.update, or payment_transaction.create. | "payment_transaction.create" |
| actor | object | Yes | The user, service, or principal attempting the protected action. Send stable identifiers and role context, not raw authentication tokens. | { id, authenticated, roles } |
| actor.id | string | Yes | Stable actor identifier from your application or identity provider. Use the same value you would use in audit logs. | "user_123" |
| actor.authenticated | boolean | No | Whether your application considers the actor signed in for this transaction. | true |
| actor.role | string | No | Single role for applications that do not use role arrays. TxnShield checks both actor.role and actor.roles when enforcing requireRoles. | "support" |
| actor.roles | string[] | No | List of roles or grants the actor has for this request. Policies can require at least one matching role. | ["support", "billing_admin"] |
| actor.trusted | boolean | No | Optional application-side trust flag for the actor. Use it only if your app has a meaningful trusted-user concept. | false |
| actor.sessionAgeMinutes | number | No | Age of the actor session in minutes. Useful when your app wants policies to distinguish fresh and old sessions. | 42 |
| resource | object | Yes | The object being read, changed, exported, approved, or deleted. | { type: "customer", id: "cus_456" } |
| resource.type | string | Yes | Stable resource category, such as customer, account, invoice, payment_method, admin_user, or report. | "customer" |
| resource.id | string | Yes | Stable resource identifier. Avoid sending full records when an id is enough. | "cus_456" |
| resource.ownerId | string | No | Application owner identifier when ownership matters for policy or review. | "user_789" |
| resource.classification | string | No | Data classification or sensitivity label from your app, such as public, internal, PII, restricted, or critical. | "PII" |
| requestData | object | No | Security-relevant shape of the request. Include counts, field lists, and operation metadata, not raw secrets or unnecessary PII. | { requestedCount: 1 } |
| requestData.requestedCount | number | No | Number of records, resources, or items affected by the action. The risk engine uses this for volume-sensitive actions. | 25 |
| session | object | No | Browser or server continuity context. The web SDK can prepare these values from client-side signals. | { sessionId, tabId, continuityStrength } |
| session.sessionId | string | No | Stable browser or app session identifier for continuity analysis. | "sess_abc" |
| session.tabId | string | No | Browser tab identifier produced by the web SDK. | "tab_abc" |
| session.isNewDevice | boolean | No | Whether the current browser/device appears new for this publishable key. | false |
| session.continuityStrength | number | No | Continuity confidence from 0 to 1. Lower values raise weak_session_continuity risk. | 0.95 |
| session.recentHumanSignalAt | string | No | ISO timestamp for recent pointer, keyboard, or touch activity captured by the web SDK. | "2026-05-19T01:22:00.000Z" |
| session.recentHumanSignalAgeSeconds | number | No | Age in seconds of the latest human signal. Policies can require a recent signal before allowing an action. | 12 |
| session.geoChanged | boolean | No | Whether your app detected a geography change for the session. | false |
| session.networkChanged | boolean | No | Whether your app detected a network change for the session. | false |
| session.ipAddress | string | No | IP address observed by your server, if you choose to send it. | "203.0.113.10" |
| session.userAgent | string | No | User-Agent observed by your server, if useful for investigation. | "Mozilla/5.0 ..." |
| metadata | object | No | Normalized risk metadata used by the risk engine and policy engine. | { changedFields: [] } |
| metadata.requestedCount | number | No | Canonical count used by policy rules. If omitted, TxnShield falls back to requestData.requestedCount or 1. | 1 |
| metadata.velocityWindowCount | number | No | Number of similar actions observed in your chosen velocity window. | 8 |
| metadata.changedFields | string[] | No | Field names changed by this action. Non-empty arrays increase privileged_write risk and help audits explain what changed. | ["routingNumber", "accountNumber"] |
| metadata.resourceCount | number | No | Number of resources included in the action, often the same as requestedCount for exports and bulk operations. | 250 |
| metadata.abnormalSequence | boolean | No | Whether your app detected an unusual workflow sequence before this action. | false |
| metadata.objectAccessRare | boolean | No | Whether this actor rarely accesses this resource or resource class. | true |
| metadata.suspiciousTimeWindow | boolean | No | Whether your app considers the local time or operating window suspicious. | false |
| metadata.localHour | number | No | Local hour from 0 to 23. The risk engine treats late-night hours as a possible signal. | 23 |
| metadata.proofToken | string | No | Application proof token used when retrying after a challenge flow. | "proof_abc" |
| metadata.notes | string | No | Short operational context for review. Do not include secrets or full protected records. | "support escalation SUP-123" |
| challengeResult | object | No | Result of a completed step-up challenge when retrying an action. | { type: "proof_token", passed: true } |
| challengeResult.type | "passkey" | "proof_token" | No | Challenge mechanism completed by the app. | "proof_token" |
| challengeResult.passed | boolean | No | Whether the challenge was successfully completed. | true |
| rawSignals | Record<string, boolean | number> | No | Optional raw signal map for advanced integrations. Supported values are booleans and numbers. | { "new_device": true } |
const evaluation = await txnShield.evaluate({
operationKey: "bank_account.update",
actor: { id: body.actorId, authenticated: true, roles: ["support"], trusted: false },
resource: { type: "customer", id: body.customerId },
requestData: { requestedCount: 1 },
metadata: { changedFields: [] },
});Evaluate response shape
Your app must enforce the decision before committing the action. Do not continue a write, export, payment change, or permission change after deny, throttle, or step_up_required unless your application has completed the required flow and reevaluated the transaction.
| Field | Type | Required | Description | Example |
|---|---|---|---|---|
| decision | "allow" | "allow_redacted" | "step_up_required" | "throttle" | "deny" | Yes | Outcome your app must enforce before committing the protected action. | "step_up_required" |
| score | number | Yes | Risk score from 0 to 100 after base risk and optional AI advisory adjustments. | 72 |
| riskBand | "low" | "medium" | "high" | Yes | Risk band derived from policy thresholds. | "medium" |
| reasons | string[] | Yes | Deduplicated reason codes explaining the score or policy outcome. | ["missing_recent_human_signal"] |
| telemetryId | string | Yes | Unique event id for correlating app logs with TxnShield Event Stream and Decision Logs. | "8f8c..." |
| challenge | object | No | Present when decision is step_up_required and the app should collect stronger proof. | { type: "proof_token", id: "..." } |
| challenge.type | "passkey" | "proof_token" | No | Challenge type requested by policy. | "proof_token" |
| challenge.id | string | No | Challenge identifier to carry through the app challenge flow. | "challenge_123" |
| redaction | object | No | Present when decision is allow_redacted and fields should be masked or dropped. | { fields: ["email"], strategy: "mask" } |
| redaction.fields | string[] | No | Field paths your app or SDK should redact before returning data. | ["email", "taxId"] |
| redaction.strategy | "mask" | "drop" | No | How to redact the listed fields. | "mask" |
| policyVersionId | string | No | Policy version used for the decision, when a bound policy was evaluated. | "clx..." |
| aiAssessment | object | No | Optional BYOK AI advisory assessment when configured. Policies remain the enforcement contract. | { status: "ok", scoreDelta: 8 } |
Common request and response examples
These examples show the same shapes used by the SDK and the direct REST API. The exact score, reasons, telemetryId, and policyVersionId vary by environment, policy, and risk signals.
Allowed transaction
Use this shape when the protected action is low enough risk to continue immediately.
Request
{
"operationKey": "customer.create",
"actor": {
"id": "user_123",
"authenticated": true,
"roles": ["support"]
},
"resource": {
"type": "customer",
"id": "cus_456"
},
"requestData": {
"requestedCount": 1
},
"metadata": {
"changedFields": ["name", "email"]
}
}Response
{
"decision": "allow",
"score": 18,
"riskBand": "low",
"reasons": ["low_risk_operation"],
"operationKey": "customer.create",
"operationDisplayName": "Create customer",
"actionType": "create",
"resourceType": "customer",
"sensitivity": "medium",
"policyId": "pol_123",
"telemetryId": "0bff0f7e-9e7e-4b7f-bb76-6ccfbf81e8b1",
"policyVersionId": "pv_123",
"warnings": []
}Step-up required
Pause the protected action, complete the challenge in your app, then retry with challengeResult.
Request
{
"operationKey": "bank_account.update",
"actor": {
"id": "user_123",
"authenticated": true,
"roles": ["finance_manager"]
},
"resource": {
"type": "bank_account",
"id": "acct_789"
},
"metadata": {
"changedFields": ["routingNumber", "accountNumber"],
"velocityWindowCount": 3
},
"session": {
"continuityStrength": 0.62,
"recentHumanSignalAgeSeconds": 420
}
}Response
{
"decision": "step_up_required",
"score": 58,
"riskBand": "medium",
"reasons": ["policy_recent_human_signal_required"],
"operationKey": "bank_account.update",
"challenge": {
"type": "proof_token",
"id": "challenge_123"
},
"telemetryId": "3a26ce75-9924-4607-9fc3-ec628e1c7d84",
"policyVersionId": "pv_123",
"warnings": []
}Retry after step-up
Only retry after your app has verified the proof token or passkey assertion.
Request
{
"operationKey": "bank_account.update",
"actor": {
"id": "user_123",
"authenticated": true,
"roles": ["finance_manager"]
},
"resource": {
"type": "bank_account",
"id": "acct_789"
},
"metadata": {
"changedFields": ["routingNumber", "accountNumber"]
},
"challengeResult": {
"type": "proof_token",
"passed": true
}
}Response
{
"decision": "allow",
"score": 58,
"riskBand": "medium",
"reasons": ["policy_recent_human_signal_required", "challenge_satisfied"],
"operationKey": "bank_account.update",
"telemetryId": "91c50970-801e-4210-9d06-7f6a78a6f9d7",
"policyVersionId": "pv_123",
"warnings": []
}Redacted allow
Continue the action, but mask or drop the fields listed in redaction before returning data.
Request
{
"operationKey": "invoice.export",
"actor": {
"id": "user_123",
"authenticated": true,
"roles": ["support"]
},
"resource": {
"type": "invoice",
"id": "batch_123"
},
"requestData": {
"requestedCount": 250
},
"metadata": {
"resourceCount": 250
}
}Response
{
"decision": "allow_redacted",
"score": 46,
"riskBand": "medium",
"reasons": ["bulk_or_export_volume", "policy_redaction_applied"],
"operationKey": "invoice.export",
"redaction": {
"fields": ["customer.email", "customer.taxId"],
"strategy": "mask"
},
"telemetryId": "a7239c98-39bb-448e-9c79-7649b014f64d",
"policyVersionId": "pv_123",
"warnings": []
}Denied transaction
Do not commit the action. Return a blocked response from your app and keep the telemetryId for investigation.
Request
{
"operationKey": "payment_transaction.create",
"actor": {
"id": "user_123",
"authenticated": true,
"roles": ["support"]
},
"resource": {
"type": "payment_transaction",
"id": "pay_456"
},
"requestData": {
"amount": 25000,
"currency": "USD"
},
"session": {
"isNewDevice": true,
"continuityStrength": 0.28
}
}Response
{
"decision": "deny",
"score": 91,
"riskBand": "high",
"reasons": ["weak_session_continuity", "high_sensitivity_operation"],
"operationKey": "payment_transaction.create",
"telemetryId": "43e58781-5f54-446c-8524-9f2e8a7acbe9",
"policyVersionId": "pv_123",
"warnings": []
}Decision handling
- allow: continue the protected action.
- allow_redacted: continue, but apply redaction.fields using redaction.strategy before returning sensitive data.
- step_up_required: pause the action, complete the challenge, and retry with challengeResult.
- throttle: stop or delay the action and return a rate-limit style response.
- deny: block the action and do not commit the protected change.
Next steps