Error handling and duplicate prevention
The vast majority of API requests are processed without any issues, but unfortunately a small number may error due to various reasons, from bad data to internet connectivity. It is important that error handling is efficient to prevent manual effort, but also to ensure that in retrying API requests - particularly payments - duplicates are not processed.
Modulr offers ways within API requests to detect and prevent duplicate requests, but it is key that these are used appropriately (depending on the error conditions). The guide below should assist you in understanding the error scenarios and recommended actions.
This guidance is particularly applicable to operations or endpoints that create new objects / requests (POST requests). Please review how to make idempotent requests in the Modulr API documentation here before reading this guide as it uses some of these concepts.
| Type | Description | Is experienced as | Recommendation |
|---|---|---|---|
| 1 | Network, connectivity or system processing errors |
|
|
| 2 | Forbidden.The request was valid, but the server is refusing action. Generally this relates to permission /access issues, but could also occur if nonce is re-used and modulr are not able to return the original response (because it is still processing the original request, or x-mod-retry is not set to true) | 403 error |
|
| 3 | Bad request, bad data in request The server cannot or will not process the request due to an apparent client error. Example: account does not have enough balance, account number basic checks fail, badly formatted data, key HMAC signature calculation errors | 400 error |
|
| 4 | Rate limit or Quota errorsIn order to protect all system clients from the actions of a single client limits are placed on how many requests can be made in a short period (rate limit) and over a longer period (quota)You should not experience these errors in the course of normal operations for the vast majority of clients. If you do please look into the volume/pattern of requests you are making and check for any issues. Note: Limits and quotas work across all your requests | 429 error "Rate limit exceeded"403 error "Quota exceeded" |
|
| 5 | Applicable to payment requestsPayment request is accepted/validated when you submit, you get a payment id from Modulr, but payment subsequently errors. This can be due to further error checking in the payments chain, e.g. the sort code is not reachable, account is closed | 2XX successful response on initial submission and initial status of VALIDATED, but on checking payment status later it is an error condition Payment status may be checked by doing a GET (after a wait period), subscribing to webhooks to your system, or checking for errors regularly in the web portal. |
|
| 6 | Applicable to payment requestsOutbound payment fully succeeds (PROCESSED status) but is subsequently later returned as a new inbound payment by the receiving bank. Unfortunately with some destinations the receiving bank may accept the payment but subsequently reject and return it | An unexpected credit on your account. As much detail will be provided as we get to allow you to match it to an outbound payment |
|
General recommendations
- On error default to either not re-sending a payment request, or re-sending a fixed number of times with the same nonce and x-mod-retry=true
- 1Retry attempts should use some form of expanding backoff to prevent overloading of requests in cases where multiple requests have failed and are retried
- Only resend as a new payment with a new nonce if you understand the specific error condition and are therefore confident the payment has not succeeded
- If you re-use a nonce you should not change any other contents of a request (i.e. it should be a resend of the same data)
- Idem-potency checking on nonce is valid for 48 hours from the initial submission of a unique nonce. Beyond this time do not retry any requests even using the same nonce unless you are sure it has not succeeded before
- If you also set an "externalReference" field in the body of a request (recommended), you should use a corresponding unique operation/object in your system to allow matching and reconciliation to your system

