Errors
Quick start

OneView documentation

Errors

The error envelope, every status and code, validation messages, and retries.

Errors

Any 4xx or 5xx response means no decision was made for the request. The transaction was not evaluated, and your system must apply its own fallback. A lapsed licence or an outage never appears as a BLOCK.

The error envelope

Every error has the same shape:

{
  "message": "Transaction payload validation failed",
  "status": false,
  "statusCode": 400,
  "code": "VALIDATION_FAILED",
  "errors": [
    {
      "field": "transactionReference",
      "code": "required",
      "message": "transactionReference is required"
    }
  ]
}
FieldMeaning
messageA human-readable summary. Log it, but do not branch on it: the wording can vary.
statusAlways false for an error.
statusCodeThe HTTP status, repeated in the body.
codeA stable machine-readable code. Branch on this. A few errors, such as 413 and 500, have no code.
errorsPresent only on validation failures. Up to 20 entries, each with field, code and message.

400 Bad Request

VALIDATION_FAILED

The body broke one or more validation rules. Every problem found is listed, up to 20.

{
  "message": "Transaction payload validation failed",
  "status": false,
  "statusCode": 400,
  "code": "VALIDATION_FAILED",
  "errors": [
    {
      "field": "riskScore",
      "code": "not_accepted",
      "message": "riskScore is assigned by One View and must not be supplied"
    },
    {
      "field": "transactionReference",
      "code": "required",
      "message": "transactionReference is required"
    },
    {
      "field": "counterparty",
      "code": "required",
      "message": "counterparty.merchantName is required for a CARD counterparty"
    },
    {
      "field": "currency",
      "code": "format",
      "message": "currency has an unsupported format"
    }
  ]
}

Fix the request and send it again. Do not retry it unchanged.

INVALID_JSON

The body is not well-formed JSON, or it is a bare value such as 5, "text" or null instead of an object. This check runs before authentication, so it is returned even when the API key is wrong. Fix the body and send it again.

{
  "message": "Request body must be a well-formed JSON object or array",
  "status": false,
  "statusCode": 400,
  "code": "INVALID_JSON"
}

A well-formed JSON array passes this check but is then rejected with VALIDATION_FAILED, because the transaction body must be an object.

INVALID_TENANT_HEADER

You sent an X-Tenant-Id header that is not a UUID. Remove the header: your credential already determines the tenant.

{
  "message": "X-Tenant-Id must be a UUID",
  "status": false,
  "statusCode": 400,
  "code": "INVALID_TENANT_HEADER"
}

Validation error codes

Each entry in errors[] has a field, which is the path to the problem (such as accountHolder.riskLevel, counterparty or ledgerPostings.0), and one of the codes below. The messages shown are the ones OneView returns.

errors[].codeMeaning
requiredA required value is missing.
invalidThe value has the wrong type, is not an allowed value, or breaks a rule.
formatThe value is the right type but has the wrong shape.
unknownA field OneView does not recognise.
not_acceptedA field OneView will not take from a caller: one it assigns itself, or one that does not apply to the rest of the request.
too_largeAn object has too many keys or a value is too long.

required

fieldmessageCause
transactionReferencetransactionReference is requiredThe field is missing or null. The same message pattern applies to every required top-level field.
accountHolderaccountHolder.customerUniqueId is required when accountHolderType is CUSTOMERaccountHolderType is CUSTOMER and customerUniqueId is missing, not a string, or blank.
counterpartycounterparty.accountName is required for this counterparty typeAn EXTERNAL_BANK, INTERNAL_USER or INTERNAL_GL counterparty has no accountName, or it is blank.
counterpartycounterparty.merchantName is required for a CARD counterpartyA CARD counterparty has no merchantName, or it is blank.
counterpartycounterparty.billerName is required for a VAS counterpartyA VAS counterparty has no billerName, or it is blank.
counterpartya WALLET counterparty requires at least one of: accountNumber, email, emailFingerprint, counterpartyFingerprintA WALLET counterparty carries none of those four identifiers, or every one it carries is blank. accountName is optional for this type and does not satisfy the check. See Collection channels.
collectionAccountcollectionAccount is required when paymentMethod is STATIC_ACCOUNT and direction is INBOUNDA static-account collection with no collectionAccount, or with null in its place.
collectionAccount.accountNumbercollectionAccount.accountNumber is requiredThe object was sent without an accountNumber, or it is blank.
usdExchangeRateusdExchangeRate is required for cross-border or foreign-currency transactionsA non-USD transaction is cross-border or in a currency other than your base currency, and has no rate.
ledgerPostings.0ledgerPostings.0.glCode is requiredA ledger leg has no glCode.

