Test Cards
Quick Reference
Why test cards matter
| Without systematic testing | With A55 test cards |
|---|---|
| You discover declines in production, from real customers | You simulate every outcome in sandbox before go-live |
| Edge cases (timeout, expired card, blocked card) are untested | One digit change exercises any scenario |
| QA takes days of manual card swiping | Batch-test 9 scenarios in a single script run |
| You don't know how your UI handles failures | You see exactly what your error screens look like |
How the simulator works
In sandbox, only the last digit of the card number controls the transaction outcome. The first 15 digits can be anything.
Rules:
- Use any plausible 16-digit card number — only the last digit matters.
- CVV: any 3 digits (e.g.,
123). - Expiry: any future date in
MM/YYYY(e.g.,12/2030).
Last-digit outcomes
| Last digit | Status | Return code | Message | Use case |
|---|---|---|---|---|
| 0, 1, 4 | Authorized | 4 or 6 | Operation completed successfully | Happy path — test successful payments |
| 2 | Not authorized | 05 | Not authorized | Generic decline — test error handling |
| 3 | Not authorized | 57 | Expired card | Test expired-card UX |
| 5 | Not authorized | 78 | Blocked card | Test blocked/fraud-flagged card |
| 6 | Not authorized | 99 | Timeout | Test timeout handling and retries |
| 7 | Not authorized | 77 | Canceled card | Test canceled-card UX |
| 8 | Not authorized | 70 | Credit card problems | Test generic card error |
| 9 | Random | 4–99 | Success or timeout (random) | Chaos testing — verify resilience |
Use these ready-made numbers — change only the last digit:
| Scenario | Card number |
|---|---|
| Confirmed | 4024 0071 5376 3191 |
| Declined | 4024 0071 5376 3192 |
| Expired | 4024 0071 5376 3193 |
| Blocked | 4024 0071 5376 3195 |
| Timeout | 4024 0071 5376 3196 |
Step-by-step: test each scenario
1. Test a successful payment
- cURL
- Python
- JavaScript
curl -s -X POST https://sandbox.api.a55.tech/api/v1/bank/wallet/charge/ \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"wallet_uuid": "YOUR_WALLET_UUID",
"merchant_id": "YOUR_MERCHANT_UUID",
"payer_name": "Test User",
"payer_email": "test@example.com",
"payer_tax_id": "12345678909",
"payer_cell_phone": "+5511999999999",
"installment_count": 1,
"installment_value": 100.00,
"currency": "BRL",
"due_date": "2026-12-31",
"description": "Sandbox test — confirmed",
"type_charge": "credit_card",
"card_name": "TEST USER",
"card_number": "4024007153763191",
"card_expiry_month": "12",
"card_expiry_year": "2030",
"card_cvv": "123"
}'
import requests
API_BASE = "https://sandbox.api.a55.tech/api/v1"
def create_test_charge(token: str, card_number: str, description: str):
headers = {
"Authorization": f"Bearer {token}",
"Content-Type": "application/json",
}
payload = {
"wallet_uuid": "YOUR_WALLET_UUID",
"merchant_id": "YOUR_MERCHANT_UUID",
"payer_name": "Test User",
"payer_email": "test@example.com",
"payer_tax_id": "12345678909",
"payer_cell_phone": "+5511999999999",
"installment_count": 1,
"installment_value": 100.00,
"currency": "BRL",
"due_date": "2026-12-31",
"description": description,
"type_charge": "credit_card",
"card_name": "TEST USER",
"card_number": card_number,
"card_expiry_month": "12",
"card_expiry_year": "2030",
"card_cvv": "123",
}
resp = requests.post(f"{API_BASE}/bank/wallet/charge/", json=payload, headers=headers)
return resp.json()
result = create_test_charge(token, "4024007153763191", "Sandbox test — confirmed")
print(f"Status: {result['status']}")
const API_BASE = "https://sandbox.api.a55.tech/api/v1";
async function createTestCharge(token, cardNumber, description) {
const resp = await fetch(`${API_BASE}/bank/wallet/charge/`, {
method: "POST",
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
wallet_uuid: "YOUR_WALLET_UUID",
merchant_id: "YOUR_MERCHANT_UUID",
payer_name: "Test User",
payer_email: "test@example.com",
payer_tax_id: "12345678909",
payer_cell_phone: "+5511999999999",
installment_count: 1,
installment_value: 100.0,
currency: "BRL",
due_date: "2026-12-31",
description,
type_charge: "credit_card",
card_name: "TEST USER",
card_number: cardNumber,
card_expiry_month: "12",
card_expiry_year: "2030",
card_cvv: "123",
}),
});
return resp.json();
}
const result = await createTestCharge(token, "4024007153763191", "Sandbox test — confirmed");
console.log(`Status: ${result.status}`);
2. Test a declined payment
Change only the last digit to 2:
Card: 4024007153763192 → Return code 05 (Not authorized)
Your application should show an appropriate error message and let the user retry with a different card.
3. Test a timeout
Change the last digit to 6:
Card: 4024007153763196 → Return code 99 (Timeout)
Your application should implement retry logic with exponential backoff and display a "please wait" state.
Batch-test all scenarios
Run all 9 scenarios in a single script to validate your error handling.
- Python
- JavaScript
scenarios = [
("4024007153763190", "Confirmed (0)"),
("4024007153763191", "Confirmed (1)"),
("4024007153763192", "Declined (2)"),
("4024007153763193", "Expired card (3)"),
("4024007153763194", "Confirmed (4)"),
("4024007153763195", "Blocked card (5)"),
("4024007153763196", "Timeout (6)"),
("4024007153763197", "Canceled card (7)"),
("4024007153763198", "Card problems (8)"),
("4024007153763199", "Random (9)"),
]
for card_number, label in scenarios:
result = create_test_charge(token, card_number, f"Batch test — {label}")
print(f"{label:25s} → status={result.get('status', 'N/A'):15s} code={result.get('return_code', 'N/A')}")
const scenarios = [
["4024007153763190", "Confirmed (0)"],
["4024007153763191", "Confirmed (1)"],
["4024007153763192", "Declined (2)"],
["4024007153763193", "Expired card (3)"],
["4024007153763194", "Confirmed (4)"],
["4024007153763195", "Blocked card (5)"],
["4024007153763196", "Timeout (6)"],
["4024007153763197", "Canceled card (7)"],
["4024007153763198", "Card problems (8)"],
["4024007153763199", "Random (9)"],
];
for (const [cardNumber, label] of scenarios) {
const result = await createTestCharge(token, cardNumber, `Batch test — ${label}`);
console.log(`${label.padEnd(25)} → status=${(result.status || "N/A").padEnd(15)} code=${result.return_code || "N/A"}`);
}
Zero Auth in sandbox
The zero-auth endpoint (POST /api/v1/bank/wallet/zeroauth/) uses the same last-digit simulator as charges. Dedicated 3DS test cards take precedence when the card number matches exactly.
Prerequisite: zeroauth_enabled must be true on the merchant configuration. Contact your account manager to enable it.
| Last digit | is_valid | Typical code | Use case |
|---|---|---|---|
| 0, 1, 4 | true | 00, 4, or 6 | Card passes validation |
| 2 | false | 05 | Generic decline |
| 3 | false | 57 | Expired / not permitted |
| 5 | false | 78 | Blocked card |
| 6 | false | 99 | Timeout / issuer unavailable |
| 7 | false | 77 | Canceled card |
| 8 | false | 70 | Insufficient funds / card problems |
| 9 | Random | 4 or 99 | Chaos testing |
The endpoint always returns HTTP 200 — inspect is_valid and code in the response body.
# Decline — last digit 2
curl -s -X POST https://sandbox.api.a55.tech/api/v1/bank/wallet/zeroauth/ \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"wallet_uuid": "YOUR_WALLET_UUID",
"holder_name": "TEST USER",
"card_number": "4024007153763192",
"expiry_month": "12",
"expiry_year": "2030",
"cvv": "123",
"brand": "visa"
}'
Expected: { "is_valid": false, "code": "05", ... }
Tokenization in sandbox
The tokenization endpoint (POST /api/v1/bank/wallet/tokenization/) follows the same last-digit simulator. Failures return HTTP 400 with card_tokenization_failed.
Prerequisite: tokenization_enabled must be true on the merchant configuration.
| Last digit | Outcome | HTTP | Use case |
|---|---|---|---|
| 0, 1, 4 | Success — returns token_uuid | 200 | Happy path |
| 2, 5, 7, 8 | declined | 400 | Card rejected for enrollment |
| 3 | not_eligible | 400 | Card not eligible (e.g. expired) |
| 6 | retryable_error | 400 | Timeout — retry with backoff |
| 9 | Random success or timeout | 200 or 400 | Chaos testing |
Use 4024007153763191 in card.number for a successful tokenization. See Tokenize card for the full request shape.
Recommended sandbox flow
Test the full validate → store → charge sequence:
Repeat with ...3192 at each step to verify your error handling for declines.
Important limitations
- Sandbox return codes and messages are simulated. Production responses come from real issuers and networks — codes and messages will differ.
- Never use real card numbers in sandbox. The simulator overrides outcomes based on the last digit regardless of PAN validity.
- If your gateway requires a specific card format (e.g., BIN prefix), keep the last digit per the table above and adjust other digits to satisfy the gateway.
The simulator supports authorization, capture (full and partial), cancellation, status checks, zero-auth, and tokenization. All follow the same last-digit rules (3DS test cards take precedence when matched).