Every customer has limits on what they can move in a rolling window — a single payment, a day, a month, a year. They come from a profile the program assigns: a default from onboarding, which compliance can change (for example when approving the application). A customer can set their own, lower, limits on top.

The two kinds of limit

That distinction is the whole of the error handling. Read GET /transaction-limits for what applies today, what has been used and what is left.
Only limits that apply appear. A window with no limit is absent, not zero. Amounts are decimals to two places and add up at face value across currencies — there is no conversion.

Going over one

A payment over a limit is refused with 422 and nothing is created — no payment, no reservation. The body carries data.reviewable:

While a review is open

The payment is held: the money is reserved and out of the customer’s available balance, but nothing has reached the bank. It stays that way until compliance decides, which may take up to a working day. A review takes the customer’s reason once, and their documents once. A payment re-sent with a reason already carries it, so that review takes no second reason, and it can carry the documents too: upload them for the payment first, then re-send with limitReview: { note, documents }. Sent that way, even with documents: [], it is the review’s whole submission, and the review takes nothing more. A payment held without a reason, such as a scheduled payment that goes over when it runs, asks the customer, who explains it once. Documents come with the reason or, if the reason didn’t carry any, in one later submission with documents and no note. After that the review takes nothing more. Either way the customer can cancel and take the payment back until compliance decides.

Direct debits

A direct-debit collection over the customer’s limits is held for review in the same way, and the review’s kind is DIRECT_DEBIT. A collection can’t wait for ever, so its review carries a cutoffAt: if compliance hasn’t approved it by then, the collection is refused and the money is handed back. Show the customer that deadline and ask them to explain before it: once it has passed without an approval, an explanation is refused with 409 LIMIT_REVIEW_CUTOFF_PASSED. The customer can cancel a collection’s review too, but the collection stays reserved until cutoffAt and is refused there, not straight away. A collection that only goes over the limits when it is funded on its collection day leaves no time to ask: it is refused on the spot, and its review is never put to the customer, so it has no askedAt. Either way the payment request reads limitMonitoring: REJECTED with status FAILED.

Money arriving

On a program that checks money arriving, a credit that takes a customer over their inbound limits is never refused — it has already arrived. It is held instead: it shows in the balance but is not available to spend, and the transaction carries limitMonitoring: HELD. The customer is asked what it is for and answers once with submit, with any documents in the same call or in one follow-up; they can’t cancel it. That includes money from another customer’s account in Orenda. The sender’s payment completes as usual, and the receiver’s credit is held the same way: it isn’t available to spend and isn’t put on their card until compliance decides. Moving money between a customer’s own accounts is never measured. The transaction also carries limitReviewId: open the review with get a limit review. Credits held before this field was added carry the hold without it; they still appear in the customer’s open reviews. Once compliance decides, limitMonitoring reads APPROVED (the money is theirs to spend) or REJECTED (it is being sent back). If transaction monitoring rejects the credit first it reads SUPERSEDED, and the review closes.

Finding a review

The app reaches a review four ways:
  • the limitReview.reviewId in the response to a payment re-sent with a reason;
  • limitReviewId on a held payment request;
  • limitReviewId on a held credit’s transaction;
  • the customer’s open reviews.
Each review says which account it is about (accountId) and who paid whom: payer and payee by name, with the IBAN or account number masked to the last four characters, and the payment’s reference. See get a limit review. The events that ask the customer to explain and that announce a decision come over the WebSocket, and only reach an app that is connected when they are sent. Read the open reviews when the app opens and whenever the WebSocket reconnects, so a customer who was away still sees what is waiting for them.

Back office

Back office, custodians included, can use every route here for the customer: read their limits and reviews, explain, upload to, cancel or decline a review, upload documents for a payment, and set their own limits. It names the program with ?programId= and is bounded by its token’s claims: each route needs the same permission a customer’s token does (programs.transactionLimits.view or .update, programs.limitReviews.view or .update). When staff actually change the customer’s limits, the app is told with a TRANSACTION_LIMITS_CHANGED event over the WebSocket. There is no email.
Counts are enforced only where the limit profile turns them on. Transaction counts per window are measured for every customer. A count is enforced, like an amount, only for a window whose count the customer’s limit profile enforces; everywhere else nothing is refused or held for a count. A count the customer sets on their own limits can lower a count the profile enforces, but can’t switch one on: where the profile doesn’t enforce that count, it’s saved but not applied.