> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://amer.developers.trustly.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://amer.developers.trustly.com/_mcp/server.

# Accept payments with Trustly Pay

Trustly Pay provides a deferred payment flow that separates the user bank authorization from the movement of funds. Unlike a standard checkout, Trustly Pay establishes a persistent authorization for the user bank account. This tokenization generates a secure transactionId once, which serves as a reference for multiple operations later without requiring the user to re-authenticate.

Use [Trustly Pay](/integrate/accept-payments/trustly-pay) for all new integrations, including one-time payments. It offers better risk optimization and a better user experience.

* **Code Parameter:** Even when the user pays immediately, the `paymentType` for Trustly Pay is technically `'Deferred'`.

* **Legacy Requirements:** Only use `paymentType: 'Instant'` if your backend specifically requires the legacy, single-phase capture rail.

## When to use Trustly Pay

* One-click deposits: Tokenize the bank account so returning users can fund their account instantly without logging into the bank again.

* Wallets and trading platforms: Use a single authorization to handle the full lifecycle of a user account for both funding (Pay-ins) and cashing out (Payouts).

* Session-based charges: Authorize a user account at the start of a session (such as gameplay or service usage) and determine the final capture amount at the end.

## Core capabilities

The Trustly Pay workflow supports the following API operations:

* Pay-ins (Capture): Pull funds from the user bank account to your platform.

* Payouts (Deposit): Push winnings or withdrawals back to the user bank account.

* Refunds: Return funds to the user from a previous Pay-in.

## Payment workflow

The following diagram illustrates the two-phase lifecycle of a Trustly Pay transaction. The process begins with the initial user authorization, which Trustly recommends initiating through the Select Bank Widget to reduce checkout abandonment. The server-side funds capture follows the user authorization.

```mermaid
sequenceDiagram
  participant User
  participant Client as Merchant Frontend
  participant Server as Merchant Backend
  participant Trustly as Trustly UI / API

  User->>Client: A (Select Bank Widget)
  Client->>Trustly: B (Establish Call)
  Trustly-->>User: C (Lightbox UI)
  User->>Trustly: D (Authentication)
  Trustly-->>Client: E (Browser Redirect)
  Trustly-)Server: F (Split Token Webhook)

  Note over User, Trustly: Phase 2: Capture Funds
  Server->>Trustly: G (Capture Request)
  Trustly-->>Server: H (Immediate Response)
  Trustly-)Server: I (Settlement Webhook)
```

The following table describes each step in the workflow, corresponding to the lettered annotations in the diagram.

| Workflow Step | Action              | Description                                                                  |
| :------------ | :------------------ | :--------------------------------------------------------------------------- |
| **A**         | User initiates      | The user interacts with the **Select Bank Widget** on the frontend.          |
| **B**         | Client calls SDK    | The frontend calls `Trustly.selectBankWidget` with `paymentType="Deferred"`. |
| **C**         | Trustly launches UI | The Lightbox opens for the user to authenticate with the bank.               |
| **D**         | User authorizes     | The user logs in and confirms the bank connection.                           |
| **E**         | Redirect            | Trustly sends the user back to the `returnUrl` with a `transactionId`.       |
| **F**         | Webhook             | Trustly sends a notification containing the `splitToken` to the backend.     |
| **G**         | Server captures     | The backend calls the Capture API through a server-to-server request.        |
| **H**         | API Response        | Trustly returns an immediate `PENDING` status for the capture.               |
| **I**         | Final Webhook       | Trustly sends a final webhook once the funds clear the network.              |

## Prerequisites

* **Client-side SDK:** You must integrate the JavaScript SDK (Web) or Mobile SDK to launch the Trustly UI. See [Integrate the Client-Side SDK](/integrate/accept-payments/integrate-client-sdk).
* **Sandbox credentials:** You need your `accessId` and `accessKey`. Contact [Trustly Support](mailto:us.integrations@trustly.com) if you do not have them.
* **Legal agreement:** Sign the non-disclosure agreement (NDA) and commercial agreements.

