> ## Documentation Index
> Fetch the complete documentation index at: https://docs.y.uno/llms.txt
> Use this file to discover all available pages before exploring further.

# createPayment

> Override to create the payment on your own backend.

`createPayment` is the controller you override when you want to create the payment on your own backend instead of letting the SDK do it. The SDK delivers the One-Time Token to your handler and waits for you to signal that the payment has been created.

## Behavior

If you do not override this controller, the SDK creates the payment automatically after tokenization, handles 3DS if needed, and delivers the final status to `onStatus`.

When you override it, the SDK delivers the token to your handler and waits for the returned Promise/Task to resolve before continuing. On Web the SDK sets no timeout on your handler. Settle the Promise on every path, including a network failure, or the transaction stays in progress. Resolve the Promise/Task once your backend has created the payment by calling the [Create Payment API](https://docs.y.uno/reference/payments/create-payment) (`POST /v1/payments`); the SDK then queries the payment status, handles 3DS if needed, and invokes `onStatus`.

On Web, send `token.token` as the one-time token and `token.checkout_session` as the checkout session. After a retryable card decline the SDK moves the form to a new checkout session, so the session in your transaction config can be stale. If you set [`autoContinuePayment: false`](/docs/yuno-sdk/reference/objects-you-pass#autocontinuepayment), the SDK stops after your handler resolves. It runs no status query and no 3DS, does not call `onStatus`, and marks the checkout session as finished, so a later `start()` or `submit()` on it throws. The PayPal button ignores the flag and always continues.

If the Promise/Task is rejected, the SDK stops the flow. `onStatus` is not invoked. `showLoading` emits `isLoading: false` and the view is closed at that point. You are responsible for showing the error to your user.

On iOS you can create the payment yourself for some methods only. Call `SdkPayments.defaultCreatePayment(token:)` from your override to fall through to the SDK's own payment creation, which needs a session created with `workflow: "SDK_SEAMLESS"`:

```swift theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
func createPayment(token: [String: Any]) async throws {
    guard createsPaymentsOnBackend else {
        try await SdkPayments.defaultCreatePayment(token: token)
        return
    }
    try await myBackend.createPayment(token: token)
}
```

In an enrollment flow, this controller is not invoked with payment data and overriding it has no effect. On Web the enrollment config does not accept `createPayment`. TypeScript rejects it and JavaScript ignores it.

<Warning>
  Match the checkout session's `workflow` to this decision. Sessions created with the default workflow (`SDK_CHECKOUT`) require this override, because the backend rejects payment creation coming from the SDK. If you don't override `createPayment`, create the session with `workflow: "SDK_SEAMLESS"`. The field lives on the [`POST /v1/checkout/sessions` body](https://docs.y.uno/reference/checkout-sessions/create-checkout-session#body-workflow), not on `TransactionConfig`.
</Warning>

## Signature

<Tabs>
  <Tab title="Web">
    ```typescript theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
    sdkPayments.transaction({
      ...,
      createPayment: async (token) => {
        await myBackend.pay({
          token: token.token,
          checkout_session: token.checkout_session,
        })
      },
    })
    ```
  </Tab>

  <Tab title="iOS">
    ```swift theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
    func createPayment(token: [String: Any]) async throws
    ```
  </Tab>

  <Tab title="Android">
    ```kotlin theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
    suspend fun createPayment(token: Map<String, Any>)
    ```
  </Tab>
</Tabs>

<Tip>
  Your backend call must follow the [Create Payment API reference](https://docs.y.uno/reference/payments/create-payment), including its required headers.
</Tip>

## OneTimeToken

`OneTimeToken` is a dictionary/map containing the token value plus associated metadata.

| Platform | Type |
| - | - |
| Web | `CreatePaymentTokenInformation`. The `OneTimeToken` fields (`token`, `type`, `vaulted_token`, `vault_on_success`, `customer`, `card_data`, `bank_transfer`) plus `checkout_session`, and `recognitionToken` and `quote` when present. |
| iOS | `[String: Any]` |
| Android | `Map<String, Any>` |

See [`OneTimeToken`](/docs/yuno-sdk/reference/objects-you-receive#one-time-token) for the full reference.

## Threading

On iOS and Android, `createPayment` is invoked on the main thread. You can update UI directly from inside this handler. But keep in mind that any backend call you make should happen off the main thread.

## Related

* [Transactions](/docs/basic-concepts/transactions). How a payment flows through Yuno.
* [Payment status values](https://docs.y.uno/reference/payments/status-and-response-codes/payment). Status and substatus reference.
* [`OneTimeToken`](/docs/yuno-sdk/reference/objects-you-receive#one-time-token). The token object reference.
* [`onStatus`](/docs/yuno-sdk/controllers/on-status). Invoked after the SDK queries the payment status.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.