Idempotency
The Mangopay API supports idempotency for all POST calls, which allows you to safely retry an operation while only performing the operation once. This helps avoid unwanted duplicated calls that can have detrimental consequences, for example in case of a network error.
Using an idempotency key
To make a POST call idempotent, include the Idempotency-Key header in your API request and generate a unique value for it.
The unique value allows the system to identify any subsequent retries of the same operation within 24 hours.
The idempotency key must contain between 16 and 36 alphanumeric characters or dashes (-).
Best practice – Use a UUID for idempotency keys
We strongly recommend generating a universally unique identifier (UUID) to use as the value for the Idempotency-Key header of your API request.
While using an idempotency key is optional, it is strongly recommended and necessary for some operations.
This is notably the case for:
- Multiple card pay-in captures against the same Preauthorization within 24 hours
Looking up an idempotency key
To retrieve an API response, call the GET View an API Response endpoint using your Idempotency-Key header value as the path parameter.
If Mangopay finds that the key was used in the last 24 hours, then the API response shows the outcome of the original request:
StatusCode– The HTTP response code of the original request.Resource– The response body of the original request.
Note – Idempotency lookup limited to within 24 hours
An idempotency key is only valid for 24 hours:
- A request only returns a 409 response if its
Idempotency-Keyheader value was used in the last 24 hours - The GET View an API Response returns a 400 error if the value wasn’t used in the last 24 hours
Blocking duplicated calls
If you use the same idempotency key within 24 hours, Mangopay will block all requests except the first. This means you are able to retry the same request safely knowing that it will only be processed once.
If the idempotency key has already been used in the last 24 hours, the API returns a 409 HTTP response code error:
Idempotent requests are blocked regardless of the HTTP response code of the first API call. This means you can’t reuse an idempotency key that was used on a failed call.
Handling timeouts
A timeout means that you didn’t receive a response from the API within the timeout configured in your HTTP client.
If your initial call used an Idempotency-Key header, then you can safely retry automatically using the same key:
Retry the request once with the same idempotency key
If the retry is successful, then it means that the original attempt did not reach Mangopay, so the retry is the one that gets processed.
If the API responds with a 409 response, then the original request did reach Mangopay and can be looked up using the dedicated endpoint below.
If the retry returns a 409 response, look up the idempotency key
Use the idempotency key value with the GET View an API Response endpoint as described above.
If StatusCode reflects success, then you know that the original request was processed (for example, the payment was initiated), and Resource gives the response body.
If StatusCode is not successful, then the Resource gives the error message. If StatusCode is 500, then you can attempt to check for the operation as described below.
If the original request that timed out didn’t include an idempotency key, or occurred more than 24 hours ago, then you should attempt to check for the operation before attempting a single retry. Integrating idempotency is recommended in all cases.
Handling server errors (500 response)
A 500 response code means Mangopay encountered an unexpected issue while processing the request, with the result of the operation being unknown.
In such cases, looking up the idempotency key with GET View an API Response will typically return the 500 error of the first call – the StatusCode in the response will be 500 along with the error message in Resource.
Therefore, to understand what happened you can attempt to check for the operation.
Checking for an operation
Before proceeding to a retry, and if the idempotency key can’t tell you the outcome of an operation, then you can try to check whether the resource exists using other parts of the system by:
- Webhooks – Receiving a webhook notification for the relevant creation event (for example,
PAYIN_NORMAL_CREATED), provided it was previously set up - Listing endpoints – Calling a list endpoint based on a resource related to the operation you attempted
Common areas where listing endpoints are available include:
- Transactions – Pay-ins, transfers, and payouts appear in the transaction listing endpoints which are based on various other objects (GET List Transactions for a User, GET List Transactions for a Wallet, etc)
- Pay-in refunds – GET List Refunds for a PayIn
- Wallets – GET List Wallets for a User
- Virtual accounts – GET List Virtual Accounts for a Wallet
- Users – GET List all Users
Using unique values in the common Tag property can facilitate this lookup operation. To store multiple values in the Tag, you can serialize them into a single string, for example a JSON object: "{\"id_1\":AB123,\"id_2\":DE456}".
If you find the resource and the operation was successful, then no retry is necessary.
Retrying an operation
In cases where you are unable to find a resource via its idempotency key, a webhook notification, or after checking all the available list endpoints, then it may be safe to retry with a new idempotency key. For any operation where an unintended duplicate would be costly, wait if possible and check again before attempting the retry.
Best practice – Retry once, with backoff
We recommend a single retry for temporary errors like 500 or 429, rather than retrying indefinitely.
- For a 500, wait using an exponential backoff with jitter before retrying.
- For a 429, use the
x-ratelimit-resetresponse header to know when to retry.
Retrying immediately or in a tight loop adds load to the service and can mean you quickly hit rate limits, which may affect your operations.