Idempotency
Mises API implements idempotency to ensure that critical operations (such as withdrawals) are not accidentally duplicated.
What is Idempotency?
Idempotency is the property that ensures an operation can be executed multiple times without changing the result beyond the first execution.
Practical example:
- You send a withdrawal request for R$ 100.00
- The request fails due to network timeout
- You resend the same request with the same key
- The API recognizes that it has already processed this operation and returns the original result
- Result: Only 1 withdrawal is created, not 2
Idempotency-Key Header
For idempotent operations, you must include the Idempotency-Key header:
POST /v1/withdrawals HTTP/1.1
Host: api.misespay.com
Authorization: Bearer {token}
Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000
Content-Type: application/jsonAccepted Format
- UUID v4 (recommended):
550e8400-e29b-41d4-a716-446655440000 - Alphanumeric with hyphens/underscores:
my-unique-key-123 - Size: 1 to 255 characters
- Allowed characters: Letters, numbers, hyphens (
-) and underscores (_)
IMPORTANT
Each unique operation attempt must have a different Idempotency-Key. Use the same key only for retry of the same operation.
Endpoints that Require Idempotency
| Endpoint | Requires Idempotency-Key | Description |
|---|---|---|
POST /v1/withdrawals | ✅ Yes (required) | Create withdrawal |
POST /v1/sales | ❌ No | Create sale |
GET /v1/balance | ❌ No | Query balance |
How It Works
First Request (201 Created)
curl -X POST https://api.misespay.com/v1/withdrawals \
-H "Authorization: Bearer {token}" \
-H "Idempotency-Key: abc-123-xyz" \
-H "Content-Type: application/json" \
-d '{"amount": 10.00, "authorize": true}'Response:
{
"success": true,
"message": "Withdrawal requested successfully",
"data": {
"withdrawal_id": "881c686a-9e53-4809-a63c-c2730b924ea7",
"amount": "R$ 10,00",
"status": "processing"
}
}Duplicate Request (200 OK)
# Same Idempotency-Key
curl -X POST https://api.misespay.com/v1/withdrawals \
-H "Authorization: Bearer {token}" \
-H "Idempotency-Key: abc-123-xyz" \
-H "Content-Type: application/json" \
-d '{"amount": 10.00, "authorize": true}'Response:
{
"success": true,
"message": "Withdrawal already processed previously",
"data": {
"withdrawal_id": "881c686a-9e53-4809-a63c-c2730b924ea7",
"amount": "R$ 10,00",
"status": "processing"
},
"idempotent": true
}Differences:
- HTTP Status:
200 OK(instead of201 Created) - Additional field:
"idempotent": true - Same data from original withdrawal
Best Practices
✅ Do
- Generate a unique key for each new operation
- Reuse the same key only for retry of the same operation
- Use UUID v4 to ensure global uniqueness
- Store the key along with the request for possible retries
- Implement automatic retry in case of timeout/network error
❌ Don't
- Don't reuse keys between different operations
- Don't use sequential values (1, 2, 3...)
- Don't use timestamps as unique key
- Don't omit the header in endpoints that require it
Related Errors
400 - Missing Idempotency-Key
{
"success": false,
"message": "Idempotency-Key header is required"
}Solution: Add the Idempotency-Key header to the request.
400 - Invalid Idempotency-Key
{
"success": false,
"message": "Invalid Idempotency-Key. Use only letters, numbers, hyphens and underscores (maximum 255 characters)"
}Solution: Use only allowed characters (a-z, A-Z, 0-9, -, _).
409 - Idempotency Conflict
If you send the same Idempotency-Key with different data, the API may return an error:
{
"success": false,
"message": "Conflict: Idempotency-Key already used with different data"
}Solution: Generate a new Idempotency-Key for the new operation.
Use Cases
1. Network Timeout
// First attempt - timeout
try {
await createWithdrawal(idempotencyKey, 100);
} catch (error) {
// Retry with the SAME key
await createWithdrawal(idempotencyKey, 100); // ✅ Safe
}2. Server Error 500
// First attempt - error 500
const response = await createWithdrawal(idempotencyKey, 100);
if (response.status === 500) {
// Retry with the SAME key
await createWithdrawal(idempotencyKey, 100); // ✅ Safe
}3. Multiple Operations
// Operation 1
const key1 = uuidv4();
await createWithdrawal(key1, 100);
// Operation 2 - NEW key
const key2 = uuidv4();
await createWithdrawal(key2, 50); // ✅ CorrectNext Steps
- Withdrawals - Create withdrawals with idempotency
