Submitting transactions
Your core banking system submits a transaction to OneView and receives a decision in the same response.
Authenticate with a service account that has the Ingest transactions permission. Create one under Administration → Service accounts; the API key is shown once, at creation and at rotation.
POST /api/transactions
Idempotency
A transaction is identified by its transactionReference together with its direction. Direction is part of
the key because an intra-bank transfer legitimately produces the same reference twice, once per leg.
- Resubmitting the same reference and direction with an identical body returns the stored decision, with
replayed: trueand a200instead of a201. It is safe to retry. - Resubmitting the same reference and direction with a different body is rejected with
409andIDEMPOTENCY_CONFLICT. OneView will not silently overwrite audit evidence.
You do not supply a separate idempotency key.
Fields OneView will not accept
transactionId, riskScore, riskStatus and any decision field are rejected. Identity and the decision are
OneView outputs; accepting them from a caller would let a caller assert its own approval.
status remains yours — it is your core banking lifecycle value. OneView's decision is a separate field.
Unknown fields are rejected rather than ignored, so a typo surfaces immediately instead of being silently dropped.
A successful response
{
"status": true,
"message": "Transaction evaluated",
"data": {
"transaction": {
"id": "0f4c1e2a-...",
"transactionReference": "TXN-20260729-009218",
"direction": "OUTBOUND",
"receivedAt": "2026-07-29T11:45:02.140Z",
"replayed": false
},
"decision": {
"outcome": "FLAG",
"riskScore": 65,
"evaluatedAt": "2026-07-29T11:45:02.152Z",
"evaluationMs": 11.8,
"complete": true,
"rulesEvaluated": 42,
"rulesetSnapshot": "a3f81c...",
"triggeredRules": [
{
"ruleId": "7c9e...",
"ruleVersion": 3,
"name": "High velocity 1h",
"action": "FLAG",
"riskScoreImpact": 40
}
]
}
}
}
Always check complete
complete: false means the decision is partial — some rules could not run. A skippedRules array names
which, with a reason code. The decision is still returned, and it is your policy whether to trust a partial
PASS.
This is not an error case and does not change the HTTP status. A rule that fails is neither treated as firing nor as not firing, because either would be misleading: one would block traffic on a bug, the other would weaken a control silently.
rulesetSnapshot identifies the exact set of rules and thresholds that ran, so a decision can be correlated
back to the policy in force at the time.
Errors
| HTTP | code | What to do |
|---|---|---|
| 401 | — | Fix credentials. Do not retry. |
| 403 | FORBIDDEN | Fix permissions. Do not retry. |
| 403 | LICENSE_MODULE_NOT_INCLUDED | Apply your fallback and alert operations. |
| 409 | IDEMPOTENCY_CONFLICT | Do not retry — same reference and direction, different body. |
| 400 | VALIDATION_FAILED | Fix the payload. Do not retry. An errors array names the fields. |
| 429 | — | Back off and retry. |
| 503 | UPDATE_MAINTENANCE_ACTIVE | Switch to bypass mode and retry after the update. |
| 503 | TRANSACTIONS_UNAVAILABLE | Apply your fallback and retry. |
UPDATE_MAINTENANCE_ACTIVE is the explicit signal for an update drain, so you never have to infer maintenance
from a generic 503.
Reading a decision later
GET /api/transactions/{id}
Requires Read transactions. This is how you resolve a held transaction: poll for the reference you
submitted and read releaseDecision once an analyst has recorded a review.
The detail response also carries the rule evaluations, so an integration can retrieve the same explanation the analyst sees.