Quickstart
One server route, one redirect, one webhook. This walkthrough uses the sandbox key sk_test_demo, which needs no account.
Sandbox behaviour. Amounts ending in 01 authenticate, 02 fail, 03 return unavailable. Everything else is randomised deterministically by authenticationId.
1. Create the session
Server side only. The secret never reaches the browser.
POST /v2/authentications
Authorization: Bearer sk_test_demo
{
"amount": 19901,
"currency": "BRL",
"messageVersion": "2.2.0",
"card": { "brand": "mastercard", "bin": "555555", "last4": "4444" },
"buyer": { "email": "[email protected]", "locale": "pt-BR" },
"notificationUrl": "https://localhost:3000/api/3ds/notify",
"returnUrl": "https://localhost:3000/checkout/return"
}
The response carries challengeUrl. Persist authenticationId on the order before redirecting.
2. Redirect the buyer
res.redirect(302, body.challengeUrl);
The buyer confirms with the issuer on the challenge host. Nothing runs on your page during this step.
3. Receive the notification
The service posts to notificationUrl. Verify before reading:
const expected = crypto
.createHmac('sha256', ENDPOINT_SECRET)
.update(rawBody)
.digest('hex');
if (!crypto.timingSafeEqual(Buffer.from(sig, 'hex'), Buffer.from(expected, 'hex'))) {
return res.sendStatus(401);
}
const { authenticationId, transStatus, eci } = JSON.parse(rawBody);
if (transStatus === 'Y') {
// proceed to authorisation with authenticationId and eci
} else if (transStatus === 'N') {
// decline
} else {
// U or A: route per risk policy
}
4. Answer 200 quickly
Any 2xx marks the notification delivered. Retries run at 10 s, 1 min, 5 min, 30 min and 6 h, then the event is parked and shown in the dashboard. Handle duplicates — delivery is at-least-once, keyed by authenticationId.
5. Check the audit trail
GET /v2/authentications/ath_01J9Z4K2V6/events
Returns the ordered timeline: created, method step, challenge rendered, mode used, attempts, result. This is the same record used in a chargeback reply.
Go live
- Replace the key with
sk_live_…from the dashboard. - Register the production notification URL — sandbox URLs are not accepted in live mode.
- Whitelist the challenge host in your CSP
frame-ancestorsif you embed instead of redirecting. - Run the conformance checklist before opening traffic: version fallback,
Uhandling, signature check, idempotency.
Next: sandbox controls · challenge lifecycle