Statements
Overview
Four read-only services covering what is in an account and what has moved through it. No money moves here.
| Service | Answers |
|---|---|
| BalanceInquiry | What the balance is right now |
| MT940 | What settled on a past day — finalized, end-of-day |
| MT942 | What has moved so far today — intraday, not final |
| TransactionHistory | What moved across a date range — built by Neotek |
Prerequisites
- Authentication: Obtain an access token using the OAuth2 Client Credentials flow (see Getting Started → Authentication). Every endpoint in this product takes
Authorization: Bearer <ACCESS_TOKEN>— there are no exceptions. - Subscription: Subscribe to Statements in your chosen environment.
A token carries only the scopes you asked for, so one issued for a different product is rejected here. Request this product's scope, or ask for several scopes in a single token as described on the Authentication page.
Choosing between them
The split that matters: MT940 and MT942 are live calls to the bank; Transaction History is not.
MT940 and MT942 are the SWIFT industry standard, and they carry the standard's limitations — 2 to 5 seconds per call, no pagination, one date per request, no continuity across dates. Transaction History exists because of those limits: Neotek syncs each connected bank into its own store, so queries return instantly, paginate up to 500 per page, and span any date range in a single call.
Put another way, MT940 and MT942 are per-day snapshots while Transaction History is a continuous ledger. For yesterday's statement, MT940 gives you a bank-authoritative document with opening and closing balances. For every transaction in a quarter, 50 at a time, only Transaction History can do it — MT940 would mean 90 separate calls.
The tradeoff is freshness. Transaction History caps toDate at T-1 and serves only finalized data, so anything happening today needs MT942. It also requires the account to be onboarded first, and data starts from the onboarding date rather than retroactively.
Errors
All four services share the same failure shape. category and errors appear only on failure, and the category determines the HTTP status.
{ "success": false, "code": "INVALID_IBAN", "message": "The provided IBAN is not valid", "category": "ERROR_CATEGORY_VALIDATION_FAILED", "errors": [ { "field": "accountIban", "message": "IBAN must start with SA and be 24 characters" } ]}| Status | Codes | Cause |
|---|---|---|
400 ERROR_CATEGORY_VALIDATION_FAILED | INVALID_IBAN, INVALID_ACCOUNT, INVALID_BANK_CODE, ACCOUNT_NOT_FOUND | Malformed IBAN, unknown bankCode, missing parameter |
401 ERROR_CATEGORY_AUTH_FAILED | AUTH_FAILED, CREDENTIALS_NOT_FOUND, UNAUTHORIZED | Token missing or expired, or no vault credentials for your app with that bank |
404 ERROR_CATEGORY_NOT_FOUND | NOT_FOUND | Account not found at that bank |
422 ERROR_CATEGORY_BANK_REJECTED | ACCOUNT_BLOCKED, ACCOUNT_CLOSED | The account exists but the bank will not serve it |
500 ERROR_CATEGORY_SYSTEM_FAILURE | SYSTEM_ERROR, INTERNAL_ERROR | Gateway-side failure |
503 ERROR_CATEGORY_TEMPORARY_FAILURE | SERVICE_UNAVAILABLE, BANK_UNAVAILABLE, NETWORK_ERROR, NETWORK_TIMEOUT, REQUEST_TIMEOUT | Bank unreachable — retry with backoff |