v1.0

Operations#

Running a live integration: callback delivery and verification, status queries, chargebacks, settlement and reconciliation, testing and go-live.

Settlement#

Settlement Cycle

CentaPay settles to clients on a T+1 (next business day) cycle. Transactions that reach SETTLED status before the daily cutoff are included in the next business day's settlement batch.

ParameterValue
CycleT+1 (next business day)
Settlement currencyAgreed at onboarding (typically USD)

Transaction Status Lifecycle

How a transaction moves through the system toward settlement:

StatusMeaning
PENDINGAUTH hold placed — funds reserved on cardholder's account but not yet captured
PREPAREProcessing in progress — final status not yet determined
3DSAwaiting cardholder 3DS authentication
REDIRECTAwaiting redirect completion
SETTLEDTransaction completed successfully. Funds will be included in the next settlement batch to you.
DECLINEDTransaction rejected by issuer or risk engine
VOIDSame-day cancellation — no funds movement
REFUNDFull refund processed — amount deducted from your settlement balance
REVERSALAUTH hold released (no capture occurred)
CHARGEBACKIssuer-initiated dispute — amount debited from your settlement balance
ℹ️
After partial refund: The original transaction retains SETTLED status. The partial refund amount is deducted from your settlement balance. Use GET_TRANS_DETAILS to see the full transaction history including partial refund entries.

FX & Currency Conversion

When the transaction currency differs from your settlement currency, CentaPay applies a foreign exchange conversion. The applicable rate is included in callback parameters:

Callback FieldDescription
exchange_rateFX rate applied to the transaction
exchange_rate_baseBase conversion rate (if double conversion applies)
exchange_currencyOriginal transaction currency
exchange_amountOriginal transaction amount before conversion

Settlement Reports

Settlement reports are available via the admin panel and include transaction-level detail for reconciliation against your callback records. Contact [email protected] for details on report format, delivery schedule, and available export options for your account.

Querying Settlement Status

Use GET_TRANS_STATUS or GET_TRANS_DETAILS to check whether a transaction has settled.

GET_TRANS_STATUS returns the current status field. A value of SETTLED confirms the transaction completed successfully and will be included in settlement.

GET_TRANS_DETAILS returns the full order history including an array of all sub-transactions (sale, 3ds, auth, capture, credit, chargeback, reversal, refund) with individual dates, statuses, and amounts.

ℹ️
Best practice: Do not poll GET_TRANS_STATUS for settlement confirmation. Use callbacks as the authoritative source. Reserve status queries for reconciliation or when a callback has not arrived within your expected window.

Settlement & Reporting#

PSP clients receive a single aggregated settlement per cycle covering all sub-merchant transactions.

ParameterValue
CycleT+1 (next business day)
Settlement currencyAgreed at onboarding (typically USD)
ScopeAll sub-merchants under your account, aggregated

Each transaction callback includes order_id (your reference), trans_id (CentaPay reference), and channel_id (if provided) for sub-merchant-level reconciliation.

Use GET_TRANS_DETAILS to retrieve the full history of any transaction, including payer details, masked card, and all status transitions.

ℹ️
Tip: Enable Extended Data in your admin panel (Configuration → Protocol Mappings → "Add Extended Data to Callback") to receive rrn, approval_code, connector_name, and other acquirer-level fields in callbacks — useful for cross-referencing with upstream acquirer reports.

For details on sub-merchant settlement breakdowns and report formats, contact [email protected].

Transaction Status (GET_TRANS_STATUS)#

Query the current status of a transaction. Use when a callback hasn't arrived or for reconciliation.

ParameterDescriptionRequired
actionGET_TRANS_STATUSYes
client_keyYour account keyYes
trans_idCentaPay transaction IDYes
hashFormula 2 (or Formula 6 for CREDIT2CARD)Yes

Response includes status (one of: 3DS, REDIRECT, PENDING, PREPARE, DECLINED, SETTLED, REVERSAL, REFUND, VOID, CHARGEBACK), plus decline_reason if declined, and recurring_token / schedule_id / digital_wallet if applicable, arn* if configured.

ℹ️
SETTLED is the terminal success status — the transaction has been authorised and captured, and will be included in the next settlement batch to you. For the full settlement lifecycle and status definitions, see Settlement.

Transaction Details (GET_TRANS_DETAILS)#

Returns full order history including payer details, card mask, and an array of all transactions in the order.

ParameterDescriptionRequired
actionGET_TRANS_DETAILSYes
client_keyYour account keyYes
trans_idCentaPay transaction IDYes
hashFormula 2 (or Formula 6 for CREDIT2CARD)Yes

Response includes: name, mail, ip, amount, currency, card (masked), decline_reason if declined, recurring_token, schedule_id, pan_type, digital_wallet, arn* if configured, and a transactions array with entries containing date, type (sale, 3ds, auth, capture, credit, chargeback, reversal, refund), status, and amount.

Status by Order ID (GET_TRANS_STATUS_BY_ORDER)#

Look up the most recent transaction status using your order_id instead of trans_id. Useful when trans_id is lost or for reconciliation.

