Skip to main content

Idempotency Guide

Quick Reference

WhatPrevent duplicate charges with idempotency keys
WhyNetwork failures and retries must never result in double-charging a customer
Reading Time8 min
DifficultyIntermediate
PrerequisitesWorking API integration

In payment processing, a non-idempotent retry is a financial error:

  1. Your server sends a charge request
  2. The charge succeeds, but the response is lost due to a network timeout
  3. Your server retries — without an idempotency key, A55 creates a second charge
  4. The customer is billed twice

Idempotency keys solve this: if A55 receives a duplicate key, it returns the original response instead of creating a new charge. This makes retries safe — the customer is charged exactly once regardless of how many times you send the request.

How It Works

Send an Idempotency-Key header with every POST request:

POST /api/v1/bank/wallet/charge/ HTTP/1.1
Authorization: Bearer <token>
Content-Type: application/json
Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000

A55 stores the key and its associated response. If the same key is sent again within the expiration window:

  • Same payload → Returns the original response (HTTP 200/201)
  • Different payload → Returns HTTP 409 Conflict

Key Format

Use UUID v4 for idempotency keys:

550e8400-e29b-41d4-a716-446655440000

Requirements:

  • Unique per business operation (not per retry attempt)
  • Generated once and reused across all retry attempts for the same operation
  • Minimum 16 characters, maximum 128 characters

Supported Endpoints

All POST endpoints support idempotency:

EndpointUse Case
POST /api/v1/bank/wallet/Wallet creation
POST /api/v1/bank/wallet/charge/Charge creation
POST /api/v1/bank/wallet/charge/refund/Refund
POST /api/v1/bank/wallet/charge/capture/Capture
POST /api/v1/bank/wallet/charge/cancel/Cancellation

GET, PUT, and DELETE requests are naturally idempotent and do not require the header.

Duplicate Request Behavior

ScenarioResult
Same key + same payloadReturns original response
Same key + different payloadHTTP 409 Conflict
Same key after expiration (24h)Treated as a new request
No key providedEach request creates a new resource

Key Expiration

Idempotency keys expire after 24 hours. After expiration, the same key can be reused for a new request. Design your retry strategy to complete well within this window.

Code Examples

# Generate an idempotency key ONCE for this operation
IDEMPOTENCY_KEY=$(uuidgen)

# First attempt
curl -s -X POST "https://sandbox.api.a55.tech/api/v1/bank/wallet/charge/" \
-H "Authorization: Bearer ${A55_ACCESS_TOKEN}" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: ${IDEMPOTENCY_KEY}" \
-d '{
"amount": "100.00",
"currency": "BRL",
"type_charge": "credit_card",
"card": { "number": "4111111111111111", "holder_name": "TEST", "expiration_month": "12", "expiration_year": "2030", "cvv": "123" },
"payer": { "name": "Test", "email": "test@example.com", "document": "12345678909", "document_type": "CPF" }
}'

# Retry with SAME key — returns the same response, no duplicate charge
curl -s -X POST "https://sandbox.api.a55.tech/api/v1/bank/wallet/charge/" \
-H "Authorization: Bearer ${A55_ACCESS_TOKEN}" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: ${IDEMPOTENCY_KEY}" \
-d '{
"amount": "100.00",
"currency": "BRL",
"type_charge": "credit_card",
"card": { "number": "4111111111111111", "holder_name": "TEST", "expiration_month": "12", "expiration_year": "2030", "cvv": "123" },
"payer": { "name": "Test", "email": "test@example.com", "document": "12345678909", "document_type": "CPF" }
}'
Never generate a new key per retry

The idempotency key must be generated once per business operation. If you generate a new key for each retry attempt, you lose duplicate protection entirely.