Overview
This guide covers the core card payment integration end to end: registering a user, collecting their card through the Push Widget, authorizing a transaction, handling step-up authentication when the authorization engine requires it, and retrieving the final result. The widget renders and tokenizes the card, so your integration is limited to generating a URL, tokenizing through the widget, and authorizing against the Push API.
cash_out), see Withdrawals.
Integration overview
The steps below show an overview of how to process a card payment.-
Register the user. Call the create-user endpoint with the user’s identity information (name, email, address, and phone number).
- Store the returned Push
idalongside your internal user record. - Register each user only once and reuse the
idon every subsequent transaction. Provide your internal user identifier in thetagfield to ensure idempotency.
- Store the returned Push
-
Display the widget. Call the create-user-url endpoint with the user’s
idand paymentdirection, then render the widget to your payment page using the returnedurl.- The widget automatically validates the card and invokes the
onValidcallback when the form is complete — enable your submit button there. - For a returning user, you can skip the widget and let them pay with a previously-stored credential instead. See Stored credentials.
- The widget automatically validates the card and invokes the
-
Authorize the transaction. When the user submits, generate a
tokenfrom the widget (or use a storedcredential_id) and call the authorize-payment endpoint with the payment details (amount,currency,direction), thetoken, and aredirect_url. Handle the response by its HTTP status code:202 Accepted— the user must complete authentication. Persist the returned intentid, then continue to step 4 using the returnedurl.200 OK— the payment was approved immediately. Notify the user that the payment succeeded.401 Unauthorized— the payment was declined.
If your organization is assigned multiple settlement accounts, include the relevantaccount_idon every authorization request — retrieve the list with list-accounts. Omittingaccount_idwhile multiple accounts exist will fail the request. Organizations with a single settlement account can ignore this. -
Direct the user to complete authentication. Navigate the user to the
urlreturned from the authorize call. When the flow completes, the user is returned to your application via theredirect_urlyou set on the authorize request. Present the authentication UI in an iframe or the device’s system browser depending on your environment — see Presenting the authentication UI. -
Retrieve the result. Call the get-an-intent endpoint and inspect the
statusfield.- If
statusisapproved, update your internal transaction record and notify the user the payment succeeded. - If
statusisdeclined, the payment could not be approved (e.g.insufficient_funds).
- If
Widget
The Push SDK exposes aWidget that renders the card form and tokenizes the card. Instantiate it with the url returned by create-user-url, rendering it into an element on your payment page. The widget validates the card as the user types and invokes onValid when the form is complete; enable your submit button there.
widget.tokenize() to generate a token, then send it to your backend to authorize the payment.
Stored credentials
After a user’s first payment, their card is stored as a reusable credential. A returning user can pay without re-entering card details — skip the widget and let them select a previously-stored credential instead.
-
List and display the stored credentials. Call the list-user-credentials endpoint with the user’s
idand render the returned credentials so the user can pick one. Use these fields to build an identifiable selection UI and enforce eligibility:card_last4,account_last4,bank_name— display these so the user recognizes the card and, where present, the linked bank account.authenticated— whether the credential has completed authentication.type— determines what the credential can be used for:secure_debit— a debit card with a linked bank account. Eligible for both deposits (cash_in) and withdrawals (cash_out).card_only_debit— a debit card with no linked account. Deposits only.card_only_credit— a credit card. Deposits only.
Only credentials with typesecure_debitcan be used for withdrawals. When the user is withdrawing funds, filter the list tosecure_debitcredentials before presenting the selection UI. -
Authorize with the
credential_id. Call authorize-payment with the selectedcredential_id(instead of a widgettoken), the payment details, and aredirect_url. Handle the response by its HTTP status code exactly as in the Integration overview. -
Direct the user to complete authentication. If authorization returns
202 Accepted, navigate the user to the returnedurl— authentication may be requested even for a stored credential. See Presenting the authentication UI. -
Retrieve the result. Call the get-an-intent endpoint and inspect
statusto confirm the payment wasapprovedordeclined.
Authorize With Credential ID
Withdrawals
The steps above collect a payment (cash_in). To pay a user out, follow the same five-step flow with direction: cash_out and the differences below.
-
Restrict the widget to debit cards. Withdrawals settle to a bank account, so they require a
secure_debitcredential — a debit card with a linked account. When collecting a new card for a withdrawal, passtype: secure_debitto create-user-url so the widget only accepts debit cards. For a returning user, filter stored credentials tosecure_debitbefore presenting the selection UI (see Stored credentials). -
Authorize with
direction: cash_out. Call authorize-payment withdirection: cash_out. Optionally setapproval_mode: manualto hold the approved withdrawal for review instead of posting it to the network automatically — see Reviewing withdrawals. -
Direct the user to complete authentication. Identical to a deposit — when the authorization returns
202 Accepted, navigate the user to the returnedurl. See Presenting the authentication UI. -
Retrieve the result. Call get-an-intent and inspect
status. A withdrawal authorized withapproval_mode: manualreturnsstatus: pending— Push has approved it, but it is not posted to the network until you approve it. -
(Optional) Approve the payment. If you authorized with
approval_mode: manual, approve the pending intent to post it to the network — see Reviewing withdrawals.
Create User URL (Withdrawal)
Reviewing withdrawals
Settingapproval_mode: manual on a cash_out authorization holds the approved withdrawal in a pending state so your team can review it before funds are posted to the network. Review the intent with get-an-intent, then either approve it to post the payment or cancel it.
Automatic posting can only be disabled for
cash_out payments. Always approve or cancel manual withdrawals so every intent reaches a terminal status and is not left pending indefinitely.Authorize Withdrawal (Manual Approval)
Approve Pending Intent
Cancel Pending Intent
Refunds
Return funds to a user by refunding an approvedcash_in intent.
-
Submit the refund. Call the create-refund endpoint with the
intent_idof the payment you want to refund.- Optionally include an
amountto refund a portion of the intent. Ifamountis omitted, the full intent amount is refunded. - Only one refund is allowed per intent — subsequent refund attempts on the same intent return a
200with the already-created refund.
To check whether an intent has already been refunded, call get-an-intent and inspect therefundfield on the response. - Optionally include an
-
Handle the response. Check the HTTP status code:
200 OK— the refund was created.401 Unauthorized— the refund was declined by the payment network. The response body includes theidof the declined refund.400 Bad Request— a validation error (e.g. the refundamountis greater than the intent amount).
Create Refund (full amount)
Create Refund (partial amount)
Presenting the authentication UI
When authorize-payment returns202 Accepted, present the authentication UI hosted at the returned url. Choose the presentation based on how the user accesses your application:

