Host-to-Host Integration
Quick Reference
Host-to-Host (H2H) is direct API integration: your backend calls A55 with card and order data. You retain full control over retries, idempotency, and error handling.
Why H2H (comparison)
| Criterion | H2H | SDK | Checkout Page |
|---|---|---|---|
| Control level | Full | Partial | Minimal |
| Card data handling | You collect, A55 secures | Browser SDK collects, A55 secures | A55-hosted — fully managed |
| 3DS management | You handle redirect | SDK handles | A55 handles |
| Security | A55 encrypts and tokenizes | A55 handles in browser | A55 manages end-to-end |
| Best for | Teams needing full control | Native checkout experience | Fastest launch |
When to use
- You need to collect card data on your servers before sending it to A55.
- You need maximum server-side control over the charge lifecycle.
- You will implement 3DS redirects when the API returns
pendingandurl_3ds.
Card fields (request body)
| Field | Description |
|---|---|
card_name | Cardholder name as printed on the card |
card_number | Primary Account Number (PAN) |
card_expiry_month | Expiry month (1–12) |
card_expiry_year | Expiry year (four digits) |
card_cvv | Card verification value |
Technical flow
Step-by-step integration
Get an access token
- cURL
- Python
- Node.js
- Go
- Java
- PHP
curl -s -X POST "https://a55-auth.auth.us-east-1.amazoncognito.com/oauth2/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials&client_id=$CLIENT_ID&client_secret=$CLIENT_SECRET"
import os, requests
resp = requests.post(
"https://a55-auth.auth.us-east-1.amazoncognito.com/oauth2/token",
data={"grant_type": "client_credentials",
"client_id": os.environ["CLIENT_ID"],
"client_secret": os.environ["CLIENT_SECRET"]},
headers={"Content-Type": "application/x-www-form-urlencoded"},
)
access_token = resp.json()["access_token"]
const resp = await fetch(
"https://a55-auth.auth.us-east-1.amazoncognito.com/oauth2/token",
{
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: "grant_type=client_credentials"
+ "&client_id=" + process.env.CLIENT_ID
+ "&client_secret=" + process.env.CLIENT_SECRET,
}
);
const { access_token } = await resp.json();
data := url.Values{
"grant_type": {"client_credentials"},
"client_id": {os.Getenv("CLIENT_ID")},
"client_secret": {os.Getenv("CLIENT_SECRET")},
}
resp, _ := http.PostForm(
"https://a55-auth.auth.us-east-1.amazoncognito.com/oauth2/token", data)
defer resp.Body.Close()
var tok struct{ AccessToken string `json:"access_token"` }
json.NewDecoder(resp.Body).Decode(&tok)
HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create("https://a55-auth.auth.us-east-1.amazoncognito.com/oauth2/token"))
.header("Content-Type", "application/x-www-form-urlencoded")
.POST(HttpRequest.BodyPublishers.ofString(
"grant_type=client_credentials&client_id=" + CLIENT_ID
+ "&client_secret=" + CLIENT_SECRET))
.build();
HttpResponse<String> resp = HttpClient.newHttpClient()
.send(req, HttpResponse.BodyHandlers.ofString());
String accessToken = new JSONObject(resp.body()).getString("access_token");
$ch = curl_init("https://a55-auth.auth.us-east-1.amazoncognito.com/oauth2/token");
curl_setopt_array($ch, [
CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ["Content-Type: application/x-www-form-urlencoded"],
CURLOPT_POSTFIELDS => http_build_query([
"grant_type" => "client_credentials",
"client_id" => getenv("CLIENT_ID"),
"client_secret" => getenv("CLIENT_SECRET"),
]),
]);
$token = json_decode(curl_exec($ch))->access_token;
Build and send the charge
POST https://core-manager.a55.tech/api/v1/bank/wallet/charge/
- cURL
- Python
- Node.js
- Go
- Java
- PHP
curl -sS -X POST 'https://core-manager.a55.tech/api/v1/bank/wallet/charge/' \
-H 'Authorization: Bearer $ACCESS_TOKEN' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: ord_001' \
-d '{
"wallet_uuid": "00000000-0000-4000-8000-000000000001",
"merchant_id": "merchant_123",
"payer_name": "Jane Doe",
"payer_email": "jane@example.com",
"payer_cell_phone": "+5511999999999",
"payer_tax_id": "12345678901",
"items": [{"name": "Order", "quantity": 1, "value": 10000}],
"payer_address": {"street": "Av. Paulista 1000", "city": "São Paulo", "state": "SP", "zip_code": "01310100", "country": "BR"},
"currency": "BRL",
"installment_value": 10000,
"installment_count": 1,
"due_date": "2026-12-31",
"description": "H2H charge",
"type_charge": "credit_card",
"card_name": "JANE DOE",
"card_number": "4111111111111111",
"card_expiry_month": 12,
"card_expiry_year": 2030,
"card_cvv": "123",
"reference_external_id": "ord_001",
"threeds_authentication": false,
"webhook_url": "https://merchant.example/webhooks/a55",
"redirect_url": "https://merchant.example/return"
}'
import os, requests
r = requests.post(
"https://core-manager.a55.tech/api/v1/bank/wallet/charge/",
headers={
"Authorization": f"Bearer {os.environ['ACCESS_TOKEN']}",
"Content-Type": "application/json",
},
json={
"wallet_uuid": "00000000-0000-4000-8000-000000000001",
"merchant_id": "merchant_123",
"payer_name": "Jane Doe", "payer_email": "jane@example.com",
"payer_tax_id": "12345678901",
"currency": "BRL", "installment_value": 10000, "installment_count": 1,
"type_charge": "credit_card",
"card_name": "JANE DOE", "card_number": "4111111111111111",
"card_expiry_month": 12, "card_expiry_year": 2030, "card_cvv": "123",
"reference_external_id": "ord_001",
"threeds_authentication": False,
"webhook_url": "https://merchant.example/webhooks/a55",
},
timeout=60,
)
print(r.status_code, r.json())
const res = await fetch(
"https://core-manager.a55.tech/api/v1/bank/wallet/charge/",
{
method: "POST",
headers: {
Authorization: `Bearer ${process.env.ACCESS_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
wallet_uuid: "00000000-0000-4000-8000-000000000001",
merchant_id: "merchant_123",
payer_name: "Jane Doe", payer_email: "jane@example.com",
payer_tax_id: "12345678901",
currency: "BRL", installment_value: 10000, installment_count: 1,
type_charge: "credit_card",
card_name: "JANE DOE", card_number: "4111111111111111",
card_expiry_month: 12, card_expiry_year: 2030, card_cvv: "123",
reference_external_id: "ord_001",
threeds_authentication: false,
webhook_url: "https://merchant.example/webhooks/a55",
}),
}
);
console.log(await res.json());
payload := map[string]interface{}{
"wallet_uuid": "00000000-0000-4000-8000-000000000001",
"type_charge": "credit_card",
"card_name": "JANE DOE", "card_number": "4111111111111111",
"card_expiry_month": 12, "card_expiry_year": 2030, "card_cvv": "123",
"currency": "BRL", "installment_value": 10000, "installment_count": 1,
"reference_external_id": "ord_001",
"threeds_authentication": false,
"webhook_url": "https://merchant.example/webhooks/a55",
}
body, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST",
"https://core-manager.a55.tech/api/v1/bank/wallet/charge/", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer "+os.Getenv("ACCESS_TOKEN"))
req.Header.Set("Content-Type", "application/json")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
io.Copy(os.Stdout, resp.Body)
String json = """
{"wallet_uuid":"00000000-0000-4000-8000-000000000001",
"type_charge":"credit_card","card_name":"JANE DOE",
"card_number":"4111111111111111","card_expiry_month":12,
"card_expiry_year":2030,"card_cvv":"123",
"currency":"BRL","installment_value":10000,"installment_count":1,
"reference_external_id":"ord_001","threeds_authentication":false,
"webhook_url":"https://merchant.example/webhooks/a55"}
""";
HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create("https://core-manager.a55.tech/api/v1/bank/wallet/charge/"))
.header("Authorization", "Bearer " + System.getenv("ACCESS_TOKEN"))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(json)).build();
HttpResponse<String> resp = HttpClient.newHttpClient()
.send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(resp.body());
$payload = [
"wallet_uuid" => "00000000-0000-4000-8000-000000000001",
"type_charge" => "credit_card",
"card_name" => "JANE DOE", "card_number" => "4111111111111111",
"card_expiry_month" => 12, "card_expiry_year" => 2030, "card_cvv" => "123",
"currency" => "BRL", "installment_value" => 10000, "installment_count" => 1,
"reference_external_id" => "ord_001", "threeds_authentication" => false,
"webhook_url" => "https://merchant.example/webhooks/a55",
];
$ch = curl_init("https://core-manager.a55.tech/api/v1/bank/wallet/charge/");
curl_setopt_array($ch, [
CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv("ACCESS_TOKEN"),
"Content-Type: application/json",
"Idempotency-Key: ord_001"],
CURLOPT_POSTFIELDS => json_encode($payload),
]);
echo curl_exec($ch);
Handle the response
- Confirmed
- 3DS pending
- Error
{
"uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"status": "confirmed",
"reference_external_id": "ord_001"
}
{
"uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"status": "pending",
"url_3ds": "https://confirmacion.a55.tech/charge/a1b2c3d4...",
"reference_external_id": "ord_001"
}
Redirect the buyer to url_3ds. See 3D Secure for challenge handling.
{
"uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"status": "error",
"message": [{"message": "Declined or validation failed"}],
"code": "CARD_DECLINED"
}
Handle 3DS redirect (if pending)
If the response includes url_3ds, redirect the buyer, then listen for the completion event:
window.addEventListener('message', function (event) {
if (event.data?.event === '3ds-auth-complete') {
const chargeUuid = event.data.chargeUuid;
// Fetch charge status and update your UI
}
});
Confirm via webhook
Configure webhook_url so you receive async status updates even if the buyer closes the browser.
{
"charge_uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"status": "paid",
"transaction_reference": "txn_ref_001"
}
Test with sandbox cards
| Card Number | Brand | Scenario | Expected Status |
|---|---|---|---|
4111 1111 1111 1111 | Visa | Successful payment | confirmed |
5500 0000 0000 0004 | Mastercard | Successful payment | confirmed |
4000 0000 0000 0002 | Visa | Card declined | declined |
4000 0000 0000 0101 | Visa | 3DS challenge required | confirmed |
4000 0000 0000 0069 | Visa | Processing error | error |
5105 1051 0510 5100 | Mastercard | Insufficient funds | declined |
Want higher approval rates?
Visa Data Only sends enriched transaction data to issuers through 3DS rails — without any challenge redirect. Square's pilot over 6 million transactions showed up to +646 basis points improvement.
If you already send device_info for 3DS, you already have the data. Set data_only: true instead of threeds_authentication: true.
Trade-off: no liability shift (merchant bears fraud). For high-volume, low-risk LATAM transactions, the approval rate gain typically exceeds fraud cost.