Idempotency
Malga’s API supports idempotency keys to avoid duplicate request processing in case of multiple repetitions of the same operation. This feature is useful when a request fails due to a communication error and you have not received a conclusive answer. If you receive a connection error on a given call you can simply reattempt a new request using the same idempotency key, this way our API can guarantee that the second call will not be processed in duplicity.
To make calls with idempotency just send an additional header X-Idempotency-Key.
curl --location --request POST 'https://api.malga.io/v1/charges' \
--header 'X-Client-Id: <YOUR_CLIENT_ID>' \
--header 'X-Api-Key: <YOUR_PUBLIC_KEY>' \
--header 'Content-Type: application/json' \
--header 'X-Idempotency-Key: <IDEMPOTENCY_KEY>'
Our service saves the Idempotency-Key
and the Body
sent in your request, given a request, regardless of failure or success in the processing. We save the processing result, and when a second request is made with the same idempotency key our service returns the same content returned on the first call, including the errors.
caution
The idempotency key needs to be unique, generated client-side, and it is necessary to ensure on your side that the keys do not collide. We suggest using V4 UUID or a similar algorithm that guarantees unique hashes.
The result is only stored on the Malga’s side if processing of the first request has been started. If there is a failure in the validation of the fields, or if another key is being processed simultaneously, no idempotency response is given.
All POST calls accept idempotent key.
Race condition
If a transaction is sent more than once at the same time, using the same idempotency key, the process enters a race condition. If this occurs, you may receive 1 transaction with a success status and another with an error stating this condition. Errors returned in case of race condition are:
- Http 409 - Transaction is processing
- Http 400 - There is a transaction with the same idempotency key in transaction at that time
To avoid race condition we recommend you to add a minimum interval time between two calls with same idempotency key, and handle received 409 and 400 errors to retry. We recommend at least 3 attempts, a maximum of 5, with a minimum interval of 10 seconds between them.
See an example:
- Node.js
To run the example install axios npm i axios axios-retry
so run node index.js
const axios = require('axios');
const axiosRetry = require('axios-retry');
const MERCHANT_ID = '<YOUR_DATA_HERE>';
const CARD_ID = '<YOUR_DATA_HERE>';
const CLIENT_ID = '<YOUR_DATA_HERE>';
const API_KEY = '<YOUR_DATA_HERE>';
const IDEMPOTENCY_KEY = '<USE_RANDOM_UUID_V4>';
axiosRetry(axios, {
retries: 3,
retryDelay: () => {
return 10_000;
},
retryCondition: (error) => {
if (axiosRetry.isNetworkOrIdempotentRequestError(error)) {
return true;
}
const isUsingIdempotencyKey = error.request.getHeader('x-idempotency-key') !== undefined;
const isMethodPost = error.request.method === 'POST';
if (isUsingIdempotencyKey && isMethodPost) {
return true;
}
return false;
},
onRetry: (retryCount) => {
console.debug(`retried ${retryCount}`);
}
});
async function main() {
const data = JSON.stringify({
"merchantId": MERCHANT_ID,
"amount": 150,
"currency": "BRL",
"statementDescriptor": "Pedido #231 loja joão",
"capture": true,
"paymentMethod": {
"paymentType": "credit",
"installments": 1
},
"paymentSource": {
"sourceType": "card",
"cardId": CARD_ID
}
});
const headers = { 'x-idempotency-key': IDEMPOTENCY_KEY };
const result = await createCharge(data, headers);
console.log(result?.data);
}
/**
* Create a transaction without using idempotency key
*/
async function createCharge(data, headers = {}) {
const config = {
method: 'post',
url: 'https://api.malga.io/v1/charges',
headers: {
'x-client-id': CLIENT_ID,
'x-api-key': API_KEY,
'Content-Type': 'application/json',
...headers
},
data: data
};
try {
const response = await axios(config);
return response;
} catch (e) {
return e.response;
}
}
main();