## Create a bank authorization

The `Establish` call is the foundation of Trustly Pay. This launches the Lightbox and generates a `transactionId` that represents the authorized user.

### Configure the transaction

Create an `establishData` object to define the transaction parameters. To create a deferred authorization, you must set the `paymentType` to `Deferred`.

While you can set the `amount` to `'0.00'` for open-ended authorizations, Trustly recommends passing the full purchase value if you know it. This ensures Trustly validates that the user has sufficient funds during the initial authorization step.

```javascript
var establishData = {
  accessId: 'YOUR_ACCESS_ID',
  merchantId: 'YOUR_MERCHANT_ID',
  merchantReference: 'user_session_8829',
  description: 'Wallet funding', // Do not put PII here
  currency: 'USD',
  amount: '100.00', // Set to 0.00 or the specific deposit amount
  paymentType: 'Deferred', 
  splitToken: 'YOUR_STORED_SPLIT_TOKEN', // Required for returning users (Trustly Remember Me)
  requestSignature: 'GENERATED_SIGNATURE',
  // verifyCustomer: true, // Required for Gaming/Sportsbook
  customer: {
    externalId: 'merchant_user_123', // Required to identify the returning user
    name: 'Jane Doe',
    email: 'jane.doe@example.com',
    phone: '+15555555555',
    address: {
        country: 'US'
    }
  },
  returnUrl: 'https://merchant.com/return',
  cancelUrl: 'https://merchant.com/cancel'
};
```

#### Implementation details

* **requestSignature (Required):** You must generate an HMAC-SHA256 signature to prevent tampering. See [Generate request signatures](/integrate/api-fundamentals/secure-requests-and-signature-validation/generate-request-signatures).
* **verifyCustomer (gaming only):** Electronic Gaming clients must set `verifyCustomer: true` and pass all PII (Name, Email, and so on) inside the `customer` object. Do not pass PII in the `description` field.

### Launch the Lightbox

While a standard button can call `Trustly.establish()`, Trustly recommends the Select Bank Widget as the primary integration method. The widget displays bank logos directly on the checkout page, which helps more users complete the bank authorization process. This visual familiarity often leads to a higher rate of successful transactions.

To initialize the widget, pass the transaction data and options to the `selectBankWidget` function:

```javascript
// Launches the inline bank selection widget
Trustly.selectBankWidget(establishData, TrustlyOptions);
```

To configure the widget container and other UI settings, see [Integrate the Client-Side SDK](/integrate/accept-payments/integrate-client-sdk).

### Handle the redirect

Once the user successfully authorizes the request, Trustly redirects them to your `returnUrl`. If the user cancels, Trustly redirects them to your `cancelUrl`.

Example Return URL: `https://merchant.com/return?transactionId=1002633191&status=2`

You must capture and store the `transactionId` from the URL parameters. This ID is the unique key you'll use to execute all subsequent API requests. You should also confirm that the `status` parameter is `2` (Authorized). For a complete list of transaction statuses, see [Status codes](/integrate/api-fundamentals/status-codes-and-type-definitions).

### Enable Trustly Remember Me

Trustly Remember Me significantly reduces friction for returning users and increases conversion rates by enabling a seamless, one-click payment experience.

You’ll receive the `splitToken` through a backend webhook once the user finishes the authorization. You must store this token securely in your database; don’t rely on the frontend redirect to pass this sensitive data. Use this token in future `establish` calls to let users pay with a single click.

To enable this functionality, ensure you provide the user's `email`, `phone`, and `externalId` in the `customer` object of your `establishData`.

For implementation details, see [Enable Trustly Remember Me](/integrate/accept-payments/remember-me).

## Capture funds

Once you have a valid bank authorization (`transactionId`), you can pull funds from the user's account into your merchant account using the Capture API.