Only one counterparty problem is reported at a time. After you fix it, a second one may appear.

invalid

fieldmessageCause
paymentMethodpaymentMethod must be one of: NIP, NEFT, RTGS, SWIFT, INTERNAL_TRANSFER, CARD, CASH, CHEQUE, DIRECT_DEBIT, STANDING_ORDER, STATIC_ACCOUNT, WALLET, MOBILE_MONEYA value outside the list, such as BANK_TRANSFER. Enums are case-sensitive.
accountHolder.riskLevelaccountHolder.riskLevel must be one of: LOW, MEDIUM, HIGHA value such as medium or VERY_HIGH.
accountHolder.identityTypeaccountHolder.identityType must be one of: BVNAny identity type other than BVN, such as NIN.
accountHolder.identityNumberaccountHolder.identityNumber must be an 11-digit BVNNot an 11-digit string, for example a JSON number.
counterpartycounterparty.counterpartyType is not a supported valuecounterpartyType is missing or not one of the six types.
counterpartycounterparty.bankCode is the former name of counterparty.institutionCode; they must not be supplied with different valuesBoth names of an institution field are sent with different values. bankName against institutionName gives the same message with those two names. Sending a pair with identical values is accepted. See Counterparty object in Submitting transactions.
counterparty.countrycounterparty.country must be an ISO 3166-1 alpha-2 country codeA three-letter code such as NGA, or an unassigned code.
telemetry.countrytelemetry.country must be an uppercase ISO 3166-1 alpha-2 or alpha-3 country codeLowercase, unassigned or numeric codes.
amountamount must be a decimal with at most 4 fractional digitsToo many decimal places, leading zeros, commas, or exponent notation such as 1e21.
amountamount must be a non-negative decimalA negative amount. balanceBefore and balanceAfter are the only amounts that may be negative.
usdExchangeRateusdExchangeRate must be 1 when currency is USDA USD transaction with a rate other than 1.
usdExchangeRateusdExchangeRate must be greater than zeroA rate of 0.
usdExchangeRateusdExchangeRate is too small for this amount: the derived USD amount would exceed 14 whole digitsThe rate is so small that amount / usdExchangeRate would be larger than 14 whole digits. Usually a sign the rate was sent the wrong way round.
isCrossBorderisCrossBorder must be a booleanA string such as "false" instead of false.
executedAtexecutedAt must be an ISO 8601 timestampA value that is not a date and time, or is longer than 40 characters.
externalReferenceexternalReference must be a string of 1 to 128 charactersAn empty string, a value that is not a string, or more than 128 characters. The same message pattern applies to other length-limited fields, with their own maximum: sourceOfFunds and ledger costCenter 64, transactionReference 64, remittancePurposeCode 32.
accountHolder.firstNameaccountHolder.firstName must be at most 64 charactersA customer profile value over its limit. See Customer account holder for every limit.
accountHolder.nationalityaccountHolder.nationality must be an ISO 3166-1 alpha-2 country codeA customer nationality or country that is not an assigned two-letter code, such as NGA.
accountHolder.dateOfBirthaccountHolder.dateOfBirth must be a calendar date in YYYY-MM-DD formatA customer date of birth such as 15/06/1990 or 1990-02-30.
counterpartycounterparty must not contain the NUL character (U+0000)A NUL character in any key or value. The same applies to accountHolder, telemetry and collectionAccount.
accountHolderaccountHolder contains an unsupported valueAn array inside the object, or a nested object with more than 64 keys.
ledgerPostingsledgerPostings must be an array of at most 64Not an array, or more than 64 legs.
ledgerPostings.1ledgerPostings.1.entryType must be DEBIT or CREDITThe second leg has a missing or wrong entryType. Legs are numbered from 0.
collectionAccountcollectionAccount must be an objectcollectionAccount was sent as a string, number or array. The same message pattern applies to accountHolder, counterparty and telemetry.
bodyA JSON object body is requiredThe body is not a JSON object, for example an array.

