Submitting transactions
Quick start

OneView documentation

Submitting transactions

The ingest API, idempotency, decision responses, and error handling.

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: true and a 200 instead of a 201. It is safe to retry.
  • Resubmitting the same reference and direction with a different body is rejected with 409 and IDEMPOTENCY_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

HTTPcodeWhat to do
401Fix credentials. Do not retry.
403FORBIDDENFix permissions. Do not retry.
403LICENSE_MODULE_NOT_INCLUDEDApply your fallback and alert operations.
409IDEMPOTENCY_CONFLICTDo not retry — same reference and direction, different body.
400VALIDATION_FAILEDFix the payload. Do not retry. An errors array names the fields.
429Back off and retry.
503UPDATE_MAINTENANCE_ACTIVESwitch to bypass mode and retry after the update.
503TRANSACTIONS_UNAVAILABLEApply 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.