Skip to main content

Common Integration Mistakes

Quick Reference

WhatTop 15 integration mistakes and their fixes
WhySave hours of debugging by learning from other integrators' mistakes
Reading Time12 min
DifficultyIntermediate

1. Using production credentials in sandbox

Symptom: 401 Unauthorized on every request to sandbox.api.a55.tech.

Fix: Sandbox and production use separate Cognito pools. Use sandbox client_id/client_secret with the sandbox auth URL, and production credentials with the production auth URL.


2. Not handling 3DS redirect

Symptom: Charges with 3DS-enrolled cards stay in awaiting_3ds forever.

Fix: When the charge response includes a redirect_url, redirect the cardholder to that URL. After authentication, the user returns to your callback_url and you must poll the charge status.


3. Hardcoding API tokens

Symptom: Tokens expire after 1 hour, and every request fails with 401.

Fix: Never hardcode tokens. Implement a token manager that calls the OAuth2 endpoint before expiry:

import time

class TokenManager:
def __init__(self):
self._token = None
self._expires_at = 0

def get_token(self):
if time.time() > self._expires_at - 60:
self._refresh()
return self._token

def _refresh(self):
# Call OAuth2 token endpoint
self._token = response["access_token"]
self._expires_at = time.time() + response["expires_in"]

4. Not verifying webhook signatures

Symptom: Your system processes forged webhook payloads, leading to incorrect order status updates.

Fix: Always verify the HMAC-SHA256 signature before processing:

import hmac
import hashlib

def verify_webhook(payload: bytes, signature: str, secret: str) -> bool:
expected = hmac.new(secret.encode(), payload, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, signature)

5. Missing idempotency keys on retries

Symptom: Customer is charged twice because a timeout triggered a retry without the same Idempotency-Key.

Fix: Generate a UUID v4 once per business operation and send it on every attempt:

import uuid

idempotency_key = str(uuid.uuid4()) # Generate ONCE
# Use the same key on retries
headers = {"Idempotency-Key": idempotency_key}

6. Wrong amount format

Symptom: 422 Unprocessable Entity with validation error on amount.

Fix: Amount format depends on the currency's decimal places:

CurrencyDecimalsCorrectWrong
BRL, MXN, USD, EUR, PEN, ARS2150.00150, "150", 150.0
CLP, COP05000050000.00, 50000.50
Zero-decimal currencies (CLP, COP)

Chilean Peso and Colombian Peso have no fractional units. The backend rounds amounts to integers for these currencies. Sending 50000.50 for CLP results in 50000. Always send whole numbers for CLP and COP to avoid unexpected truncation.


7. Missing required payer fields

Symptom: 422 error listing missing fields like payer.document or payer.email.

Fix: Every charge requires at minimum:

{
"payer": {
"name": "Customer Name",
"email": "customer@example.com",
"document": "12345678909",
"document_type": "CPF"
}
}

Document requirements vary by country (CPF for Brazil, RFC for Mexico).


8. Not implementing retry with exponential backoff

Symptom: Your system hammers the API after a 500 error, gets rate-limited, and makes the outage worse.

Fix: Implement exponential backoff with jitter:

import time
import random

for attempt in range(4):
response = make_request()
if response.status_code < 500:
break
delay = (2 ** attempt) + random.uniform(0, 1)
time.sleep(delay)

9. Ignoring rate limits

Symptom: Sudden 429 Too Many Requests responses during peak traffic.

Fix: Read rate limit headers (X-RateLimit-Remaining, X-RateLimit-Reset) and throttle proactively. See the rate limiting guide.


10. Not checking charge status after creation

Symptom: Order marked as paid immediately after charge creation, but the charge was actually pending or declined.

Fix: After creating a charge, check the status field in the response. For async methods (PIX, Boleto), set up webhooks to receive status updates — do not assume the charge is confirmed.


11. Missing webhook_url in charge creation

Symptom: No webhook notifications arrive, even though your endpoint works.

Fix: Include webhook_url in the charge creation request body, or configure a default webhook URL in your merchant settings.


12. Wrong currency for country

Symptom: 422 error or unexpected conversion fees.

Fix: Use the correct currency for each country. Pay special attention to zero-decimal currencies:

CountryCurrencyDecimalsDocument typeExample amount
BrazilBRL2CPF / CNPJ150.00
MexicoMXN2RFC / CURP2500.00
ChileCLP0RUT50000
ColombiaCOP0CC (Cédula)200000
PeruPEN2DNI350.00
ArgentinaARS2DNI / CUIT85000.00

13. Not handling partial captures correctly

Symptom: Authorized amount is fully captured when only a partial shipment was made.

Fix: When capturing less than the authorized amount, explicitly set the capture amount:

{
"amount": "75.00"
}

The remaining authorized amount is automatically released.


14. Missing error handling in code

Symptom: Unhandled exceptions crash your application when the API returns unexpected responses.

Fix: Wrap every API call in try/catch and handle all possible HTTP status codes. Log the request_id for every failed request.


15. Not testing all card decline scenarios

Symptom: Application crashes or shows generic error when a card is declined.

Fix: Test with all decline test cards and verify your UI shows appropriate messages:

Test CardScenario
4000 0000 0000 0002Card declined
4000 0000 0000 0069Processing error
4000 0000 0000 0119Insufficient funds