fig-financial-payments-b2b-xapi
Idempotency
Idempotency ensures that repeating the same API request — due to retries, timeouts, or network issues — does not result in duplicated operations or inconsistent payment states.\
This mechanism is mandatory for all POST operations that create or trigger payment intents.
Concept
In simple terms:
Same request, same key → same result.
Same key, different request → conflict.
Each POST /intents/mbway request must include an Idempotency-Key header, which uniquely identifies the operation being performed.\
When the same key is received again:
- If the request body is identical, the API returns the same response (safe retry).
- If the body differs, the API returns HTTP 409 Conflict to signal a potential duplication.
Header Specification
| Header | Type | Required | Description | Example |
|---|---|---|---|---|
| Idempotency-Key | string | ✅ Yes | Unique identifier for each creation request (UUID v4). Used to deduplicate retries. | 7d0f7e4e-6fcb-4b74-befc-d5f3b77b2f47 |
💡 Recommendation: Use a new UUID v4 for every distinct payment intent request.
Behavior Example
1️⃣ First Request
POST /intents/mbway
Idempotency-Key: 7d0f7e4e-6fcb-4b74-befc-d5f3b77b2f47
Authorization: Bearer eyJhbGciOi...
{
"amount": { "gross": { "value": "50.00", "currency": "EUR" }, "net": { "value": "50.00", "currency": "EUR" } },
"paymentKey": { "phoneNumber": "+351912345678" },
"customer": { "name": "John Doe", "fiscalNumber": "123456789" },
"payments": { "items": [ { "receipt": { "systemCode": "CGN", "companyCode": "128" }, "amount": "50.00" } ] }
}Response (201 Created)
{
"id": "SR29667_yMpWnf7Vl2CXFBQkF",
"status": "pending",
"links": {
"self": "/intents/SR29667_yMpWnf7Vl2CXFBQkF",
"status": "/intents/SR29667_yMpWnf7Vl2CXFBQkF/status"
}
}✅ The system successfully created the payment intent and returned a unique id.\
If the same request is resent using the same Idempotency-Key, the system will respond with the exact same payload, ensuring that no duplicate transactions are created.
Safe Retries
Transient network errors, timeouts, or gateway interruptions can occasionally cause uncertainty about whether a payment request was processed successfully.\
To prevent accidental duplicate payments, clients must always retry using the same Idempotency-Key when re-submitting a previously failed or timed-out request.\
When the same key and payload are used:
- The backend detects the replay.
- The API returns the exact same response as the original request.
- No duplicate operations or payment intents are created.
Example: Safe Retry Scenario
2️⃣ Retry Request (Identical Payload)
POST /intents/mbway
Idempotency-Key: 7d0f7e4e-6fcb-4b74-befc-d5f3b77b2f47
Authorization: Bearer eyJhbGciOi...
{
"amount": { "gross": { "value": "50.00", "currency": "EUR" }, "net": { "value": "50.00", "currency": "EUR" } },
"paymentKey": { "phoneNumber": "+351912345678" },
"customer": { "name": "John Doe", "fiscalNumber": "123456789" },
"payments": { "items": [ { "receipt": { "systemCode": "CGN", "companyCode": "128" }, "amount": "50.00" } ] }
}Response (201 Created)
{
"id": "SR29667_yMpWnf7Vl2CXFBQkF",
"status": "pending",
"links": {
"self": "/intents/SR29667_yMpWnf7Vl2CXFBQkF",
"status": "/intents/SR29667_yMpWnf7Vl2CXFBQkF/status"
}
}✅ The system recognizes the Idempotency-Key and returns the same response as the original request without creating a new payment intent.
3️⃣ Retry with Different Payload (Conflict)
POST /intents/mbway
Idempotency-Key: 7d0f7e4e-6fcb-4b74-befc-d5f3b77b2f47
Authorization: Bearer eyJhbGciOi...
{
"amount": { "gross": { "value": "75.00", "currency": "EUR" }, "net": { "value": "75.00", "currency": "EUR" } },
"paymentKey": { "phoneNumber": "+351912345678" },
"customer": { "name": "John Doe", "fiscalNumber": "123456789" },
"payments": { "items": [ { "receipt": { "systemCode": "CGN", "companyCode": "128" }, "amount": "75.00" } ] }
}Response (409 Conflict)
{
"error": {
"code": "CONFLICT",
"message": "Idempotency key already used with a different request payload."
}
}❌ The system detects the same Idempotency-Key but a different payload (changed amount), returning a 409 Conflict to prevent unintended behavior.
Implementation Guidelines
- Generate Unique Keys: Always use a new UUID v4 for each distinct payment intent. Avoid reusing keys across unrelated requests to prevent conflicts.
- Store Idempotency Keys: Clients should store the
Idempotency-Keyalongside the request data to ensure safe retries in case of network issues. - Handle 409 Conflicts: If a 409 Conflict is received, verify the request payload. If the intent is to create a new payment, generate a new
Idempotency-Keyand retry. - Timeout Handling: Set appropriate retry timeouts (e.g., exponential backoff) to avoid overwhelming the API during transient failures.
- Validate Responses: Always check the response status and payload to confirm the operation's success or handle errors appropriately.
Best Practices
- Use HTTPS: Ensure all API requests are made over secure HTTPS connections to protect sensitive data like
Idempotency-Keyand payment details. - Log Requests: Log the
Idempotency-Keyand response details for debugging and auditing purposes. - Monitor Conflicts: Track 409 Conflict errors to identify potential issues in client retry logic or payload generation.
- Test Retries: Simulate network failures in a staging environment to verify that your client handles idempotency correctly.
💡 Pro Tip: Use a client library that supports automatic retry logic with idempotency headers to simplify implementation and reduce errors.