Wallets

Thirteen wallets, one payload shape. Device wallets (Apple Pay, Google Pay) confirm with a biometric payment sheet; app wallets (PayPal, Alipay, TWINT, …) approve in the wallet's own app. Either way you get the same Payment object, the same webhooks, and the same refund call.

The wallet methods

Walletpayment_methodRegion
Apple Payapple_payGlobal
Google Paygoogle_payGlobal
PayPalpaypalGlobal
AlipayalipayChina / Asia
WeChat Paywechat_payChina / Asia
Cash App PaycashappUS
Kakao Paykakao_paySouth Korea
GrabPaygrabpaySoutheast Asia
GoPaygopayIndonesia
MobilePaymobilepayDenmark / Finland
VippsvippsNorway
TWINTtwintSwitzerland
SatispaysatispayItaly

Regions and currencies for each are in the method catalog. Behind the wallet, the funding source varies — a tokenized card for the device wallets, a linked bank account or stored balance for most of the app wallets. You don't handle the difference; it shows up only in what comes back and in dispute exposure.

How the flow works

Every wallet payment starts the same way: POST /v1/payments answers requires_action with a next_action.url. What happens on that Finscale-hosted page depends on the wallet family:

POST /v1/payments requires_action payment sheet biometric confirm on device apple_pay · google_pay wallet app / QR approve in the wallet paypal · alipay · twint · … processing succeeded
  • Device walletsapple_pay, google_pay. The hosted page presents the native payment sheet; the customer confirms with Face ID, Touch ID, or the device lock. The wallet hands over a tokenized card with a one-time cryptogram — never the underlying PAN.
  • App wallets — everything else. The page hands off to the wallet app on mobile, or shows a QR code to scan on desktop. The customer approves inside the wallet and is returned to your return_url.

On hosted checkout you skip even the create call — checkout shows each shopper the wallets that fit their device and region, and Apple Pay / Google Pay buttons render natively.

Creating a wallet payment

POST /v1/payments — Apple Pay
curl https://api.finscale.dev/v1/payments \
  -H "Authorization: Bearer sk_test_51FinscaleDemo…" \
  -H "Idempotency-Key: idem_ord_9f21_0716" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 4900,
    "currency": "EUR",
    "payment_method": "apple_pay",
    "reference": "ord_9f21_0716",
    "customer": { "email": "anna@example.com" },
    "return_url": "https://shop.example.com/checkout/return"
  }'

The response is the standard requires_action shape — redirect the customer to next_action.url and wait for the webhook, exactly as in the quickstart.

What comes back

Once the wallet approves, payment_method_details carries a snapshot keyed by the method id. For device wallets that includes the underlying card's brand and last4 — note this is the device account number, not the plastic in the customer's pocket, so don't match it against a card on file:

GET /v1/payments/pay_8Q2mX4nT1cVb — after wallet approval
{
  "id": "pay_8Q2mX4nT1cVb",
  "object": "payment",
  "amount": 4900,
  "currency": "EUR",
  "status": "succeeded",
  "payment_method": "apple_pay",
  "payment_method_details": {
    "apple_pay": { "brand": "visa", "last4": "0342", "funding": "debit" }
  },
  "risk": {
    "score": 9,
    "decision": "approved",
    "checks": { "avs_result": "unavailable", "cvv_result": "unavailable" }
  },
  "reference": "ord_9f21_0716",
  "provider": "prov_eu_acq_01",
  "next_action": null,
  "created_at": "2026-07-16T09:24:31Z",
  "livemode": false
}

Risk & authentication

Apple Pay and Google Pay are card-family methods, so risk screening runs and risk is populated. Expect avs_result and cvv_result to be unavailable — wallet charges authenticate with a per-transaction cryptogram instead, which is also why wallet fraud rates run low and 3-D Secure challenges are rarely required on top.

The app wallets authenticate the customer inside the wallet itself (login + app approval), so risk is null — there is nothing further for Finscale to score.

Refunds & disputes

Refunds are the standard call — POST /v1/refunds, full or partial — and the money returns to whatever funded the wallet payment. See Refunds.

Dispute exposure follows the funding rail. Device-wallet payments are card payments underneath: chargebacks are possible and arrive as Dispute objects (dp_…), though biometric confirmation keeps fraudulent disputes rare. App wallets run buyer-protection programs inside their own ecosystems; when a wallet claim lands, Finscale normalizes it into the same Dispute object with the same reason enum, deadlines, and evidence API — one dispute queue, whatever the source.

Settlement timing

Wallet approvals confirm in seconds. Funds clear on the underlying rail's schedule — card-speed for the device wallets, wallet-scheme timing for the rest — and join your unified payout on the standard T+2 schedule. One payout per currency, wallets included; see Settlement & payouts.

Error scenarios

ScenarioWhat the API does
Underlying card declines (device wallets)Standard card error: card_declined, insufficient_funds, … The payment is failed with the matching failure_code.
Wallet balance or account can't cover itpayment.failed with failure_code: "insufficient_funds".
Customer dismisses the sheet or app promptThe payment stays requires_action until the session expires, then fails. Cancel it sooner with POST /v1/payments/{id}/cancel if checkout restarts.
Wallet not available for the currency or region400 invalid_request_error with currency_not_supported at create — surface only wallets that fit the customer, as hosted checkout does.
Wallet scheme outageRetriable failures route to the next capable provider automatically — see Smart routing.