Endpoint: `POST /transactions/{transactionId}/capture`

Replace `{transactionId}` with the ID from the original bank authorization.

#### Request parameters

| Parameter           | Description                                                       |
| :------------------ | :---------------------------------------------------------------- |
| `amount`            | The amount to debit from the user.                                |
| `merchantReference` | Your unique identifier for this order. For example, the order ID. |

### Example request

```bash
curl -X POST https://sandbox.trustly.one/api/v1/transactions/&#123;transactionId&#125;/capture \
  -u "YOUR_ACCESS_ID:YOUR_ACCESS_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": "10.00",
    "merchantReference": "order_12345"
  }'
```

## Response handling

The Capture API processes requests synchronously, while Trustly processes subsequent transaction statuses asynchronously. The immediate response is typically `Pending`. You must wait for a webhook to confirm the final status.

| Status     | Description                                                      | Action                                                                                                 |
| :--------- | :--------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------- |
| `PENDING`  | Transaction accepted and processing.                             | Record the transaction. Wait for the final confirmation webhook. For example, `CAPTURED` or `SETTLED`. |
| `DECLINED` | Transaction rejected. For example, non-sufficient funds or risk. | Ask the user for a different payment method.                                                           |

## Send funds (payouts)

To send winnings or withdrawals back to the user's bank account, use the Deposit API. See [Send payouts](/integrate/send-money/send-payouts-using-online-banking).

## Event notifications

Trustly Pay relies on the ACH network, so transaction statuses are asynchronous. You must configure a webhook listener to track when funds actually settle.

Key events for the Trustly Pay workflow include:

* `debit`: Confirms a successful Pay-in (Capture).
* `credit`: Confirms a successful Payout (Deposit).

See [Handle webhooks](/integrate/core-concepts/webhooks-and-events).

## Refresh bank authorization

Bank authorizations may expire or require refreshing. For example, if a user changes their bank password. See [Refresh bank authorization](/integrate/manage-your-integration/refresh-bank-authorization)

## Error codes

The following table lists the error codes you may encounter during pay-in or payout requests.

For detailed user messaging recommendations for each error code, see [Status codes and type definitions](/integrate/api-fundamentals/status-codes-and-type-definitions).

| Transaction Status |  Error Code | Description                          | Action                                                                                                                                  |
| :----------------- | :---------: | :----------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------- |
| **Failed**         | SW057 / 326 | Expired token                        | See [Refresh bank authorization](/integrate/manage-your-integration/refresh-bank-authorization).                                        |
| **Failed**         | SW051 / 380 | Invalid / corrupt token              | See [Refresh bank authorization](/integrate/manage-your-integration/refresh-bank-authorization).                                        |
| **Failed**         | SW056 / 330 | Invalid account                      | Remove the bank account from the user profile. Prompt the user to add a new payment method.                                             |
| **Failed**         | SW054 / 390 | Fraud analysis                       | Prompt the user to use a different payment method. If the response includes a `thirdPartyDeclineCode`, direct the user to the supplier. |
| **Failed**         | SW055 / 390 | Fraud analysis (Negative Data)       | Remove the bank account from the user profile. Prompt the user to add a new payment method.                                             |
| **Failed**         | SW052 / 378 | Internal error or bank request error | Show a generic error message and allow the user to try again.                                                                           |
| **Denied**         | SW021 / 331 | Not enough balance                   | Prompt the user to check their balance or use another payment method.                                                                   |

## Next steps

* [**Display confirmation →**](/integrate/retrieve-data/retrieve-bank-and-user-information)
  Retrieve account details to show a confirmation screen or pre-fill checkout forms.
* [**Test your integration →**](/integrate/api-fundamentals/testing)
  Verify that your application handles success and error states correctly.
* **Schedule certification**
  Complete a formal integration certification with the Trustly team before moving to production. Contact your integration manager to schedule your review.