Skip to content
API DocsDocs

APM Payment Flows

Redirect, QR code, and server-to-server flows for alternative payment methods

4 min readUpdated Mar 24, 2026

When you initiate an APM payment, the response includes an apmResponseData.actionType field that determines what happens next. There are three flow types — Redirect, QR Code, and Server-to-Server (S2S) — each requiring different handling on your side.

All three flows share the same API endpoint and the same webhook-based final result. The difference is what happens between the initial response and the final webhook.

The webhook callback is always the source of truth for the final transaction result. Never rely on redirects, QR scanning confirmation, or the initial response status to determine payment outcome.


#Quick Reference

actionTypeCustomer ActionYou HandleExample APMs
REDIRECTIONRedirected to provider's pageRedirect or iframePayPal, iDEAL, Skrill, SEPA, Giropay
QRScans QR code with payment appDisplay QR image or deep linkPIX, Alipay, WeChat Pay, UPI, BLIK
NONENone — server-to-serverWait for webhookBank transfers (auto-debit), some voucher methods

#Flow 1: Redirect (actionType = REDIRECTION)

The most common APM flow. The customer is redirected to the payment provider's hosted page to authenticate and authorize the payment.

APM Redirect Flow

  1. You receive transactionStatus: "CUSTOMER_VERIFICATION" with apmResponseData.redirectUrl (and optionally iframeUrl)
  2. Redirect the customer to redirectUrl — or embed iframeUrl on desktop if your UX supports it
  3. The customer authenticates on the provider's page
  4. The provider redirects them back to your successRedirectUrl or failureRedirectUrl
  5. You receive the final result via webhook

#Redirect vs Iframe

OptionBest ForConsideration
redirectUrl (full-page)Mobile and simple integrationsCustomer leaves your site temporarily
iframeUrl (embedded)Desktop checkoutSome providers set X-Frame-Options: DENY — always test in sandbox

If both URLs are returned, use the iframe on desktop and fall back to redirect on mobile or if the iframe fails to load.


#Flow 2: QR Code (actionType = QR)

Used for payment methods where the customer scans a QR code with their mobile payment app (PIX, Alipay, WeChat Pay, UPI, etc.).

APM QR Code Flow

  1. You receive transactionStatus: "CUSTOMER_VERIFICATION" with apmResponseData.qrData (Base64 QR image), qrDeepLink (opens payment app directly), and/or qrCodeImageUrl (pre-hosted image URL)
  2. On desktop: display the QR code image for the customer to scan with their phone
  3. On mobile: use the deep link to open the payment app directly
  4. The customer's browser stays on your page while they pay on their phone — you must update the UI when the payment completes
  5. You receive the final result via webhook; push the result to the frontend via your preferred mechanism (WebSocket, SSE, or polling your own backend)

#QR Expiration

QR codes typically expire within 1–5 minutes (varies by provider). Your UI should show a countdown and offer a refresh option when expired. Never cache or reuse an expired QR.


#Flow 3: Server-to-Server (actionType = NONE)

Some APMs process entirely server-side with no customer interaction after the initial request. Common for pre-authorized bank transfers, certain voucher payments, and repeat APM transactions.

APM S2S Flow

The response may be immediately final (SUCCEED or FAILED) or async (PROCESSING / PENDING). In the async case, wait for the webhook — do not poll more frequently than every 5 minutes as a fallback.


#Handling the Response (All Flows)

APM Response Handling


#Common Patterns

PatternRecommendation
Customer closes browser mid-redirectWebhook still arrives — always honor it
QR code expires before scanningShow "Refresh QR" button, retry with new request
S2S payment stuck in PROCESSINGWait for webhook; poll status after 5 min as fallback
Provider returns both redirectUrl and iframeUrlUse iframe on desktop, redirect on mobile
Multiple webhooks for same transactionIdempotent handler — process only the first terminal status
Redirect URL says success but webhook says FAILEDTrust the webhook.

Was this helpful?