Skip to main content
Two ways in. The customer is present and pays a link, or they’re away and you charge under a COLLECT contract they approved once. You never pass card or method details in either — Atoa charges the method the customer saved.
  • expiresIn (milliseconds) shortens the link’s window; an unpaid link reads back EXPIRED.
  • Cancel an unpaid link with payment.cancel(paymentRequestId)CANCELLED, reason MERCHANT_CANCELLED.
Sandbox: open the link, choose the Atoa Test Bank, and pick the outcome — COMPLETED, FAILED, or PENDING. Cancelling on the bank page gives CUSTOMER_CANCELLED.

Off-session — under a COLLECT contract [#off-session]

The customer approves the contract (and links a payment method) once at its authorizationUrl. After that you charge under the contract while they’re away — pass the contractId, never a payment method.
Atoa enforces the limits on every charge. Check what’s left in the window before charging, rather than finding out from a failed charge:

Charge on approval [#charge-on-approval]

A COLLECT contract can bundle a first charge into the customer’s single approval — one page both activates the contract and takes that payment (a joining fee, a deposit, the first bill). Pass initialCharge to contract.create; don’t call payment.collect separately for charge #1.
Read the outcome from the contract’s initialCharge. initialCharge.paymentRequestId only exists once the customer approves. After that, poll payment.get with it; before it, match on your own orderId. A status of INITIATION_FAILED means the charge never started — the contract still becomes ACTIVE. Only take the first charge with payment.collect when the contract was created without an initialCharge. Doing both charges the customer twice. Pass storeId to attribute the charge to one of your stores. That store’s name and logo appear on the customer’s contract page.

SCA on a charge

An off-session charge doesn’t settle until the customer approves it. payment.collect returns a nextAction (next_action in Python) holding an approvalUrl. Send the customer there. They approve with a one-time code or a passkey on a page hosted by Atoa. Your app never sees the credential.
To keep the customer on your own site instead of sending a URL, pass nextAction.clientSecret to confirmApproval from the Approvals SDK. A declined charge comes back as FAILED with failureReason: APPROVAL_DECLINED. One nobody approved in time comes back as APPROVAL_EXPIRED. Neither throws — read them off the Payment. In sandbox, open the approvalUrl yourself and pick the decision you want to test.

Refunds

Refund a COMPLETED collect, in full or in part. A refund moves INITIATED → COMPLETED (or FAILED).
A pending refund can be cancelled with cancelRefund(refundId). Sandbox: set reason to "FAILURE TEST" to force a FAILED refund and exercise that branch.