ParameterDescriptionRequired
actionGET_TRANS_STATUS_BY_ORDERYes
client_keyYour account keyYes
order_idYour order IDYes
hashFormula 7 (or Formula 6 for CREDIT2CARD)Yes

Response: status (3DS/REDIRECT/PENDING/PREPARE/DECLINED/SETTLED/REVERSAL/REFUND/VOID/CHARGEBACK), decline_reason if declined, recurring_token, schedule_id, digital_wallet if applicable. With cascading enabled, returns most recent transaction only.

Chargebacks#

Chargebacks are initiated by the issuing bank, not by API request. CentaPay sends a callback notification when a chargeback occurs.

Callback ParameterDescription
actionCHARGEBACK
resultSUCCESS
statusCHARGEBACK
order_idYour order ID
trans_idCentaPay transaction ID
amountChargeback amount
chargeback_dateSystem date of the chargeback
bank_dateBank date of the chargeback
reason_codeChargeback reason code
connector_name*Payment gateway name
rrn*Retrieval Reference Number
approval_code*Issuer authorisation code
gateway_id* / extra_gateway_id*Gateway transaction identifiers
merchant_name* / mid_name*Merchant and MID names
issuer_country* / issuer_bank*Card issuer details
hashFormula 2

* Extended data fields - included only if configured in admin panel (Configuration → Protocol Mappings → "Add Extended Data to Callback").

Callback Delivery Rules#

CentaPay sends HTTP POST callbacks to your notification URL as transaction states change. Always use callbacks — not the synchronous response — as the authoritative result.

Client Server CentaPay Platform Payer Browser Flow A — No 3DS POST /post sync response (SUCCESS / DECLINED / UNDEFINED) — later — callback POST to client callback URL client responds 200 OK Flow B — 3DS POST /post sync REDIRECT (redirect_url) client redirects payer browser payer completes 3DS at ACS payer returns to term_url_3ds callback POST with final result Callback delivery: response 200 with body OK required. Retry: up to 5 attempts, then blocked 5 min, then 15 min. The callback, not the sync response, is the authoritative outcome.

Content Type

Callbacks are sent as application/x-www-form-urlencoded.

Required Response

Your endpoint must return the plain string OK — nothing else. Any other content, HTML, or timeout is treated as a failure.

⚠️
Blocking: 5 consecutive timeouts within 5 minutes will block your callback URL for 15 minutes. All merchants sharing that URL are affected. The counter resets on any successful response. You can manually unblock via the admin panel (Configuration → Merchants → Edit Merchant).

When Callbacks Are Sent

Transaction TypeCallback Sent On
SALE, CREDITVOID, RECURRING_SALESUCCESS, FAIL, WAITING, UNDEFINED
CAPTURE, VOID, CREDIT2CARDSUCCESS, FAIL, UNDEFINED
CHARGEBACKAlways (platform-initiated)

Hash Verification#

Always verify the callback hash before processing. For most actions, use Formula 2. For CREDIT2CARD, use Formula 6. For VOID callbacks, use the Void signature: md5(strtoupper(strrev(trans_id)) . PASSWORD).

⚠️
Formula 2 requires data not in the callback. The payer's email is not included in callback parameters. You must store it from the original SALE request. For SUCCESS callbacks, the card field provides the masked PAN (first 6 + last 4 visible). For DECLINED callbacks, card is not present — use the card mask stored from your original request.
$data = $_POST;
// Use card from callback if present (SUCCESS), otherwise use stored mask (DECLINED)
$cardMask = isset($data['card']) ? $data['card'] : $storedCardMask;
$cardPart = substr($cardMask,0,6).substr($cardMask,-4);
$expected = md5(strtoupper(
  strrev($storedEmail) . PASSWORD . $data['trans_id'] . strrev($cardPart)
));
if (!hash_equals($expected, $data['hash'])) {
    http_response_code(400);
    exit('ERROR');
}
// Process based on result
if ($data['result'] === 'SUCCESS') {
    fulfillOrder($data['order_id'], $data['trans_id']);
}
echo 'OK';
import hashlib, hmac
data = request.form.to_dict()
# Use card from callback if present (SUCCESS), otherwise use stored mask (DECLINED)
card_mask = data.get('card', stored_card_mask)
card_part = card_mask[:6] + card_mask[-4:]
raw = stored_email[::-1] + PASSWORD + data['trans_id'] + card_part[::-1]
expected = hashlib.md5(raw.upper().encode()).hexdigest()
if not hmac.compare_digest(expected, data.get('hash','')):
    return 'ERROR', 400
if data['result'] == 'SUCCESS':
    fulfill_order(data['order_id'])
return 'OK'
const rev = s => s.split('').reverse().join('');
app.post('/webhook', express.urlencoded({extended:false}), (req,res) => {
  const d = req.body;
  // Use card from callback if present (SUCCESS), otherwise use stored mask (DECLINED)
  const cardMask = d.card || storedCardMask;
  const cp = cardMask.slice(0,6) + cardMask.slice(-4);
  const raw = rev(storedEmail) + PASSWORD + d.trans_id + rev(cp);
  const exp = crypto.createHash('md5').update(raw.toUpperCase()).digest('hex');
  if (!crypto.timingSafeEqual(Buffer.from(exp), Buffer.from(d.hash||'')))
    return res.status(400).send('ERROR');
  if (d.result === 'SUCCESS') fulfillOrder(d.order_id);
  res.send('OK');
});