- Web (mobile or desktop): present the authentication UI in an iframe. The authentication UI signals the conclusion of the flow by submitting a message to the top-level browser window using postMessage. Omit
redirect_urlfrom the authorization request. - Native mobile app: open the authentication URL in the device’s default system browser (Safari on iOS, Chrome on Android). Set
redirect_urlon the authorization request to bring the user back to your app when authentication completes.
pushcash://) or a Universal Link / App Link as your redirect_url so the system browser can hand control back to your app.
Sandbox testing
Work through the following against the sandbox host (sandbox.pushcash.com) before requesting production access:
- Register each user only once and reuse their
idon subsequent transactions - Simulate an approved transaction using test card
5555 5555 5555 4444 - Simulate a declined transaction using test card
5999 9919 6976 9266 - Test an authentication-required (
202 Accepted) response using test card6011 0009 9013 9424, and confirm you persist the intentidand present the authentication UI aturl - Test a payment decline after the user completes authentication using test card
5999 9819 6976 9283 - Add a new card, then submit a second transaction using the stored
credential_id - Verify that only
secure_debitcredentials are presented for withdrawals - Process a withdrawal (
cash_out) with asecure_debitcard, then authorize withapproval_mode: manualand approve the pending intent - Refund an approved intent, and test a partial refund by specifying an
amountless than the original intent amount - Test a refund decline by processing an intent with test card
5999 9619 6976 9301and then submitting a refund