Skip to main content

Performance and Best Practices

Quick Reference

WhatPerformance optimization
WhyBuild reliable, high-throughput integrations with proper retry and idempotency
DifficultyIntermediate
PrerequisitesAuthentication → Create charge

Reliable integrations depend on idempotent requests, smart retries, and cached authentication. This guide covers every technique you need for production-grade throughput.

Rate limits​

TierLimitScope
Standard100 requests / minutePer API key
Burst20 requests / secondPer API key
CustomNegotiatedEnterprise accounts
Rate limit backoff

If you receive 429 Too Many Requests, back off and retry. Never retry in a tight loop — this extends the rate-limit window and can trigger a temporary block.

Timeouts​

Set client-side timeouts per operation to avoid hanging connections:

OperationRecommended timeoutNotes
Auth token10 sToken endpoint is lightweight
Create charge60 sIncludes acquirer round-trip and 3DS
3DS authentication30 sWaiting for issuer challenge
Zero auth15 sPre-authorization only
GET / list endpoints10 sRead operations

Retry strategy​

Exponential backoff​

import time, requests

def charge_with_retry(payload, token, max_retries=4):
for attempt in range(max_retries):
resp = requests.post("https://sandbox.api.a55.tech/api/v1/bank/charge/",
headers={"Authorization": f"Bearer {token}"}, json=payload, timeout=60)
if resp.status_code < 500:
return resp
time.sleep(min(2 ** attempt, 30))
return resp

Idempotency keys​

Prevent duplicate charges by sending an Idempotency-Key header:

curl -X POST https://sandbox.api.a55.tech/api/v1/bank/charge/ \
-H "Authorization: Bearer $TOKEN" \
-H "Idempotency-Key: order_12345_attempt_1" \
-H "Content-Type: application/json" \
-d '{"amount":15000,"currency":"BRL","card_token":"tok_a55_7f3c2d1e"}'
ScenarioBehavior
Same key + same bodyReturns the original response (no new charge)
Same key + different bodyReturns 409 Conflict
No keyCreates a new charge every time
Idempotency key format

Use a deterministic format for idempotency keys: {order_id}_{attempt} or a UUID v4. Keys expire after 24 hours.

Authentication performance​

Cache your access token and refresh it only when it expires:

import time, requests

class TokenCache:
def __init__(self, client_id, client_secret):
self._id, self._secret = client_id, client_secret
self._token, self._expires = None, 0

def get_token(self):
if time.time() < self._expires - 60:
return self._token
resp = requests.post("https://sandbox.api.a55.tech/api/v1/o/token/",
data={"grant_type": "client_credentials",
"client_id": self._id, "client_secret": self._secret}).json()
self._token = resp["access_token"]
self._expires = time.time() + resp["expires_in"]
return self._token

Optimization stack​

LayerTechniqueImpact
AuthenticationToken caching with TTL bufferEliminates redundant auth calls
CredentialsStore tokens, not raw PANsFaster charges, no sensitive data on your servers
DevicePersistent device fingerprintBetter fraud scoring, fewer declines
ReliabilityIdempotency keys + exponential backoffZero duplicate charges
EfficiencyConnection pooling and keep-aliveLower latency per request
Never log secrets

Never log full card numbers, CVVs, or access tokens. Use masked PANs (**** 1111) and token references in your application logs.

Everything on this page — caching, retries, idempotency — makes your integration reliable. But the single biggest lever for approval rates is Visa Data Only: sharing enriched transaction data with issuers through 3DS rails without any challenge.

Square's pilot showed up to +646 basis points improvement. Combined with the performance techniques above, Data Only gives you both reliability and revenue.

Learn how to activate Data Only →