format

fieldmessageCause
currencycurrency has an unsupported formatNot three uppercase letters, for example ngn.
transactionReferencetransactionReference has an unsupported formatA space or another disallowed character, or it starts with -.
sourceOfFundssourceOfFunds has an unsupported formatA code with spaces or other disallowed characters, or one that starts with ., _ or -.
narrationnarration must not contain control charactersA line break, tab or other control character.
collectionAccount.accountNumbercollectionAccount.accountNumber has an unsupported formatA disallowed character, such as a space, a value starting with -, or more than 64 characters.

unknown

fieldmessageCause
usdAmountusdAmount is not a recognised fieldA top-level field that is not part of the request. usdAmount, baseAmount and isForeignCurrency are calculated by OneView and are rejected this way.
initiatorinitiator is not a recognised field; it was renamed to accountHolderA request using the earlier field name. Rename initiator to accountHolder.
initiatorTypeinitiatorType is not a recognised field; it was renamed to accountHolderTypeA request using the earlier field name. Rename initiatorType to accountHolderType.
bodybody contains a field name that is not recognisedAn unknown top-level key that is not a plain field name, for example one that starts with a digit or underscore, contains spaces or non-ASCII characters, or is longer than 64 characters. It is reported once, however many such keys there are.
ledgerPostings.0ledgerPostings.0 contains the unrecognised field narrationA ledger leg with a key outside the eight allowed leg fields.
ledgerPostings.0ledgerPostings.0 contains an unrecognised fieldThe same, when the unknown key is not a plain field name.

not_accepted

fieldmessageCause
riskScoreriskScore is assigned by One View and must not be suppliedYou sent a value that OneView assigns. The same applies to transactionId, id, receivedAt, riskStatus, decision and decisionOutcome.
collectionAccountcollectionAccount is only accepted when paymentMethod is STATIC_ACCOUNT and direction is INBOUNDYou sent a collection account on any other payment method or direction. See Collection channels.

too_large

fieldmessageCause
accountHolderaccountHolder may contain at most 64 fieldsMore than 64 keys in accountHolder, counterparty, telemetry or collectionAccount.
counterpartycounterparty contains an oversized valueA string longer than 512 characters.

401 Unauthorized

AUTH_REQUIRED

No Authorization header was sent.

{
  "message": "Authentication is required",
  "status": false,
  "statusCode": 401,
  "code": "AUTH_REQUIRED"
}

INVALID_API_CREDENTIAL

The API key is wrong, unknown, revoked or expired.

{
  "message": "API credential is invalid",
  "status": false,
  "statusCode": 401,
  "code": "INVALID_API_CREDENTIAL"
}

Check the key in your secret manager, and check the service account's status and expiry in OneView.

403 Forbidden

SERVICE_ACCOUNT_INTEGRATION_ONLY

The path is not available to API service accounts. This happens with a trailing slash (/api/transactions/) or with GET /api/transactions/{id}. Use the exact path, and look transactions up through the list endpoint.

{
  "message": "API Service Accounts can access integration APIs only",
  "status": false,
  "statusCode": 403,
  "code": "SERVICE_ACCOUNT_INTEGRATION_ONLY"
}

SERVICE_ACCOUNT_SCOPE_FORBIDDEN

The service account's module scope is not Transaction Monitoring or All licensed modules.

