> ## 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.

# Secure Fields

> Migrate Web Secure Fields (yuno.secureFields) integrations to the unified Transaction API.

Secure Fields collected card data in PCI-compliant iframes, so your code never touched the raw PAN. You created each field (`pan`, `expiration`, `cvv`), placed it in your layout, generated a token, POSTed it from your backend, and called `yuno.continuePayment()` to finish.

In the unified API **your field code is nearly unchanged**: same field names, same options, same `onChange`. The one rename: mount a field with `.mount('#sel')` instead of `.render('#sel')`. What changes around it is bigger: the fields come from the `Transaction` (no second argument bag), and the three-step finish (`generateTokenWithInformation` → backend POST → `continuePayment()`) collapses into one repeatable `start()`.

## Before you start

* Load the unified SDK bundle instead of the legacy one and initialize it as the side-by-side shows: `window.Yuno.initialize(...)` becomes `SdkPayments.initialize(...)`. Your public API key and the checkout sessions your backend creates do not change ([Before you begin](/docs/yuno-sdk/get-started#before-you-begin)).
* Decide who creates the payment. The checkout session's `workflow` must match that decision:

| Who creates the payment | In Secure Fields you had | In the unified API | Session `workflow` |
| - | - | - | - |
| Your backend | Always: `generateTokenWithInformation`, then your own backend call | Override `createPayment` | Default (`SDK_CHECKOUT`) |
| The SDK | No equivalent: Secure Fields never created the payment | No override | `SDK_SEAMLESS` |

<Warning>
  A default-workflow session with no `createPayment` override ends in `INTERNAL_ERROR`: the backend rejects the SDK's payment creation. See [`createPayment`](/docs/yuno-sdk/controllers/create-payment).
</Warning>

## Side-by-side

<CodeGroup>
  ```typescript Before. Secure Fields theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
  const yuno = await window.Yuno.initialize('your-public-api-key')

  const secureFields = await yuno.secureFields({
      checkoutSession: 'session-from-backend',
      countryCode: 'CO',
      installmentEnable: true,
  })

  secureFields.create({ name: 'pan', options: { label: 'Card number' } }).render('#pan')
  secureFields.create({ name: 'expiration', options: { label: 'Expiry' } }).render('#exp')
  secureFields.create({ name: 'cvv', options: { label: 'CVV' } }).render('#cvv')

  document.getElementById('pay').addEventListener('click', async () => {
      const ott = await secureFields.generateTokenWithInformation({
          cardHolderName: 'John Doe',
      })
      await myBackend.pay({ oneTimeToken: ott.token, checkoutSession: ott.checkout_session })
      yuno.continuePayment()
  })
  ```

  ```typescript After. Unified Transaction theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
  const sdkPayments = await SdkPayments.initialize('your-public-api-key')

  const transaction = sdkPayments.transaction({
      checkoutSession: 'session-from-backend',
      countryCode: 'CO',
      createPayment: async (token) => {
          await myBackend.pay({ oneTimeToken: token.token, checkoutSession: token.checkout_session })
      },
      onStatus: (result) => showResult(result),
  })

  const secureFields = await transaction.secureFields({ installmentEnable: true })

  secureFields.create({ name: 'pan', options: { label: 'Card number' } }).mount('#pan')
  secureFields.create({ name: 'expiration', options: { label: 'Expiry' } }).mount('#exp')
  secureFields.create({ name: 'cvv', options: { label: 'CVV' } }).mount('#cvv')

  document.getElementById('pay').addEventListener('click', () => {
      transaction.start({
          paymentMethod: { type: 'CARD', data: { card: { holderName: 'John Doe' } } },
      })
  })
  ```
</CodeGroup>

## What changes

Grouped in the order you edit the code. **Renamed**: same role, new name. **Moved**: same value, new owner. **Removed**: nothing to call. The last column is the only thing you have to do beyond the rename.

### Initialization and config

| Secure Fields | Unified | Change | What to do |
| - | - | - | - |
| `window.Yuno.initialize(publicApiKey)` | `SdkPayments.initialize(publicApiKey)` | Renamed | The global is `window.SdkPayments`. As before, `await` it: it resolves to the `SdkPayments` instance you create transactions from. |
| `checkoutSession` / `customerSession` argument of `yuno.secureFields()` | The same field on the transaction config | Moved | Payment vs enrollment stays implicit in which session you pass. Every `yuno.secureFields()` argument except `installmentEnable` moves to the transaction config: the fields inherit the transaction's context instead of duplicating it. |
| `countryCode`, `language`, `deviceFingerprints` arguments of `yuno.secureFields()` | The same fields on the transaction config | Moved | `deviceFingerprints` moves for payment transactions only. An enrollment config (`customerSession`) does not accept it. |
| `installmentEnable` argument of `yuno.secureFields()` | `transaction.secureFields({ installmentEnable })` | Moved | The one knob the transaction can't derive. |
| `enableV2`, `enableMultiplesCard` arguments of `yuno.secureFields()` | *(removed)* | Removed | Dead in v1: declared, never read. |

### Callbacks

| Secure Fields | Unified | Change | What to do |
| - | - | - | - |
| Your own backend POST after `generateTokenWithInformation` | `createPayment(token)` on the transaction config | Moved | Optional. If you own the payment POST, use manual mode (`createPayment` + `start()`): you keep the backend call, the SDK keeps 3DS and the result. Omit it to let the SDK create the payment for you (managed). See [`createPayment`](/docs/yuno-sdk/controllers/create-payment) and [`OneTimeToken`](/docs/yuno-sdk/reference/objects-you-receive#one-time-token). |
| `continuePayment({ paymentResult })` for the outcome | `onStatus(result)` on the transaction config | Moved | In v1 you only got a status by remembering `continuePayment({ paymentResult })`, an easy miss. In the unified API `onStatus` is part of the transaction config. In manual mode (you pass `createPayment`) it also receives a retryable `DECLINED` or `ERROR` result, so you know to re-enable your Pay button while the fields stay mounted (see `start()` under Entry points). In managed mode the SDK retries in place and `onStatus` fires only for the final outcome. See [`onStatus`](/docs/yuno-sdk/controllers/on-status). |

### Views

| Secure Fields | Unified | Change | What to do |
| - | - | - | - |
| `secureFields.create({ name, options }).render('#sel')` | `secureFields.create({ name, options }).mount('#sel')` | Renamed | The only change in your field code. Names (`pan`, `expiration`, `cvv`, `cardLoadPreview`, `cardPin`), options, and `onChange` payloads are all unchanged. |

### Entry points

| Secure Fields | Unified | Change | What to do |
| - | - | - | - |
| `yuno.secureFields({ checkoutSession, countryCode, language, ... })` | `sdkPayments.transaction({ checkoutSession, countryCode, language, ... }).secureFields()` | Renamed | The fields come from the `Transaction`, with no second argument bag beyond `installmentEnable` (see Initialization and config). The typed instance exposes only `create`, `getElement`, and `unmountSync`. |
| `secureFields.generateTokenWithInformation(...)` + backend POST + `yuno.continuePayment()` | `transaction.start({ paymentMethod: { type: 'CARD', data: { card: { holderName } } } })` | Renamed | Tokenize, create, and 3DS in one call. `holderName` and other non-PCI details travel on `paymentMethod.data` instead of `generateTokenWithInformation` args. Declined payments are retryable in place: as in v1, the SDK rotates the checkout session and paints field errors after a decline. New: `start()` is **repeatable**, the next call tokenizes against the rotated session. In v1 this loop required re-running your token → POST → `continuePayment` sequence by hand. |
| `generateToken*` / `generateVaultedToken*` | *(removed)* | Removed | Raw tokenization is no longer public: all tokenization runs inside `start()`. |
| `yuno.continuePayment()` | *(removed)* | Removed | Delete the call. In v1, forgetting it silently skipped 3DS and the result; `start()` runs the full chain automatically. A payment created outside `start()` could never run 3DS or report a status. |
| `yuno.updateCheckoutSession(checkoutSession)` | `transaction.updateCheckoutSession(checkoutSession)` | Moved | Same call, now on the transaction that owns the fields. Payment transactions only. |

## Related

* [Secure Fields](/docs/yuno-sdk/features/secure-fields). The full feature reference: fields, options, methods, retry.
* [`createPayment`](/docs/yuno-sdk/controllers/create-payment). Take over payment creation (manual mode).
* [`onStatus`](/docs/yuno-sdk/controllers/on-status). Receive the final result.
* [`OneTimeToken`](/docs/yuno-sdk/reference/objects-you-receive#one-time-token). Token payload sent to your backend.


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