Cascading Behaviour#

When cascading is enabled (auto-retry across MIDs on decline):

Extended Callback Data#

Additional fields if configured in admin panel (Configuration → Protocol Mappings → "Add Extended Data to Callback"): connector_name, rrn, approval_code, gateway_id / extra_gateway_id, merchant_name / mid_name, issuer_country / issuer_bank, brand, arn, extended_data.

Test Cards#

Use these test values in the sandbox environment. All transactions are processed by the test engine — no real funds are moved. Use any 3-digit CVV.

S2S CARD — Scenario Simulation

All scenarios use card number 4111111111111111. The expiry date determines the outcome:

ExpiryScenarioResponse
01/2038 Successful SALE (also use for recurring init — only card that returns recurring_token) result: SUCCESS, status: SETTLED
AUTH: status: PENDING
02/2038 Declined SALE / AUTH result: DECLINED, status: DECLINED
03/2038 Successful AUTH, then declined CAPTURE AUTH: SUCCESS/PENDING
CAPTURE: DECLINED/PENDING
05/2038 3DS verification → Success SALE: REDIRECT/3DS → After ACS: SUCCESS/SETTLED
06/2038 3DS verification → Decline SALE: REDIRECT/3DS → After ACS: DECLINED
12/2038 Redirect → Success SALE: REDIRECT/REDIRECT → Return: SUCCESS/SETTLED
12/2039 Redirect → Decline SALE: REDIRECT/REDIRECT → Return: DECLINED

CREDIT2CARD Test Card

Card NumberScenarioResponse
4601541833776519 Successful card payout result: SUCCESS, status: SETTLED
⚠️
Recurring token generation only works with 4111111111111111 expiry 01/2038. Other test cards will process the SALE but will not return a recurring_token.

Go-Live Checklist#

Complete these items before requesting production credentials.

Technical

ItemDetail
✅ SALE tested — successCard 4111111111111111 exp 01/2038 returns SUCCESS/SETTLED
✅ SALE tested — declineExp 02/2038 returns DECLINED
✅ 3DS redirect handledExp 05/2038 → redirect → return → SUCCESS. Exp 06/2038 → DECLINED
✅ Callback handler implementedEndpoint returns plain OK. Hash verified using Formula 2. Tested with all result types.
✅ CREDITVOID testedFull and partial refunds work correctly
✅ VOID tested (if used)Same-day cancellation on SETTLED transaction
✅ GET_TRANS_STATUS testedStatus polling works as fallback when callback delayed
✅ Error handling implementedAll error codes handled gracefully. User sees meaningful messages.
✅ Idempotent order IDsEach payment attempt uses a unique order_id. Duplicates handled.
✅ IP addresses providedProduction server IPs sent to CentaPay for whitelisting
✅ Callback URL configuredProduction callback URL registered with CentaPay
✅ HTTPS everywhereAll endpoints use TLS. No plain HTTP.

If Using Recurring

ItemDetail
✅ RECURRING_SALE testedInitial SALE with recurring_init=Y, then RECURRING_SALE with token
✅ RETRY testedSoft decline → RETRY → final result via callback
✅ Schedule ops tested (if used)CREATE, PAUSE, RUN, DELETE, SCHEDULE_INFO, DESCHEDULE

If Using Payouts

ItemDetail
✅ CREDIT2CARD testedTest card 4601541833776519 returns SUCCESS
✅ Formula 5 hash verifiedRequest hash uses Formula 5 (not Formula 1)
✅ Formula 6 callback hashCallback verification uses Formula 6 (not Formula 2)

If Using Digital Wallets

ItemDetail
✅ Apple Pay: Merchant ID configuredCertificates and keys uploaded to admin panel
✅ Apple Pay: Domains verifiedAll payment domains registered in Apple Developer
✅ Google Pay: Integration checklistCompleted per Google's requirements
✅ Google Pay: Domains verifiedVerified in Google Business Console
✅ Formula 8 hash usedWallet SALE uses email + PASSWORD only

Compliance

ItemDetail
✅ PCI DSS evidenceSAQ D or full assessment (for raw card S2S). Reduced scope for wallet-only.
✅ KYB completeBusiness verification documents submitted and approved
✅ Prohibited MCCs reviewedBusiness model confirmed against prohibited categories
✅ Client agreement signedExecuted with CentaPay

Commercial

ItemDetail
✅ Production credentials receivedSeparate CLIENT_KEY, PASSWORD, PAYMENT_URL for production
✅ Settlement currency confirmedUSD or preferred currency agreed with CentaPay
✅ MID configuredProduction MID mapped to your account by CentaPay ops

Contact [email protected] when all items are complete to begin the go-live process.