{
  "message": "API credential is not scoped to this module",
  "status": false,
  "statusCode": 403,
  "code": "SERVICE_ACCOUNT_SCOPE_FORBIDDEN"
}

SERVICE_ACCOUNT_TENANT_MISMATCH

You sent an X-Tenant-Id for a tenant other than the one the credential belongs to. Remove the header.

{
  "message": "X-Tenant-Id does not match this credential's bound tenant",
  "status": false,
  "statusCode": 403,
  "code": "SERVICE_ACCOUNT_TENANT_MISMATCH"
}

LICENSE_MISSING

{
  "message": "A valid license is required",
  "status": false,
  "statusCode": 403,
  "code": "LICENSE_MISSING"
}

LICENSE_INVALID_OR_EXPIRED

{
  "message": "The license is invalid or expired",
  "status": false,
  "statusCode": 403,
  "code": "LICENSE_INVALID_OR_EXPIRED"
}

LICENSE_MODULE_NOT_INCLUDED

The licence does not include the Transaction monitoring module or its Transactions sub-module. Optional controls, such as rules or screening, never cause this error: without them, the decision changes instead.

{
  "message": "Module is not included in the license",
  "status": false,
  "statusCode": 403,
  "code": "LICENSE_MODULE_NOT_INCLUDED"
}

For any licence error, apply your fallback and alert the team that manages OneView.

Origin not allowed

A request with an Origin header that OneView does not allow is rejected. This response has no code. Call the API from your servers without an Origin header.

{
  "message": "Origin is not allowed",
  "status": false,
  "statusCode": 403
}

409 Conflict

TRANSACTION_MONITORING_NOT_CONFIGURED

The base currency has not been set. Ask an administrator to set it under Transaction Monitoring → Settings.

{
  "message": "Transaction monitoring base currency must be configured before ingestion",
  "status": false,
  "statusCode": 409,
  "code": "TRANSACTION_MONITORING_NOT_CONFIGURED"
}

IDEMPOTENCY_CONFLICT

A transaction with the same transactionReference and direction already exists with a different body. OneView does not overwrite a stored transaction. If this is a genuinely new transaction, give it a new reference. If it is a retry, resend the original body exactly.

{
  "message": "A different transaction already exists for this reference and direction",
  "status": false,
  "statusCode": 409,
  "code": "IDEMPOTENCY_CONFLICT"
}

413 Payload Too Large

The body is larger than 1 MB. This response has no code.

{
  "message": "Request body is too large",
  "status": false,
  "statusCode": 413
}

503 Service Unavailable

TRANSACTIONS_UNAVAILABLE

Transaction monitoring cannot accept transactions right now.

{
  "message": "Transaction monitoring is unavailable",
  "status": false,
  "statusCode": 503,
  "code": "TRANSACTIONS_UNAVAILABLE"
}

AUTH_UNAVAILABLE

OneView could not check the credential right now.

{
  "message": "API authentication is unavailable",
  "status": false,
  "statusCode": 503,
  "code": "AUTH_UNAVAILABLE"
}

500 Internal Server Error

An unexpected error. This response has no code.

{
  "message": "An unexpected error occurred",
  "status": false,
  "statusCode": 500
}

Retry guidance

StatusRetry?What to do
400NoFix the request, including INVALID_JSON.
401NoFix or replace the credential.
403NoFix the path, scope, tenant header or licence. Apply your fallback meanwhile.
409 TRANSACTION_MONITORING_NOT_CONFIGUREDNoRetry only after an administrator sets the base currency.
409 IDEMPOTENCY_CONFLICTNoUse a new reference for a new transaction, or resend the original body.
413NoReduce the body size.
500YesRetry with the identical body, with increasing delays. Apply your fallback meanwhile.
503YesRetry with the identical body, with increasing delays. Apply your fallback meanwhile.

Retrying with the identical body is always safe. If the first attempt was stored before the error reached you, the retry returns 200 with replayed: true and the stored decision, instead of creating a second transaction. OneView does not rate-limit these requests, so there is no 429 to handle. It also never returns 404 or 422 for a submission.