# Android SDK Changelog
Source: https://docs.y.uno/changelog/android
Latest updates and version history for the Yuno Android SDK
## v2.21.0
*July 6, 2026*
**Payments**
* **Installment dropdown now shows the per-installment value and the total amount**\
Aligned the card installment dropdown with the Web SDK: each option now shows the per-installment value and the total amount (for example '2x of R$ 500,31 - Total R$ 1.000,61'). The same template is applied to every option regardless of whether financial\_costs is present, since its amount is already reflected in the rendered total. If the total is not available the option falls back to the previous per-installment format, and if no amount is available it falls back to the installment count only.
*See also: [CORECM-17537](https://yunopayments.atlassian.net/browse/CORECM-17537)*
* **NuPay renders expanded in the unfolded payment method list**\
When the unfolded payment method list is enabled, NuPay now expands directly in the list like other alternative payment methods, matching the iOS SDK. The inline form shows the buyer's fields together with the NuPay payment types banner, which loads the available options as soon as the buyer enters their document. With the setting off, NuPay keeps opening its separate form screen as before.
*See also: [CORECM-18227](https://yunopayments.atlassian.net/browse/CORECM-18227)*
* **NuPay one-click renders expanded in the unfolded payment method list**\
The NuPay one-click experience now also expands directly in the payment method list when the unfolded list is enabled, completing the parity with the iOS SDK. The inline form shows the credit or debit selector and the selectable payment conditions with their installment options; the chosen condition travels with the payment exactly as it does from the full form screen, and paying without choosing a condition is blocked with an inline message. With the setting off, the one-click flow keeps opening its separate form screen as before.
*See also: [CORECM-18227](https://yunopayments.atlassian.net/browse/CORECM-18227)*
* **Unfolded payment method list for alternative payment methods**\
The payment method list can now show the payment form for alternative payment methods (such as PSE, Nequi, or Boleto) expanded directly in the list, matching the existing behavior for cards and the Web SDK. When a buyer selects one of these methods, its fields unfold inline, and startPayment() charges with the data entered in the list without opening a separate form screen. Saved (enrolled) methods and methods without a form keep their current collapsed behavior. This reuses the existing unfolded payment method list setting and is turned on by Yuno per account; when it is off, the list behaves exactly as before.
* **Payment method selection indicator moved to the leading edge of each row**\
The selection indicator in the payment method list now appears at the leading edge of each row (before the payment method logo) instead of the trailing edge, matching the placement used by major checkouts. The position mirrors automatically for right-to-left languages such as Arabic and Urdu, while card number, expiration date, and CVC inputs keep left-to-right formatting. Each row is now also announced to screen readers as a selectable option within the list, improving accessibility. This is a global visual change applied to all merchants by default across Yuno SDKs.\
\[Migration guide →]\(No code changes are required. If your UI tests or visual snapshots assert the position of the selection indicator in the payment method list, update them to expect it at the leading edge of the row.)
*See also: [CORECM-17649](https://yunopayments.atlassian.net/browse/CORECM-17649)*
* **OTP codes received by SMS can be filled in automatically**\
When a buyer is asked for a one-time password during a payment or enrollment, the SDK can now read the code from the incoming SMS and fill the OTP field for them, matching the experience already offered on iOS. The buyer sees a one-tap system prompt asking for permission before any message is read, so nothing happens without their consent, and a code they have already started typing is never overwritten. The SDK does not request any SMS permissions, works with codes sent from any sender, and silently falls back to manual entry on devices without Google Play services.
*See also: [CORECM-18295](https://yunopayments.atlassian.net/browse/CORECM-18295)*
* **Secure payment badge copy changed to "Powered by Yuno"**\
The badge shown on checkout and enrollment surfaces now reads "Powered by" followed by the Yuno wordmark logo instead of "Secure payment with YUNO". The copy is translated in every language that already localized the badge; the few locales that never localized it keep their existing English fallback.
*See also: [CORECM-17338](https://yunopayments.atlassian.net/browse/CORECM-17338)*
* **Privacy link next to the Powered by Yuno badge**\
A localized "Privacy" link is rendered next to the Powered by Yuno wordmark and opens the privacy policy URL from the account configuration in a Chrome Custom Tab (with an in-app browser fallback); when the configuration provides no URL, the link performs no action. The link is announced to screen readers as a button and is hidden together with the badge when the merchant configuration disables the tag.
*See also: [CORECM-17338](https://yunopayments.atlassian.net/browse/CORECM-17338)*
* **Inline data-privacy disclosure removed from all payment forms**\
The "By paying, you agree to the Personal Data Processing Policy" sentence no longer appears anywhere: it is removed from the one-step, enrolled-card, and step-by-step card forms and from every alternative payment method form. The privacy disclosure is now the "Privacy" link rendered next to the Powered by Yuno badge on the payment form and list surfaces. Mid-action legacy screens (OTP and bank-instruction views, which never carried the inline disclosure) keep the badge without the link.\
\[Migration guide →]\(If UI tests assert the terms\_and\_conditions\_text test tag, remove that assertion; the tag no longer exists on any form.)
*See also: [CORECM-17338](https://yunopayments.atlassian.net/browse/CORECM-17338)*
* **privacy\_tag\_displayed consent signal on completion telemetry**\
The SDK completion telemetry now includes params.privacy\_tag\_displayed=true when the Powered by Yuno badge actually rendered during the session (the parameter is omitted when the badge was hidden), and enrollment completion now emits the enrollCheckoutSdk\_completed event with enrollment\_status. This supports privacy-compliance reporting; merchant-facing behavior and integration contracts are unchanged.
*See also: [CORECM-17338](https://yunopayments.atlassian.net/browse/CORECM-17338) · [CORECM-17340](https://yunopayments.atlassian.net/browse/CORECM-17340)*
* **Powered by Yuno badge below the payment method list and on render forms**\
The payment method list component now shows the Powered by Yuno badge with the Privacy link once, centered below the full list of methods (never inside each method row or expanded form). Forms rendered with a merchant-side pay button (render flows) also show the badge below the form, where the removed inline disclosure used to appear. Both placements follow the existing secure-payment-tag merchant setting: disabling it hides the badge and the link everywhere.
*See also: [CORECM-17338](https://yunopayments.atlassian.net/browse/CORECM-17338)*
* **Host app no longer crashes when a Google Pay Pix result arrives after the checkout screen is closed**\
Fixed a crash that could occur during Google Pay Pix payments when the payment availability or payment result callback arrived after the user had already left the checkout screen (for example by navigating back while the payment was processing). The SDK now silently ignores results delivered after the screen is gone instead of raising an exception in the host app.
* **Account type and account holder type fields for ACH bank transfers**\
The ACH bank-transfer form now shows two additional dropdowns — account type (checking or savings) and account holder type (individual or company) — rendered between the routing number and the beneficiary name. In addition, the whole bank-transfer block (account number, routing number, account type, account holder type, beneficiary name) now renders at the top of the form, before the customer fields, for any payment method whose configuration requires those bank fields. The new dropdowns appear only when the merchant configuration requires them, and the selected values are sent with the bank\_transfer data on both the create-payment token and the enrollment request. Forms whose configuration requires none of the bank-transfer fields are unchanged.
*See also: [CORECM-18130](https://yunopayments.atlassian.net/browse/CORECM-18130)*
**Enrollment**
* **enrollment\_status no longer dropped from enrollment telemetry**\
The event reporter silently dropped params.enrollment\_status when rebuilding event payloads, so enrollStatus\_\* events reached the backend without it. The field is now forwarded.
*See also: [CORECM-17338](https://yunopayments.atlassian.net/browse/CORECM-17338)*
## v2.20.1
*July 28, 2026*
**Payments**
* **Google Pay Pix late-callback crash**\
Fixed a host-app crash when a Google Pay Pix result arrived after the checkout screen was closed — late callbacks are now safely ignored.
## v2.20.0
*July 22, 2026*
**Payments**
* **onInstallmentSelected card callback (Web parity)**\
`startCheckout` now accepts an optional `onInstallmentSelected` callback that fires every time the shopper selects or changes an installment option in the card form — including the default pre-selection at render and recalculations after a BIN change — so merchants can keep the cart total in sync with the selected installment. The payload mirrors the Web SDK's `OnInstallmentSelectedArgs`: `installment` (Int), `label` (String), `amount` as strings, `additionalData` (reserved), and `isMerchantInstallment` (nullable, reserved for the merchant-installments feature). When installments stop being available after a selection was reported (e.g. the shopper switches to a card without installments), the callback fires once with null so the merchant knows the previous installment information is no longer valid. Fully backwards compatible: with no callback registered there is no behavior change, and an exception inside the merchant's callback never affects the payment flow.
*See also: [CORECM-18470](https://yunopayments.atlassian.net/browse/CORECM-18470)*
## v2.19.1
*July 28, 2026*
**Payments**
* **Google Pay Pix late-callback crash**\
Fixed a host-app crash when a Google Pay Pix result arrived after the checkout screen was closed — late callbacks are now safely ignored.
## v2.19.0
*July 9, 2026*
**Payments**
* **Card number length is now validated per card scheme**\
Card numbers are now validated against the expected length for each card scheme, on top of the existing checks, so a number with an invalid length is caught as the customer types and again on submit, before the payment is sent.
* **Saved cards now show a compact summary instead of full card artwork**\
Saved cards now display a compact summary — brand logo, brand name, last 4 digits, cardholder name, and expiry date — instead of the large card artwork, keeping the CVV field visible without scrolling.
* **Stricter card expiry date validation with auto-formatting**\
The card expiry field now auto-formats the date as it is typed, shows a clear "Card has expired" message for past dates, and better distinguishes invalid months.
* **Stronger document and phone field validation**\
Document and phone fields now use numeric-only keyboards where applicable, support many more national document types, show clearer error messages, and reliably prefill saved values without overwriting what the customer has typed.
* **Barcodes on flexible payment actions now render in landscape**\
Fixed an issue where barcodes on flexible payment actions (such as Boleto and INDOMARET) did not display in landscape with the correct proportions. They now match iOS and Web, making them clearer and easier to scan. QR-based methods are unchanged.
* **Click to Pay no longer stalls without a callback URL**\
Fixed an issue where Click to Pay stalled when the checkout session was created without a callback URL. The payment now continues seamlessly with the standard flow.
* **Google Pay payments now include the customer's language for 3DS**\
Fixed an issue where Google Pay payments left the customer's language empty in the browser information used for 3DS authentication and risk evaluation. The language is now correctly included.
* **Card payments with an installment plan now return the one-time token**\
Fixed a regression where card payments with an installment plan did not correctly return the one-time token, preventing these payments from being completed.
* **Card number field no longer advances too early for longer card numbers**\
Fixed an issue where the card number field moved focus to the next field too early for cards that accept more than one length, preventing customers from finishing typing a longer number.
## v2.18.0
*July 5, 2026*
**Payments**
* **Card type toggle no longer shows in the unfolded card form when credit\_card\_only\_processing is enabled**\
Fixed an issue where the credit/debit card type toggle was displayed for Brazilian cards in the unfolded card form (payment method list) even when the merchant had credit\_card\_only\_processing enabled. The full-screen card form received the flag through its call chain, but the unfolded call site did not propagate it, so the composable fell back to its default and always showed the toggle. The visibility check now also resolves the flag directly from the SDK settings, so every card form honors it regardless of the call site.
* **Installment dropdown now shows the per-installment value and the total amount**\
Aligned the card installment dropdown with the Web SDK: each option now shows the per-installment value and the total amount (for example '2x of R$ 500,31 - Total R$ 1.000,61'). The same template is applied to every option regardless of whether financial\_costs is present, since its amount is already reflected in the rendered total. If the total is not available the option falls back to the previous per-installment format, and if no amount is available it falls back to the installment count only.
*See also: [CORECM-17537](https://yunopayments.atlassian.net/browse/CORECM-17537)*
## v2.17.3
*June 30, 2026*
**Payments**
* **Host app no longer fails when a payment return deeplink cannot be opened**\
Fixed an issue so that WebViews no longer fail when trying to open a deeplink if the target app is not installed.
## v2.17.2
*June 26, 2026*
**Payments**
* **Merchant callbacks registered before initialize are no longer lost**\
Fixed a regression where one-time-token and payment-state callbacks were silently dropped for integrations that register their callbacks once and then call Yuno.initialize afterwards (for example cross-platform wrappers that register in the host Activity's onCreate and initialize later). Initialization was unconditionally clearing the previously registered callbacks, so the merchant never received the token or the final/cancellation status even though the payment completed. Initialization no longer clears these callbacks; native integrations that re-register on each call are unaffected.
* **startPayment and startPaymentLite accept an optional payment-state callback**\
Added an optional callbackPaymentState parameter to startPayment and startPaymentLite, aligning them with startPaymentSeamlessLite and continuePayment. Integrators can now re-supply the payment-state callback on each call, giving a per-call registration path for the state delivered through the start-payment flow, such as the cancellation reported when the user dismisses the payment sheet. The parameter is optional and defaults to null, so existing callers are unaffected.
## v2.17.1
*June 22, 2026*
**Payments**
* **Card payments with an installment plan now return the one-time token**\
Fixed a regression where selecting a card with an installment plan produced no one-time token on the merchant callback, so the payment could not be completed. The token endpoint response was being rejected while parsing because the installment amount is delivered as a money object (currency + value); the SDK now reads it correctly and surfaces the token through callbackOTT / callBackTokenWithInformation as before. Other payment methods were not affected.
## v2.17.0
*June 12, 2026*
**Payments**
* **Headless SDK: resume card payments with continueCardPayment**\
Merchants integrating the Headless SDK can now resume a CARD payment created from their backend by calling `continueCardPayment`. The SDK internally executes any pending action — such as the 3DS challenge — waits for the final result, and delivers every payment state and sub-state through a callback, so merchants keep full control of their checkout UI without rendering the challenge themselves. The method works in pure headless integrations: no prior Yuno checkout UI flow is required.
* **Removed getThreeDSecureChallenge from the Headless SDK**\
The headless `getThreeDSecureChallenge` method and its `ThreeDSecureChallengeResponse` type were removed. It returned the raw 3DS challenge URL and required merchants to render and complete the challenge themselves. Migrate to `continueCardPayment`, which executes the challenge internally and reports the resulting payment states through a callback.\
[Migration guide →](https://docs.y.uno/docs/sdks/headless-android/checkout)
## v2.16.2
*June 22, 2026*
**Payments**
* **Card payments with an installment plan now return the one-time token**\
Fixed a regression where selecting a card with an installment plan produced no one-time token on the merchant callback, so the payment could not be completed. The token endpoint response was being rejected while parsing because the installment amount is delivered as a money object (currency + value); the SDK now reads it correctly and surfaces the token through callbackOTT / callBackTokenWithInformation as before. Other payment methods were not affected.
## v2.16.1
*June 2, 2026*
**Payments**
* **Back gesture/button now cancels the 3DS challenge in render mode**\
In render mode, pressing the back button or using the back gesture during a 3D Secure challenge now closes the challenge and returns a cancellation result (CANCELED\_BY\_USER) to the merchant, matching iOS. Previously the back press was ignored and the payment hung until the server-side challenge timeout. The challenge WebView history is no longer walked on back (which could leave a blank screen); back always cancels.
## v2.16.0
*May 13, 2026*
**3DS**
* **Native 3DS via the optional Yuno3DSNetcetera module**\
A new optional companion module that runs native 3DS challenges and device data collection inside your app. Add the dependency alongside the core SDK and it gets picked up automatically — no extra wiring. Published as Yuno3DSNetcetera 1.0.1 on JFrog and compatible with the core SDK starting at 2.16.0.
**Forms**
* **Real-time form validation**\
Card and alternative payment method forms now validate each field as the buyer types, instead of only at submit. Errors are shown inline, on the field, the moment the input becomes invalid.
* **New compact card form (server-driven slimmerFormEnabled flag)**\
When the `slimmerFormEnabled` flag is turned on for your account, the card form (new card, alternative methods and enrolled card) switches to a more compact visual style: card and address fields render as grouped rows with a single consolidated error message per group. When the flag is off, the previous visual is preserved exactly as is.
* **Auto-advance on the enrolled card form**\
When the buyer enters valid data in the enrolled card flow, focus now jumps to the next field automatically, matching the behavior already present in the new-card form.
* **Google Autofill on card fields**\
Card number, cardholder name, expiration and CVV fields are now eligible for Google Autofill, so buyers can fill them in with a saved card from Google on Android.
**Google Pay**
* **Google Pay: collect billing address, shipping address and cardholder name**\
Google Pay now requests billing address, shipping address and cardholder name from the buyer whenever the selected payment method requires them, picking the right address format automatically (name only vs. full address). The collected values are forwarded to the backend together with the wallet payload.
* **Google Pay: collect buyer email and phone**\
Google Pay now requests the buyer's email and phone whenever the payment method requires them, and the values are forwarded to the backend as part of the customer payer.
**Checkout UI**
* **Hide the 'secure' badge via flag**\
The 'secure' badge shown in the checkout UI can now be hidden through a server-driven flag.
**Anti-fraud**
* **ClearSale device fingerprint**\
On previous versions the ClearSale anti-fraud fingerprint silently failed to register the buyer's device. The fingerprint is now collected and submitted correctly.
**Payments**
* **Correct installment plan selected when the backend ships per-installment ids**\
In some configurations the wrong installment plan could be selected when the backend returned both a generic code and a per-installment id. The SDK now consistently uses the per-installment id, so the buyer's chosen plan matches what is sent to the backend.
* **Every code is shown on payment-code screens**\
On payment methods where the post-payment screen presents more than one code to the buyer (for example a barcode plus a digital line), only the first one was being rendered. All codes returned by the backend are now displayed.
* **Visible separator on the payment-code screen**\
On the post-payment code screen (PIX, OXXO, boleto, and similar flows), the horizontal line that separates the code area from the copy / download buttons was rendered in a color so close to the background that it was effectively invisible. It now uses a contrasting tone in both light and dark mode.
## v2.15.1
*May 19, 2026*
* **Flutter Plugin Lifecycle Crash**\
Fixed a crash caused by Flutter plugin lifecycle incompatibility with the Android SDK on process death.
## v2.15.0
*May 8, 2026*
* **Flexible Actions in Enrollment**\
Enrollment now supports the same dynamic action screens used in payments, including PIN, image, payment code, OTP, and info screens.
* **Installment Details on Tokenization**\
When a card is tokenized with installments selected, the installment information — plan, rate, amount, and selected option — is now returned alongside the one-time token.
## v2.14.0
*April 30, 2026*
* **Separate Billing and Shipping Address Forms**\
Added separate billing and shipping address sections with a same-as-shipping checkbox, including a `BILLING_ONLY` section type and refined field ordering and focus behavior.
* **Auto-Advance Between Card Fields**\
Card form now auto-advances focus to the next field on valid input, including correct handling when the CVV field is hidden, when the save-card checkbox is present, and inside the unfolded card form.
* **Dynamic CVV Limit for Enrolled Cards**\
The CVV input now applies the correct length limit for enrolled cards based on the card's `securityCodeLength` instead of the default 3-digit limit.
* **Seamless Flow Automation Mode**\
Added a seamless checkout flow tailored for automation mode to support end-to-end testing scenarios.
* **3DS WebView Loading Indicator**\
Added a loading progress indicator to the 3DS `WebView` to communicate state during authentication.
* **MVVM and Architecture Cleanup**\
Refactored to MVVM using use cases and `StateFlow`, migrated `BehaviorSubject` usages to `StateFlow`, decomposed `ContinueCheckoutFragment`, removed the service locator, and purified the domain layer by removing `Parcelable` and Android framework dependencies. No public API changes required.
* **Customer Session for Enrollment Card Info**\
The card-info API now receives `customer_session` in enrollment flows for improved fraud and risk signals. No integration changes required.
* **Enrolled Card Flow Address Sections**\
Migrated the enrolled card flow to use the new billing and shipping address sections, prefilling shipping with billing when empty.
* **Shipping and Billing Validation Focus**\
Submit now scrolls to and focuses the first invalid shipping or billing field, and the keyboard `Next` button correctly advances through address fields.
* **Installments Dropdown Amount**\
The installments dropdown now shows the amount for items that don't have `financial_costs`, ensuring consistent display.
* **CheckoutModel Singleton Update**\
Fixed `updateCheckoutSession` replacing the `CheckoutModel` singleton with a copy, which broke captured references across the SDK.
* **Edge-to-Edge in SeamlessCheckoutActivity**\
Applied the edge-to-edge fix to `SeamlessCheckoutActivity` and fixed double system-bars padding after the WebView and 3DS flows on Samsung devices.
* **Custom Font Family Coverage**\
Merchant-defined `YunoConfig.styles.fontFamily` is now applied across all SDK components.
* **Mercado Pago Fingerprint Obfuscation**\
Serialized Mercado Pago SDK fingerprint fields and added consumer ProGuard rules so fingerprinting survives R8 obfuscation in merchant release builds.
* **WebSocket Reconnection in 3DS Flow**\
Fixed WebSocket reconnection after the app returns from the background during a 3DS flow.
* **Billing and Shipping Checkbox Autofill**\
Fixed the same-as-shipping checkbox autofill behavior based on prefilled customer data.
* **Locale Translations**\
Added missing translations for Hindi (`hi`), Bengali (`bn`), Malayalam (`ml`), and Urdu (`ur`) locales.
## v2.13.4
*April 20, 2026*
* **Font Family Customization**\
Merchant-defined `fontFamily` set in `YunoConfig.styles` is now applied across all SDK components. No API changes required.
## v2.13.3
*April 5, 2026*
* **WebView State**\
Improved loading state handling during WebView transitions for a smoother checkout experience. No API changes required.
## v2.13.2
*March 20, 2026*
* **3DS Redirect Handling**\
Enhanced 3DS redirect handling for broader provider compatibility. No API changes required.
## v2.13.1
*March 5, 2026*
* **Loader Timing Behavior**\
Adjusted loader timing behavior in extended payment flows for a more consistent user experience. No API changes required.
## v2.13.0
*February 15, 2026*
* **Keeploader Support**\
Added integration support for Keeploader. Contact your Yuno technical account manager to enable this feature for your account.
## v2.12.1
*April 29, 2026*
* **WebSocket Alignment with iOS**\
Backported the WebSocket alignment hotfix from the 2.6 line: the socket connection now forwards `code`, `public-api-key`, `x-version`, and `x-platform`, and propagates the payment code on reconnect.
## v2.12.0
*January 10, 2026*
**Enhancements**
* **Dynamic Regional Base URLs**\
The SDK now selects its base URL dynamically based on the region prefix, improving routing reliability for multi-region deployments. No API changes required.
* **Alphanumeric CNPJ Validation**\
Added support for alphanumeric CNPJ validation in Brazilian payment flows. No API changes required.
* **Dynamic CVV Length by Card Type**\
The SDK now fetches the maximum CVV length per card type from the API and maps per-brand `security_code_length` values. No API changes required.
* **Cardholder Name Limit Increase**\
The maximum allowed length for `cardholderName` has been increased from 50 to 255 characters. No API changes required.
* **OTT Payment Method Type Display**\
The `payment_parent_method_type` field is now displayed in the OTT component and included in the OTT response. No API changes required.
* **Dynamic Action Warning Banner**\
A warning banner has been added to the dynamic action screen to surface important messaging to users during payment flows. No API changes required.
* **Headless Flow Coroutines Migration**\
Headless payment flows have been migrated from callbacks to Kotlin coroutines for improved performance and reliability. No API changes required.
**Bug Fixes**
* **WebView Toolbar Overlap on Android 15**\
Fixed a layout issue where the `WebViewActivity` toolbar overlapped the system status bar on devices running Android 15 and above. No API changes required.
* **PSE Issuers Null Response Crash**\
Fixed a crash that occurred when the PSE issuers endpoint returned a null or empty response. No API changes required.
* **CVV State Desync on Brand Switch**\
Fixed a CVV state desynchronization issue that occurred when switching card brands in the step-by-step card form. No API changes required.
* **Enrolled Card Form Skip Bug**\
Fixed a bug where an enrolled card skipped the form entry step when `billingAddress` or `cardholderName` were required fields. No API changes required.
* **Empty Form on All-False Fields**\
Fixed a bug where the card form rendered as empty when all `FieldsRequired` flags were set to false. No API changes required.
## v2.11.3
*March 31, 2026*
* **Mercado Pago Fingerprint R8 Obfuscation**\
Added `@SerializedName` annotations to Mercado Pago fingerprint classes to prevent R8 from obfuscating field names, which was causing declined transactions in merchant release builds.
## v2.11.2
*December 18, 2025*
* **Cardholder Name Visibility Control**\
The cardholder name field is now shown or hidden based on the backend response, replacing the previous static display logic. No API changes required.
## v2.11.1
*December 1, 2025*
* **Punto Pago Kiosk Disclaimer**\
Added a disclaimer message to the Punto Pago kiosk screen to communicate relevant payment terms to users. No API changes required.
* **Cartes Bancaires UI Updates**\
Updated the visual presentation of the Cartes Bancaires payment option to align with current design standards. No API changes required.
## v2.11.0
*November 10, 2025*
* **CheckoutBuilder Migration**\
Removed `cardFlow` from `YunoConfig`. Card flow configuration is now handled exclusively through the Dashboard Checkout Builder. Update your integration before upgrading.\
[Migration guide →](/changelog/migration-guides/android/v2-10-to-v2-11)
## v2.10.2
*February 26, 2026*
* **Seamless Flow Crash**\
Fixed a crash in the seamless checkout flow.
* **URL Download Null Handling**\
Fixed crashes when a URL download fails or returns null, improving robustness of asset and resource fetching.
* **Android 16 Edge-to-Edge Overlap**\
Backported the Android 16 edge-to-edge fix from 2.9.4: corrected UI overlap caused by edge-to-edge layout changes.
* **Payment Method List Enabled State**\
Backported the enabled-state fix from 2.9.4 so payment methods in `PaymentMethodListViewModel` are correctly enabled or disabled based on availability.
## v2.10.1
*February 10, 2026*
* **Mercado Libre SDK Dependency Removed**\
Backported the Mercado Libre SDK dependency removal from the 2.9.3 hotfix: `PaypalMagnesFraud` now uses a remote dependency instead of the embedded library.
## v2.10.0
*January 27, 2026*
* **Payment Selected Callback**\
Added a payment-selected callback to the payment method list composable so merchants can react when the user chooses a payment method.
* **Size Callback for Payment Method List**\
Added a size callback to the payment method list composable, letting merchants adapt their layout to the rendered list dimensions.
* **Arabic Language Support**\
Added Arabic translations across the SDK, including enrollment status screens, with proper plural handling.
## v2.9.4
*February 12, 2026*
* **Android 16 Edge-to-Edge Overlap**\
Fixed UI overlap on Android 16 caused by edge-to-edge changes in `BaseActivity`, `ContinueCheckoutActivity`, and `ScaffoldComponent`.
* **Payment Method List Enabled State**\
Fixed enabled-state conditions in `PaymentMethodListViewModel` so payment methods are correctly enabled or disabled based on availability.
## v2.9.3
*February 3, 2026*
* **Mercado Libre SDK Dependency Removed**\
Removed the bundled Mercado Libre SDK dependency and updated `PaypalMagnesFraud` to use the remote dependency instead of the embedded library, reducing SDK size and easing dependency management.
## v2.9.2
*January 22, 2026*
* **Enrollment Status Polling**\
Improved `GetStatusEnrollmentViewModel` and `EnrollmentHeadlessViewModel` status handling for more reliable enrollment result delivery in headless flows. No API changes required.
## v2.9.1
*January 19, 2026*
* **Bundled PayPal Magnes and Mercado Pago JARs**\
Removed the embedded `magnes-paypal.jar` and `sdk-3.1.0.jar` binaries together with the local `PaypalMagnesFraud` and `MercadoPagoFraud` providers and their initialization paths. Fingerprinting is now provided through remote dependencies, reducing SDK size.
## v2.9.0
*September 15, 2025*
* **subPaymentState Parameter**\
Added a `subPaymentState` parameter to the `callbackPaymentState` callback in `startCheckout()` and `continuePayment()`, providing finer-grained payment status reporting. No API changes required.
* **Google Pay in startPayment**\
Google Pay is now supported in the `startPayment` flow in addition to `startCheckout`. No API changes required.
## v2.8.1
*August 20, 2025*
* **Google Pay Card Type Field**\
Added a new card type field to the Google Pay response object to improve card identification in payment flows. No API changes required.
## v2.8.0
*August 5, 2025*
* **Card Scanning via OCR**\
Added card scanning (OCR) functionality powered by Google Pay's solution, allowing users to scan their credit or debit cards using the device camera during checkout. No additional integration changes required beyond enabling the feature.
## v2.7.0
*July 10, 2025*
* **Architecture Improvements**\
Internal architecture improvements to improve SDK stability and maintainability. No API changes required.
* **EdgeToEdge WebView Layout**\
Fixed an EdgeToEdge rendering issue in `WebViewActivity` that caused layout overlap on devices with edge-to-edge display mode enabled. No API changes required.
## v2.6.7
*May 12, 2026*
* **WebSocket Alignment with iOS**\
Aligned the Android `SocketManager` behavior with iOS by forwarding `code`, `public-api-key`, `x-version`, and `x-platform` on socket connect and propagating the payment code on reconnect. Improves stability for payment-code driven flows.
## v2.6.6
*November 3, 2025*
* **Click to Pay Passkey Support**\
Added passkey support for the Click to Pay flow, including `FLAG_ACTIVITY_CLEAR_TASK` handling for the in-app browser session.
* **WebView Edge-to-Edge Rendering**\
Fixed an edge-to-edge rendering issue affecting `WebView` content on devices using the newer Android display model.
## v2.6.5
*October 27, 2025*
* **Internal Release Pipeline Updates**\
Maintenance release with internal build and versioning updates. No merchant-facing API changes.
## v2.6.4
*November 13, 2025*
* **Google Pay PIX Direct Flow**\
Added support for the Google Pay PIX direct flow, enabling merchants to offer PIX payments through the Google Pay integration.
* **Google Pay PIX merchantName**\
Fixed the `merchantName` parameter being passed incorrectly in the Google Pay PIX flow.
## v2.6.0
*June 10, 2025*
* **Google Pay PIX Direct**\
Added support for Google Pay PIX direct integration, enabling PIX payments via the Google Pay flow. No API changes required.
## v2.5.0
*April 25, 2025*
* **Brazil Hybrid Card Support**\
Added support for Brazil hybrid cards, which are processed as credit by default and can be saved for future use. No API changes required.
* **Chinese Localization (zh-CN)**\
Added complete Chinese Simplified (zh-CN) localization across payment flows, error messages, loaders, and APM screens. No API changes required.
* **External Browser for APM Links**\
APM payment links now open in the device's external browser, improving compatibility and security for third-party payment flows. No API changes required.
## v2.4.2
*March 20, 2025*
* **Default Credit Processing for Hybrid Cards**\
Hybrid cards in Brazil are now processed as credit by default in both payment and enrollment flows, and cards can be saved. This behavior is country-gated; ensure your 3DS flow is compatible before upgrading.
## v2.4.0
*March 5, 2025*
* **OTP Screen Visibility in APM Render Mode**\
Fixed an issue where the OTP screen in APM render mode was cut off, making the digit input fields invisible to the user. No API changes required.
* **Checkout Builder Endpoint Updates**\
Updated Checkout Builder endpoint signatures and aligned styling and action rendering with the latest builder schema. No API changes required.
* **Name Fields in Card Forms**\
The `first_name` and `last_name` input fields are now included in the One Step, Step-by-Step, and Enrolled Payment card forms when required by the payment configuration. No API changes required.
## v2.3.0
*February 5, 2025*
* **Geolocation in customer\_payer**\
Added support for `latitude` and `longitude` fields in `customer_payer` to enable geolocation data collection for fraud analysis. Pass the coordinates when initializing checkout.
* **renderMode Enrollment Support**\
Added `renderMode` support for enrollment flows in Mobile Lite, enabling manual rendering control via Checkout Builder. No API changes required.
* **CVV Validation Improvements**\
CVV validation for UATP cards is no longer applied when the CVV field is hidden in One Step and Step-by-Step forms. The CVV tooltip no longer reappears when the keyboard is dismissed. No API changes required.
* **Mandatory Expiration Date for Voucher Brands**\
The `expirationDate` field is now mandatory for voucher brands that require it (Sodexo, VR, Elo, Alelo, Ticket), determined via card-iin detection. No API changes required.
## v2.2.2
*January 15, 2025*
* **Luhn Validation Restored**\
Reverted card validation to use Luhn algorithm for all card types. This change restores the previous validation behavior and improves consistency across card brands. No API changes required.
## v2.2.1
*January 5, 2025*
* **Minor Fixes and Updates**\
Applied minor bug fixes and internal stability updates. No API changes required.
## v2.2.0
*December 10, 2024*
* **SVG Icon Support for Brands**\
Added SVG icon support in form headers across full, lite, seamless, and list modes for brands including Sodexo, Elo, Alelo, Bradexco, and Cartes Bancaires. No API changes required.
* **PayPal Enrollment Support**\
Added support for enrolling PayPal as a payment method through the SDK enrollment flow. No API changes required.
## v2.1.0
*November 10, 2024*
* **13 New Localization Languages**\
Added support for 13 new languages: Indonesian, Malaysian, Thai, Filipino, Traditional Chinese, French, Polish, Italian, German, Russian, Turkish, Dutch, and Swedish. No API changes required.
* **PagBank Integration**\
Integrated PagBank as a new payment method, launched via Chrome Custom Tab. No API changes required.
* **Enhanced Enrolled Card Fields**\
Enrolled card entries now expand instantly to show all payment fields in an unfolded state, improving checkout UX. No API changes required.
## v2.0.0
*October 1, 2024*
* **NuPay Payment Conditions**\
Added NuPay payment conditions and installment options including debit, credit, and additional limit flows. No API changes required.
* **Render Integration for Loader Control**\
Added a render integration mode that allows merchants to manually control SDK loader visibility during payment flows. No API changes required.
* **Astropay Enrollment**\
Added support for enrolling Astropay as a payment method through the SDK enrollment flow. No API changes required.
## v1.24.0
*August 15, 2024*
* **MODO APM**\
Added support for MODO as an alternative payment method via deeplink flow.
* **Mercado Pago External Browser**\
Mercado Pago Checkout Pro now opens in the device's external browser instead of a WebView. No integration changes required.
* **Mercado Pago WebView Flow**\
The in-SDK WebView flow for Mercado Pago Checkout Pro is deprecated and will be removed in a future version. Migrate to the external browser flow, which is now the default behavior.
## v1.20.2
*April 10, 2024*
* **Token With Information Callback**\
Added a new `tokenWithInformation` callback to surface card token data during payment flows. No API changes required.
* **NuPay Redirect Issue**\
Fixed an issue where NuPay payment redirects did not complete correctly. No API changes required.
* **CVV Validation in Enrollment**\
Fixed incorrect CVV validation logic during the card enrollment flow. No API changes required.
## v1.17.0
*January 20, 2024*
* **Nubank Flow Improvements**\
Improved the Nubank payment flow for a more reliable and consistent user experience. No API changes required.
## v1.16.0
*December 5, 2023*
* **3DS FAC Fraud Engine**\
Added support for the FAC fraud engine in 3DS authentication flows. Contact your Yuno account manager to enable this feature.
## v1.15.1
*November 15, 2023*
* **Java Version Compatibility**\
Fixed a compatibility issue affecting builds targeting specific Java versions. No API changes required.
## v1.15.0
*November 1, 2023*
* **Cards and Nubank UI/UX**\
Improved the visual design and user experience for card payment forms and the Nubank flow. No API changes required.
* **Chile RUT Validation**\
Improved RUT (Chilean tax ID) validation logic to handle edge cases more accurately. No API changes required.
## v1.14.0
*October 10, 2023*
* **Nubank CNPJ Field Removed**\
Removed the CNPJ input field from the Nubank payment flow to streamline the checkout experience. No API changes required.
## v1.13.0
*September 15, 2023*
* **Card Forms Design and UX**\
Refreshed the design and improved the user experience across all card payment forms. No API changes required.
## v1.12.2
*August 25, 2023*
* **3DS Netcetera Fraud Engine**\
Added support for the Netcetera fraud engine in 3DS authentication flows. Contact your Yuno account manager to enable this feature.
## v1.12.1
*August 10, 2023*
* **MercadoPago SDK Performance**\
Improved MercadoPago SDK initialization and rendering performance. No API changes required.
## v1.12.0
*July 25, 2023*
* **PIX Santander Payment Method**\
Added support for PIX payments via Santander as a new payment method option. No API changes required.
## v1.11.4
*July 10, 2023*
* **MercadoPago SDK Performance**\
Further performance improvements to the embedded MercadoPago SDK. No API changes required.
## v1.11.3
*June 25, 2023*
* **Style Overrides**\
Fixed an issue where custom style overrides were not being applied correctly across SDK components. No API changes required.
## v1.11.2
*June 10, 2023*
* **Card Flow Expiration Date UX**\
Improved the expiration date input experience in card payment flows for more intuitive data entry. No API changes required.
## v1.11.1
*May 25, 2023*
* **Card Flow Improvements**\
General improvements to the card payment flow for stability and usability. No API changes required.
## v1.11.0
*May 10, 2023*
* **DeUna Payment Method**\
Added support for DeUna as a new payment method option. No API changes required.
## v1.10.1
*April 20, 2023*
* **SDK and Card Flow Performance**\
Performance improvements across the SDK core and card payment flows. No API changes required.
## v1.10.0
*April 5, 2023*
* **Pluxe Payment Method**\
Added support for Pluxe as a new payment method option. No API changes required.
* **Google Pay Flow Improvements**\
Improved Google Pay flow reliability and user experience. No API changes required.
## v1.8.0
*February 15, 2023*
* **Headless 3DS Challenge URL**\
Added a headless flow to retrieve the 3DS challenge URL for custom 3DS integration scenarios. No API changes required.
## v1.7.0
*January 20, 2023*
* **Headless OTT and 3DS Flow**\
Added a headless flow to generate a one-time token (OTT) and retrieve the 3DS challenge URL, enabling fully custom payment UI implementations. No API changes required.
## v1.6.1
*December 15, 2022*
* **Antifraud OTT Generation Block**\
Fixed an issue where the antifraud module was incorrectly blocking one-time token generation. No API changes required.
* **showPaymentStatus Argument Added**\
Added `showPaymentStatus` boolean argument to `startPaymentLite` and `startPayment` to control whether the SDK displays the error screen after a failed payment. Pass `false` to suppress the SDK error screen and handle it yourself.
## v1.6.0
*December 1, 2022*
* **Mercado Pago Antifraud**\
Added Mercado Pago antifraud integration to enhance fraud prevention for Mercado Pago payment flows. No API changes required.
* **Click to Pay Flow Improvements**\
Improved the Click to Pay flow for better reliability and user experience. No API changes required.
## v1.5.14-HF
*November 20, 2022*
* **OTT with Card Info**\
Added a function to create a one-time token that includes full card information during both Enrollment and Payment flows. No API changes required.
* **Location Permissions Crash**\
Fixed a crash that occurred when location permissions were not granted by the user. No API changes required.
## v1.5.14
*November 10, 2022*
* **Step-by-Step and One-Step Card Improvements**\
Improved the step-by-step and one-step card payment flows for better reliability and user experience. No API changes required.
## v1.5.13
*October 25, 2022*
* **Mercado Pago Wallet Enrollment**\
Added support for enrolling Mercado Pago Wallet via deeplink and Chrome Custom Tab. No API changes required.
* **3DS and Cybersource Fraud Engines**\
Added support for 3DS and Cybersource fraud engines to strengthen fraud prevention in card payment flows. Contact your Yuno account manager to enable these features.
## v1.5.12
*October 10, 2022*
* **Card Payments Flow Improvements**\
Improved the card payments flow for stability and reliability. No API changes required.
* **SecureFields Component Consolidation**\
Replaced the separate `CardExpiryDate` `EditText` and `TextField` `ItemView` (CVV) components with a single `CardDataStackView` component for SecureFields integration. Update your layout to use `CardDataStackView`.
## v1.5.11
*September 25, 2022*
* **Discover Card Validation**\
Fixed card number validation for Discover cards that was incorrectly rejecting valid card numbers. No API changes required.
## v1.5.0
*September 1, 2022*
* **Antifraud for Cards Flow**\
Added antifraud integration for card payment flows to improve fraud detection during checkout. Contact your Yuno account manager to enable this feature.
* **Click 2 Pay Payment Method**\
Added support for Click 2 Pay as a new payment method option. No API changes required.
* **Supported Language Methods**\
Added programmatic language selection methods, allowing the SDK locale to be set at runtime. No API changes required.
* **SDK Design Refresh**\
Introduced an updated SDK visual design across payment and enrollment screens. No API changes required.
## v1.4.12
*August 20, 2022*
* **Card Payments Flow Improvements**\
Improved the card payments flow for better stability and user experience. No API changes required.
## v1.4.11
*August 5, 2022*
* **Card Enrollment Flow Improvements**\
Improved the card enrollment flow for better reliability and user experience. No API changes required.
## v1.4.10
*July 20, 2022*
* **Google Pay Flow Improvements**\
Improved Google Pay flow performance and reliability. No API changes required.
* **SDK State After App Kill**\
Fixed an issue where the SDK failed to restore its state correctly after the host app was killed by the system. No API changes required.
## v1.4.9
*July 5, 2022*
**New Payment Methods**
* **Google Pay Payment Method**\
Added Google Pay as a supported payment method. No API changes required.
* **Voucher Card Payment Method**\
Added support for VOUCHER card payments. No API changes required.
* **SafetyPay Payment Method**\
Added support for SafetyPay as a payment method. No API changes required.
* **Efecty Payment Method**\
Added support for Efecty as a payment method. No API changes required.
* **Nequi Payment Method**\
Added support for Nequi as a payment method. No API changes required.
* **Yappy Payment Method**\
Added support for Yappy as a payment method. No API changes required.
* **Sencillito Payment Method**\
Added support for Sencillito as a payment method. No API changes required.
* **Card Payment Installments**\
Added installments support for card payments, allowing customers to split payments into multiple installments. No API changes required.
* **Antifraud Session ID Generation**\
Added `sessionId` generation for antifraud providers via `startCheckout()`. No API changes required.
* **Persistent Loader Option**\
Added an option to persist the SDK loader between payment steps for a smoother transition experience. No API changes required.
* **Step-by-Step Enrollment CVV Fields**\
Fixed missing CVV and expiry fields in the step-by-step card enrollment flow. No API changes required.
## v1.4.8
*June 20, 2022*
* **Google Pay Flow Improvements**\
Improved Google Pay flow performance and reliability. No API changes required.
## v1.4.7
*June 5, 2022*
* **Step-by-Step Enrollment CVV Fields**\
Fixed missing CVV and expiry fields in the step-by-step card enrollment flow. No API changes required.
## v1.4.6
*May 25, 2022*
* **Voucher Card Payment Method**\
Added support for VOUCHER card payments. No API changes required.
* **Google Pay Flow Improvements**\
Improved Google Pay flow performance and reliability. No API changes required.
## v1.4.5
*May 10, 2022*
* **Card and PIX Flow Design**\
Improved the visual design of card step-by-step and PIX payment flows. No API changes required.
## v1.4.4
*April 25, 2022*
* **3DS Flow Improvements for Cards**\
Improved the 3DS authentication flow for card payments for better reliability and compatibility. No API changes required.
## v1.4.3
*April 10, 2022*
* **Card Step-by-Step Field Navigation**\
Improved field navigation and focus handling in the step-by-step card form for a smoother data entry experience. No API changes required.
## v1.4.2
*March 25, 2022*
* **Card Step-by-Step Design**\
Improved the visual design of the step-by-step card payment form. No API changes required.
## v1.4.1
*March 10, 2022*
* **Google Pay Payment Method**\
Added Google Pay as a supported payment method. No API changes required.
* **Sencillito Payment Method**\
Added support for Sencillito as a payment method. No API changes required.
## v1.4.0
*February 20, 2022*
**New Payment Methods**
* **SafetyPay Payment Method**\
Added support for SafetyPay as a payment method. No API changes required.
* **Efecty Payment Method**\
Added support for Efecty as a payment method. No API changes required.
* **Nequi Payment Method**\
Added support for Nequi as a payment method. No API changes required.
* **Yappy Payment Method**\
Added support for Yappy as a payment method. No API changes required.
* **Card Payment Installments**\
Added installments support for card payments, allowing customers to split payments into multiple installments. No API changes required.
* **Antifraud Session ID Generation**\
Added `sessionId` generation for antifraud providers via `startCheckout()`. No API changes required.
* **Persistent Loader Option**\
Added an option to persist the SDK loader between payment steps for a smoother transition experience. No API changes required.
## v1.3.9
*February 5, 2022*
* **Loading Screen Design**\
Added a new loading screen design for a more polished SDK experience. No API changes required.
* **Mercado Pago Checkout Pro Formless**\
Mercado Pago Checkout Pro no longer requires filling out a form before redirecting, simplifying the checkout experience. No API changes required.
* **Card Step-by-Step Flow Fix**\
Fixed an issue in the step-by-step card payment flow that caused incorrect behavior in certain scenarios. No API changes required.
## v1.3.8
*January 20, 2022*
* **Null Customer Document Crash**\
Fixed a crash that occurred when the customer object had a null document field. No API changes required.
## v1.3.7
*January 5, 2022*
* **Card Flows Improvements**\
General improvements to card payment and enrollment flows for better stability and user experience. No API changes required.
## v1.3.6
*December 15, 2021*
* **Dynamic CVV Requirement for Enrolled Cards**\
Removed the static flag to require CVV on enrolled cards. CVV requirement is now determined dynamically based on the payment method configuration. No API changes required.
## v1.3.5
*December 1, 2021*
* **Cash Payment Method**\
Added support for CASH as a payment method option. No API changes required.
* **Bank Transfer Payment Method**\
Added support for BANK\_TRANSFER as a payment method option. No API changes required.
## v1.3.4
*November 15, 2021*
* **Unlimint Payment Method**\
Added support for Unlimint as a payment method option. No API changes required.
* **PagSeguro Payment Method**\
Added support for PagSeguro as a payment method option. No API changes required.
## v1.3.3
*November 1, 2021*
* **Step-by-Step Card Form Design**\
Fixed visual design issues in the step-by-step card payment form. No API changes required.
## v1.3.2
*October 15, 2021*
**New Payment Methods**
* **Tarjeta Clave Payment Method**\
Added support for Tarjeta Clave as a payment method option. No API changes required.
* **Kushki Payment Method**\
Added support for Kushki as a payment method option. No API changes required.
* **Khipu Payment Method**\
Added support for Khipu as a payment method option. No API changes required.
* **CVV Request Flag for Enrolled Cards**\
Added `requestSecurityCode` to `YunoConfig` to enable CVV requests for enrolled card payments at SDK initialization. Set `requestSecurityCode = true` in your `YunoConfig` to prompt users for CVV when paying with enrolled cards.
```kotlin theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
data class YunoConfig(
val cardFlow: CardFormType = CardFormType.ONE_STEP,
val saveCardEnabled: Boolean = false,
val requestSecurityCode: Boolean = false
)
```
* **OTP Screen Expiration Timer**\
Added a countdown timer to the OTP screen to communicate payment expiration time to users. No API changes required.
* **EnrollmentMethodsListView Component**\
Added `EnrollmentMethodsListView()` component to display payment methods available for enrollment. No API changes required.
## v1.3.1
*October 1, 2021*
* **Paga con Rappi Payment Method**\
Added support for Paga con Rappi as a payment method option. No API changes required.
## v1.3.0
*September 15, 2021*
**New Payment Methods**
* **Arcus Cash Payment Method**\
Added support for Arcus Cash as a payment method option. No API changes required.
* **Daviplata Payment Method**\
Added support for Daviplata as a payment method option. No API changes required.
* **CoDi Payment Method**\
Added support for CoDi as a payment method option. No API changes required.
* **PayValida Payment Method**\
Added support for PayValida as a payment method option. No API changes required.
* **Save Card via YunoConfig**\
Added `saveCardEnabled` to `YunoConfig` to enable or disable the Save Card option during payment. Set `saveCardEnabled = true` in your `YunoConfig` during `initialize` to allow users to save their cards.
```kotlin theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
data class YunoConfig(
val cardFlow: CardFormType = CardFormType.ONE_STEP,
val saveCardEnabled: Boolean = false
)
```
## v1.2.5
*September 1, 2021*
* **Payment and Enrollment Cancel State**\
Fixed incorrect state reported when a user cancels during payment or enrollment flows. No API changes required.
## v1.2.4
*August 15, 2021*
* **SPEI Payment Method**\
Added support for SPEI as a payment method option. No API changes required.
* **Step-by-Step Card Enrollment and Payment**\
Added a step-by-step card form for both Enrollment and Payment flows, allowing users to enter card data field by field. No API changes required.
## v1.2.2
*August 1, 2021*
* **Enrollment State Callback**\
Added an enrollment state callback to `startEnrollment`, allowing you to respond to enrollment lifecycle events without using `onActivityResult`. No API changes required.
* **Payment State Callback in continuePayment**\
Added a payment state callback to `continuePayment`, allowing you to handle payment continuation events without using `onActivityResult`. No API changes required.
* **One-Time Token Callback in startPayment**\
Added a one-time token callback to `startPayment`, allowing you to receive the OTT directly without using `onActivityResult`. No API changes required.
## v1.2.1
*July 20, 2021*
* **Spanish Typo in Card Payment**\
Fixed a typo in the Spanish localization for the card payment screen title. No API changes required.
* **Document Number Field Error Message**\
Fixed an incorrect error message displayed on the document number input field. No API changes required.
## v1.2.0
*July 5, 2021*
* **startPayment Callback Migration**\
Added a direct callback parameter to `startPayment` to replace `onActivityResult` for receiving payment results. Update your integration to use the new callback parameter instead of `onActivityResult`.
* **initEnrollment Callback Migration**\
Added `initEnrollment` method with a direct callback to replace `onActivityResult` for receiving enrollment results. Update your integration to use `initEnrollment` with the callback parameter instead of `onActivityResult`.
## v1.1.1
*June 20, 2021*
* **Production Environment Tag Hidden**\
Fixed an issue where the environment label was displayed for production API keys. The tag is now hidden in production builds. No API changes required.
## v1.1.0
*June 5, 2021*
**New Features**
* **Credit Card Enrollment Flow**\
Added a full credit card enrollment flow to the SDK, allowing users to save cards for future payments. No API changes required.
* **EnrollmentPaymentMethodListView Component**\
Added `EnrollmentPaymentMethodListView()` and `UnEnrolledPaymentMethodListView()` components to display enrolled and un-enrolled payment methods separately. No API changes required.
* **PaymentMethodListView onSelected Event**\
Added an `onSelected` event to `PaymentMethodListView` for responding to user payment method selection. No API changes required.
* **startEnrollment Requires Country Code**\
`startEnrollment` now requires a country code parameter (e.g., `"CO"`). Add the country code argument to all `startEnrollment` calls in your integration.
* **testResult Options Removed**\
Removed `testResult` configuration options from the SDK. Remove any references to `testResult` from your integration code.
* **Expiration Date Validation**\
Improved expiration date validation in the Credit Card form to reject invalid dates more accurately. No API changes required.
## v1.0.11
*May 20, 2021*
* **Enrollment UX After External App**\
Fixed a UX issue in the enrollment flow that occurred after returning from an external app interaction, such as a bank app redirect. No API changes required.
## v1.0.10
*May 10, 2021*
* **404 Error After Enrollment**\
Fixed a 404 error that was triggered after completing the card enrollment flow. No API changes required.
## v1.0.9
*April 25, 2021*
* **Infinite Loader in Payment Lite Flow**\
Fixed an issue where the loader spinner would not dismiss during the payment lite flow, blocking user interaction. No API changes required.
## v1.0.8
*April 10, 2021*
* **Replaced Moshi with Gson**\
Replaced the Moshi JSON serialization dependency with Gson to reduce SDK size and improve compatibility. No API changes required.
## v1.0.7
*March 25, 2021*
* **Android Hint Type on Attrs**\
Updated the Android hint type declaration on attributes that use resource references to ensure proper rendering across API levels. No API changes required.
## v1.0.6
*March 10, 2021*
* **Payment Method Item Design**\
Fixed visual design issues with payment method list items in the full SDK variant. No API changes required.
* **Phone Field Visibility**\
Fixed an issue where the phone number input field was incorrectly hidden in some payment flows. No API changes required.
## v1.0.5
*February 25, 2021*
* **SafetyPay Payment Method**\
Added support for SafetyPay as a payment method option. No API changes required.
* **WebSocket Payment State Notifications**\
Added WebSocket support for real-time payment state notifications during the checkout flow. No API changes required.
* **CustomerForm Regex Validators**\
Fixed regex validation errors in the CustomerForm that rejected valid input on certain fields. No API changes required.
## v1.0.4
*February 10, 2021*
* **Transaction Status Set to Pending on Start**\
The transaction status is now set to pending immediately upon payment initiation, providing more accurate state tracking. No API changes required.
## v1.0.3
*January 25, 2021*
* **Internal Error State Callback**\
Added an internal error state callback to surface SDK-level errors to the integrating application. No API changes required.
## v1.0.2
*January 15, 2021*
* **CVV Regex Reset on Card Number Delete**\
Fixed an issue where the CVV regex validator was not reset when the card number was deleted in the payment form, causing invalid CVV validation states. No API changes required.
## v1.0.1
*January 5, 2021*
* **Bank Transfer and Card Payment Filter**\
Added a payment type filter to allow displaying only bank transfer or card payment methods in the payment list view. No API changes required.
* **Payment View Models Testing**\
Added testing features for payment view models to facilitate integration testing. No API changes required.
* **PIX and NuPay Payment Type Name**\
Fixed incorrect payment type names displayed for PIX and NuPay methods in the payment list. No API changes required.
* **UTC Timezone in DateExtension**\
Updated `DateExtension` to use UTC timezone for all date formatting operations to ensure consistent date handling across regions. No API changes required.
## v1.0.0
*December 15, 2020*
**Initial Release**
* **Payment Methods**\
Initial release of the Yuno Android SDK with support for multiple payment methods including Mercado Pago Checkout Pro and debit/credit card payments.
* **Mercado Pago Enrollment**\
Added support for Mercado Pago method enrollment in the initial SDK release. No API changes required.
* **Debit and Credit Card Payments**\
Added support for debit and credit card payments with full card form UI. No API changes required.
* **Initial Bug Fixes**\
Fixed initial issues including city text field hint, PIX type in payments flow, card information on `startCheckout`, and English translation in the payment form title. No API changes required.
# API Changelog
Source: https://docs.y.uno/changelog/api
Latest updates to the Yuno Payments API and platform features
## v2026-07
*July 11, 2026*
**Security**
* **PCI Proxy**\
You can now send stored card data to any third-party API through Yuno's PCI DSS Level 1 environment using the new `/v1/pci-proxy/forward` endpoint, without bringing your systems into PCI scope.
*See also: [PCI Proxy overview](/docs/security-and-compliance/pci-proxy/overview)*
## v2025-06
*June 30, 2025*
* **Optional first and last name for customers**\
The `first_name` and `last_name` fields are now optional when creating a customer via the API. If a payment provider requires them, the SDK form will prompt the user. If you are not using the Yuno SDK, ensure these fields are provided at payment creation time when required by the provider.
*See also: [Create customer reference](/reference/create-customer)*
**Security**
* **3DS SCA exemption support**\
A new optional field `strong_customer_authentication_exemptions` is now available under `payment_method.detail.card.three_d_secure`. Yuno also propagates exemption recommendations from your fraud provider through the full payment route to the 3DS gateway, and the exemption type appears in the payment response, GET API, and webhooks.
*See also: [SCA exemptions guide](/docs/sca-exemptions)*
**Payments**
* **Airline trip type field**\
A new `type` enum field has been added inside `additional_data.airline` to specify the trip type: `ONE_WAY`, `ROUNDTRIP`, or `MULTIPLE_DESTINATIONS`. No integration changes required if you do not use airline data.
*See also: [Create payment reference](/reference/create-payment)*
* **Airline leg ordering fields**\
Two new integer fields, `order` and `route_order`, have been added inside `additional_data.airline.legs` to describe the order of legs within a route and across routes respectively. No integration changes required if you do not use airline leg data.
*See also: [Create payment reference](/reference/create-payment)*
* **Transportation data struct**\
A new `transportations` array of objects is available inside `additional_data` for non-airline travel bookings such as bus, train, ship, tram, and car. Each entry supports legs, passengers, and tickets sub-objects with departure/arrival details.
*See also: [Create payment reference](/reference/create-payment)*
## v2025-05
*May 31, 2025*
**Security**
* **Network token enrollment for vaulted cards**\
When the network tokens feature is enabled, Yuno now generates network tokens for all cards enrolled and stored in the Vault. One-time-use cards are excluded. This aligns with Visa and Mastercard network tokenization standards and improves recurring payment security and reliability.
*See also: [Network tokens guide](/docs/network-tokens)*
**Subscriptions**
* **Subscription billing date control**\
A new `billing_date` struct is available when creating a subscription, letting you define billing timing as `PREPAID`, `POSTDATE`, or a specific `DAY` of the month. This field is mutually exclusive with the `frequency` object.
*See also: [Subscriptions guide](/docs/subscriptions)*
**Payments**
* **Payment method expiration date field**\
A new `expirates_at` timestamp field is now returned inside `payment_method_detail.wallet` for asynchronous payment methods that support it. Availability depends on provider support.
*See also: [Create payment reference](/reference/create-payment)*
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
"payment_method": {
"type": "NU_PAY",
"payment_method_detail": {
"wallet": {
"expirates_at": "2025-05-14T15:06:48.383418Z"
}
}
}
```
* **Customer geolocation in payments**\
A new `geolocation` object with `latitude` and `longitude` fields is now available inside `customer_payer` when creating a payment.
*See also: [Create payment reference](/reference/create-payment)*
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
"customer_payer": {
"id": "b080db73-b12d-4710-a604-d659bce26f01",
"geolocation": {
"latitude": "-34.4720",
"longitude": "-58.5300"
}
}
```
* **Cancel PENDING APM payments**\
You can now cancel a `PENDING` payment created with an alternative payment method (APM) via the cancel endpoint. Previously this was restricted to card transactions only. Feature availability depends on provider support.
*See also: [Cancel payment reference](/reference/cancel-payment)*
**Webhooks**
* **Subscription webhook URL support**\
You can now define a `webhook_url` in the Developers section of the dashboard to receive subscription lifecycle events. Different event types produce distinct webhook payloads.
*See also: [Webhooks documentation](/docs/configure-webhooks)*
## v2025-04
*April 30, 2025*
**Security**
* **3DS setup service removed**\
The separate setup service call for the 3DS direct implementation is no longer required. Data collection and setup are now handled automatically inside payment creation, simplifying the integration flow.
*See also: [3D Secure guide](/docs/security-and-compliance/3d-secure)*
**Payments**
* **Extended airline leg fields**\
New fields have been added inside `additional_data.airline.legs`: `arrival_airport_country`, `arrival_airport_city`, `departure_airport_country`, and `departure_airport_city`. Also, a `booking_system_code` and `booking_system_name` are now available inside `airline.tickets[].issue`. No integration changes required if you do not use airline data.
*See also: [Create payment reference](/reference/create-payment)*
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
"additional_data": {
"airline": {
"legs": [
{
"arrival_airport": "AMS",
"arrival_airport_country": "AR",
"arrival_airport_city": "BUE",
"departure_airport": "EZE",
"departure_airport_country": "AR",
"departure_airport_city": "BUE"
}
],
"tickets": [
{
"issue": {
"booking_system_code": "TT01",
"booking_system_name": "booking system"
}
}
]
}
}
```
## v2025-03
*March 31, 2025*
**Payments**
* **Discounts array in order data**\
A new `discounts` array of objects is available inside `additional_data.order`. Each discount entry supports `id`, `name`, and `unit_amount` fields.
*See also: [Payment amount details guide](/docs/payment-amount-details#discounts)*
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
"additional_data": {
"order": {
"discounts": [
{
"id": "XYZ",
"name": "Offer",
"unit_amount": "100"
}
]
}
}
```
* **Monitors flag in routing rules**\
A new boolean field `monitors` has been added inside the `routing_rules` object in the payment response, indicating whether a transaction was processed through the Monitors feature. No integration changes required.
*See also: [Payment object reference](/reference/the-payment-object)*
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
"routing_rules": {
"smart_routing": false,
"monitors": true,
"condition": {
"id": 133892,
"name": null,
"description": null
}
}
```
**Refunds**
* **Customer info in refund requests**\
A new `customer_payer` object is now accepted in refund requests, allowing you to pass additional customer data (e.g., `document`) to providers that require it.
*See also: [Refund payment reference](/reference/refund-payment)*
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"description": "Duplicate",
"reason": "REQUESTED_BY_CUSTOMER",
"merchant_reference": "AAB01-432245",
"customer_payer": {
"document": {
"document_type": "DNI",
"document_number": "38919283"
}
}
}
```
## v2025-02
*February 28, 2025*
**Webhooks**
* **OAuth2 authentication for webhooks**\
Webhooks now support OAuth2 authentication. Configure `authentication_url`, `client_secret_key`, `client_id`, and `grant_type` in the Developers/Webhooks dashboard section so Yuno can obtain tokens for secure webhook delivery.
*See also: [Configure webhooks guide](/docs/configure-webhooks)*
* **Dedicated URL for chargeback webhooks**\
You can now configure a dedicated webhook URL specifically for chargeback events. Previously, chargebacks were bundled with the Purchase trigger. Update your webhook configuration in the dashboard to use the new dedicated chargeback URL.
*See also: [Configure webhooks guide](/docs/configure-webhooks)*
## v2025-01
*January 31, 2025*
**Payments**
* **Ticket data in payment orders**\
A new `tickets` array of objects is available inside `additional_data.order`, supporting fields like `id`, `name`, `description`, `type`, `amount`, and a nested `event` object with address details.
*See also: [Payment API reference](/reference/payment)*
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
"additional_data": {
"order": {
"tickets": [
{
"id": "XYZ",
"name": "Music",
"type": "VIRTUAL",
"amount": {
"currency": "COP",
"value": 5000
},
"event": {
"id": "ADMKASLMD",
"name": "Music festival",
"type": "FESTIVAL",
"date": "1990-02-28"
}
}
]
}
}
```
**Subscriptions**
* **Subscription initial payment validation**\
A new boolean field `initial_payment_validation` is available when creating a subscription. Set to `true` to continue the subscription only after a successful first payment, or `false` to continue regardless of the first payment outcome.
*See also: [Create subscription reference](/reference/create-subscription)*
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"initial_payment_validation": true
}
```
## v2024-12
*December 31, 2024*
**Payments**
* **Card type selection for vaulted tokens**\
When using a vaulted token for payment, you can now specify `card_data.type` as `CREDIT` or `DEBIT` inside `payment_method.detail.card`. Useful for markets like Brazil where the same card can be used for both transaction types.
*See also: [Payment API reference](/reference/create-payment)*
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
"payment_method": {
"type": "CARD",
"vaulted_token": "e2961d37-9898-4bac-8408-cc9f02c11cc2",
"detail": {
"card": {
"card_data": {
"type": "DEBIT"
}
}
}
}
```
* **Account funding transaction details**\
A new `account_funding` object is available inside `additional_data`, supporting `sender` and `beneficiary` sub-objects with name, email, and document fields required for Account Funding Transactions (AFT).
*See also: [AFT guide](/docs/account-funding-transactions-afts)*
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
"additional_data": {
"account_funding": {
"sender": {
"first_name": "John",
"last_name": "Doe",
"email": "john.doe@mail.com"
},
"beneficiary": {
"first_name": "Chris",
"last_name": "Martin",
"document": {
"document_number": "38192019",
"document_type": "CC"
}
}
}
}
```
* **Network transaction ID for stored credentials**\
A new `network_transaction_id` field is now available inside `payment_method.detail.card.stored_credentials`. Recommended for subscription payments with enrolled cards to ensure traceability across the payment lifecycle.
*See also: [Stored credentials guide](/docs/stored-credentials)*
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
"payment_method": {
"type": "CARD",
"vaulted_token": "eb8caa17-6407-457b-960e-125d8d7a90c1",
"detail": {
"card": {
"stored_credentials": {
"reason": "CARD_ON_FILE",
"usage": "USED",
"network_transaction_id": "583103536844189"
}
}
}
}
```
* **Smart routing flag in payment response**\
A new boolean field `smart_routing` has been added inside the `routing_rules` object in the payment response, indicating whether the transaction was processed through the smart routing feature. No integration changes required.
*See also: [Payment API reference](/reference/create-payment)*
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
"routing_rules": {
"smart_routing": false,
"condition": {
"id": 133892,
"name": null,
"description": null
}
}
```
**Subscriptions**
* **Trial period for subscriptions**\
A new `trial_period` object is available when creating a subscription. Define `billing_cycles` and a reduced `amount` to offer partial or full (free) trial periods before full billing begins.
*See also: [Create subscription reference](/reference/create-subscription)*
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
"trial_period": {
"billing_cycles": "1",
"amount": {
"currency": "COP",
"value": 2500
}
}
```
## v2024-11
*November 30, 2024*
**Payments**
* **Card expiration fields in transaction response**\
Two new fields, `expiration_month` and `expiration_year`, are now returned inside `transactions.card_data` in the payment response. No integration changes required.
*See also: [Payment object reference](/reference/the-payment-object)*
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
"card_data": {
"holder_name": "Paco",
"iin": "48710499",
"brand": "VISA",
"fingerprint": "71000db4-f8e7-4ea0-a2cc-9d9ebb76a955",
"expiration_month": 3,
"expiration_year": 30
}
```
* **Recipients for split marketplace payments**\
A new Recipients API allows you to register recipients with multiple provider mappings before sending split payments. Use `recipient_id` in the `split_marketplace` array instead of provider-specific IDs when multiple providers are involved.
*See also: [Split payments marketplace guide](/docs/payment-features/split-payments-marketplace)*
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
"split_marketplace": [
{
"amount": { "currency": "BRL", "value": 500 },
"recipient_id": "09d8bad7-4efe-47e2-b9ee-f4028460bab1",
"type": "PURCHASE"
},
{
"amount": { "currency": "BRL", "value": 500 },
"recipient_id": "d94e02c1-cc47-4e60-a20a-2b17fe58992d",
"type": "PURCHASE"
}
]
```
**Refunds**
* **Receipt support for refund transactions**\
Refund requests now accept a `response_additional_data.receipt` boolean and an optional `receipt_language` field. When set, a receipt URL is returned in `payment.transaction.receipt_url` after the refund is processed.
*See also: [Refund payment reference](/reference/refund-payment)*
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"description": "Duplicate",
"reason": "REQUESTED_BY_CUSTOMER",
"merchant_reference": "AAB01-432245",
"response_additional_data": {
"receipt": true,
"receipt_language": "ES"
}
}
```
**Subscriptions**
* **Items data for subscriptions**\
A new `additional_data.order.items` array is now available when creating a subscription, allowing you to pass item-level details (category, id, name, quantity, unit\_amount) to providers.
*See also: [Create subscription reference](/reference/create-subscription)*
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
"additional_data": {
"order": {
"items": [
{
"category": "art",
"id": "AA01",
"name": "Test item",
"quantity": 1,
"unit_amount": 10
}
]
}
}
```
**Payouts**
* **Payouts to vaulted tokens**\
The Payouts API now supports sending payouts directly to enrolled credit or debit cards using a `vaulted_token` inside `withdrawal_method`. Provider support required.
*See also: [Create payout reference](/reference/create-payout)*
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
"withdrawal_method": {
"type": "CARD",
"provider_id": "UNLIMINT",
"vaulted_token": "your-vaulted-token"
}
```
## v2024-10
*October 31, 2024*
**Subscriptions**
* **Smart retry scheme for subscriptions**\
Subscription declined transactions now support Smart Retries using machine learning to determine optimal retry timing. The retry schedule follows seven attempts over 96 hours. Configure via the Subscriptions dashboard.
*See also: [Transaction retries guide](/docs/payment-features/transaction-retries)*
**Payments**
* **Parent payment method type field**\
A new `parent_payment_method_type` field is returned inside `transactions.payment_method` indicating the wallet provider (`APPLE_PAY`, `GOOGLE_PAY`, or `CLICK_TO_PAY`) used in a direct wallet integration. No integration changes required.
*See also: [Payment object reference](/reference/the-payment-object)*
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
"transactions": {
"payment_method": {
"vaulted_token": "29b44e45-57fe-41b0-81c8-586deeb699b2",
"type": "CARD",
"parent_payment_method_type": "CLICK_TO_PAY"
}
}
```
* **Connection ID in transaction data**\
A new `connection_data.id` field is returned inside each transaction object, providing the unique identifier of the payment connection used to process the transaction. No integration changes required.
*See also: [Payment object reference](/reference/the-payment-object)*
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
"connection_data": {
"id": "88292fd3-bf5b-4b23-bb95-7186ba4e7f88"
}
```
* **Receipt support for cancel transactions**\
Cancel requests now accept a `response_additional_data.receipt` boolean. When set, a receipt URL is returned in `payment.transaction.receipt_url` after the cancellation is processed.
*See also: [Cancel payment reference](/reference/cancel-payment)*
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"description": "Duplicate",
"reason": "REQUESTED_BY_CUSTOMER",
"merchant_reference": "AAB01-432245",
"response_additional_data": {
"receipt": true
}
}
```
* **Shipping object in payment request**\
A new `shipping` object is available when creating a payment, supporting fields `type`, `description`, `carrier`, and `deliver_at` to specify shipment details.
*See also: [Payment object reference](/reference/the-payment-object)*
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
"shipping": {
"type": "STANDARD",
"description": "Test shipment",
"carrier": "UPS",
"deliver_at": "2024-09-17T20:43:54.786342Z"
}
```
## v2024-09
*September 30, 2024*
**Payments**
* **Payment link enrollment flow**\
Payment links now support card enrollment on successful payment. Set `one_time_use=true` and `vault_on_success=true` when creating a payment link to generate a new `vaulted_token` for the customer upon payment success.
*See also: [Enroll cards with payment links guide](/docs/enroll-cards-with-payment-link)*
* **Split marketplace payments**\
A new `split_marketplace` array is now available in the payment request, allowing merchants to divide a payment among multiple recipients with configurable amounts, types (`PURCHASE`, `COMMISSION`), and liability settings. Provider support required.
*See also: [Split marketplace guide](/docs/split-payments-marketplace)*
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
"split_marketplace": [
{
"provider_recipient_id": "recipient_123",
"type": "PURCHASE",
"amount": { "value": 7500, "currency": "COP" },
"liability": {
"processing_fee": "MERCHANT",
"chargebacks": false
}
},
{
"provider_recipient_id": "recipient_456",
"type": "COMMISSION",
"amount": { "percentage": 30, "currency": "COP" },
"liability": {
"processing_fee": "RECIPIENT",
"chargebacks": true
}
}
]
```
## v2024-08
*August 31, 2024*
**Subscriptions**
* **Subscription agreement ID field**\
A new `subscription_agreement_id` field is available inside `payment_method.detail.card.stored_credentials`, required by certain markets and processors (e.g., Mexico) to include the agreement ID with the customer in subscription-related payments.
*See also: [Stored credentials guide](/docs/stored-credentials#subscription-agreement)*
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
"payment_method": {
"type": "CARD",
"vaulted_token": "eb8caa17-6407-457b-960e-125d8d7a90c1",
"detail": {
"card": {
"stored_credentials": {
"reason": "CARD_ON_FILE",
"usage": "USED",
"subscription_agreement_id": "AA0001"
}
}
}
}
```
**Payouts**
* **Referenced payouts from transactions**\
Payouts to card payment methods now support a `original_transaction_id` field inside `withdrawal_method`, enabling merchants to initiate a payout using card data from a prior transaction without needing PCI compliance.
*See also: [Payouts guide](/docs/payouts)*
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
"withdrawal_method": {
"type": "STP_PAYOUT",
"provider_id": "STP",
"original_transaction_id": "9104911d-5df9-429e-8488-ad41abea1a4b"
}
```
**Payments**
* **Currency conversion in payments**\
A new `currency_conversion` object is available inside the `amount` struct, allowing you to pass `provider_currency_conversion_id`, `cardholder_currency`, and `cardholder_amount` for dual-currency settlement. Contact your technical account manager to enable.
*See also: [Currency conversion guide](/docs/currency-conversion)*
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
"amount": {
"currency": "COP",
"value": 5000,
"currency_conversion": {
"provider_currency_conversion_id": "AAA01SADOIAJSDLAKSJM",
"cardholder_currency": "ARS",
"cardholder_amount": 1146.55
}
}
```
* **ISO 8583 response code and message**\
Two new fields, `iso8583_response_code` and `iso8583_response_message`, are now returned inside `transactions.provider_data`, providing the direct ISO 8583 response from the provider. ABECS codes are also surfaced in these fields for Brazilian providers.
*See also: [Payment object reference](/reference/the-payment-object)*
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
"provider_data": {
"id": "ADYEN",
"transaction_id": "FLX4WSXF7SFZDV65",
"iso8583_response_code": "05",
"iso8583_response_message": "Approved or completed successfully"
}
```
* **Cancel or refund payment by payment ID**\
A new endpoint allows you to cancel or refund a payment by providing only the `payment_id`, without needing the `transaction_id`. The existing transaction-level endpoint remains available.
*See also: [Cancel or refund payment reference](/reference/cancel-or-refund-a-payment)*
## v2024-07
*July 31, 2024*
**Payments**
* **Wallet cryptogram for native pay**\
A new `cryptogram` field is available inside `payment_method.detail.wallet` when creating a payment, enabling direct Apple Pay and Google Pay API integrations without using the Yuno SDK.
*See also: [Apple Pay direct integration guide](/docs/apple-pay-direct-integration)*
* **Taxes array in order data**\
A new `taxes` array of objects is available inside `additional_data.order`, supporting multiple tax lines per payment. The prior top-level `tax` object remains supported but the new array is recommended for better tax management.
*See also: [Payment amount details guide](/docs/payment-amount-details#taxes)*
**Refunds**
* **Simplified mode for refund retries**\
The `simplified_mode: true` flag is now supported in refund requests. Yuno will return a `DECLINED` status and automatically retry the refund up to five times within 24 hours, keeping the payment in `PENDING`/`RETRY_IN_PROCESS` status.
*See also: [Transaction retries guide](/docs/transaction-retries)*
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"simplified_mode": true,
"reason": "REQUESTED_BY_CUSTOMER",
"merchant_reference": "AA01"
}
```
## v2024-06
*June 30, 2024*
**Payouts**
* **Payouts product launch**\
Yuno Payouts is now available as a new API product for sending funds to beneficiaries (users, merchants, providers, customers) across banks, cards, and wallets through multiple providers. Refer to the payouts documentation to get started.
*See also: [Payouts guide](/docs/payouts)*
**Payments**
* **Payment method fingerprint field**\
A new `fingerprint` field is returned in the payment method object and in the payment response for card transactions. It uniquely identifies a card across multiple `vaulted_tokens` within your organization.
*See also: [Enroll payment methods guide](/docs/enroll-payment-methods#step-5-retrieve-payment-methods)*
## v2024-05
*May 31, 2024*
**Payments**
* **Simplified mode for capture retries**\
A new `simplified_mode` boolean is available in capture requests. When set to `true`, Yuno returns a `SUCCEEDED` status immediately and automatically retries failed transactions up to five times within a 24-hour period.
*See also: [Transaction retries guide](/docs/transaction-retries)*
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"amount": { "currency": "COP", "value": "5000" },
"simplified_mode": true,
"reason": "PRODUCT_CONFIRMED",
"merchant_reference": "AA01"
}
```
* **Benefit type field for Pluxee payments**\
A new `benefity_type` field has been added to the payment object for the Pluxee payment method in Chile. Required when using the `DIRECT` workflow.
*See also: [Payment object reference](/reference/the-payment-object)*
## v2024-04
*April 30, 2024*
* **Routing rules in payment response**\
A new `routing_rules` object is now returned in the payment response, containing a `condition` sub-object with the `id`, `name`, and `description` of the routing rule applied during payment creation. No integration changes required.
*See also: [Payment object reference](/reference/the-payment-object)*
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
"routing_rules": {
"condition": {
"id": 76152,
"name": "PAYMENTS_COLOMBIA",
"description": "This condition is set for payments made only in Colombia"
}
}
```
## v2024-03
*March 31, 2024*
**Payments**
* **Merchant customer created at field**\
A new `merchant_customer_created_at` field (ISO 8601 format) is available in the Customer and `customer_payer` objects, representing the date the customer registered on the merchant platform.
*See also: [Customer object reference](/reference/the-customer-object)*
* **Installments plan in checkout session**\
A new `installments.plan` array and `installments.plan_id` field are available in the checkout session object, allowing you to specify a custom installments plan per session. If omitted, the account-level plan is used.
*See also: [Create checkout session reference](/reference/create-checkout-session)*
* **Callback URL for payment links**\
A new `callback_url` field is available when creating a payment link, specifying the URL the customer is redirected to after completing payment.
*See also: [Payment link object reference](/reference/the-payment-link-object)*
## v2024-02
*February 29, 2024*
* **Neighborhood field in address objects**\
A new `neighborhood` field (3–255 characters) has been added to `shipping_address` and `billing_address` in the Customer object.
*See also: [Customer object reference](/reference/the-customer-object)*
**Payments**
* **Transactions history array**\
A new `transactions_history` array is now returned in the payment object, listing all transactions associated with a payment including those across multiple provider routes.
*See also: [Payment object reference](/reference/the-payment-object)*
* **Tip amount field in order data**\
A new `tip_amount` field is available inside `additional_data.order`. This is informational only — the tip amount is already included in the total transaction value and is not added separately.
*See also: [Payment amount details guide](/docs/payment-amount-details)*
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
"additional_data": {
"order": {
"tip_amount": 50.00
}
}
```
* **In-progress capture error message**\
The API now returns a specific error response when a capture is attempted while another capture is already in progress: `INVALID_STATUS` with message "Invalid transaction status. Transaction already in progress". No integration changes required.
*See also: [Payment object reference](/reference/the-payment-object)*
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"code": "INVALID_STATUS",
"messages": [
"Invalid transaction status. Transaction already in progress"
]
}
```
## v2024-01
*January 31, 2024*
* **Provider data fields in transaction**\
Three new fields are now returned inside `transactions.provider_data`: `response_code` (provider outcome code), `third_party_account_id` (processor account ID), and `third_party_transaction_id` (processor transaction ID). No integration changes required.
*See also: [Payment object reference](/reference/the-payment-object)*
**Security**
* **Stored credentials support**\
Yuno now supports Visa and Mastercard stored credentials rules, allowing merchants to mark payments as Customer Initiated Transactions (CIT) or Merchant Initiated Transactions (MIT) via the `stored_credentials` struct inside `payment_method.detail.card`.
*See also: [Stored credentials guide](/docs/stored-credentials)*
# Flutter SDK Changelog
Source: https://docs.y.uno/changelog/flutter
Latest updates and version history for the Yuno Flutter SDK
## v1.0.17
* **Update Android SDK Version**\
Native Android SDK updated to version 2.17.3.
## v1.0.16
* **Native Android SDK Update**\
Updated the native Android SDK to version 2.17.2.
## v1.0.15
* **Android OTT and Payment Status Delivery**\
Resolved an issue where the Android one-time token and payment status were not delivered to the app when using native Android SDK 2.15.0 or newer.
* **Native SDK Updates**\
Updated native Android SDK to version 2.17.1 and iOS SDK to version 2.18.0.
## v1.0.14
* **Android SDK Update**\
Updated the native Android SDK to version 2.15.1.
## v1.0.13
* **Updated Android SDK**\
The native Android SDK has been updated to version 2.15.0.
* **Updated iOS SDK**\
The native iOS SDK has been updated to version 2.16.0.
## v1.0.12
* **Android SDK Update**\
Updated the native Android SDK to version 2.13.4.
* **Cross-Platform Appearance Configuration**\
Added a shared appearance configuration that lets integrators customize the SDK look and feel across Android and iOS from a single setting.
* **Platform-Specific Appearance Overrides**\
Added platform-specific appearance settings that take priority over the shared appearance configuration, letting integrators tailor the look and feel per platform.
* **Android Font Name Normalization**\
Android automatically normalizes font names so integrators can reference fonts using their natural name (for example, Dancing Script).
## v1.0.11
* **Native Android SDK Version Update**\
Updated the native Android SDK dependency to the latest version. No API changes required.
## v1.0.10
* **Native Android SDK Version Update**\
Updated the native Android SDK dependency to the latest version. No API changes required.
## v1.0.9
* **Hindi, Bengali, Malayalam, and Urdu Support**\
Added support for Hindi, Bengali, Malayalam, and Urdu languages. No additional configuration is required to enable these languages.
* **Updated Android SDK**\
The native Android SDK has been updated to version 2.13.0.
* **Updated iOS SDK**\
The native iOS SDK has been updated to version 2.14.1.
## v1.0.8
* **Native SDK Versions Update**\
Updated the native Android and iOS SDK dependencies to their latest versions. No API changes required.
## v1.0.5
* **Transparent Button Colors**\
Fixed an issue where button colors appeared as clear or transparent when not explicitly configured.
## v1.0.4
* **Dependency Updates**\
Updated internal dependencies to resolve compatibility conflicts. No integration changes required.
## v1.0.3
* **Updated Android SDK**\
The native Android SDK has been updated to version 2.10.0.
* **Updated iOS SDK**\
The native iOS SDK has been updated to version 2.11.1.
## v1.0.2
* **Updated Android SDK**\
The native Android SDK has been updated to version 2.8.1.
* **Updated iOS SDK**\
The native iOS SDK has been updated to version 2.9.0.
* **Kotlin 2.x Compatibility**\
Fixed Android compatibility with Kotlin 2.x and the Compose Compiler plugin.
## v1.0.1
* **Android SDK Version Correction**\
Corrected the native Android SDK version to 2.6.5.
## v1.0.0
* **Native SDK Versions Update**\
Updated the native Android and iOS SDK dependencies to their latest versions.
# Changelog Overview
Source: https://docs.y.uno/changelog/index
Stay up to date with the latest changes across all Yuno SDKs and plugins
## Types of changes
* : for new features.
* : for changes in existing functionality.
* : for soon-to-be removed features.
* : for now removed features.
* : for any bug fixes.
* : in case of vulnerabilities.
* : for changes that require merchant adaptation.
# iOS SDK Changelog
Source: https://docs.y.uno/changelog/ios
Latest updates and version history for the Yuno iOS SDK
## v2.21.2
*August 4, 2026*
* **One-Time Token Creation**\
All fields in the headless `detail` object are now optional.
## v2.21.1
*July 28, 2026*
* **Saved-Card Checkout Behavior**\
The saved-card checkout now correctly collapses the expanded area when no additional information is required, such as when no installment plans are available.
## v2.21.0
*July 23, 2026*
* **Installment Selection Callback**\
Introduced an optional callback to notify merchants whenever an installment option is selected or changed in the card form. This helps in keeping the cart total in sync with the selected installment options.
## v2.20.0
*July 8, 2026*
* **Standard Click to Pay Flow**\
The payment process will now fall back to the standard Click to Pay flow if a checkout session with Passkey enabled lacks a callback URL.
* **Card Number Validation**\
Improved card number validation according to specific card schemes.
* **Document Number Validation**\
Enhanced validation for document numbers with country-specific rules and clearer error messages.
* **Expiry Date Smart Parser**\
Introduced a smart parser for expiry dates that auto-prefixes '0', formats '1X' as '01/X', and caps input at four digits, along with a dedicated error for expired cards.
* **Instruction Icon Display**\
Empty or null icons in the instruction view are now respected, aligning iOS behavior with Web and Android when no icon is provided.
* **Installment ID in Payment Requests**\
The payment request now includes the selected installment ID, defaulting to the plan ID if the installment ID is empty.
* **Saved-Card Checkout Layout**\
Saved-card checkout now shows a compact card summary instead of the large card image, so the CVV field is visible without scrolling.
## v2.19.0
*July 6, 2026*
* **Installments Dropdown Display**\
The total amount is now shown for each option in the installments dropdown.
## v2.18.0
*June 12, 2026*
* **Headless Resume Card Payment**\
Introduced a new method to resume a server-side created card payment, handle remaining actions such as post-3DS challenge, and deliver results through a closure.
## v2.17.2
*June 10, 2026*
* **Bug Fix with Card Forms**\
Resolved a crash issue that occurred with unfolded card forms when using multiple payment methods.
## v2.17.1
*June 2, 2026*
* **Render Mode and Apple Pay Form Issues**\
Resolved issues with the render mode loader and the Apple Pay form view to ensure proper functionality.
## v2.17.0
*May 25, 2026*
* **Netcetera Native 3DS SDK Support**\
Introduced support for the Netcetera Native 3DS SDK, enabling enhanced security for transactions.
* **Slim Form Variant**\
A new form layout is available that consolidates card information and address sections into a more compact format. This is available as an opt-in setting.
* **Secure Payment Badge Visibility**\
Added an opt-in setting to hide the "Secure payment with YUNO" badge, providing greater flexibility in UI customization.
## v2.16.0
*May 8, 2026*
* **Flexible Actions in Enrollment**\
Enrollment now supports the same dynamic action screens used in payments, including PIN, image, payment code, OTP, and info screens.
## v2.15.0
*April 10, 2026*
**Form Experience**
* **Optional Delegate viewController**\
`delegate.viewController` is now optional, simplifying integrations that do not need to provide a presenting controller. No changes required if you are already setting it.
* **Auto-advance**\
The form now auto-advances to the next field when input is valid, reducing keystrokes during checkout. No configuration required.
* **Glass Keyboard Toolbar**\
Added a keyboard toolbar with a glass effect for iOS 26. The toolbar appears automatically on iOS 26 and has no effect on earlier versions.
* **Expiration Date Single Source**\
Removed redundant `@Published` `expirationMonth` and `expirationYear` properties. Expiration date now has a single canonical source, eliminating potential state inconsistencies.
**Address & Contact Collection**
* **Apple Pay Contact Fields**\
The Apple Pay sheet now requests billing/shipping address, name, email, and phone based on the merchant's required fields configuration. Driven by Dashboard settings — no code changes required.
* **Shipping Address Support**\
Card and APM forms now support shipping address entry, including a billing/shipping toggle and field validation.
**Enrollment & Validation Fixes**
* **CVV Length for Enrolled Cards**\
Fixed the CVV field character limit for enrolled cards: the field now enforces the correct length from `securityCodeLength` in the enrollment data. Previously the default 3-digit limit was always applied.
* **Validate IIN Session Header**\
The validate IIN endpoint now sends `customer_session` instead of `checkout_session` during enrollment. This fixes a validation error that occurred when the session type was mismatched.
## v2.14.2
*March 25, 2026*
* **Render Flow Form Hang**\
Fixed an issue where the render flow could hang on the form view when the form was disabled.
## v2.14.1
*March 10, 2026*
* **Card Expiration Year Mismatch**\
Fixed an inconsistency in the card form expiration year value.
## v2.14.0
*February 25, 2026*
* **Apple Pay Flow Order**\
Apple Pay is now triggered before the OTT step for a faster checkout experience.
* **Free Trial Support**\
Added support for free trial transactions.
* **Loader Dismiss Behavior**\
Fixed the loader dismissal so that it properly closes the last presented view controller, preventing stuck screens after loading finishes.
* **Hindi, Bengali, Malayalam and Urdu Localization**\
Added Hindi, Bengali, Malayalam and Urdu language support, including Right-to-Left layout for Urdu.
* **Country Data Endpoint Migration**\
Migrated country data lookups to the checkout country-data endpoint with session headers. No integration changes required.
## v2.13.0
*January 30, 2026*
* **Dynamic CVV Max Length**\
The CVV field now enforces a dynamic maximum length based on the `securityCodeLength` value returned by the API. Previously the field always used a fixed 3-digit limit.
* **Card IIN Endpoint Migration**\
Migrated card IIN lookups to the `card-info` endpoint with checkout session headers. Dynamic co-badged card brand selection is now supported. No integration changes required.
* **Platform Identification API**\
Added a public `setPlatform` method and sub-platform header to all requests. Use `setPlatform` when integrating the SDK inside a wrapper framework.
* **Punto Pago Warning Banner**\
Added a warning banner for the Punto Pago kiosk disclaimer. Activated automatically for eligible payment methods — no integration changes required.
* **Cardholder Name Max Length**\
Increased the cardholder name field maximum length from 50 to 255 characters. No integration changes required.
* **Alphanumeric CNPJ Validation**\
The CNPJ field now accepts alphanumeric input to support the updated Brazilian tax ID format. No integration changes required.
* **API Key Region Support**\
Added region parsing from the API key. The SDK now routes requests to the correct regional endpoint automatically.
* **OKTO PIX Payment**\
Fixed PIX payments through OKTO so that the payment method is correctly sent in the issuers request and bank-transfer form validation accepts the right field combinations.
## v2.12.3
*January 20, 2026*
* **Cardholder Name Now Optional**\
The cardholder name field is now optional in card forms. Forms no longer block submission when this field is empty.
## v2.12.2
*January 8, 2026*
* **Data Race in Payment Methods List**\
Resolved a data race condition in the payment methods list loading function. This fix eliminates intermittent crashes on devices running concurrent background tasks.
## v2.12.1
*December 20, 2025*
* **Apple Pay in Render Mode**\
Fixed an Apple Pay initialization issue that prevented the payment sheet from appearing in render mode. Apple Pay now initializes correctly in all integration modes.
## v2.12.0
*December 5, 2025*
* **cardFormType Removed from Initialization**\
Removed `cardFormType` from SDK initialization. Card form type must now be configured in the Dashboard Checkout Builder. Update your integration before upgrading.\
[Migration guide →](/changelog/migration-guides/ios/v2-11-to-v2-12)
* **3DS in Enrollment**\
Added 3D Secure authentication support during card enrollment flows.
* **3DS Fallback Behavior**\
Added fallback handling for 3DS authentication when the primary path is unavailable.
* **Luhn Card Number Verification**\
Card numbers are now validated with the Luhn algorithm before submission, surfacing invalid numbers earlier in the form.
* **Co-Badged Card Choice UI**\
Added a card-brand selector when the entered card supports more than one network, letting customers choose which network to use.
* **Installments Financial Cost Table**\
Added a financial cost table to the installments view so customers can see total cost details per plan.
* **Substatus from WebSocket**\
Payment notifications delivered via WebSocket now include the substatus value, enabling finer-grained status handling in the host app.
* **Headless Enrollment Raw Status**\
Headless enrollment now returns the raw backend status instead of a mapped enum value, giving integrators direct access to provider-specific states.
* **Card Form Placeholder Font**\
Fixed an issue where card form placeholders did not pick up the custom font configured through Appearance.
## v2.11.3
*December 1, 2025*
* **RTL Driven By SDK Language**\
Right-to-Left layout is now applied based on the SDK language setting instead of the device language, giving merchants direct control over checkout direction.
## v2.11.1
*November 20, 2025*
* **Bug Fixes and Stability**\
Various bug fixes and stability improvements. No API changes required.
## v2.11.0
*November 5, 2025*
* **Podspec Configuration Updates**\
Updated podspec configuration for improved CocoaPods compatibility. No API changes required.
* **Bug Fixes and Stability**\
Various bug fixes and stability improvements. No API changes required.
* **RTL Layout and Arabic Language**\
Added Right-to-Left layout support and Arabic localization for checkout screens.
* **Brand Field in Headless**\
The brand field is now mapped and surfaced through the headless integration.
## v2.10.1
*October 20, 2025*
* **Updated Package Checksum**\
Updated the Swift Package Manager checksum. Re-resolve your package dependencies after upgrading.
## v2.10.0
*October 5, 2025*
* **Bug Fixes and Stability**\
Various bug fixes and stability improvements. No API changes required.
* **Architecture Improvements**\
Internal architecture refactoring for improved maintainability. No API changes required.
* **Payment and Enrollment in a Single Flow**\
Added support for combining payment and enrollment in the same checkout flow.
* **CEP Address Auto-Fill**\
Added support for calling CEP services to auto-fill Brazilian address fields from a postal code.
* **Notification URL in Apple Pay Token**\
The Apple Pay payment token payload now includes the notification URL.
## v2.9.0
*September 10, 2025*
* **Cards Expiring This Month Allowed**\
Cards expiring in the current month and year are now accepted at checkout. Previously these cards were incorrectly rejected as expired.
* **Click to Pay Passkey Support**\
Added Click to Pay passkey authentication support. Activated automatically for eligible transactions — no integration changes required.
* **PayPal Installments**\
Added support for PayPal installments payment flow. Activated automatically when PayPal installments is configured for your account.
* **Dark Mode Support**\
The SDK UI now adapts to the system dark mode setting. No configuration required; the SDK follows the device appearance automatically.
* **Dark Mode in Dropdowns**\
Fixed dropdown components so they render correctly in dark mode.
* **Processing Status on Close**\
The SDK now reports a processing status when the customer closes an action screen mid-flow.
* **CEP Neighborhood Handling**\
Fixed CEP address auto-fill so the neighborhood field is populated correctly.
## v2.8.1
*August 20, 2025*
* **Hide Debit Cards When Credit Only**\
Debit cards are now hidden from the payment methods list when the merchant has enabled credit-only mode. No integration changes required.
* **Click to Pay Passkey for Render Mode**\
Click to Pay passkey authentication is now supported in render mode. No integration changes required.
## v2.8.0
*August 5, 2025*
* **ACH Field Enrollment**\
Added ACH bank account fields to the enrollment form. No integration changes required; the fields appear automatically when ACH enrollment is configured.
* **Settings Migration v1 to v2**\
SDK settings have been migrated from the v1 schema to v2. Existing settings are migrated automatically on first launch after upgrading.
* **Secondary Background Color in Flexible Actions**\
Flexible actions now support a secondary background color for improved UI customization. Configure via the `YunoConfig.styles` object.
* **Full Payment List Styling**\
Added styling support to the full payment list view. Configure appearance via the `YunoConfig.styles` object.
* **Traditional Chinese Date Format**\
Added Traditional Chinese (zh-TW) date format for the MM/YY expiration field.
* **Payment Full Notifications**\
Fixed an incorrect notification surfaced in the payment-full flow.
* **Duplicate Events in Payment Full**\
Fixed duplicate events emitted when the payment-full list was used in its unfolded state.
* **Duplicate Merchant Notifications**\
Fixed a duplicate notification sent to the merchant when an action view finished with an expire or cancel result.
## v2.7.1
*July 20, 2025*
* **Click to Pay with Passkey**\
Added Click to Pay authentication with passkey support. Activated automatically for eligible transactions — no integration changes required.
* **Pending Status Enrollment Notification**\
The SDK now notifies the host app of pending status during enrollment when redirecting to a deeplink. Listen for the `pending` status in your enrollment callback.
* **NuPay Copy**\
Fixed an incorrect copy string in the NuPay payment method UI.
## v2.7.0
*July 5, 2025*
* **ClearSale Web Integration**\
Integrated ClearSale fraud prevention via web integration. Activated automatically when ClearSale is configured for your account — no integration changes required.
## v2.6.0
*June 20, 2025*
* **Navigation Toolbar for Keyboard**\
Added a navigation toolbar that appears above the keyboard in payment and enrollment forms. The toolbar provides previous/next field navigation and a dismiss button.
## v2.5.0
*June 5, 2025*
* **Recurring Apple Pay Support**\
Added support for recurring Apple Pay subscriptions. The SDK handles the recurring payment sheet automatically when the checkout is configured for subscriptions.
* **Simplified Chinese and Traditional Chinese**\
Added Simplified Chinese (zh-CN) and Traditional Chinese (zh-TW) language support. Activated automatically based on the device language setting.
* **iPad Screen Support**\
The payment forms now adapt to iPad screen sizes with an optimized layout. No integration changes required.
* **OCR Card Scanning**\
Added OCR card scanning to automatically populate card number, expiry, and cardholder name fields from the device camera. The button appears automatically in the card form when the device supports it.
* **ELO Card Icon**\
Added the ELO brand icon to card form and payment list. Displayed automatically when an ELO card is detected.
* **Coinflow Chargeback Protection**\
Integrated Coinflow chargeback protection. Activated automatically for eligible transactions — no integration changes required.
## v2.4.2
*May 28, 2025*
* **Call Settings in Enrollment**\
The SDK now calls the settings service during enrollment initialization. No integration changes required.
* **Credit-Only Enrollment Mode**\
Added support for restricting enrollment to credit cards only. Configure via your Dashboard payment method settings.
## v2.4.0
*May 20, 2025*
* **Deprecated startCheckout Method**\
Removed the deprecated `startCheckout(with: self)` method. Use the async `startCheckout` API instead. See the migration guide for details.
* **getPaymentMethodView Async Replacement**\
Replaced `getPaymentMethodView` with an async version that returns the view via a completion handler. Update call sites to use the new async signature.
* **startPaymentRender Replacement**\
Replaced `startPaymentRender` with a new render flow method. Update call sites to use the new method name.
* **startPaymentLite Replacement**\
Replaced `startPaymentLite` with an updated version. Update call sites to use the new method name.
* **Missing Apple Pay Values**\
Added missing values in the `/payment/complete` service call for Apple Pay. This resolves payment failures that occurred for some Apple Pay transactions.
* **Nuvei 3DS Support**\
Integrated Nuvei 3DS challenge handling. Activated automatically for eligible Nuvei transactions — no integration changes required.
* **Styling Object Update**\
Updated the `YunoConfig.styles` object structure. Review the styling documentation if you customize SDK appearance.
* **Banner View Payment Action**\
Added banner view support within the payment action view for flexible actions. No integration changes required.
## v2.3.0
*May 18, 2025*
* **Text Component Identifier Separation**\
Separated view block identifiers into specific text components for improved customization. Review custom text configurations if your integration overrides identifier labels.
* **NuPay Banner Text Weight**\
NuPay banner messages are now displayed in bold for improved readability. No integration changes required.
* **CVV and Expiry Field Proportions**\
Adjusted the width proportions of the CVV and expiration date fields in the card form for a more balanced layout. No integration changes required.
* **External Browser Redirect**\
Redirects now open in the external browser when the backend flag is set, instead of always using an in-app web view. No integration changes required.
## v2.2.2
*May 16, 2025*
* **Luhn Validation**\
Added Luhn algorithm validation to the card number field. Cards with invalid Luhn checksums are now rejected before submission, reducing server-side errors.
## v2.2.1
*May 17, 2025*
* **Bug Fixes and Stability**\
Various bug fixes and stability improvements. No API changes required.
## v2.2.0
*May 16, 2025*
* **PayPal Enrollment**\
Added PayPal enrollment support. Users can now save their PayPal account during the enrollment flow.
## v2.1.0
*May 15, 2025*
* **Color Codable Initializers Hidden**\
Color `Codable` initializers are no longer part of the public API. If you were using these initializers directly, switch to the documented color configuration methods.
* **Sodexo Expiration Date Validation**\
Added expiration date validation specific to Sodexo brand cards. No integration changes required.
* **Redirect Payment Action Support**\
Added support for the redirect payment action type, enabling redirect-based APMs to operate through the flexible actions flow.
## v2.0.0
*May 15, 2025*
* **NuPay Installments**\
Added support for NuPay installments payment flow.
* **Flexible Actions Migration**\
Migrated legacy Alternative Payment Methods (APMs) to the flexible actions architecture. Merchants using APMs should verify their payment flows after upgrading.
* **Mercado Pago 3DS**\
Integrated Mercado Pago 3DS for enhanced fraud protection. Activated automatically for eligible transactions — no integration changes required.
* **Socket Connection Support**\
Added WebSocket connection support based on a backend feature flag. No integration changes required.
* **Airwallex Anti-fraud Integration**\
Integrated Airwallex anti-fraud detection. Activated automatically for eligible transactions — no integration changes required.
* **3DS Unlimit Support**\
Added 3DS challenge support for Unlimit payment method. Activated automatically — no integration changes required.
## v1.25.0
*April 1, 2025*
* **Astropay Enrollment Support**\
Added support for Astropay card enrollment. Users can now save their Astropay account during the enrollment flow.
* **Redirect-Type Enrollment**\
Added support for redirect-type enrollment flows. The SDK now handles the redirect and returns the enrollment result to the host app.
## v1.24.2
*March 20, 2025*
* **Loader Recursive Presentation**\
Enhanced loader display with recursive view controller presentation for more reliable loading indicators in complex navigation stacks.
## v1.24.1
*March 15, 2025*
* **Full Payment View Size Notification**\
Added a notification for the full payment view size. Use this to adjust your container layout when the SDK view changes height.
## v1.24.0
*March 5, 2025*
* **Mercado Pago Checkout Pro Browser**\
Mercado Pago Checkout Pro now opens in an in-app browser instead of a web view. No integration changes required.
* **Preselected Payment Methods**\
Added support for preselecting a payment method programmatically. Pass the payment method token when starting checkout to skip the payment list.
* **Full Payment List Migrated to SwiftUI**\
The full payment list UI has been migrated to SwiftUI for improved performance and customization. No API changes required.
* **Flexible Actions Styling and QR Button**\
Added styling support and a QR button to flexible actions. Configure via `YunoConfig.styles`.
* **3DS Loading URL Support**\
Added support for loading external URLs during 3DS challenges. No integration changes required.
## v1.23.2
*February 20, 2025*
* **cancelByUser Notification for Enrollment**\
The SDK now sends a `cancelByUser` notification when the user closes enrollment forms. Handle this event in your enrollment callback to update your UI accordingly.
## v1.23.1
*February 15, 2025*
* **cancelByUser Notification for Apple Pay**\
The SDK now sends a `cancelByUser` notification when the user closes the Apple Pay modal. Handle this event in your payment callback to update your UI accordingly.
## v1.23.0
*February 5, 2025*
* **Generic Enrollment Forms and WebSocket**\
Added support for generic enrollment forms and WebSocket connectivity. Tested with Bancolombia button integration.
## v1.22.1
*January 20, 2025*
* **Embedded Web View Publisher**\
Fixed an issue where embedded web views did not return `anyPublisher` directly. No integration changes required.
## v1.22.0
*January 5, 2025*
* **Nationality Removed from Required Fields**\
Nationality has been removed from the required fields list. Forms no longer request this field during enrollment.
* **OTP View in Flexible Actions**\
Added an OTP (one-time password) input view within the flexible actions flow. Activated automatically for payment methods requiring OTP verification.
* **x-sdk-type Request Header**\
Added `x-sdk-type` to all outbound request headers for improved platform telemetry. No integration changes required.
* **Enrolled Card Support in Dynamic SDK**\
Added enrolled card handling to the dynamic SDK. Enrolled cards can now be used in dynamic payment flows.
* **Authorized Substatus Notification**\
Added notification for the authorized payment substatus. Handle this event to take action when a payment is authorized but not yet captured.
## v1.21.2
*December 20, 2024*
* **Enrollment Cancellables Memory Leak**\
Added `anyCancellables` to `YunoEnrollmentHeadlessImpl` to prevent memory leaks in long-running enrollment sessions.
## v1.21.1
*December 15, 2024*
* **Koin Dependency Removed**\
Removed the Koin dependency from the SDK package. This reduces binary size and eliminates potential conflicts with apps that include Koin independently.
## v1.21.0
*December 5, 2024*
* **Xendit Indoramart Payment Method**\
Added support for Xendit - Indoramart payment method. Activated automatically when configured for your account.
* **MetricKit Performance Monitoring**\
Integrated MetricKit and `URLSessionTaskMetrics` for performance monitoring and diagnostics. Metrics are collected automatically — no integration changes required.
* **Combined Payment and Enrollment Flow**\
Added support for a combined payment and enrollment flow. Users can enroll a payment method and complete a payment in a single session.
* **Dynamic Actions Image Support**\
Added IMAGE action type support to the dynamic actions framework. No integration changes required.
## v1.20.0
*November 20, 2024*
* **Koin SDK Integration**\
Integrated the Koin SDK package for Koin PIX Parcelado support. Add the Koin dependency to your project if you plan to use Koin payment methods.
* **Koin PIX Parcelado**\
Added Koin PIX Parcelado installment payment support including socket-based status updates, OTP handling, and in-review status display.
* **Click to Pay Token Storage**\
Added saving and sending of Click to Pay (C2P) tokens in user defaults. C2P is activated via a feature flag — no integration changes required.
* **Delayed Provider Response Screen**\
Added a delayed provider response screen for payment methods that take additional time to confirm. No integration changes required.
## v1.19.3
*November 5, 2024*
* **NuPay Redirect Payment**\
Added NuPay redirect payment flow support. The SDK now handles the redirect and returns the payment result to the host app.
## v1.19.2
*October 28, 2024*
* **Socket on Authorized Substatus**\
The SDK now opens a socket connection when the payment substatus is `authorized`, enabling real-time status updates for authorized-but-pending payments.
## v1.19.1
*October 20, 2024*
* **Document Required Field in Enrollment**\
Added document number as a required field in enrollment forms when specified by the payment method configuration. No integration changes required.
## v1.19.0
*October 5, 2024*
* **Inswitch Cash Payment**\
Added support for Inswitch cash payment method. Activated automatically when configured for your account.
* **Inswitch Bank Transfer**\
Added support for Inswitch bank transfer payment method. Activated automatically when configured for your account.
* **Xendit QRIS Payment Method**\
Added support for Xendit QRIS payment method. Activated automatically when configured for your account.
## v1.18.0
*September 10, 2024*
* **SDK Seamless Integration**\
Added SDK seamless integration mode for a frictionless checkout experience. Contact your Yuno technical account manager to enable this feature.
* **RUT Validation and Masks**\
Added Chilean RUT validation and input mask to document fields. Activated automatically for CLP transactions.
* **Dynamic SDK Cleanup**\
Removed `OptionalStateValue` and `YunoDynamicConnection` class from the dynamic SDK. Internal refactoring — no API changes required.
## v1.17.0
*August 15, 2024*
* **Copy Voucher in Enrollment Flow**\
Added a copy button for voucher codes in the enrollment flow. Users can now copy the voucher code directly from the enrollment screen.
* **Dynamic SDK Conditional Dependencies**\
Added dependencies for dynamic SDK condition evaluation. No integration changes required.
* **Dynamic SDK Text Field Restrictions**\
Restricted allowed characters in dynamic SDK text fields for CARD and APM types to improve input validation. No integration changes required.
## v1.16.0
*July 20, 2024*
* **FAC 3DS Action**\
Added FAC 3DS action support. Activated automatically for eligible FAC transactions — no integration changes required.
* **Enrolled Card Form in Dynamic SDK**\
Added enrolled card form support to the dynamic SDK. Enrolled cards can now be managed through dynamic SDK flows.
* **Step-by-Step Card Form in Dynamic SDK**\
Implemented step-by-step card form in the dynamic SDK. The multi-step card entry flow is now available in dynamic integrations.
* **Backend-Driven Icons and View Names**\
Icons and view names in the dynamic SDK are now fetched from the backend. No integration changes required.
## v1.15.0
*June 20, 2024*
* **Step-by-Step Dynamic SDK**\
Implemented step-by-step card form functionality in the dynamic SDK. The multi-step flow guides users through card entry one field at a time.
* **RUT Validation**\
Added Chilean RUT document validation. Validation is applied automatically to RUT fields in payment and enrollment forms.
* **Dynamic SDK Analytics**\
Added analytics event tracking for dynamic SDK flows. Events are sent automatically — no integration changes required.
* **Accessibility Identifiers for Automation**\
Added accessibility identifiers to the sample app for UI automation testing. No production integration changes required.
## v1.9.0
*April 10, 2024*
* **Loader and Service Timeout**\
Added loader display during service calls and configurable service timeout. No integration changes required.
* **Analytics Event Flow**\
Improved the analytics event flow for more accurate and complete event reporting. No integration changes required.
## v1.6.2
*February 15, 2024*
* **Background Payment Status Query**\
Added automatic payment status query when the app returns from background. This ensures the SDK has the latest payment state after the user completes a redirect flow.
## v1.1.19
*January 10, 2024*
* **Mercado Pago Checkout Pro Caching**\
Resolved a caching issue in Mercado Pago Checkout Pro that caused stale payment sessions to be reused. The SDK now always fetches a fresh session.
* **Daviplata Document Type Filtering**\
Implemented document type filtering in the Daviplata enrollment form. Only supported document types are shown, reducing user errors.
## v1.1.18
*December 20, 2023*
* **Loader Persistence Support**\
Added support for persisting the loader between navigation steps. No integration changes required.
## v1.1.17
*December 5, 2023*
* **Terms and Conditions Opening Bug**\
Fixed a bug that prevented the terms and conditions link from opening correctly. The link now opens in the in-app browser as expected.
* **CheckboxColor in Yuno Appearance**\
Added a `checkboxColor` field to the `Yuno.Appearance` object. Use this to customize the checkbox color in forms.
* **Payment Method Form Improvements**\
Improved the payment method form layout and usability. No API changes required.
## v1.1.16
*November 20, 2023*
* **Card Form Improvements**\
Multiple improvements to the card form UI and validation. No API changes required.
## v1.1.15
*November 5, 2023*
* **Required Fields in Card Form**\
Added required field enforcement to the card form. Fields marked as required by the payment method configuration now block form submission when empty.
## v1.1.14
*October 20, 2023*
* **Openpay Payment Method**\
Added support for Openpay payment method. Activated automatically when configured for your account.
* **One-Step Card Form Customization**\
Added customization options for the one-step card form. Configure appearance via the `Yuno.Appearance` object.
## v1.1.13
*October 5, 2023*
* **New Payment Method Types**\
Added support for additional payment method types. New methods are activated automatically when configured for your account.
## v1.1.12
*September 20, 2023*
* **PagSeguro Checkout Support**\
Added support for PagSeguro checkout payment method. Activated automatically when configured for your account.
* **UNLIMINT Checkout Support**\
Added support for UNLIMINT checkout payment method. Activated automatically when configured for your account.
## v1.1.11
*September 5, 2023*
* **Multistep Card Form Improvements**\
Multiple improvements to the multistep card form flow and validation. No API changes required.
## v1.1.9
*August 10, 2023*
* **Yuno Appearance Initialization Bug**\
Fixed a bug where `Yuno.Appearance` object initialization could fail under certain configurations. The object now initializes correctly in all cases.
* **Dlocal Redirect Payment Method**\
Added support for Dlocal redirect payment method. Activated automatically when configured for your account.
* **Khipu Payment Method**\
Added support for Khipu payment method. Activated automatically when configured for your account.
* **Dlocal PSE Payment Method**\
Added support for Dlocal PSE payment method. Activated automatically when configured for your account.
* **Multiple Step Card Form Improvements**\
Multiple improvements to the multiple-step card form validation and navigation. No API changes required.
## v1.1.8
*July 20, 2023*
* **Multiple Step Card Form Improvements**\
Multiple improvements to the multiple-step card entry flow. No API changes required.
## v1.1.7
*July 5, 2023*
* **Tarjeta Clave Payment Method**\
Added support for Tarjeta Clave payment method. Activated automatically when configured for your account.
* **Kushki Payment Method**\
Added support for Kushki payment method. Activated automatically when configured for your account.
* **Daviplata UX Improvements**\
Improved the Daviplata payment form user experience. No API changes required.
* **Diners Card Form Improvements**\
Improved the Diners card entry experience in the card form. No API changes required.
## v1.1.3
*May 15, 2023*
* **Multi-Step Card Form Option**\
Added multi-step card form as an alternative to the single-step form. Configure via `cardFormType` in SDK initialization.
## v1.1.0
*April 10, 2023*
* **Swift Package Manager Support**\
Added Swift Package Manager distribution. You can now integrate the SDK using either Swift Package Manager or CocoaPods.
## v1.0.17
*March 20, 2023*
* **Card Form General Improvements**\
General improvements to the card form including layout, validation, and accessibility. No API changes required.
## v1.0.16
*March 5, 2023*
* **Card Form Wording Improvements**\
Updated card form field labels and error messages for clarity. No API changes required.
## v1.0.9
*February 1, 2023*
* **PIX and NuPay Async Payments**\
Added async payment support for PIX and NuPay. The SDK now polls for status and notifies the host app when the payment completes.
* **Card Enrollment Support**\
Added card enrollment to allow users to save cards for future payments.
* **Wibond Payment Method**\
Added support for Wibond payment method. Activated automatically when configured for your account.
* **MercadoPago Wallet Support**\
Added support for MercadoPago Wallet payment method. Activated automatically when configured for your account.
# Android SDK: From v1.1 to v1.2 (Legacy)
Source: https://docs.y.uno/changelog/migration-guides/android/v1-1-to-v1-2
Historical migration guide for Android SDK v1.1 to v1.2
# Migrating from v1.1 to v1.2
This guide covers a historical version change. For the current cardFlow migration, see [Migrating to Android SDK v2.11](/changelog/migration-guides/android/v2-10-to-v2-11).
The `cardFlow` configuration has been moved to the Dashboard.
### 1. Remove Code Configuration
Remove the following line from your `YunoConfig`:
```kotlin theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
cardFlow = CardFormType.ONE_STEP
```
### 2. Update Dashboard
Configure your desired card flow in the **Checkout Builder** on the Yuno Dashboard.
# Android SDK: Migrating to v2.11
Source: https://docs.y.uno/changelog/migration-guides/android/v2-10-to-v2-11
How to upgrade from Android SDK v2.10.x to v2.11.0
# Migrating to Android SDK v2.11
Version 2.11.0 removes the `cardFlow` parameter from `YunoConfig`. Card flow configuration moves to the Yuno Dashboard.
## What changed
The `cardFlow` parameter on `YunoConfig` has been removed. Passing it will cause a **compile error** after upgrading.
## Steps
### 1. Remove `cardFlow` from YunoConfig
**Before:**
```kotlin theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
val config = YunoConfig(
apiKey = "your_api_key",
cardFlow = CardFormType.ONE_STEP
)
```
**After:**
```kotlin theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
val config = YunoConfig(
apiKey = "your_api_key"
)
```
### 2. Configure card flow in the Dashboard
Open **Dashboard → Checkout → Builder** and select your card flow:
* **One Step** — all card fields on a single screen
* **Multi Step** — card fields across multiple screens
The Dashboard setting applies to all SDK instances for your account.
# iOS SDK: From v1.1 to v1.2 (Legacy)
Source: https://docs.y.uno/changelog/migration-guides/ios/v1-1-to-v1-2
Historical migration guide for iOS SDK v1.1 to v1.2
# Migrating from v1.1 to v1.2
This guide covers a historical version change. For the current cardFormType migration, see [Migrating to iOS SDK v2.12](/changelog/migration-guides/ios/v2-11-to-v2-12).
The `cardFormType` configuration is now managed via the Dashboard.
### 1. Update Initialization
Remove `cardFormType` from your `Yuno.initialize()` call.
### 2. Dashboard Sync
Ensure your Checkout Builder settings match your desired UI flow.
# iOS SDK: Migrating to v2.12
Source: https://docs.y.uno/changelog/migration-guides/ios/v2-11-to-v2-12
How to upgrade from iOS SDK v2.11.x to v2.12.0
# Migrating to iOS SDK v2.12
Version 2.12.0 removes the `cardFormType` parameter from `Yuno.initialize()`. Card form type configuration moves to the Yuno Dashboard.
## What changed
The `cardFormType` parameter on `Yuno.initialize()` has been removed. Passing it will cause a **compile error** after upgrading.
## Steps
### 1. Remove `cardFormType` from Yuno.initialize()
**Before:**
```swift theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
Yuno.initialize(apiKey: "your_api_key", cardFormType: .oneStep)
```
**After:**
```swift theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
Yuno.initialize(apiKey: "your_api_key")
// Configure in Dashboard → Checkout → Builder
```
### 2. Configure card form type in the Dashboard
Open **Dashboard → Checkout → Builder** and select your card form type:
* **One Step** — all card fields on a single screen
* **Multi Step** — card fields across multiple screens
The Dashboard setting applies to all SDK instances for your account.
# Web SDK: Migrating to v1.1
Source: https://docs.y.uno/changelog/migration-guides/web/v1-0-to-v1-1
How to upgrade from Web SDK v1.0 to v1.1.0
# Migrating to Web SDK v1.1
Version 1.1.0 makes `initialize()`, `mountCheckout()`, and `startCheckout()` asynchronous and introduces `continuePayment()` as a required step for dynamic payment flows (3DS, PayPal redirects, and similar).
## What changed
* `Yuno.initialize()`, `yuno.mountCheckout()`, and `yuno.startCheckout()` now return Promises and must be awaited.
* `continuePayment()` is now required when `sdk_action_required: true` is returned from the payment API.
* Separate 3DS setup service calls are no longer needed — 3DS setup is now integrated into payment creation.
## Steps
### 1. Update the script tag
```html theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
```
### 2. Await all SDK method calls
**Before:**
```js theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
const yuno = Yuno.initialize(publicApiKey, config)
yuno.mountCheckout({ checkoutSession, elementSelector: '#root', countryCode: 'US' })
yuno.startCheckout({ checkoutSession, countryCode: 'US' })
```
**After:**
```js theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
const yuno = await Yuno.initialize(publicApiKey, config)
await yuno.mountCheckout({ checkoutSession, elementSelector: '#root', countryCode: 'US' })
await yuno.startCheckout({ checkoutSession, countryCode: 'US' })
```
### 3. Implement `continuePayment` for dynamic flows
After creating a payment via your backend, check whether the SDK needs to continue the flow (e.g. 3DS challenge, PayPal redirect):
```js theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
// After payment creation
if (paymentResponse.sdk_action_required) {
const result = await yuno.continuePayment({
checkoutSession,
showPaymentStatus: true,
yunoPaymentResult,
yunoError,
countryCode: 'US',
})
// result may contain a redirect object; handle appropriately
}
```
If `sdk_action_required` is not `true`, no call to `continuePayment` is needed.
### 4. Remove separate 3DS setup calls
If your v1.0 integration called a separate 3DS setup service before payment creation, remove that call. In v1.1, 3DS data collection is handled automatically during payment creation.
## Checklist
* [ ] Updated script tag to v1.1
* [ ] Added `await` to `Yuno.initialize()`, `yuno.mountCheckout()`, and `yuno.startCheckout()`
* [ ] Implemented `continuePayment()` handling for dynamic flows
* [ ] Confirmed `yunoPaymentResult()` callback is properly configured
* [ ] Removed any standalone 3DS setup service calls
# Web SDK: Migrating to v1.2
Source: https://docs.y.uno/changelog/migration-guides/web/v1-1-to-v1-2
How to upgrade from Web SDK v1.1 to v1.2.0
# Migrating to Web SDK v1.2
Version 1.2.0 is a **non-breaking** release. No changes are required for existing v1.1 integrations.
## What changed
### Optional `options` parameter in `Yuno.initialize()`
`Yuno.initialize()` now accepts an optional `options` configuration object as a second argument. Existing calls without this argument continue to work without modification.
```js theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
// v1.1 — still valid in v1.2
const yuno = await Yuno.initialize(publicApiKey)
// v1.2 — optional options parameter
const yuno = await Yuno.initialize(publicApiKey, {
// additional options here
})
```
### Extended `continuePayment` parameters
`continuePayment()` now accepts additional optional parameters: `checkoutSession`, `showPaymentStatus`, `yunoPaymentResult`, `yunoError`, `countryCode`, and `language`. All parameters are optional — existing calls with fewer arguments continue to work.
```js theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
// v1.1 usage — still valid in v1.2
await yuno.continuePayment()
// v1.2 — additional optional params available
await yuno.continuePayment({
checkoutSession,
showPaymentStatus: true,
yunoPaymentResult,
yunoError,
countryCode: 'US',
language: 'en',
})
```
## Steps
### 1. Update the script tag
```html theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
```
### 2. (Optional) Adopt new parameters
No code changes are required. If you want to take advantage of the new optional parameters, update your `initialize()` and `continuePayment()` calls as shown above.
## Checklist
* [ ] Updated script tag to v1.2
* [ ] (Optional) Added `options` parameter to `Yuno.initialize()` if needed
* [ ] (Optional) Extended `continuePayment()` with additional params if needed
# Web SDK: Migrating to v1.5
Source: https://docs.y.uno/changelog/migration-guides/web/v1-4-to-v1-5
How to upgrade from Web SDK v1.4 to v1.5.0
# Migrating to Web SDK v1.5
Version 1.5.0 changes how Google Pay and Apple Pay are rendered in the **Lite SDK**. Full SDK integrations are not affected.
## What changed
In v1.5.0, Lite SDK users must explicitly call `mountExternalButtons()` to render Google Pay and Apple Pay buttons. These payment methods no longer render automatically as radio buttons within the payment method list.
Full SDK integrations have **no breaking changes** — Google Pay and Apple Pay will automatically display as direct buttons instead of radio buttons, requiring no code changes.
## Who is affected
* **Lite SDK users**: action required (see steps below)
* **Full SDK users**: no action required
## Steps (Lite SDK only)
### 1. Update the script tag
```html theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
```
### 2. Add HTML elements for wallet buttons
Add container elements in your HTML where you want the buttons to appear:
```html theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
```
### 3. Call `mountExternalButtons()` after `startCheckout`
**Before:**
```js theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
// Lite SDK — wallet buttons rendered automatically
await yuno.startCheckout({ checkoutSession, countryCode, elementSelector: '#root' })
```
**After:**
```js theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
// Explicitly mount wallet buttons after startCheckout
await yuno.startCheckout({ checkoutSession, countryCode, elementSelector: '#root' })
await yuno.mountExternalButtons([
{
paymentMethodType: 'APPLE_PAY',
elementSelector: '#apple-pay',
},
{
paymentMethodType: 'GOOGLE_PAY',
elementSelector: '#google-pay',
},
])
```
### 4. (Optional) Unmount buttons when needed
To unmount a single button:
```js theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
yuno.unmountExternalButton('APPLE_PAY')
```
To unmount all external buttons at once:
```js theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
yuno.unmountAllExternalButtons()
```
# VTEX Plugin Changelog
Source: https://docs.y.uno/changelog/plugins/vtex
Latest updates and version history for the Yuno VTEX Plugin
## v4.2.335
*July 29, 2026*
**Payments**
* **Samsung Pay support**\
Shoppers can now pay with Samsung Pay at checkout, alongside the existing digital wallets. The connector routes Samsung Pay authorizations to the wallet flow so the payment app can render the Samsung Pay button and complete the payment through Yuno.
## v4.2.333
*July 27, 2026*
**Payments**
* **Per-storefront seller website in payment metadata**\
Payments now report the storefront the order actually came from instead of the store's default host, improving reporting and reconciliation for merchants running multiple storefronts on one account. A new "Sales Channel Domains" affiliation setting optionally maps each sales channel to its public domain (for example `2:b2b.example.com;18:members.example.com`); unmapped channels fall back to the order's storefront host, and stores without the setting keep working with no configuration changes.
* **VTEX order sequence as processor transaction reference**\
A new affiliation setting, Send Order Sequence as Merchant Reference, makes payments carry the VTEX order sequence as the merchant reference, so payment providers configured with a custom transaction identification (such as Mercado Pago) receive the sequence as the external reference shown in their panel, matching pre-migration VTEX behavior. The setting is off by default; when it is disabled or the sequence is unavailable the reference falls back to the VTEX Order ID, and connections without the custom identification option are unaffected.
## v4.2.331
*July 22, 2026*
**Order Modifications**
* **Additional charges for modified orders**\
When an order's total increases after checkout — VTEX order modifications, such as items sold by weight — the connector now charges the difference automatically using the card saved on the original order, with the shopper absent and no security code. Enable it per affiliation with the new "Vault Card for Order Modification" setting (requires "Create Customer" to also be enabled); orders and affiliations without it are unaffected.
## v4.2.324
*July 14, 2026*
**Subscriptions**
* **Recurring subscription charges are now linked to the original authorization**\
The connector securely stores a card reference after the first successful subscription charge and reuses it on every recurring charge, so the network transaction id of the original authorization reaches the issuer and merchant-initiated charges are approved at a significantly higher rate.
## v4.2.323
*July 14, 2026*
**Payments**
* **Subscription cards are now saved for recurring charges**\
On the first charge of a VTEX subscription order, the connector now requests secure storage of the card on successful payment, so subsequent recurring charges can reuse the stored card instead of failing for lack of a saved payment method.
## v4.2.307
*June 11, 2026*
* **VTEX subscription (recurring) order support**\
Adds support for orders created with VTEX subscriptions. The first charge keeps the security code as today, while subsequent recurring charges are authorized without a security code and flagged to the gateway as stored-credential transactions, so automatic renewals no longer fail. Regular checkout is unchanged.
## v4.2.304
*May 28, 2026*
**Configuration**
* **CIELO\_CYBERSOURCE\_FRAUD antifraud provider for split orders**\
Adds CIELO\_CYBERSOURCE\_FRAUD as an accepted value in the Antifraud Providers for Split Orders setting, alongside RISKIFIED, CYBERSOURCE, and SIGNIFYD.
## v4.2.302
*May 26, 2026*
* **Split-order payment support**\
Adds payment support for VTEX orders that get split into multiple suborders (carts combining products from different sellers or franchises). Each suborder now settles at the gateway with a shared antifraud session, instead of only the first one being paid.
**Configuration**
* **Antifraud providers for split orders setting**\
Adds a configuration field so merchants can choose which antifraud providers (RISKIFIED, CYBERSOURCE, SIGNIFYD) receive the shared session. Defaults to RISKIFIED + CYBERSOURCE when left empty.
## v4.2.301
*May 20, 2026*
**Observability**
* **Less noise in error monitoring for expected outcomes**\
Expected outcomes (cancellation denials, callback retries) are now recorded at debug level instead of as errors. Internal observability change — no impact on merchant-facing flows.
## v4.2.300
*May 13, 2026*
**Performance & Latency**
* **Optimize authorize hot path**\
Reduces authorization latency by parallelizing previously sequential calls, coalescing duplicate in-flight requests, and tightening the data flow around preflight, persistence, and Yuno API calls. Functional behaviour is preserved end-to-end.
## v4.2.299
*May 11, 2026*
**Apple Pay**
* **Installments-plan endpoint**\
Exposes a new endpoint that returns the configured installments plan for an affiliation, used by Apple Pay and Google Pay to render the correct installment options at checkout.
## v4.2.298
*April 27, 2026*
**Configuration**
* **Choose Yuno vs provider transaction ID**\
Adds a Transaction Identification From setting so merchants can choose whether the Yuno TID (default) or the underlying provider TID is returned to VTEX.
## v4.2.297
*April 15, 2026*
**Configuration**
* **Transaction Identification From custom field**\
Adds a Transaction Identification From option in the VTEX Admin so merchants can pick between the Yuno TID and the underlying provider TID for the transaction reference.
## v4.2.296
*April 14, 2026*
**Configuration**
* **Re-add Payment Mode field to configuration**\
Restores the Payment Mode configuration with the same two options as before: Payment App (default) and Redirect (legacy).
## v4.2.295
*April 12, 2026*
**Configuration**
* **Remove Payment Mode setting (later restored)**\
Temporarily removes the Payment Mode configuration field. The setting is restored in the following release.
## v4.2.294
*April 10, 2026*
**Configuration**
* **Payment Mode setting for legacy redirect**\
Adds a Payment Mode configuration so merchants can choose between the default Payment App flow and the legacy redirect flow.
## v4.2.293
*April 10, 2026*
**Dependency Updates**
* **Upgrade diff and cookie to patch CVE-2026-24001 and CVE-2024-47764**\
Patches two reported third-party vulnerabilities: a denial-of-service in the diff library and a cookie attribute injection in cookie.
## v4.2.292
*April 6, 2026*
* **Recognize VTEX IO transient errors**\
Treats common transient infrastructure errors (timeouts, dropped connections, refused connections) as recoverable so the authorization stays pending instead of failing immediately.
## v4.2.290
*March 31, 2026*
**Apple Pay**
* **Preflight payments for Apple Pay and Google Pay**\
Adds pre-created checkout sessions for Apple Pay and Google Pay so the wallet sheet can be opened immediately when the buyer clicks pay.
## v4.2.288
*March 26, 2026*
**Multi-Account**
* **Route franchise sub-account payments to the correct account**\
On franchise sub-accounts the connector now routes the payment using the order's merchant identifier instead of the parent account hostname, so payments reach the correct sub-account.
## v4.2.287
*March 18, 2026*
**Reliability**
* **Retry-payment-validation endpoint**\
Adds an endpoint that resolves "phantom" orders by retrying the payment validation, restoring the simple fire-and-forget callback behaviour.
## v4.2.286
*March 17, 2026*
**Dependency Updates**
* **Patch qs vulnerability (CVE-2026-2391)**\
Patches a reported vulnerability in the qs query-string dependency.
## v4.2.285
*March 12, 2026*
* **External-button action for Yuno SDK v1.5**\
Adds an external-button action option that targets Yuno SDK v1.5, used for payment methods that render their own UI outside the SDK.
## v4.2.284
*March 10, 2026*
**Dependency Updates**
* **Pin minimatch and koa**\
Locks minimatch and koa to patched versions to close reported regular-expression and request-handling vulnerabilities.
## v4.2.283
*March 4, 2026*
**Dependency Updates**
* **Pin qs to 6.14.2**\
Locks qs to the patched version across both root and node workspaces to close a reported vulnerability.
## v4.2.282
*February 27, 2026*
**Customer & Address**
* **Customer payer city for Chile**\
Reads the city from the neighborhood field for Chilean orders, where VTEX populates the city there, so payments are no longer declined for missing city data.
## v4.2.281
*February 25, 2026*
**Dependency Updates**
* **Upgrade vulnerable dependencies**\
Bulk upgrade addressing several reported third-party dependency vulnerabilities.
**Pagaleve**
* **OTT metadata headers and Pagaleve close-button toggle**\
Sends OTT metadata headers to the secure-proxy and adds a toggle for the Pagaleve Transparente checkout to hide the VTEX close button.
## v4.2.280
*February 23, 2026*
**Configuration**
* **Order placed page URL setting**\
Adds a configuration option for the VTEX order-placed page URL and forwards it through the pending-authorization flow.
**Dependency Updates**
* **Patch js-yaml vulnerability**\
Forces js-yaml to a patched version to close CVE-2024-4068.
## v4.2.277
*January 14, 2026*
**Performance & Latency**
* **Per-client caching for VTEX APIs**\
Adds in-memory caches across VTEX clients (Account, Affiliations, Catalog, Master Data) to cut redundant API calls and reduce checkout latency.
## v4.2.273
*January 7, 2026*
**Tax IDs**
* **Per-merchant tax ID mapping**\
Adds merchant-aware tax ID (CNPJ) mapping so each payment is tagged with the correct ID and merchant metadata for downstream reconciliation.
## v4.2.272
*January 6, 2026*
**Tax IDs**
* **Add default CNPJ for testing**\
Provides a default merchant tax ID (CNPJ) when the configured affiliation has none, so testing flows can run without manual setup.
## v4.2.271
*January 5, 2026*
**Pagaleve**
* **Update Pagaleve parcelado integration tag**\
Updates the configuration tag for Pagaleve installment-Pix so the connector targets the latest provider integration.
## v4.2.267
*December 24, 2025*
**Payment Metadata**
* **Map VTEX fields to Cybersource MDD metadata**\
Maps additional VTEX order fields into Yuno metadata so Cybersource MDD (Merchant Defined Data) rules can use them for fraud screening.
## v4.2.266
*December 24, 2025*
**Pagaleve**
* **Pagaleve Transparente for Pix parcelado**\
Adds Pagaleve Transparente as a supported method for both Pix and installment-Pix flows.
## v4.2.264
*December 24, 2025*
**Click to Pay**
* **Hide installments for Click to Pay**\
Hides the installments option when the buyer is paying with Click to Pay, where instalments are not supported by the upstream networks.
## v4.2.263
*December 15, 2025*
**Cancellation Flow**
* **Validate transactions before cancel**\
Validates that VTEX transactions exist on the order before triggering the cancellation flow, preventing spurious failures.
## v4.2.262
*December 12, 2025*
**PicPay**
* **Restore PicPay support**\
Restores PicPay as a supported payment method after it was unintentionally removed.
## v4.2.260
*December 11, 2025*
* **Group-order handling**\
Treats VTEX order groups as a single payment, avoiding partial-payment artifacts when several orders are placed together.
**Apple Pay**
* **Apple Pay installment plans**\
Adds installment-plan support for Apple Pay so the merchant's configured installment options appear in the Apple Pay sheet.
## v4.2.258
*December 9, 2025*
**Mercado Pago**
* **Add Mercado Pago Checkout Pro**\
Adds Mercado Pago Checkout Pro as a redirect-style payment method. Existing Monnet and PicPay redirect flows are unified onto the same shared flow and forward additional payment metadata, including the merchant domain.
## v4.2.252
*November 27, 2025*
**Card Payments**
* **Defense-mode fallback for delayed card payments**\
Falls back to direct card processing (defense mode) when the standard flow is delayed by fraud screening, completing the payment without losing the order.
## v4.2.251
*November 20, 2025*
**Mercado Pago**
* **Mercado Pago Checkout Pro**\
Adds Mercado Pago Checkout Pro as a supported redirect-style payment method.
## v4.2.250
*November 19, 2025*
**Card Payments**
* **Show status page when a Gift Card is present**\
Renders the standard status page when the order includes a gift-card payment, preventing the connector from short-circuiting the flow.
## v4.2.248
*November 12, 2025*
**Configuration**
* **Create-customer toggle**\
Adds an optional Create Customer setting so the connector can register the buyer in Yuno's customer registry before the first payment.
## v4.2.247
*November 11, 2025*
**Fulfillment**
* **Verify tracking\_id and tracking\_url in fulfillment events**\
Validates tracking\_id and tracking\_url before forwarding carrier fulfillment events to Yuno so updates with missing values are skipped gracefully.
## v4.2.244
*October 31, 2025*
**Pix**
* **NSU on Pix responses**\
Includes the NSU transaction identifier in the Pix response so it can be reconciled with the bank.
## v4.2.242
*October 22, 2025*
* **Skip redundant payment-status call**\
Skips the payment-status check when the local state is already PENDING, reducing redundant gateway round-trips.
**Card Payments**
* **Card IIN lookup and dynamic card type detection**\
Looks up the card BIN (IIN) at checkout so the connector can detect the card brand and whether it is credit or debit dynamically, instead of relying on a static configuration.
* **Soft Descriptor configuration**\
Adds a Soft Descriptor configuration field so merchants can control the text that appears on the customer's card statement.
## v4.2.241
*September 24, 2025*
**Payment Metadata**
* **Send payment reference in metadata**\
Sends the merchant payment reference along with the payment metadata so it can be used for downstream reconciliation.
**Dependency Updates**
* **Patch brace-expansion dependency**\
Upgrades the brace-expansion dependency to a patched version to close a reported vulnerability.
* **Pin brace-expansion across transitive paths**\
Pins brace-expansion across all transitive paths so only the patched version is resolved.
## v4.2.240
*September 4, 2025*
* **Update koa dependency**\
Upgrades the Koa server framework to a newer release line.
* **Revert Koa upgrade**\
Rolls back the Koa framework upgrade shipped in the previous release while compatibility issues are resolved.
## v4.2.238
*July 31, 2025*
* **Non-blocking hostname lookup**\
Removes blocking I/O from the connector's hostname lookup so a slow DNS response can't stall the request.
**Webhooks**
* **Support webhook v2**\
Adds support for webhook v2.
## v4.2.235
*July 7, 2025*
**PSE**
* **PSE for Colombia**\
Adds PSE (Pagos Seguros en Línea) as a supported payment method for Colombian merchants, using the bank-redirect flow.
## v4.2.234
*July 7, 2025*
**PCI & Secure Proxy**
* **Proxy authorization header on PCI calls**\
Adds the Proxy-Authorization header on outbound calls that traverse the VTEX IO proxy, fixing 407 responses on tokenized requests.
## v4.2.231
*June 27, 2025*
* **Forward proxy and protocol headers**\
Forwards the original VTEX request headers (X-Forwarded-Proto and Port) so downstream services see the merchant's protocol correctly.
## v4.2.230
*June 18, 2025*
* **Uppercase platform identifier**\
Normalizes the platform identifier sent to Yuno to upper-case, aligning with the gateway's expected enum value.
## v4.2.229
*June 11, 2025*
**Reliability**
* **Axios request timeout**\
Adds an explicit timeout to the Axios HTTP client so hanging connections fail fast instead of stalling the payment.
**Dependency Updates**
* **Patch tar-fs vulnerability**\
Upgrades the tar-fs dependency to a patched version to close a reported security advisory.
## v4.2.227
*May 14, 2025*
* **Update dependencies**\
Bumps several third-party dependencies to their latest patched versions, including the Koa server framework.
## v4.2.226
*May 13, 2025*
**Capture**
* **Use the VTEX-supplied amount on capture**\
Captures the exact amount that VTEX sends with the capture request, instead of recomputing it from the original order total. This prevents capture mismatches when the order total has changed (partial refunds, gift cards, marketplace splits).
## v4.2.225
*May 7, 2025*
**Reliability**
* **Log retry-limit exhaustion**\
Adds a clear log entry when the connector exhausts the retry budget for an outbound request, easing on-call diagnosis.
## v4.2.223
*April 30, 2025*
**Fulfillment**
* **Additional shipping-type mappings**\
Extends the fulfillment mapping with extra shipping types (such as store pickup and marketplace handoff) so more order flows are reported back to the gateway.
## v4.2.222
*April 29, 2025*
**Payment Metadata**
* **Total cart value as metadata**\
Includes the total cart value as metadata on each payment, useful for risk scoring and reporting.
## v4.2.221
*April 29, 2025*
* **Preserve original order dates**\
Stops overriding the original order dates when updating a payment, preserving the merchant-facing timestamps.
## v4.2.218
*April 11, 2025*
**Reliability**
* **4-hour retry window for stuck payments**\
Adds a 4-hour retry window before re-attempting a stuck payment, reducing pressure on the gateway.
## v4.2.217
*April 11, 2025*
**Capture**
* **Capture wallet payments**\
Triggers the capture call to Yuno for wallet-based payments so capture timing matches the auto-settle window.
## v4.2.216
*April 10, 2025*
**Cancellation Flow**
* **4-hour auto-cancel window**\
Raises the auto-cancellation window to 4 hours, giving slow alternative payment methods enough time to settle.
## v4.2.215
*April 9, 2025*
**Fulfillment**
* **Forward carrier status**\
Retrieves the carrier status from VTEX and forwards it to Yuno as part of the fulfillment update.
## v4.2.214
*April 9, 2025*
**Fulfillment**
* **Send fulfillment completed event**\
Sends a fulfillment-completed event to Yuno when the VTEX order has been fully delivered.
## v4.2.213
*March 28, 2025*
**Fulfillment**
* **Include shipped-at timestamp**\
Sends the actual shipping timestamp in fulfillment updates so Yuno can compute accurate delivery SLAs.
**Dependency Updates**
* **Upgrade Axios HTTP client**\
Updates the Axios HTTP client to the latest stable version, picking up bug fixes and security patches.
## v4.2.210
*March 21, 2025*
* **Include product brand on items**\
Includes the product brand on each line item sent to Yuno so brand-level reporting is possible.
## v4.2.209
*March 20, 2025*
**Multi-Account**
* **Skip account lookup when main account is configured**\
Skips the account-lookup call when a main account is already configured, removing a redundant VTEX API request.
## v4.2.204
*March 17, 2025*
**Cancellation Flow**
* **Skip cancel when payment is still pending**\
Skips the cancellation path when a payment is not yet made and the order is in a transient state, preventing premature aborts.
## v4.2.202
*March 14, 2025*
**Fulfillment**
* **Tracking URL and ID as arrays**\
Sends shipping tracking URL and ID as arrays in fulfillment updates, matching Yuno's updated schema.
## v4.2.201
*March 12, 2025*
* **Reject non-numeric order IDs**\
Adds order-id format validation to reject non-numeric or malformed identifiers before the payment is created.
## v4.2.199
*March 10, 2025*
* **Check for existing Yuno payment before creating**\
Before creating a new Yuno session the connector first checks whether the merchant order already has a payment recorded, avoiding duplicates.
## v4.2.198
*March 10, 2025*
* **Validate and recover order ID**\
Validates the order ID before processing and, when invalid, attempts to recover the canonical order ID from VTEX.
## v4.2.197
*March 6, 2025*
**Customer & Address**
* **Send customer creation date**\
Includes the customer creation date in the payment payload so Yuno can apply customer-tenure-based rules.
## v4.2.196
*March 6, 2025*
**Monnet**
* **Support Monnet in Yuno VTEX SDK**\
Adds support for monnet in Yuno VTEX SDK.
## v4.2.195
*March 5, 2025*
**Dependency Updates**
* **Patch dependency vulnerabilities (cross-spawn, koa)**\
Patches reported vulnerabilities across two dependencies (cross-spawn and koa) in one update.
**Fulfillment**
* **Send fulfillment events to Yuno**\
Forwards VTEX fulfillment events (shipped, delivered) to Yuno so it reflects the order lifecycle.
## v4.2.186
*February 24, 2025*
**Multi-Account**
* **Expose account name to the front-end**\
Exposes the connector account name to the front-end so multi-account checkouts can be routed correctly.
## v4.2.184
*February 7, 2025*
**PicPay**
* **PicPay Wallet**\
Adds PicPay digital wallet as a supported payment method through the wallet-redirect flow.
## v4.2.182
*January 30, 2025*
* **Handle socket hang-ups on Yuno calls**\
Adds handling for socket-level hang-ups when calling the Yuno API, retrying instead of failing the transaction.
## v4.2.176
*January 20, 2025*
* **Coupons total as a separate line item**\
Sends the coupon-discount total as a separate line item to Yuno so the order totals reconcile correctly.
## v4.2.175
*January 17, 2025*
**Multi-Account**
* **Sub-store / multi-account routing**\
Adds sub-store support so franchises can route payments through a parent account when needed.
## v4.2.168
*December 18, 2024*
**Reliability**
* **Retry secure-proxy tokenization**\
Adds retries on the Yuno Secure Proxy tokenization call so transient PCI gateway failures don't fail the payment.
## v4.2.155
*December 16, 2024*
**Multi-Account**
* **Sales-channel policy resolution**\
Resolves the sales-channel policy so the connector picks the right policy when multiple are configured on the merchant account.
## v4.2.146
*December 9, 2024*
* **Wait before auto-cancelling**\
Adds a wait window before auto-cancelling a payment, giving wallet redirects enough time to complete.
## v4.2.144
*December 6, 2024*
**Cancellation Flow**
* **Faster auto-cancel for generic Yuno method**\
Reduces the auto-cancel delay when the payment method is the generic Yuno option, improving the merchant's view of pending transactions.
## v4.2.141
*December 4, 2024*
* **Upgrade semver-regex**\
Upgrades the semver-regex dependency to patch a reported vulnerability.
* **Patch reported vulnerabilities (group 1)**\
Bulk upgrade of dependencies to patch a batch of reported third-party vulnerabilities.
* **Patch reported vulnerabilities (group 2)**\
Bulk upgrade of dependencies to patch a further batch of reported third-party vulnerabilities.
**Dependency Updates**
* **Bump the npm\_and\_yarn group across 2 directories with 19 updates**\
Patches 19 reported third-party dependency vulnerabilities in one bulk security update.
* **Bump the npm\_and\_yarn group across 2 directories with 15 updates**\
Patches 15 reported third-party dependency vulnerabilities in one bulk security update.
* **Bump the npm\_and\_yarn group across 2 directories with 8 updates**\
Patches 8 reported third-party dependency vulnerabilities in one bulk security update.
**Card Payments**
* **Debit cards (Maestro, Voucher, Elo Débito)**\
Adds Maestro, Visa Electron, Elo Débito, Mastercard Debit and Voucher as supported debit-card payment methods.
## v4.2.137
*November 19, 2024*
**Webhooks**
* **Webhook logging**\
Adds structured logging to the webhook handler so incoming Yuno events can be traced.
## v4.2.136
*November 14, 2024*
**Fulfillment**
* **Send shipping status to Yuno**\
Forwards the order's shipping status as part of the fulfillment update so Yuno has end-to-end order context.
## v4.2.135
*November 8, 2024*
* **Expanded payment status mapping**\
Recognizes additional payment statuses from Yuno so terminal states are mapped correctly back to VTEX.
## v4.2.134
*November 7, 2024*
**Monnet**
* **Monnet cash and bank transfer**\
Adds Monnet cash and bank transfer as supported payment methods through an iframe flow.
## v4.2.133
*October 22, 2024*
**Pix**
* **Pix Parcelado**\
Adds Pix Parcelado (installment Pix) as a supported payment method for Brazilian merchants.
## v4.2.132
*September 19, 2024*
**Cancellation Flow**
* **Approve cancellation when order is already known**\
Returns a cancellation-approved response when the merchant order is already on record, avoiding spurious cancellation failures.
## v4.2.131
*September 5, 2024*
**Pagaleve**
* **Pagaleve one-time Pix**\
Adds support for Pagaleve's single-payment Pix option (a vista).
## v4.2.130
*August 29, 2024*
**Pagaleve**
* **Pagaleve installment Pix**\
Adds support for Pagaleve's installment-Pix offering, letting buyers split a Pix payment over multiple instalments.
## v4.2.129
*August 29, 2024*
**Pagaleve**
* **Add Pagaleve initial support**\
Adds initial support for Pagaleve as a buy-now-pay-later option for Brazilian merchants.
## v4.2.128
*August 28, 2024*
**Boleto**
* **Boleto Banco do Brasil**\
Adds Boleto Banco do Brasil as a supported payment option.
## v4.2.127
*August 28, 2024*
**Pix**
* **Pix redirect flow**\
Adds the Pix redirect flow as an alternative to QR code, so merchants can route customers to the bank-side payment page.
## v4.2.126
*August 19, 2024*
**Customer & Address**
* **Richer logs and neighborhood extraction**\
Enriches connector logs with more context and extracts the neighborhood field from VTEX addresses so it can be sent to the gateway.
## v4.2.117
*August 15, 2024*
**Customer & Address**
* **Improve customer address handling**\
Forwards all address sub-fields (state, neighborhood, complement) to Yuno so payments include the complete buyer address.
## v4.2.115
*August 14, 2024*
**Alelo**
* **Add Alelo brand**\
Adds the Alelo card brand to the supported payment-method list in the provider configuration.
## v4.2.114
*August 12, 2024*
**Refunds**
* **Fix typo on refund description**\
Corrects a typo in the message returned to VTEX after a refund is processed.
## v4.2.113
*August 8, 2024*
* **Fetch payment details from VTEX**\
Looks up payment details from the VTEX transactions API so the connector has accurate context when handling captures and refunds.
## v4.2.107
*July 18, 2024*
**Configuration**
* **Remove custom field**\
Removes a custom configuration field that was no longer used by any merchant.
## v4.2.106
*July 18, 2024*
* **Restore AES session encryption**\
Restores AES-256-CBC encryption for sensitive session data passed between front-end and back-end after a regression removed it.
## v4.2.92
*July 15, 2024*
**Card Payments**
* **Two-card split payments**\
Adds support for splitting a payment across two cards in the same VTEX checkout.
## v4.2.91
*July 10, 2024*
**Alelo**
* **Alelo (initial support)**\
Adds Alelo benefit cards as a supported payment method (initial integration).
## v4.2.90
*July 5, 2024*
**Apple Pay**
* **Support Apple pay**\
Adds Apple Pay support, including the Apple-Pay-sheet flow at the VTEX checkout.
## v4.2.89
*June 28, 2024*
* **Alternative payment method status validation**\
Adds payment-status validation for alternative payment methods so the connector reports the correct final state back to VTEX.
## v4.2.88
*June 20, 2024*
**Multi-Account**
* **Forward merchant account on payments**\
Sends the merchant account identifier with each payment so Yuno can resolve the correct affiliation when multiple are configured.
## v4.2.87
*June 19, 2024*
**Google Pay**
* **Enable Google Pay**\
Activates Google Pay as a supported payment method at the VTEX checkout.
## v4.2.86
*June 17, 2024*
**Nubank**
* **Nu Pay support**\
Adds Nu Pay (Nubank's credit-line payment) as a supported method for Brazilian merchants.
## v4.2.85
*June 13, 2024*
**Boleto**
* **Boleto Bancário integration**\
Adds support for Boleto Bancário, returning the barcode and payment URL so merchants can render them at checkout.
## v4.2.84
*May 31, 2024*
**Card Payments**
* **Improve card logs**\
Adds more context to card-payment logs to speed up incident triage and merchant support investigations.
## v4.2.83
*May 28, 2024*
**Webhooks**
* **Webhook receiver for payment status**\
Adds a webhook receiver so the connector can update VTEX payment status when Yuno publishes terminal events.
## v4.2.81
*April 30, 2024*
**Nubank**
* **Add Nubank**\
Adds Nubank as a supported payment method for Brazilian merchants.
## v4.2.80
*April 26, 2024*
**PagoEfectivo & SafetyPay**
* **PagoEfectivo and SafetyPay**\
Adds initial support for PagoEfectivo and SafetyPay as redirect-style payment options targeting Peru.
## v4.2.76
*April 4, 2024*
**Capture**
* **Declare auto-settle support**\
Declares auto-settle support in the provider configuration so VTEX correctly hands off capture timing to the connector.
## v4.2.74
*March 19, 2024*
**Apple Pay**
* **Enable Apple Pay**\
Activates Apple Pay as a supported payment method at the VTEX checkout for merchants enrolled in the Apple Pay program.
## v4.2.73
*March 15, 2024*
**Pix**
* **Support vtex pix**\
Adds support for vtex pix.
## v4.2.72
*March 11, 2024*
* **NSU transaction identifier**\
Includes the NSU (transaction sequence number) in the payment response so merchants can reconcile transactions with the acquirer.
## v4.2.71
*March 4, 2024*
* **Send raw payment response**\
Includes the raw Yuno payment response in the VTEX callback so merchants and support teams have full provider context when investigating.
## v4.2.70
*October 4, 2023*
**Observability**
* **Upgrade event-log library to v1**\
Picks up new fields, bug fixes, and improved trace-ID support from the v1 release of the event-log library.
## v4.2.69
*October 4, 2023*
**Performance & Latency**
* **Performance improvement**\
Reduces latency on the payment authorization path through targeted optimizations in the hottest code paths.
## v4.2.67
*September 20, 2023*
**Observability**
* **Yuno event-log library integration**\
Wires in the Yuno event-log library so connector errors are tracked centrally with trace IDs that link gateway and merchant logs.
## v4.2.55
*September 13, 2023*
**Observability**
* **Structured event logs**\
Introduces structured event logging across the connector to make production troubleshooting easier.
## v4.2.35
*August 17, 2023*
**3-D Secure**
* **3-D Secure support**\
Adds end-to-end 3-D Secure for card payments so merchants can comply with strong-customer-authentication requirements.
## v3.0.0
*May 26, 2023*
**Observability**
* **Event log parsed error fixed**\
Fixes a parsing error that prevented some failures from being recorded in the event log.
## v1.2.0
*December 21, 2021*
**Dependency Updates**
* **Bump urijs from 1.19.6 to 1.19.11 in /node**\
Patches several reported vulnerabilities in the urijs URL-parsing dependency.
## v1.1.0
*December 21, 2021*
**Dependency Updates**
* **Bump minimatch from 3.0.4 to 3.1.2 in /node**\
Patches a regular-expression denial-of-service issue in the minimatch dependency.
## v1.0.6
*November 18, 2021*
**Dependency Updates**
* **Bump @babel/traverse from 7.13.0 to 7.23.6 in /node**\
Patches an arbitrary-code-execution vulnerability in the @babel/traverse build-time dependency.
* **Bump async from 2.6.3 to 2.6.4 in /node**\
Patches a prototype-pollution issue in the async dependency.
## v1.0.5
*May 20, 2021*
* **Return undefined when the payment state is pending**\
Aligns the connector's response for pending payments with VTEX expectations so pending payments are no longer marked as failed.
## v1.0.4
*May 17, 2021*
**3-D Secure**
* **Support for the VTEX card form**\
Adds full support for the VTEX card-payment form across all major brands, including 3-D Secure authentication.
## v1.0.3
*April 28, 2021*
**Dependency Updates**
* **Bump semver from 5.7.1 to 5.7.2 in /node**\
Patches a denial-of-service vulnerability reported in the semver dependency.
## v1.0.2
*March 2, 2021*
**Dependency Updates**
* **Bump minimatch from 3.0.4 to 3.1.2**\
Patches a regular-expression denial-of-service issue in the minimatch dependency.
## v1.0.1
*March 1, 2021*
**Dependency Updates**
* **Bump path-parse from 1.0.6 to 1.0.7**\
Patches a regular-expression denial-of-service vulnerability in the path-parse transitive dependency.
## v1.0.0
*February 27, 2021*
* **Fix discount handling**\
Corrects how discount amounts are forwarded to the gateway so coupon and promotion values are reflected accurately on the payment.
**Dependency Updates**
* **Bump json5 from 1.0.1 to 1.0.2**\
Patches a **proto** prototype-pollution vulnerability in the json5 dependency.
**Fulfillment**
* **Order events**\
Adds order-event tracking so VTEX order state transitions propagate to Yuno.
## v0.0.2
*February 28, 2020*
**Dependency Updates**
* **Bump minimist from 1.2.5 to 1.2.8**\
Patches a reported prototype-pollution vulnerability in the minimist dependency.
# WooCommerce Plugin Changelog
Source: https://docs.y.uno/changelog/plugins/woocommerce
Latest updates and version history for the Yuno WooCommerce Plugin
## v1.0.1
*April 13, 2026*
**Configuration**
* **Hide payment selection when Yuno is the only gateway**\
Adds a Hide Payment Selection setting so the payment method radio buttons are hidden at checkout when Yuno is the only active gateway, presenting a cleaner one-method checkout experience. Applies to both legacy and block-based checkouts.
## v1.0.0
*April 7, 2026*
* **Initial WordPress Plugin Directory release**\
First public release of the Yuno WooCommerce payment gateway on the WordPress Plugin Directory, integrating Yuno's payment orchestration platform with WooCommerce through the Yuno Web SDK and a PHP REST API layer.
**Card Payments**
* **Card payments, wallets, and local payment methods**\
Accepts cards, digital wallets, and local payment methods through Yuno's payment orchestration platform from a single integration, with intelligent payment routing across multiple providers.
* **3D Secure and additional authentication support**\
Handles 3D Secure challenges and additional authentication flows during payment, including a return-from-3DS detection that prevents accidental order duplication.
**Block Checkout**
* **WooCommerce block-based checkout support**\
Supports both the legacy shortcode checkout and the WooCommerce block-based checkout (default since WooCommerce 8.3). Both flows converge at the order-pay page so the SDK orchestration is shared.
**Webhooks**
* **Webhook receiver for asynchronous payment status**\
Receives Yuno payment events (succeeded, pending, failed, chargeback, refund) with three-layer HMAC verification and idempotent processing through transient locks.
**Marketplace**
* **Marketplace split payments**\
Splits the order total between a seller recipient and a platform commission, configurable as a percentage or a fixed minor-unit amount.
**Reliability**
* **In-place retry on failed payments**\
Lets the customer retry a failed payment in place by remounting the SDK, instead of creating a new duplicate order on each retry attempt.
* **Server-side payment verification**\
Verifies every reported payment status against the Yuno API before updating the WooCommerce order, never trusting client-reported status.
**Order Management**
* **Auto-complete for virtual and downloadable orders**\
Orders that contain only virtual or downloadable products skip the processing state and go straight to completed after payment.
* **HPOS compatibility**\
Declares compatibility with WooCommerce High-Performance Order Storage (custom order tables) and uses HPOS-safe order queries throughout.
**Customer & Address**
* **Per-order Yuno customer strategy**\
Creates a fresh Yuno customer per WooCommerce order, with automatic recovery from duplicate-customer and customer-not-found errors so payments are never blocked by stale customer state.
**Configuration**
* **Multi-environment support**\
Auto-detects the Yuno API environment (development, staging, sandbox, production) from the Public API Key prefix.
* **Configurable debug logging with PII redaction**\
Optional WooCommerce-integrated logging for troubleshooting payments and webhooks. Phone numbers, email addresses, and full API payloads are never logged.
# React Native SDK Changelog
Source: https://docs.y.uno/changelog/react-native
Latest updates and version history for the Yuno React Native SDK
Release notes for the React Native SDK are published here as new versions are released. Check back after each SDK update for a detailed summary of changes, new features, and migration guidance.
## v1.3.2
*August 3, 2026*
* **Headless Token Generation and Enrollment Accept the Documented camelCase Properties**\
`YunoSdk.generateToken()` and `YunoSdk.continueEnrollment()` failed at runtime when called with the camelCase properties declared by the package's own TypeScript types (`checkoutSession`, `paymentMethod`, `expirationMonth`, …), because the native bridges decode snake\_case keys only. On iOS this surfaced as `TOKEN_GENERATION_ERROR` ("No value associated with key checkout\_session") and on Android as a `NullPointerException` on `PaymentMethod.getType()`. The SDK now converts payload keys from camelCase to snake\_case at the JS boundary before invoking the native bridge, so the documented TypeScript contract works on both platforms. Payloads already using snake\_case keys are passed through unchanged, so no migration is required.
## v1.3.1
*July 13, 2026*
* **iOS Build Failure on Case-Insensitive File Systems**\
Renamed the React Native bridge pod from `YunoSdk` to `YunoSdkReactNative` to eliminate a name collision with the native `YunoSDK` pod on case-insensitive macOS file systems (the default on all Macs). The collision caused linker failures during `pod install` / build — notably on Xcode 26 — unless `use_frameworks!` was enabled. Projects using React Native autolinking require no changes; if your Podfile references `pod 'YunoSdk'` directly, update it to `pod 'YunoSdkReactNative'`.
* **TypeScript Definitions Now Published to npm**\
The npm package now ships the TypeScript declaration files referenced by its `types` field (`lib/typescript/index.d.ts`). Previous versions declared the types but did not include them in the published package, so TypeScript consumers got no type resolution out of the box. TypeScript projects now get full typing and autocompletion without workarounds.
## v1.3.0
*July 2, 2026*
* **Native SDK Bumps**\
Updated the underlying native SDKs to Android `2.17.2` and iOS `2.18.0`.
* **Android Compilation Failure in v1.2.0**\
Fixed an issue where v1.2.0 failed to compile on Android projects.
**Payments**
* **getThreeDSecureChallenge Removed**\
Removed `YunoSdk.getThreeDSecureChallenge()` and the `ThreeDSecureChallengeResponse` type. Use the new `continueCardPayment()` method instead — the SDK now handles the 3DS challenge internally and returns the final payment state.
* **continueCardPayment Headless Method**\
Added `YunoSdk.continueCardPayment(checkoutSession, countryCode?, showPaymentStatus?)` to complete headless card payments that require an additional action, such as a 3DS challenge. It resolves with the final payment state (`CardPaymentResult`). Supports CARD payments only.
## v1.2.0
*May 19, 2026*
* **Payment Render Flow**\
Added the new Payment Render flow with the `` component and bridge methods (`startRenderFlow`, `showForm`, `submitForm`, `continueRender`) so merchants can embed the payment form inline with full lifecycle control.
* **Enrollment Render Flow**\
Added the Enrollment Render flow with the `` component for embedded card enrollment, mirroring the Payment Render API.
* **Native SDK Bumps**\
Bumped the underlying native SDKs to Android `2.15.1` and iOS `2.16.0`, bringing the latest payment, enrollment, and security improvements to the React Native wrapper.
* **Android 15 Edge-to-Edge Overlap**\
Configured edge-to-edge on Android 15 to prevent the payment UI from overlapping system bars, and now runs `enableEdgeToEdge` on the UI thread.
* **Samsung One UI Compatibility**\
Uses `setDecorFitsSystemWindows` for Samsung One UI compatibility, preventing layout glitches on affected devices.
* **Seamless Payment Startup Crashes**\
Made native module access fully lazy, ensured payment status events are dispatched on the main thread, safely unwrap the iOS view controller, and resolved a `TurboModuleRegistry` error in seamless flows.
* **Android Status Alignment**\
Aligned Android status values with the TypeScript `YunoStatus` enum and kept render flow status mappings separate from shared mappings.
* **fast-xml-parser DoS Vulnerability**\
Upgraded `fast-xml-parser` to address denial-of-service advisories (VULS-1511 and CVE-2026-25128).
## v1.1.0
*March 10, 2026*
* **CardFlow Configuration Removed**\
The `CardFlow` enum and the `cardFlow` property in `YunoConfig` have been removed. Card form type is now configured from the Yuno Dashboard instead of the client SDK. Remove any `CardFlow` import and `cardFlow` references from your initialization code before upgrading.\
[Migration guide →](https://github.com/yuno-payments/yuno-sdk-react-native#breaking-changes-v110)
* **Native SDK Bumps**\
Bumped the underlying native SDKs to Android `2.11.0` and iOS `2.12.9-RC`.
* **iOS Seamless Payment Flow**\
Switched iOS seamless payments to `startPaymentSeamlessLite`, now resolves promises with the final payment status instead of `PROCESSING`, runs the call on `MainActor`, and uses the `currentLanguage` from `initialize` in `SeamlessParams`.
* **Android removeListeners Crash**\
Fixed an Android crash caused by a type mismatch on `removeListeners`. The parameter type now matches what React Native passes from JS.
* **Android onPaymentSelected Signature**\
Updated the `onPaymentSelected` callback signature to match Android SDK 2.11.0.
* **minimatch ReDoS Vulnerability**\
Updated `minimatch` to resolve a regular-expression denial-of-service (ReDoS) advisory in the dependency tree.
## v1.0.30
*January 13, 2026*
* **TurboModule Support**\
Added TurboModule support for React Native 0.82+ via a new `NativeYunoSdk` codegen spec, while remaining backward compatible with the Old Architecture through a `NativeModules` fallback.
## v1.0.29
*January 13, 2026*
* **New Architecture Preparation**\
Internal updates preparing the package for React Native 0.82+ and the New Architecture (TurboModules). No public API changes; full TurboModule support arrived in 1.0.30.
## v1.0.28
*January 13, 2026*
* **Internal Release Pipeline Updates**\
Maintenance republish with no functional changes. No API changes required.
## v1.0.27
*January 13, 2026*
* **Internal Release Pipeline Updates**\
Maintenance republish with no functional changes. No API changes required.
## v1.0.26
*December 23, 2025*
* **iOS saveCardEnabled Parsing**\
Fixed a typo in the iOS config key parser that prevented `saveCardEnabled` from being applied. The toggle now correctly reaches the native SDK.
## v1.0.25
*December 22, 2025*
* **iOS Podspec Pin**\
Pinned the iOS `YunoSDK` dependency to `2.9.0-r`. No API changes required.
## v1.0.24
*December 17, 2025*
* **iOS Language in Payment Full Flow**\
Fixed iOS Payment Full flow to respect the `language` parameter passed at initialization.
## v1.0.23
*December 17, 2025*
* **iOS CardFlow Initialization**\
Fixed iOS initialization to honor the `cardFlow` configuration parameter that was previously ignored on iOS.
## v1.0.22
*December 15, 2025*
* **Documentation Updates**\
Expanded README documentation. No API changes required.
## v1.0.21
*December 10, 2025*
* **Simplified Language API**\
The `language` parameter now accepts a plain string instead of requiring the `YunoLanguage` enum, simplifying initialization. No migration required for existing integrations using the enum.
## v1.0.20
*December 10, 2025*
* **iOS Language Initialization**\
Fixed iOS initialization to honor the `language` configuration parameter (matching the Android key), while keeping backward compatibility with the legacy `lang` parameter.
## v1.0.19
*December 3, 2025*
* **Android SDK 2.8.1 Callback Compatibility**\
Updated Android callback signatures to be compatible with Android SDK 2.8.1. No API changes required.
## v1.0.18
*December 3, 2025*
* **Internal Release Pipeline Updates**\
Internal version alignment between the React Native wrapper and the underlying native SDK references. No API changes required.
## v1.0.17
*December 3, 2025*
* **Headless Payment Flow**\
Added a Headless Payment Flow for Android and iOS so merchants can drive payment progression from their own UI while delegating native execution to the SDK.
* **Headless Enrollment Flow**\
Added a Headless Enrollment Flow for Android and iOS for card enrollment via custom merchant UI.
* **iOS Payment Full Flow**\
Added Payment Full flow support on iOS with the native `YunoPaymentMethods` component for parity with Android.
* **iOS Native Module for YunoSDK 2.x**\
Updated the iOS native module to YunoSDK 2.x, including correct delegate passing for `startPayment` and `continuePayment` and using the `.succeeded` enum case.
* **iOS Module Registration**\
Fixed the iOS native module registration by adding `moduleName()` and `constantsToExport()` and switching `NativeEventEmitter` to lazy loading, resolving linking issues at startup.
* **OTT and Payment Status Events**\
OTT and payment status events are now emitted from the Full Payment Flow delegate on iOS, and the Android Payment Full flow no longer reports a stale `CANCELLED` status across sessions.
## v1.0.16
*December 2, 2025*
* **CardFlow Default Alignment**\
Aligned the default `CardFlow` value with the native SDK by switching from `MULTI_STEP` to `STEP_BY_STEP` to prevent mismatched card form rendering.
# Web SDK Changelog
Source: https://docs.y.uno/changelog/web
Latest updates and version history for the Yuno Web SDK
## v1.10.3
*August 5, 2026*
**Core SDK**
* **Dead analytics events cleanup**\
Removes 17 analytics emit methods that had zero callers (verified against develop plus a cross-repo audit of the card iframe and mobile SDKs), including the miswired `securityCodeForm.*` methods that emitted `enrollStatus_pageViewed`. No emitted event changes: every event that fires today keeps firing; `enrollPaymentMethodForm_submitted` keeps its live inline emitter and `payment_created` stays reserved for the audit pipeline.
* **Phone Country Code Autofill From Customer**\
The checkout form phone country-code dropdown now preselects the country matching the customer's phone prefix sent at session creation, disambiguated by the customer's country, instead of always defaulting to the session country.
**Card Payments**
* **Null onInstallmentSelected event when installments become unavailable**\
The `onInstallmentSelected` callback now fires with a `null` payload when installment options that were previously notified become unavailable — most commonly when the shopper switches from a card with installments to a card without them. The null event only fires if a real installment selection was notified before; forms where installments were never available stay silent. Callback invocations are also wrapped so a merchant handler that throws on `null` cannot break the card form. Applies to new-card, secure-fields, enrolled-card, and Click to Pay flows.
* **Environment-Aware 3DS Host Resolution**\
Resolve the sdk-3ds host (challenge.html, session-id.html and the 3DS event origin) from the SDK's runtime environment — encoded in the public API key — instead of freezing it into the bundle at build time. A bundle built for one environment (e.g. prod) but run against another (e.g. sandbox) was sending an environment-mismatched 3DS session token to the wrong `sdk-3ds..y.uno` host, where the session-binding verifier rejected it with 403 Forbidden and the challenge never loaded. The API and WebSocket hosts already resolve per environment this way; the 3DS host now does too. Backward-compatible: a concrete host with no `_ENVIRONMENT_` placeholder passes through unchanged.
## v1.10.2
*August 3, 2026*
* **PayPal Enrollment**\
Resolve the payment status reported to the merchant from the server instead of assuming SUCCEEDED when PayPal approves, and avoid double error handling when the payment lookup fails after approval — the error screen or merchant error callback now fires exactly once, honoring `showPaymentStatus`.
## v1.10.1
*July 30, 2026*
**Core SDK**
* **Faster Full Checkout Loading**\
The Full and Seamless Full checkouts now load faster: SDK resources and express button scripts download in parallel with the initial API calls, reducing the time to show the payment method list and express buttons.
**Samsung Pay**
* **Samsung Pay Sheet Close Reports Cancellation**\
Closing the Samsung Pay payment sheet now reports a user cancellation instead of showing a "Transaction failed" screen, and no longer leaves the merchant loading state stuck.
**Card Payments**
* **Fixed Enrolled Card Installment Notifications**\
The onInstallmentSelected callback now fires only from the enrolled card the customer selected: it notifies the default installment on first selection, changes made while the card is active, and the last selection when returning to the card. Cards not selected no longer emit duplicate notifications when switching payment methods.
## v1.10.0
*July 29, 2026*
**Samsung Pay**
* **Samsung Pay support in the Web SDK**\
Adds Samsung Pay as an external wallet button. The SDK loads Samsung's Web Checkout SDK, reads the sdk\_provider configuration returned by the backend, opens the Samsung payment sheet and forwards the tokenized payment credential to Yuno for authorization.
**Card Payments**
* **Streamlined Saved Card Display**\
Removed the card image preview from the saved (tokenized) card flow and replaced it with a compact preview showing the card brand, last four digits, cardholder name and expiry date.
* **Improved Enrolled Card Form Rendering**\
The enrolled card form no longer reserves empty space when it has no fields to display, and now renders the card holder name field when the payment method configuration requires it.
* **onInstallmentSelected Callback for Enrolled Cards**\
Added support for the onInstallmentSelected callback on enrolled cards.
**Google Pay**
* **Fixed Google Pay Button Colors**\
The Google Pay button now always honors an explicitly configured buttonColor (white or black), even when the page runs in dark mode. The default setting keeps adapting to the page color scheme automatically.
**Core SDK**
* **Improved Express Buttons Layout**\
The full checkout now renders up to three express payment buttons side by side with unified default styles. Express buttons that do not fit in the row are shown inside the payment method list and render their native button when selected.
* **EU Region Initialization Support**\
The Web SDK can now be initialized against the EU region, routing all SDK network calls to the EU checkout API. Existing integrations without a region set continue to use the current endpoint unchanged.
* **Checkout Lifecycle Analytics Events**\
Adds `checkoutSdk_started` and `payment_resolved`, and enriches the existing `checkoutSdk_completed` with UX attributes (clicks, taps, keystrokes, scroll), so a checkout can be measured end to end: when it starts, how the payment resolved, and — from the presence of `checkoutSdk_completed` — whether it was completed or abandoned. Both new events flush on emission so they are not lost to the batch debounce.
**PayPal**
* **PayPal Billing Agreement Enrollment Support**\
The SDK now supports enrolling customers with PayPal billing agreements (PAYPAL\_BA\_ENROLLMENT) and sends the PayPal partner attribution ID when loading the PayPal SDK.
**Checkout**
* **Express-Only Payment Methods Callback**\
Added an optional `onlyExpressPaymentMethods` callback to the full checkout configuration that reports `true` when every available payment method renders as an express button (Apple Pay, Google Pay, PayPal, PayPal enrollment, PayPal Braintree, Revolut Pay) and `false` otherwise. When only express methods are available, the "Or pay with" divider is no longer rendered below the express buttons.
* **Click to Pay footers use the shared modal footer**\
The Click to Pay card form, enrolled card, and installment selection screens now render the shared modal footer instead of a Click to Pay-specific copy, matching the full-width button and centered "Powered by Yuno" tag redesign. The legacy CSS hooks (`sdk-payments-c2p-button-bottom__modal-bottom`, `__button-continue`, `__button-back`) are preserved and the shared classes are added alongside them; the internal wrapper classes `sdk-payments-c2p-button-bottom__buttons-content` and `__button-wrapper` no longer exist in the DOM. The Click to Pay footer badge now links the country-specific privacy policy URL instead of always the global fallback.
* **Full-width action button in modal footers**\
The action button in the shared modal footer now spans the full width on every viewport, with the "Powered by Yuno" privacy tag centered above it. Lite keeps the tag below the button. Embedded forms rendered with `renderMode: element` are unchanged.
## v1.9.25
*August 6, 2026*
**Payment Actions**
* **Fixed showPaymentStatus on Payment Failures**\
When showPaymentStatus is set to false, the SDK no longer renders the full-screen "Transaction failed" message on early payment failures (payment not found or not yet processed); the error is delivered through the onError callback instead.
## v1.9.24
*August 3, 2026*
* **PayPal Enrollment**\
Avoid double error handling when the payment lookup fails after approval — the error screen or merchant error callback now fires exactly once, honoring `showPaymentStatus`.
## v1.9.23
*July 31, 2026*
* **PayPal Enrollment Payment Status**\
Resolve the payment status reported to the merchant from the server instead of assuming SUCCEEDED when PayPal approves.
## v1.9.19
*July 29, 2026*
**Card Payments**
* **onInstallmentSelected Callback for Enrolled Cards**\
Added support for the onInstallmentSelected callback on enrolled cards.
## v1.9.18
*July 28, 2026*
**Checkout**
* **Express-Only Payment Methods Callback**\
Added an optional `onlyExpressPaymentMethods` callback to the full checkout configuration that reports `true` when every available payment method renders as an express button (Apple Pay, Google Pay, PayPal, PayPal enrollment, PayPal Braintree, Revolut Pay) and `false` otherwise. When only express methods are available, the "Or pay with" divider is no longer rendered below the express buttons.
## v1.9.17
*July 20, 2026*
**Core SDK**
* **Payment method radio moved to the leading edge (RTL-aware)**\
BREAKING (visual default): the payment-method selection radio now renders at the leading (left) edge of each row, mirrored to the right automatically in RTL locales (Arabic, Hebrew, Persian, Urdu). Merchants with custom CSS targeting the old right-aligned radio may need to adjust their selectors. The trailing position remains available via the RadioButton showRadioLeft= prop in sdk-web-core.
* **Six New Checkout Languages**\
Adds Greek, Hebrew, Romanian, Slovak, Serbian (Latin), and Ukrainian localization to the Web SDK checkout.
**Fraud & Risk**
* **Braintree Device Data Collection**
## v1.9.16
*July 14, 2026*
**Card Payments**
* **Fixed Installments for Dual Cards in Credit-Only Mode**\
Installment options now load correctly for Brazilian dual cards when credit\_card\_only\_processing is enabled, ensuring payments are tokenized as credit with the proper installment selection.
**APM**
* **Slim Form Support for Bank Transfer Fields**\
Added slim form support to the bank transfer fields.
## v1.9.15
*July 10, 2026*
**Fraud & Risk**
* **CyberSource Fingerprint Session ID Override**\
CyberSource/Cielo CyberSource fingerprint now honors the per-provider session\_id override (deviceFingerprints), enabling merchant-specific MID prefixes on the ThreatMetrix session id.
**Card Payments**
* **Consistent Card Field Labels**\
The card number, expiration date, and CVV fields now resolve their labels from the same UI copy source across all card form variants, so the full checkout and the Lite SDK render identical texts for the same checkout session configuration.
## v1.9.14
*July 9, 2026*
**Core SDK**
* **Backend-driven checkout field labels and required fields**\
The checkout form now renders from the configuration returned with each payment method. Field labels, placeholders, validation messages, selection options, and which fields are shown are driven by the backend, so the form always reflects exactly what each payment method and provider requires, displayed in the shopper's language. When this configuration isn't provided, the SDK falls back to its built-in localized text, so existing integrations keep working with no code changes required.
**Card**
* **Consistent installment dropdown format**\
The installment dropdown now renders every option with the same template (`Nx of {value} - Total {total}`) regardless of whether the option includes financial costs, fixing mixed layouts when a plan combines options with and without `financial_costs`.
**APM**
* **ACH Direct Debit Account Fields**\
Added two new fields to the bank transfer form: Account Type (Checkings/Savings) and Account Holder Type (Individual/Company).
**PayPal**
* **Improved PayPal Braintree Button Loading**\
The loading placeholder now matches the button style configured via `externalButtons.paypalBraintree.style` (width, height and border radius), removing the visual mismatch while the button loads
## v1.9.13
*July 7, 2026*
**Address Autofill**
* **Address Autofill via Google Places + Brazil ViaCEP**\
A single feature flag `address_autofill_enabled` enables a new address autofill experience. For non-Brazilian countries the user gets a Google Places combobox with up to 5 live suggestions, cadence guard, silent fallback to manual entry and analytics events. For Brazil the field collapses to the CEP only, and ViaCEP auto-fires when the postal code matches the regex `/^\d{5}-?\d{3}$/` (with blur as fallback); the remaining fields unfold after the attempt succeeds or fails. The form country drives the decision and resets cleanly across switches. 6 new i18n keys translated in 26 locales.
## v1.9.12
*July 6, 2026*
**PayPal**
* **Improved PayPal Braintree Checkout Flow**\
Improves the PAYPAL\_BRAINTREE external button payment method, now built on braintree-web and PayPal Web SDK v6
## v1.9.11
*July 2, 2026*
**Payment Actions**
* **Payment retry in Lite checkout**\
Payment retry now works in the Lite checkout flow (`mountCheckoutLite`). A declined or errored card payment shows inline field errors and retries without restarting checkout, gated by `settings.card.enable_payment_retry`.
## v1.9.10
*June 30, 2026*
**Checkout**
* **Localized currency formatting by merchant language**\
Amounts now follow the merchant-configured YunoLanguage + per-checkout countryCode (via Intl.NumberFormat) instead of being derived from the currency, fixing decimal/thousand separators, symbol position and spacing for non-English checkouts. The currency still drives symbol vs ISO code and decimals.
**Alternative Payment Methods**
* **Render the BLIK OTP Input in Every Checkout Display Mode**\
BLIK now prompts for its one-time code in all checkout display modes — unfolded, modal (Lite SDK) and render — instead of only the unfolded flow. The entered code is sent in the One Time Token request so the payment can be completed from any integration mode.
**Core SDK**
* **Auto-Select Single Payment Method**\
When there is no enrolled payment method and only a single non-button payment method is available, it is now preselected automatically.
**Payment Actions**
* **Status Action Notification**\
The SDK now notifies the onActionExecuted callback with a CHECK\_STATUS action when the payment status screen is shown, so merchants can reliably dismiss their own loaders.
## v1.9.9
*June 24, 2026*
**Core SDK**
* **Pass a per-session JWT to challenge.html and add a postMessage handshake with nonce/origin verification for the 3DS frame-restriction flow.**
## v1.9.8
*June 23, 2026*
* **FIXED: Enable downloading the QR image for client-generated QR codes (`GENERATE_QR`, e.g. QRIS/Xendit). The "Download QR image" button now renders for these payment methods and saves the on-screen code as a PNG generated on the client with `qrcode`. Previously the button only appeared for ready-to-use image QRs (URL/BASE64), so QRIS never showed it even though the backend sent the `download_qr` label.**
**Card Payments**
* **Per-Scheme Card Number Length Validation**\
Card number length is now validated per card scheme using backend-driven rules combined with the Luhn check, reducing false rejections of valid cards. Gated behind a feature flag.
* **FIXED: Route sdk-web-card iframe assets (secure-field pages, card form, mediator) through the asset host in whitelabel mode. They were resolved against `apiUrl`, so when a merchant set a distinct `assetUrl` carrying a proxy sub-path (e.g. `/hosted-payment-methods/orchestrator`) the sub-path was dropped and secure fields loaded from the wrong path in enrollment and enrolled-card flows (CORECM-17901).**
## v1.9.7
*June 17, 2026*
**Payment Actions**
* **Report The Executed Payment Action**\
`continuePayment()` now tells you which payment action is running: it resolves with the executed action and accepts a new optional `onActionExecuted` callback that fires for each action. Use it to keep your loader on screen until a 3DS redirect navigates, avoiding the card-form flash before the challenge.
**Card Payments**
* **Card Form Title No Longer Flashes While Loading**\
In the slim card form embedded with `elementSelector`, the "Card information" title now appears together with the card fields once they finish loading, instead of showing above an empty form.
**Core SDK**
* **Consistent Payment Method Preselection**\
Payment method preselection is now consistent between the checkout state and the UI across the expanded and collapsed lists: the selected method is always reflected in the list, and one method is preselected when the backend doesn't specify a preference.
## v1.9.5
*June 15, 2026*
**Secure Fields**
* **Fixed Card Field Console Error**\
The card form no longer throws an uncaught error when entering a card whose network does not require a card PIN.
## v1.9.4
*June 15, 2026*
**Core SDK**
* **Prepend the configured whitelabel base path to host-overridden asset, iframe and WebSocket URLs so the SDK stays under a proxy mounted at a sub-path (e.g. `.../orchestrator`) instead of dropping to the bare origin. The 3DS postMessage origin opts out.**
**Revolut Pay**
* **Revolut Pay Mobile Return Support**\
Revolut Pay now returns shoppers to the checkout reliably on mobile after the redirect or app-to-app handoff.
## v1.9.2
*June 11, 2026*
**Core SDK**
* **Stronger Phone and Document Validation**\
Phone and document number fields now block invalid characters as you type, and document numbers run checksum validation — enabled gradually via the real-time validation rollout.
**Payment Actions**
* **Checkout Completed Event For All Methods**\
The checkoutSdk\_completed event is now emitted for every payment method that completes through the shared payment-action router (card, Google Pay, APMs), matching the existing Apple Pay and PayPal behavior. It fires once per checkout.
**Revolut Pay**
* **Revolut Pay Support**\
Adds Revolut Pay as an external payment button. Supports both seamless and merchant-driven checkout flows, with a configurable button (variant, size, radius, action, and locale).
**Card Payments**
* **Fixed Slim Variant Card Form Styles**\
Fixed an issue in SDK 1.9 where the slim input variant rendered incorrectly in the card form and address fields: grouped border radius, focus and error border colors, and hidden inline error messages were not applied.
## v1.9.1
*June 3, 2026*
**Checkout**
* **When only one regular payment method is available, it is now automatically pre-selected and its radio button appears checked on render — regardless of whether the backend marks it as preferred.**
* **In whitelabel mode (when `apiUrl` or `assetUrl` is set at `initialize()`), the data privacy / terms-and-conditions text is hidden, matching the "Secure by Yuno" badge behavior.**
**Core SDK**
* **QR codes for QR-based payment methods (like Nequi) now render with extra whitespace around the pattern, improving scan reliability on phones that auto-crop the camera view.**
* **Yuno-hosted static assets (such as brand logos) now can be served via the proxy. Only Yuno hosts are rewritten, leaving external asset URLs untouched.**
## v1.9.0
*May 26, 2026*
**White Label**
* **Whitelabel Class Names and IDs Prefix Change**\
`Yuno` class names and IDs prefix changed to `sdk-payments`. For example, `yuno-checkout` becomes `sdk-payments-checkout`.
* **Whitelabel-Neutral Public API**\
Public-facing CSS class names, DOM ids, and event/callback names have been renamed to neutral, whitelabel-friendly identifiers. Existing `window.Yuno`, the `yuno-sdk-ready` event, and `yuno*` callback aliases continue to work, so existing merchant integrations need no changes. `window.Yuno` deprecated in favor of `window.SdkPayments`.
* **Custom API and Asset URLs**\
Added `options.apiUrl` and `options.assetUrl` initialization overrides so the SDK can point at partner-hosted backends, 3DS endpoints, secure-field iframes, and card-form assets instead of the default Yuno URLs. The override is also forwarded to the monitoring layer, mediator, and card-form iframes.
* **Hide Secure Payment Badge on Custom Hosting**\
When `apiUrl` or `assetUrl` overrides are set, the `Secure Payment with Yuno` badge is automatically hidden in both the standard checkout and the Click to Pay flow.
**Core SDK**
* **More Resilient Asset Resolution**\
Guard the webpack public path when running under Vite, skip duplicate `/v` suffixes when the asset URL already includes one, and use the configured `apiUrl` directly as the API client base URL to avoid region-prefix corruption.
## v1.8.7
*July 9, 2026*
**Card**
* **Consistent installment dropdown format**\
The installment dropdown now renders every option with the same template (`Nx of {value} - Total {total}`) regardless of whether the option includes financial costs, fixing mixed layouts when a plan combines options with and without `financial_costs`.
## v1.8.1
*May 22, 2026*
**Core SDK**
* **Mongolian Language Support**\
Adds Mongolian (mn) as a supported locale for the web SDK checkout experience.
* **Auto-Select Single Payment Method**\
When the checkout renders with exactly one regular (non-express) payment method available, that method is now auto-selected so the customer goes straight to the form. Express buttons (Apple Pay, Google Pay, PayPal) are no longer treated as a backend-preferred method that short-circuits this flow.
* **Detailed Errors from generateOTT()**\
When `apiClientPayment().generateToken` (`generateOTT`) fails, the rejected error now contains the backend response body (with error codes and detail) instead of just the generic axios error. Merchants catching this call receive actionable error information.
**Click to Pay**
* **Deferred Installments in Click to Pay Golden Flow**\
Installment plans in the Click to Pay Golden Flow are now shown on a dedicated screen after the customer picks between Click to Pay and the standard card rail, instead of being fetched automatically while the PAN is typed. The card form stays mounted underneath so secure-field state is preserved between screens.
## v1.8.0
*May 14, 2026*
**Apple Pay**
* **Apple Pay Address Collection**\
Apple Pay payment sheet can now collect billing and shipping addresses when configured via `required_fields`. Default behavior is unchanged when not configured.
* **Apple Pay BIN Available Pre-Payment**\
DPAN BIN is now available in the OTT before payment, enabling BIN-based promotions and discounts. Existing card BIN flow is unaffected.
* **Improved Apple Pay Availability Detection**\
Apple Pay button now appears more accurately on supported devices, reducing cases where the button shows for users who cannot complete an Apple Pay payment.
**Google Pay**
* **Google Pay Address Collection**\
Google Pay payment sheet can now collect billing address, shipping address, and cardholder name when configured via `required_fields`. Address detail level adjusts automatically based on what is requested.
* **Google Pay Contact Field Collection**\
Google Pay payment sheet can now collect customer email and phone number when configured via `contactFields`. Works in both standard and seamless external-button integrations.
**Card Payments**
* **Separate Billing and Shipping Sections**\
Card form now renders billing and shipping as distinct sections with their own headers and an optional `Address line 2` field. When both addresses are required, a `Billing address is the same as shipping` checkbox appears, enabled by default.
* **Compact Card Form Layout**\
New slimmer card form layout with tighter spacing, grouped card details, and inline field-level error messages. Available across all SDK form variants. Behind a feature flag for A/B testing.
* **Card Form Auto-Advance**\
Card form auto-advances focus once fields reach their expected length (PAN by detected scheme, expiry, CVV), reducing the number of taps to complete the form. Manual selection always takes precedence. Behind a feature flag, default off, for A/B testing.
* **Real-Time Card Field Validation**\
Card form fields now validate on blur once the user has interacted with them, instead of only on Pay click. Errors clear immediately when the user corrects an invalid field.
**Core SDK**
* **Dynamic Enrollment Actions**\
Enrollment flow now supports server-driven dynamic UI components: image, OTP, PIN, and info screens, rendered based on the fields returned by the server.
* **Smarter Currency Display**\
Currency now shows a symbol only for the 21 currencies with globally unique symbols (€, £, etc.). All others display the 3-letter ISO code (for example `COP 9.200.000`, `MXN 1.500,00`). USD is the only currency that owns the `$` symbol.
* **Hide Yuno Secure Payment Badge**\
The `Secure Payment with Yuno` badge can now be hidden via Checkout Builder. When disabled, the badge is fully removed from the DOM in both the standard checkout and the Click to Pay flow.
**Fraud & Risk**
* **EBANX Device Session Reliability**\
Improved reliability of device ID propagation in payment requests, fixing Payment Link flows where it was occasionally dropped before reaching EBANX.
## v1.7.4
*May 26, 2026*
**Core SDK**
* **Reliable Document Number Validation**\
When the backend specifies a `validationFunction` for a document type that the SDK doesn't recognize, the field now falls back to regex validation instead of marking every value invalid. Prevents broken document inputs when a new validation function rolls out backend-first.
## v1.7.3
*May 11, 2026*
**Fraud & Risk**
* **Improved EBANX Device Session Handling**\
Improved EBANX device session recovery in supported fraud flows.
## v1.7.2
*May 11, 2026*
**Core SDK**
* **POST Redirect Support**\
Added support for payment providers that require `POST` redirects.
* **Expanded Required Field Support**\
Added support for additional required payment data such as `shipping_address` in supported flows.
**Secure Fields**
* **Improved Session Handling**\
Improved Secure Fields behavior in session-based payment flows.
**Card Payments**
* **Improved Card Retry Flows**\
Enhanced retry behavior for card payments in supported checkout flows.
## v1.7.1
*May 11, 2026*
**Core SDK**
* **More Reliable Payment Status Updates**\
Improved payment status handling when real-time connection tracking is interrupted.
**Payment Actions**
* **Improved QR, Barcode, and Image Rendering**\
Improved rendering for payment steps that rely on images, QR codes, or barcodes.
* **Improved OTP and PIN Flows**\
Refined OTP and PIN-based payment steps for a smoother authentication experience.
**Google Pay**
* **Improved Button Rendering**\
Improved Google Pay button rendering for a more consistent checkout experience.
## v1.7.0
*May 11, 2026*
**Click to Pay**
* **Card Type Filtering Support**\
Added support for card type restrictions in Click to Pay flows.
* **Transaction Amount Support for Passkey Flows**\
Click to Pay initialization now includes transaction amount metadata for supported passkey flows.
## v1.6.22
*May 27, 2026*
**Fraud & Risk**
* **Cybersource Fraud Session ID from Provider**\
The Cybersource fraud device-fingerprinting session now uses the provider-supplied `session_id` when present, falling back to `checkoutSession` if the provider doesn't supply one. Aligns the fingerprint session ID with what the fraud provider expects, improving fingerprint match rates.
## v1.6.21
*May 26, 2026*
**Core SDK**
* **Reliable Document Number Validation**\
When the backend specifies a `validationFunction` for a document type that the SDK doesn't recognize, the field now falls back to regex validation instead of marking every value invalid. Prevents broken document inputs when a new validation function rolls out backend-first.
## v1.6.20
*May 13, 2026*
**Card Payments**
* **Card Form Top Error Banner**\
On payment retry, a banner appears at the top of the card form describing why the previous attempt failed. The banner scrolls into view and is highlighted if the customer tries to submit again without correcting the issue. Invalid-card-data errors and unknown response codes are now surfaced through this banner instead of per-field errors.
## v1.6.19
*May 8, 2026*
**Click to Pay**
* **Card form button alignment on desktop**\
Restored correct LTR alignment for the action button and the "Secure Payment by Yuno" badge in the Click to Pay card form (regression on v1.6.x; v1.5 and v1.7 were unaffected). RTL layout is preserved.
## v1.6.18
*May 7, 2026*
**Card Payments**
* **Card Number Length Validation**\
Card tokenization now waits for the BIN/IIN lookup to complete before submitting, so card numbers are validated against the correct scheme-specific minimum length. Previously, a short Luhn-valid PAN submitted before the BIN lookup settled could be sent to the provider and rejected; users now see an inline length error instead.
## v1.6.17
*May 6, 2026*
**Apple Pay**
* **More Accurate Cancellation Reasons**\
Apple Pay cancellations are now reported with a precise reason, distinguishing user dismissal (`CANCELLED_BY_USER`) from merchant-validation or provider failures (`CANCELLED_BY_PROVIDER`). Improves the accuracy of drop-off analytics and provider health signals; no integration changes required.
## v1.6.16
*April 16, 2026*
**Core SDK**
* **Cancel 3DS Challenge on Browser Back**\
Pressing the browser back button during a 3DS challenge now cancels the challenge cleanly. Merchants receive the cancellation via `yunoPaymentResult` with status `PENDING` / `CANCELLED_BY_USER`; no `yunoError` is emitted and the modal unmounts without leaving stale state.
**Click to Pay**
* **Action Button Order on Mobile**\
On mobile and tablet viewports, the Click to Pay action buttons in the card form have been reordered so the primary action sits below the secondary, improving the UX hierarchy. Desktop layout is unchanged.
## v1.6.8
*April 15, 2026*
**Core SDK**
* **unMountSdk() Helper**\
Introduced a new top-level `unMountSdk()` method for explicit SDK cleanup. Call it when removing the SDK from the page to avoid memory leaks.
```js theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
yuno.unmountSdk();
```
* **Rollback Cancel Flow**\
Unified cancel flow events. The SDK now explicitly reports `CANCELED_BY_USER` in the `yunoPaymentResult` callback for all cancellation scenarios.
* **Legacy Event Rollback**\
Legacy cancel-related events have been consolidated into the standard result flow. No new API changes required.
* **Forter Token Listener**\
Added a listener for the `ftr:tokenReady` event to ensure reliable capture of the Forter session token. Previously the token could be missed on slow page loads.
**Apple Pay**
* **Metadata Support**\
The cancel flow now includes a `metadata` parameter with a `paymentCreated` boolean, letting merchants determine whether a payment object was created before cancellation.
* **Contact Info Passthrough**\
The SDK now automatically collects and forwards the customer's email, phone, and name from `shippingContact`. No configuration required.
**PayPal**
* **No OTT Flow**\
Added support for a `REDIRECT` workflow that skips OTT creation, enabling PayPal payments without a prior server-side session.
```js theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
yuno.startSeamlessCheckout({
paypal: {
workflow: 'REDIRECT',
orderId: 'YOUR_PAYPAL_ORDER_ID',
}
});
```
* **PayPal Button Modal**\
New `PaypalButtonModal` component that renders the PayPal button inside a modal overlay, useful for merchants using a custom checkout UI.
## v1.6.7
*March 31, 2026*
**Card Payments**
* **Card Password Field for Korean Cards**\
New secure field for the first 2 digits of the cardholder PIN required by Korean issuers. Available across standard card, step-by-step, and Click to Pay (new + enrolled) flows. Enable by passing `cardPinElementSelector` in `startCheckout` config; the field renders when enabled for the merchant.
**Click to Pay**
* **Passkey Activation with Multiple Card Providers**\
When multiple card providers are configured, the SDK now searches all of them for valid 3DS parameters instead of only the first. Passkey now activates correctly when the 3DS-capable provider is not listed first.
**Core SDK**
* **Hindi, Bengali, Malayalam, and Urdu Translations**\
Available via `language: 'hi' | 'bn' | 'ml' | 'ur'`.
* **Merchant Installments via `onGetInstallments`**\
Merchants can supply their own installment options via the `onGetInstallments(cardBin)` callback; the SDK falls back to Yuno installments when the callback returns empty. A new `onInstallmentSelected` callback fires on both auto-selection and user picks across all card flows. Merchant-supplied installments are omitted from one-time-token creation since the merchant handles them server-side.
* **`subStatus` in `yunoPaymentResult`**\
The callback now receives `subStatus` as a second argument: `yunoPaymentResult(status, subStatus?)`, giving finer-grained outcome information (notably on cancel flows).
* **Bundle Size Reduction (-16%)**\
SWC `env.targets` configured to eliminate ES5 polyfills on modern browsers.
**PayPal**
* **PayPal Locale**\
SDK language is now passed as `locale` to the PayPal `loadScript` call so the PayPal UI matches the configured checkout language.
## v1.6.6
*March 26, 2026*
**Apple Pay**
* **`externalButtons` Customization**\
New configuration on `externalButtons` for per-wallet button customization (Apple Pay, Google Pay, PayPal).
**Core SDK**
* **WebSocket Race Condition in Redirect Flows**\
Resolved a race that could lose status updates.
* **WebSocket Error Handling**\
Added error handling for WebSocket initialization to prevent unhandled failures in status polling.
## v1.6.5
*March 20, 2026*
**Apple Pay**
* **Unified Apple Pay Button**\
Legacy Apple Pay implementation was removed; the SDK now uses a single Apple Pay button consistently across standard checkout and `mountExternalButtons` integrations, driven by the SDK payment flow.
* **Faster Apple Pay Button Render**\
Apple Pay SDK loading, amount lookup, and config fetch now run in parallel, with a styled placeholder shown until the real button is ready.
* **Earlier Fraud Signal Collection**\
Fraud signals are collected during Apple Pay button initialization for broader coverage on wallet flows.
**Google Pay**
* **Google Pay Button Placeholder**\
A styled placeholder is shown while the Google Pay SDK loads, replacing the previous skeleton.
**Enrollment**
* **APM Enrollment Button Text**\
The enrollment confirmation button for APMs now reads "Continue" across Full, Lite, Seamless, and Render Mode flows.
**Card Payments**
* **Inline Payment Method Selection Error (Desktop)**\
Clicking "Pay" without selecting a payment method now shows an inline error message below the payment method list on desktop. Mobile continues to use the existing toast.
**Payment Actions**
* **Backend-Driven Warning Banner**\
Flexible payment instructions can now render an optional warning banner returned by the backend, enabling provider-specific notices such as the Punto Pago disclaimer.
## v1.6.4
*March 19, 2026*
**Fraud & Risk**
* **Riskified Integration**\
The Riskified script now loads with the correct shop and session identifiers, restoring reliable fraud signal collection when the shop domain is configured on the fraud provider.
## v1.6.3
*March 18, 2026*
**Core SDK**
* **Unified User-Cancel Flow**\
Wallet, APM, Click to Pay, 3DS modal and lite checkout cancellations now emit `yunoPaymentResult` with `PENDING` status and `CANCELLED_BY_USER` substatus, replacing the previous `ERROR CANCELED_BY_USER` event. Integrations that branched on the legacy error should switch to the substatus.
* **Additional Load-Time Optimizations**\
Google Pay and Apple Pay scripts are now preloaded, and `startCheckout`/`startSeamlessCheckout` prefetch payment methods earlier.
**Customer Fields**
* **Document Type Options**\
Removed a redundant country filter that could hide valid document types in some locales.
## v1.6.1
*March 12, 2026*
**Apple Pay**
* **Billing Contact Collection**\
Apple Pay can now capture the cardholder's billing name and postal address from the Apple Pay sheet when enabled via merchant configuration. The cardholder name is forwarded in the payment payload on completion.
* **Free Trial Support for Recurring Payments**\
Apple Pay now supports recurring billing with trial periods, configurable via merchant config (Apple Pay JS v14).
**Card Payments**
* **Network Selector**\
Dropdown across step-by-step payment, card unfolded, card modal, enrollment, and Click to Pay. Driven by server-side merchant configuration.
**Fraud & Risk**
* **Cielo CyberSource Fraud Provider**\
Cielo CyberSource added as a fraud provider, routed through the existing CyberSource integration.
* **EBANX Device Fingerprint Provider**\
New device-fingerprinting provider with country-based initialization. Customer country is now propagated through the fraud pipeline.
**Core SDK**
* **Crash with External-Buttons-Only Sessions**\
Fixed a crash that occurred when only external buttons (e.g. Apple Pay) were configured without SDK-rendered payment methods.
* **Enrolled Card Form Crash**\
Prevents a runtime crash when card metadata is missing while detecting Amex on enrolled cards.
* **Sanitize Functions from Log Payloads**\
Functions in the merchant-provided initial state are stripped before debug log serialization, preventing serialization issues across checkout, seamless checkout, headless payment/enrollment, and status flows.
## v1.6.0
*March 20, 2026*
* **Subresource Integrity Support**\
The SDK script tag now supports the `integrity` attribute for SRI-compliant loading, preventing unauthorized code injection. The `@yuno-payments/sdk-web` npm package exposes a `loadScript` method for SRI-compliant dynamic loading.
```html theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
```
* **Arabic Language and RTL Layout**\
Added Arabic (`ar`) language support. The checkout UI automatically switches to a Right-to-Left layout when Arabic is selected — no extra configuration required.
```js theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
const yuno = await window.Yuno.initialize(publicApiKey);
await yuno.startCheckout({
checkoutSession,
elementSelector: '#root',
countryCode: 'AE',
language: 'ar',
});
```
* **Faster Initialization**\
Improved initialization performance for both Lite and Full SDKs, reducing time-to-interactive on first load.
* **Detailed Error Codes**\
Configuration errors now surface more descriptive error codes, making it easier to diagnose integration issues during development.
* **3DS Modal Centering**\
Fixed an issue where the 3DS challenge modal was not centered on mobile devices. The modal now correctly fills and centers within the viewport.
## v1.5.26
*May 27, 2026*
**Card Payments**
* **Compact Form Variant (1.5 backport)**\
Backports the slimmer card, customer, and billing-address form layout from 1.6.x onto the 1.5.x line. Opt-in via the `slimmerFormEnabled` feature flag — disabled by default, no behavior change for merchants who don't toggle it.
## v1.5.25
*May 26, 2026*
**Core SDK**
* **Reliable Document Number Validation**\
When the backend specifies a `validationFunction` for a document type that the SDK doesn't recognize, the field now falls back to regex validation instead of marking every value invalid. Prevents broken document inputs when a new validation function rolls out backend-first.
## v1.5.20
*April 7, 2026*
**Apple Pay**
* **Cancel Flow**\
When the customer aborts an Apple Pay session, the cancel error now carries a `metadata` object with `paymentCreated` and `ottCreated` booleans so merchants can tell how far the flow had progressed. If a payment is created after the user has cancelled, the SDK automatically abandons the checkout session to prevent payments getting stuck in `PENDING`. (Backport of the v1.6.8 fix to the 1.5.x line.)
## v1.5.19
*April 2, 2026*
**Fraud & Risk**
* **Forter token isolation**\
Tokens are now scoped per Forter `siteId` so concurrent or sequential checkout sessions no longer read a stale token from a previous provider/session.
* **Forter beacon script**\
Consolidated to a single URL (`https://prod.y.uno/sdk-static-bundles-ms/v1/static/js/forter/forter.js`) with an updated SRI hash for both sandbox and production. Merchants with a strict CSP `script-src` allowlist should ensure `prod.y.uno` is permitted.
## v1.5.17
*April 1, 2026*
**Core SDK**
* **`sdkType` initialization option**\
New option on `Yuno.initialize()` for identifying integrations (plugins, embedded contexts) via the `x-sdk-type` request header for downstream attribution.
**Fraud & Risk**
* **Forter Token Capture**\
Token capture now uses a listener-based approach for reliable session capture across page lifecycles.
## v1.5.15
*March 19, 2026*
**Payment Actions**
* **Backend-Driven Warning Banner**\
Flexible payment-action screens (e.g. Punto Pago) can now render a server-driven banner (title + description) after the instruction steps. Configured server-side; no merchant code change required.
## v1.5.14
*March 19, 2026*
**Core SDK**
* **APM Enrollment Button Text**\
The enrollment confirmation button for APMs now reads "Continue" instead of "Save".
**Fraud & Risk**
* **Riskified Beacon Parameters**\
Missing query parameters added to the default beacon URL, restoring fraud signal collection.
## v1.5.11
*March 9, 2026*
**Apple Pay**
* **Billing Contact Collection**\
Apple Pay can now collect the cardholder's billing name and postal address from the Apple Pay sheet when enabled via merchant configuration. The cardholder name is forwarded in the payment payload. No SDK code change required by merchants.
**Fraud & Risk**
* **EBANX Device Session Collection**\
New EBANX fraud collector with automatic script mounting, retry, and unmount handling.
* **Cielo CyberSource Fraud Provider**\
Added Cielo CyberSource as a supported fraud provider.
* **Country-Aware Fraud Collection**\
Fraud signal collection now uses the customer's country across payment methods, lite flow, secure fields, PayPal, Google Pay, Apple Pay, and the headless API client, improving provider routing and accuracy.
## v1.5.8
*February 24, 2026*
**Apple Pay**
* **Wallet Domain URL**\
Apple Pay transactions now include the wallet domain URL.
**Card Payments**
* **Financial Cost in Enrolled Cards**\
Financial cost detail is shown for enrolled card payments.
**Click to Pay**
* **Financial Cost in C2P**\
Financial cost detail is shown for Click to Pay flows.
**Google Pay**
* **Third-Party Gateway Support**\
Google Pay can now route through third-party gateways (Adyen, Stripe, etc.) with the gateway and merchant ID supplied via a new SDK provider configuration.
## v1.5.5
*February 16, 2026*
**Google Pay**
* **Reload on Already-Open Sheet**\
Reloads if the Google Pay sheet is already open, preventing a stuck state.
## v1.5.4
*February 16, 2026*
**Core SDK**
* **Document Types by Country**\
New general-settings configuration for document types per country (server-side merchant config; no merchant code change).
## v1.5.0
*January 15, 2026*
* **mountExternalButtons Method**\
New `mountExternalButtons(buttons)` method lets merchants render Google Pay and Apple Pay buttons in any custom location within their UI, providing full control over button placement and styling.
```js theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
const yuno = await window.Yuno.initialize(publicApiKey);
await yuno.startCheckout({
checkoutSession,
elementSelector: '#root',
countryCode: 'US',
language: 'en',
});
await yuno.mountExternalButtons([
{
paymentMethodType: 'APPLE_PAY',
elementSelector: '#apple-pay',
},
{
paymentMethodType: 'GOOGLE_PAY',
elementSelector: '#google-pay',
},
]);
```
* **Button Unmounting Methods**\
Added `unmountExternalButton(paymentMethodType)` to remove a single external wallet button and `unmountAllExternalButtons()` to remove all mounted wallet buttons at once.
```js theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
// Remove a single button
yuno.unmountExternalButton('APPLE_PAY');
// Remove all buttons
yuno.unmountAllExternalButtons();
```
* **Wallet Buttons as Direct Buttons**\
Google Pay and Apple Pay now appear as direct action buttons instead of radio-button list items, providing a cleaner and more prominent placement in the checkout UI.
* **PayPal Enrollment UX**\
The PayPal payment sheet now opens immediately after the customer selects PayPal for enrollment or payment, removing an extra confirmation step for a faster checkout experience.
**Lite Web SDK**
* **Lite SDK External Buttons Required**\
Google Pay and Apple Pay in the Lite Web SDK now require explicit mounting via `mountExternalButtons()`. Previously they rendered automatically as radio buttons. Lite SDK integrations must add a `mountExternalButtons` call — Full SDK integrations are not affected.\
[Migration guide →](/changelog/migration-guides/web/v1-4-to-v1-5)
## v1.4.0
*October 15, 2025*
* **Card Payment Voucher Messages**\
Added voucher messaging for card payments, giving customers clear confirmation and transaction details immediately after a successful payment.
* **Language Override for Loader**\
The Yuno loader now accepts a `language` property, allowing explicit UI language control independent of browser settings. Useful for multi-language environments.
```js theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
Yuno.initialize({
language: 'es',
});
```
* **Enhanced Click-to-Pay Rendering**\
Improved rendering support for Click-to-Pay (C2P) elements, streamlining the checkout experience for enrolled cards.
**PayPal**
* **PayPal Installments Enrollment**\
Customers can now enroll in PayPal installment plans directly through the PayPal payment flow, providing flexible payment options at checkout.
* **PayPal External Button Redirect**\
PayPal can now be integrated via redirect flow with external buttons, giving merchants greater flexibility in building their payment UI.
## v1.3.0
*March 20, 2025*
* **Smart Payment Method Grouping**\
When a customer has an enrolled payment method, all other available methods are grouped under a collapsible "More options" dropdown. The enrolled method is prominently displayed by default.
* **European and Asian Language Support**\
Added support for German (`de`), Dutch (`nl`), Swedish (`sv`), French (`fr`), Italian (`it`), Japanese (`ja`), and Korean (`ko`). Pass the corresponding code via the `language` initialization parameter.
* **General Bug Fixes**\
Resolved various stability issues to improve reliability across payment flows.
* **Enhanced Styling and Branding**\
Improved visual consistency and expanded customization options across checkout components.
## v1.2.0
*February 20, 2025*
* **Optional Initialization Options**\
Added an optional `options` parameter to `Yuno.initialize` for teams with advanced use cases such as custom session handling or tracking requirements.
* **Extended continuePayment Parameters**\
`continuePayment` now accepts `checkoutSession`, `showPaymentStatus`, `yunoPaymentResult`, `yunoError`, `countryCode`, and `language`, allowing configuration overrides during payment continuation without restarting the checkout.
```js theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
yuno.continuePayment({
checkoutSession: '438413b7-4921-41e4-b8f3-28a5a0141638',
showPaymentStatus: true,
yunoPaymentResult: (status) => {
console.log('Payment completed with status:', status);
},
yunoError: (message, data) => {
console.error('Payment error:', message, data);
},
countryCode: 'US',
language: 'en',
});
```
* **21+ Language Support**\
Expanded language coverage to over 21 locales including Chinese Simplified (`zh-CN`), Chinese Traditional (`zh-TW`), Vietnamese (`vi`), Russian (`ru`), Turkish (`tr`), Polish (`pl`), and more. Pass the language code to the `language` parameter in `startCheckout`.
**Lite Web SDK**
* **Lite SDK continuePayment Overrides**\
The Lite SDK `continuePayment` method now accepts the same configuration overrides available in the Full SDK, enabling dynamic session, language, and callback changes during payment continuation.
```js theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
if (paymentResponse.sdk_action_required) {
await yuno.continuePayment({
countryCode: 'DE',
language: 'de',
showPaymentStatus: false,
yunoPaymentResult: (status) => {
console.log('Payment continued with result:', status);
},
yunoError: (message, data) => {
console.error('Payment error:', message, data);
},
});
}
```
* **Lite SDK Expanded Language Support**\
Lite SDK v1.2 adds support for 18+ locales (up from 7 in v1.1), including European and Asian language codes such as `de`, `fr`, `it`, `ja`, `ko`, `ru`, and `zh-CN`.
## v1.1.0
*January 20, 2025*
* **Async SDK Methods**\
The `initialize()`, `mountCheckout()`, and `startCheckout()` methods now return Promises. Add `await` or `.then()` to each call — synchronous usage will no longer work.\
[Migration guide →](/changelog/migration-guides/web/v1-0-to-v1-1)
```js theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
const yuno = await Yuno.initialize(PUBLIC_API_KEY);
await yuno.startCheckout(config);
```
* **continuePayment Method**\
Introduced `continuePayment()` for handling complex payment flows. Call it when the API response includes `sdk_action_required: true` — the SDK then automatically renders 3DS challenges, external wallet steps, or redirects as needed.
```js theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
const yuno = await Yuno.initialize(PUBLIC_API_KEY);
await yuno.startCheckout(config);
if (paymentResponse.sdk_action_required) {
const result = await yuno.continuePayment();
}
```
* **Simplified 3DS Integration**\
3DS data collection and setup are now bundled into the payment creation step. Remove any standalone 3DS setup service calls — implement `continuePayment()` and `yunoPaymentResult()` callbacks instead.
* **Boleto Bancário Support**\
Boleto Bancário is now available for merchants operating in Brazil, expanding local payment options for customers who prefer offline payment methods.
* **Hybrid Cards Default to Credit**\
Brazilian hybrid cards are now processed as credit by default, improving authorization rates for Brazil-based merchants.
* **Airwallex Security Integration**\
Integrated Airwallex as an additional security layer for web payments, enhancing fraud protection without requiring extra configuration.
* **Forter Fraud Prevention**\
Integrated Forter's fraud prevention technology. The SDK automatically collects device signals; no separate setup is required.
* **Checkout.com 3DS Support**\
Added support for Checkout.com as a 3DS provider. The SDK renders the authentication page automatically when the transaction provider is `checkout3ds`.
* **Unlimit 3DS Support**\
Introduced 3DS authentication support for Unlimit payments, enhancing fraud prevention for merchants using the Unlimit provider.
* **Click-to-Pay Enhancements**\
Terms & Conditions and card logos now update dynamically based on the selected card. C2P options are hidden for unsupported cards. A phone number field has been added for C2P registration. Compliance settings for `privacy` and `tnc` are forwarded with each card.
* **Inline Card Input**\
Customers can now enter card details directly beneath the Card option without navigating to a separate screen. Fields persist when switching payment methods, and the flow is fully compatible with installments and the card selector.
**Lite Web SDK**
* **Lite SDK Initial Release**\
Launched the Lite Web SDK (v1.1) — a streamlined integration offering essential payment methods, async `initialize()` support, and core callbacks (`yunoPaymentResult`, `yunoError`) with reduced setup complexity.
```js theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
const yuno = await Yuno.initialize(PUBLIC_API_KEY);
yuno.startCheckout({
checkoutSession: '438413b7-4921-41e4-b8f3-28a5a0141638',
elementSelector: '#root',
countryCode: 'FR',
language: 'fr',
showLoading: true,
issuersFormEnable: true,
showPaymentStatus: true,
card: {
isCreditCardProcessingOnly: true,
},
onLoading: (args) => {
console.log(args);
},
yunoPaymentResult: (status) => {
console.log('Payment result:', status);
},
yunoError: (message, data) => {
console.error('Payment error:', message, data);
},
});
```
## v1.0.3
*May 26, 2026*
**Core SDK**
* **Resilient Payment Status Updates**\
If WebSocket initialization fails (network blip, blocked port, browser restriction), the SDK now logs the error and falls back to HTTP polling for payment status instead of blocking the checkout. No integration change required.
## v1.0.0
*January 1, 2025*
**Core SDK**
* **Initial SDK Release**\
First stable release of the Yuno Web SDK. Provides four integration variants: Full Checkout SDK, Lite Checkout SDK, Seamless SDK, and Headless SDK — covering a full range of UI customization needs.
* **Core Payment Methods**\
Out-of-the-box support for credit and debit cards, digital wallets (PayPal, Apple Pay, Google Pay), bank transfers, direct debits, and regional local payment methods across multiple currencies and countries.
* **Three Integration Modes**\
SDK can be loaded via an HTML `
```
If the provider returns an **empty** `collect_url` and `token` (for example `CHECKOUT_COM_3DS` above), there is no collection step. Skip it and go straight to creating the payment.
#### Type MERCHANT\_PROVIDED
The merchant sends all the required data themselves (`browser_info` and `device_fingerprints`), so no device-data collection step is performed.
Use `device_fingerprints` only when a 3DS provider that collects this data on its own (i.e. does not use the `collect_url`) hands you the fingerprint `id`. Forward that `id` here. The `provider_id` must match the 3DS provider configured on the connection.
**Request**
```bash theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
curl --location 'https://api-staging.y.uno/v1/three-d-secure/setups' \
--header 'X-idempotency-key: idempotency-key' \
--header 'public-api-key: api-key' \
--header 'private-secret-key: secret-key' \
--header 'Content-Type: application/json' \
--data '{
"account_id": "account_id",
"type": "MERCHANT_PROVIDED",
"card": {
"holder_name": "TEST CUSTOMER",
"number": "4556557955726624",
"expiration_month": 12,
"expiration_year": 26,
"security_code": "123"
},
"browser_info": {
"user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
"accept_header": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"color_depth": "24",
"screen_height": "1080",
"screen_width": "1920",
"language": "es-CO",
"java_enabled": false,
"javascript_enabled": true,
"browser_time_difference": "300",
"platform": "WEB"
},
"device_fingerprints": [
{
"id": "3dae048e-b95e-47c6-8064-ea7f1aa16e90",
"provider_id": "NETCETERA_3DS"
}
],
"metadata": [
{
"key": "3ds_connection",
"value": "standard"
}
]
}'
```
**Response**
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"three_d_secure_setup_id": "59192489-3713-4d1b-894b-ac15ac5b6f6f",
"account_id": "account_id",
"type": "MERCHANT_PROVIDED",
"browser_info": {
"user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
"accept_header": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"color_depth": "24",
"screen_height": "1080",
"screen_width": "1920",
"language": "es-CO",
"javascript_enabled": true,
"java_enabled": false,
"browser_time_difference": "300",
"platform": "WEB"
},
"device_fingerprints": [
{
"provider_id": "NETCETERA_3DS",
"id": "3dae048e-b95e-47c6-8064-ea7f1aa16e90"
}
]
}
```
### 2. Create the payment
Create the payment using the `three_d_secure_setup_id` generated in the previous step. Since the route resolves only to the Yuno 3DS connection (no payment provider), only the authentication runs and the 3DS result is returned. No authorization takes place.
**Payment method:** because this is a standalone 3DS authentication flow, the card must already be available to it. Either send the `card_data` in the request, or reference a payment method that was **enrolled (vaulted) beforehand**. Do **not** send `vault_on_success: true`: this flow does not support it.
If you used `metadata` in the 3DS Setup to select a specific connection, you **must** send the **same** `metadata` here. Otherwise the payment may be routed to a different 3DS Standalone connection than the Setup.
**Request**
```bash theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
curl --location 'https://api-staging.y.uno/v1/payments' \
--header 'X-idempotency-key: idempotency-key' \
--header 'public-api-key: api-key' \
--header 'private-secret-key: secret-key' \
--header 'Content-Type: application/json' \
--data '{
"account_id": "account-code",
"description": "3DS",
"country": "CO",
"merchant_order_id": "order_id",
"merchant_reference": "merchant_reference",
"workflow": "DIRECT",
"callback_url": "https://www.example.com",
"amount": {
"currency": "COP",
"value": "27500"
},
"metadata": [
{
"key": "3ds_connection",
"value": "standard"
}
],
"customer_payer": {
"id": "customer_id"
},
"payment_method": {
"type": "CARD",
"detail": {
"card": {
"three_d_secure": {
"three_d_secure_setup_id": "59192489-3713-4d1b-894b-ac15ac5b6f6f"
},
"card_data": {
"holder_name": "TEST CUSTOMER",
"number": "4916994064252017",
"expiration_month": 12,
"expiration_year": 26,
"security_code": "123"
}
}
}
}
}'
```
**Workflow:** a **frictionless** / **data-only** authentication resolves inline (the examples ran with `workflow: DIRECT`) and the result comes back on the payment response. A **challenge** needs the cardholder to act, so the payment returns `PENDING` with a `redirect_url` and `checkout.sdk_action_required: true`. Handle it with a redirect-capable workflow (`REDIRECT`) or the Yuno SDK (see [Authentication outcomes → Challenge](#challenge)).
The payment's top-level `status` / `sub_status` tell you the outcome, and the 3DS result lives in `payment_method.payment_method_detail.card.three_d_secure`:
* **Frictionless / Data Only** → `status: SUCCEEDED`, `sub_status: THREE_D_SECURE_VERIFIED`.
* **Challenge** → `status: PENDING`, `sub_status: WAITING_ADDITIONAL_STEP`, with `checkout.sdk_action_required: true` and a `redirect_url` (resolves later; see [Webhook notification](#webhook-notification)).
* **Failed / rejected authentication** → `status: DECLINED`.
A standalone payment ultimately resolves to either `SUCCEEDED` / `THREE_D_SECURE_VERIFIED` (authentication completed) or `DECLINED` (authentication failed or rejected). The transaction-level status and 3DS response codes follow the standard Yuno reference: [Transaction statuses and response codes](/reference/payments/status-and-response-codes/transaction). Example codes include `SUCCEEDED_THREE_D_SECURE`, `CHALLENGE_REQUIRED`, `AUTHENTICATION_FAILED_THREE_D_SECURE`, and `REJECTED_THREE_D_SECURE_REQUIRED`.
## Authentication outcomes
### Frictionless
`three_d_secure` object (inside the card detail):
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
"three_d_secure": {
"version": "2.3.1",
"electronic_commerce_indicator": "05",
"cryptogram": "MTIzNDU2Nzg5MDA5ODc2NTQzMjE=",
"transaction_id": "7f5e8c1a-5c98-411e-b54b-dbff770ea045",
"directory_server_transaction_id": "fbaa20f0-09c4-48bd-b0fd-01fdbf9188cf",
"pares_status": "Y",
"acs_id": "ab4a9485-afdb-4003-a619-3aaeea0670d7"
}
```
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"id": "7f524e10-534c-4a3f-aad8-14128156a958",
"account_id": "5d8960b3-ca3c-4b8b-9891-0c190d4dae1c",
"description": "3DS",
"country": "CO",
"status": "SUCCEEDED",
"sub_status": "THREE_D_SECURE_VERIFIED",
"merchant_order_id": "order-833aaade-323d-40c2-9f2c-49f5964bd055",
"created_at": "2026-06-26T23:43:09.385435Z",
"updated_at": "2026-06-26T23:43:10.424600Z",
"amount": {
"captured": 0.00,
"currency": "COP",
"refunded": 0.00,
"value": 27500.00
},
"checkout": {
"session": "",
"sdk_action_required": false
},
"payment_method": {
"type": "CARD",
"payment_method_detail": {
"card": {
"verify": false,
"capture": true,
"installments": 1,
"card_data": {
"holder_name": "TEST CUSTOMER",
"iin": "45565579",
"lfd": "6624",
"number_length": 16,
"brand": "VISA",
"scheme": "VISA",
"issuer_name": "BANCO BILBAO VIZCAYA ARGENTARIA BBVA",
"country_code": "ES",
"category": "GOLD",
"type": "CREDIT",
"three_d_secure": {
"version": "2.3.1",
"electronic_commerce_indicator": "05",
"cryptogram": "MTIzNDU2Nzg5MDA5ODc2NTQzMjE=",
"transaction_id": "7f5e8c1a-5c98-411e-b54b-dbff770ea045",
"directory_server_transaction_id": "fbaa20f0-09c4-48bd-b0fd-01fdbf9188cf",
"pares_status": "Y",
"acs_id": "ab4a9485-afdb-4003-a619-3aaeea0670d7"
},
"fingerprint": "85749aa9-c233-4e72-99b9-cbc1065500b6",
"expiration_month": 12,
"expiration_year": 26
}
}
}
},
"transactions": {
"id": "6036a7d1-c3f2-4817-a73a-4402c24ea070",
"type": "THREE_D_SECURE",
"status": "SUCCEEDED",
"category": "CARD",
"amount": 27500.00,
"provider_id": "NETCETERA_3DS",
"response_code": "SUCCEEDED_THREE_D_SECURE",
"response_message": "3DS validation successful",
"merchant_reference": "merchant-17912e48-74b9-4435-996a-2fc1f44e1468"
},
"callback_url": "https://www.example.com",
"workflow": "DIRECT",
"metadata": [
{
"key": "3ds_connection",
"value": "standard"
}
],
"simplified_mode": false
}
```
**Flow summary:**
1. Authentication request sent to the ACS.
2. The ACS authenticates by risk analysis, with no user interaction.
3. Returns full data (cryptogram, ECI, dsTransID, version) with `pares_status = Y`; the payment is `SUCCEEDED` / `THREE_D_SECURE_VERIFIED`.
4. The result is available on the payment response. Liability shift = **yes**.
### Data Only
`three_d_secure` object (inside the card detail):
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
"three_d_secure": {
"version": "2.3.1",
"electronic_commerce_indicator": "04",
"cryptogram": "MTIzNDU2Nzg5MDA5ODc2NTQzMjE=",
"transaction_id": "a6f1faa7-2690-4d57-a589-311a3a62dedf",
"directory_server_transaction_id": "fcf62fd5-4ff7-429c-9882-2dadf92f7ee3",
"pares_status": "I",
"acs_id": "9caec967-14e2-4eed-bc35-3fa231c60c14"
}
```
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"id": "37372cdc-415d-46ad-95af-96b9de106ef1",
"account_id": "5d8960b3-ca3c-4b8b-9891-0c190d4dae1c",
"description": "3DS",
"country": "CO",
"status": "SUCCEEDED",
"sub_status": "THREE_D_SECURE_VERIFIED",
"merchant_order_id": "order-b3cb9c62-4c9c-4e48-89fa-f6bb09725c9d",
"created_at": "2026-06-26T23:45:21.558465Z",
"updated_at": "2026-06-26T23:45:22.373691Z",
"amount": {
"captured": 0.00,
"currency": "COP",
"refunded": 0.00,
"value": 27500.00
},
"checkout": {
"session": "",
"sdk_action_required": false
},
"payment_method": {
"type": "CARD",
"payment_method_detail": {
"card": {
"verify": false,
"capture": true,
"installments": 1,
"card_data": {
"holder_name": "TEST CUSTOMER",
"iin": "49169940",
"lfd": "2017",
"number_length": 16,
"brand": "VISA",
"scheme": "VISA",
"issuer_name": "PRIVATE OJSC BANK ASIA ALLIANCE BANK",
"country_code": "UZ",
"category": "CLASSIC",
"type": "DEBIT",
"three_d_secure": {
"version": "2.3.1",
"electronic_commerce_indicator": "04",
"cryptogram": "MTIzNDU2Nzg5MDA5ODc2NTQzMjE=",
"transaction_id": "a6f1faa7-2690-4d57-a589-311a3a62dedf",
"directory_server_transaction_id": "fcf62fd5-4ff7-429c-9882-2dadf92f7ee3",
"pares_status": "I",
"acs_id": "9caec967-14e2-4eed-bc35-3fa231c60c14"
},
"fingerprint": "b966eb1f-aea6-4d66-8532-0b76cdf9dc72",
"expiration_month": 12,
"expiration_year": 26
}
}
}
},
"transactions": {
"id": "85d030b5-3d34-4fdb-bb4f-a6dfcad243bb",
"type": "THREE_D_SECURE",
"status": "SUCCEEDED",
"category": "CARD",
"amount": 27500.00,
"provider_id": "NETCETERA_3DS",
"response_code": "SUCCEEDED_THREE_D_SECURE",
"response_message": "3DS validation successful",
"merchant_reference": "merchant-d2d686aa-d441-49f1-9b66-2608473b848d"
},
"callback_url": "https://www.example.com",
"workflow": "DIRECT",
"metadata": [
{
"key": "3ds_connection",
"value": "standard"
}
],
"simplified_mode": false
}
```
**Flow summary:**
1. Only browser/device data is shared with the issuer to feed their risk models: no real authentication occurs.
2. The flow continues like frictionless and returns a result (`SUCCEEDED` / `THREE_D_SECURE_VERIFIED`, `pares_status = I`).
3. Liability shift = **NO**: the merchant retains fraud liability. Typically ECI 04.
### Challenge
The payment comes back as `PENDING` with a `redirect_url` and `checkout.sdk_action_required: true`. At this point the `three_d_secure` object carries the challenge data (`pares_status: C`, empty ECI, and a `cryptogram` that holds the encoded challenge request):
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
"three_d_secure": {
"version": "2.3.1",
"electronic_commerce_indicator": "",
"cryptogram": "eyJhY3NUcmFuc0lEIjoiZTVmMDIzZDItMjlhNy00ODRlLWFhODgtMDlmYjdlOTRhODFmIiwiY2hhbGxlbmdlV2luZG93U2l6ZSI6IjA1IiwibWVzc2FnZVR5cGUiOiJDUmVxIiwibWVzc2FnZVZlcnNpb24iOiIyLjMuMSIsInRocmVlRFNTZXJ2ZXJUcmFuc0lEIjoiNDk5NGZmNGUtZWFkZC00MzFmLWJiMjEtY2MwMjY5YWZiMTJlIn0",
"transaction_id": "4994ff4e-eadd-431f-bb21-cc0269afb12e",
"directory_server_transaction_id": "d0a1890a-1e38-4c1c-9e05-e2019a04e772",
"pares_status": "C",
"acs_id": "e5f023d2-29a7-484e-aa88-09fb7e94a81f"
}
```
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"id": "1b5de250-2e52-4622-9c21-a30c70804d9a",
"account_id": "5d8960b3-ca3c-4b8b-9891-0c190d4dae1c",
"description": "3DS",
"country": "CO",
"status": "PENDING",
"sub_status": "WAITING_ADDITIONAL_STEP",
"merchant_order_id": "order-87af5f63-6679-4a3b-b436-3a1c9b72c823",
"created_at": "2026-06-26T23:47:51.448941Z",
"updated_at": "2026-06-26T23:47:52.397292Z",
"amount": {
"captured": 0.00,
"currency": "COP",
"refunded": 0.00,
"value": 27500.00
},
"checkout": {
"session": "39d9a15c-0ef0-4b10-b0bb-b64090b82f53",
"sdk_action_required": true
},
"payment_method": {
"type": "CARD",
"payment_method_detail": {
"card": {
"verify": false,
"capture": true,
"installments": 1,
"redirect_url": "https://checkout.sandbox.y.uno/payment?session=2e42a863-54e7-4607-8391-e504a2166b3e&3ds=true",
"card_data": {
"holder_name": "TEST CUSTOMER",
"iin": "49169940",
"lfd": "2017",
"number_length": 16,
"brand": "VISA",
"scheme": "VISA",
"issuer_name": "PRIVATE OJSC BANK ASIA ALLIANCE BANK",
"country_code": "UZ",
"category": "CLASSIC",
"type": "DEBIT",
"three_d_secure": {
"version": "2.3.1",
"electronic_commerce_indicator": "",
"cryptogram": "eyJhY3NUcmFuc0lEIjoiZTVmMDIzZDItMjlhNy00ODRlLWFhODgtMDlmYjdlOTRhODFmIiwiY2hhbGxlbmdlV2luZG93U2l6ZSI6IjA1IiwibWVzc2FnZVR5cGUiOiJDUmVxIiwibWVzc2FnZVZlcnNpb24iOiIyLjMuMSIsInRocmVlRFNTZXJ2ZXJUcmFuc0lEIjoiNDk5NGZmNGUtZWFkZC00MzFmLWJiMjEtY2MwMjY5YWZiMTJlIn0",
"transaction_id": "4994ff4e-eadd-431f-bb21-cc0269afb12e",
"directory_server_transaction_id": "d0a1890a-1e38-4c1c-9e05-e2019a04e772",
"pares_status": "C",
"acs_id": "e5f023d2-29a7-484e-aa88-09fb7e94a81f"
},
"fingerprint": "b966eb1f-aea6-4d66-8532-0b76cdf9dc72",
"expiration_month": 12,
"expiration_year": 26
}
}
}
},
"transactions": {
"id": "01aa5d77-1c91-4d95-9b5d-fbf1c7e863e2",
"type": "THREE_D_SECURE",
"status": "PENDING",
"category": "CARD",
"amount": 27500.00,
"provider_id": "NETCETERA_3DS",
"response_code": "CHALLENGE_REQUIRED",
"response_message": "Transaction waiting for the challenge completion",
"merchant_reference": "merchant-b2ceeae3-b3bb-4de5-b7d3-51ba87179781"
},
"callback_url": "https://www.example.com",
"workflow": "REDIRECT",
"metadata": [
{
"key": "3ds_connection",
"value": "standard"
}
],
"simplified_mode": false
}
```
Once the cardholder completes the challenge, the **final** result is delivered through the payment webhook (see [Webhook notification](#webhook-notification) below). On success, the payment shows `status: SUCCEEDED` / `THREE_D_SECURE_VERIFIED`, with a populated `electronic_commerce_indicator` and `cryptogram` / CAVV, `pares_status: Y`, and `has_challenge: true`. If the challenge fails, the payment shows `status: DECLINED`.
**Flow summary:**
1. The payment response comes back as `PENDING` / `WAITING_ADDITIONAL_STEP` (`response_code: CHALLENGE_REQUIRED`), with `checkout.sdk_action_required: true` and a `redirect_url`.
2. The cardholder must complete the issuer challenge:
* **With the Yuno SDK:** the SDK renders the challenge automatically.
* **With a redirect-capable workflow (`REDIRECT`):** redirect the cardholder to the `redirect_url` returned in the payment response so they can complete the challenge.
3. The cardholder completes the challenge (OTP, biometrics, Out-of-Band, Decoupled, Passkeys/FIDO-SPC). It is asynchronous.
4. When finished, the cardholder is returned to your `callback_url`. The final authentication result is delivered through the payment webhook (`payment.purchase`), or read it via `GET /v1/payments/{id}`.
5. On success (`pares_status = Y`) the payment is `SUCCEEDED` / `THREE_D_SECURE_VERIFIED` and liability shift = **yes**. If the challenge fails, the payment is `DECLINED`. Until the result arrives, the merchant sees the payment as `PENDING`.
### Failed / rejected
1. The ACS returns a non-authenticated result (`pares_status N` / `R`) or the authentication is rejected.
2. The payment resolves to `DECLINED`; the transaction carries a failure response code such as `AUTHENTICATION_FAILED_THREE_D_SECURE` or `REJECTED_THREE_D_SECURE_REQUIRED`.
3. No liability shift: there is no successful authentication.
## Receiving the result
For **frictionless** and **data-only**, the `three_d_secure` result is available on the payment response immediately (`status: SUCCEEDED`). For a **challenge**, the result is delivered asynchronously once the cardholder finishes (see [Webhook notification](#webhook-notification)). Alternatively, poll `GET /v1/payments/{id}` to read the final `three_d_secure` result.
## Webhook notification
The authentication result is delivered through the standard Yuno payment notification: the **same webhook you already use for payment status updates**. There is no separate 3DS-specific webhook. The event is a `payment` notification with `type_event: "payment.purchase"`. The payment is under `data.payment`, and the 3DS result is in `data.payment.transactions.payment_method.payment_method_detail.card.three_d_secure`.
For a **declined** authentication the same webhook (`payment.purchase`) is delivered; only the status changes. The payment is `DECLINED` and the transaction carries a failure response code such as `AUTHENTICATION_FAILED_THREE_D_SECURE` or `REJECTED_THREE_D_SECURE_REQUIRED`.
**Example: successful authentication (after a completed challenge)**
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"type": "payment",
"type_event": "payment.purchase",
"account_id": "5d8960b3-ca3c-4b8b-9891-0c190d4dae1c",
"retry": 0,
"version": 2,
"data": {
"payment": {
"id": "b5f22a56-285f-4ea5-a26c-0651a53c0771",
"account_id": "5d8960b3-ca3c-4b8b-9891-0c190d4dae1c",
"description": "3DS",
"country": "CO",
"status": "SUCCEEDED",
"sub_status": "THREE_D_SECURE_VERIFIED",
"merchant_order_id": "order-781223d2-4ade-436b-9ac1-a7f675ae0339",
"created_at": "2026-06-26T23:50:39.456437Z",
"updated_at": "2026-06-26T23:50:59.882628Z",
"amount": {
"currency": "COP",
"value": 27500,
"refunded": 0,
"captured": 0
},
"checkout": {
"session": "1ae63f1a-d587-4ee3-8fe1-7871e4dbd39f",
"sdk_action_required": true
},
"transactions": {
"id": "4aaad7e2-95c9-4499-af1d-7d8147c29a61",
"type": "THREE_D_SECURE",
"status": "SUCCEEDED",
"category": "CARD",
"amount": 27500,
"provider_id": "NETCETERA_3DS",
"response_code": "SUCCEEDED_THREE_D_SECURE",
"response_message": "3DS validation successful",
"merchant_reference": "merchant-14b2aa13-ee69-41d5-9d6c-48a2e0bde1ee",
"payment_method": {
"type": "CARD",
"payment_method_detail": {
"card": {
"verify": false,
"capture": true,
"installments": 1,
"card_data": {
"holder_name": "TEST CUSTOMER",
"iin": "49169940",
"lfd": "2017",
"number_length": 16,
"brand": "VISA",
"scheme": "VISA",
"issuer_name": "PRIVATE OJSC BANK ASIA ALLIANCE BANK",
"country_code": "UZ",
"category": "CLASSIC",
"type": "DEBIT",
"three_d_secure": {
"version": "2.3.1",
"electronic_commerce_indicator": "02",
"cryptogram": "JAmi21makAifmwqo2120cjq1AAA=",
"transaction_id": "6cf8f7dd-0d15-40f1-a520-55e89e048942",
"directory_server_transaction_id": "b24df687-0a2d-43be-b555-82aef699dfbc",
"liability_shift": null,
"authentication_created_at": null,
"has_challenge": true,
"authentication_id": null,
"pares_status": "Y",
"acs_id": "afa24c2f-fb84-4d33-8399-74e60a1e0380",
"strong_customer_authentication_exemptions": null,
"cavv_algorithm": null,
"ds_risk_score": null
},
"fingerprint": "b966eb1f-aea6-4d66-8532-0b76cdf9dc72",
"expiration_month": 12,
"expiration_year": 26
}
}
}
},
"connection_data": {
"id": "636226c6-a02b-4ef1-8925-9ec4a499fd59",
"name": "Yuno 3DS Standalone"
}
},
"callback_url": "https://www.example.com",
"workflow": "REDIRECT",
"metadata": [
{
"key": "3ds_connection",
"value": "standard"
}
]
}
}
}
```
## Response fields
| Field | Meaning |
| :-------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `version` | The 3D Secure protocol version used for the authentication (e.g. 2.1.0 / 2.2.0 / 2.3.1). Newer versions enable additional challenge methods (OOB, Passkeys/FIDO, etc.). |
| `electronic_commerce_indicator` (ECI) | Indicates the authentication result and who bears fraud liability. Visa: 05 authenticated / 06 attempted / 07 not authenticated. Mastercard: 02 authenticated / 01 attempted / 00 not authenticated. Empty while a challenge is still pending. |
| `cryptogram` | The CAVV/AAV: cryptographic proof generated by the issuer that authentication took place. Unique per transaction; sent to the acquirer in the authorization to validate the 3DS. While a challenge is pending, this field carries the encoded challenge request instead. |
| `transaction_id` | The 3DS Server Transaction ID (`threeDSServerTransID`): identifier of the 3DS transaction assigned by the 3DS Server in 3DS2. Correlates the AReq/ARes messages. (This is the 3DS2 value; the legacy 3DS1 "XID" is a different field.) |
| `directory_server_transaction_id` (dsTransID) | Unique transaction identifier assigned by the Directory Server (Visa/Mastercard) in 3DS2. A mandatory value that must travel in the authorization alongside the cryptogram. |
| `pares_status` | Authentication result (EMVCo transStatus): Y authenticated, N failed, A attempted, U unavailable, R rejected, C challenge required, I data only. |
| `acs_id` | Identifier of the issuer's ACS (Access Control Server) that processed the authentication. Used for reference/traceability to the ACS that responded. |
| `has_challenge` | Whether the authentication went through a challenge (`true`) or was frictionless / data-only (`false`). Present in the webhook payload. |
| `liability_shift` | Boolean summary of the liability outcomes described above: `true` when fraud liability shifted to the issuer, `false` when the merchant retains it. Can also be `null`, including in some successful-authentication cases — if you see `null` unexpectedly and rely on this field for chargeback handling, contact Yuno support. |
## Testing (sandbox)
The 3DS sandbox uses specific test cards to force each outcome, and the cards depend on the 3DS provider configured on the connection.
### Netcetera (default)
Holder `TEST CUSTOMER`, expiry `12/26`, CVV `123`:
| Card number | Outcome |
| :----------------- | :-------------------- |
| `4556557955726624` | Frictionless |
| `4916994064252017` | Challenge / Data Only |
### Cybersource
Holder `John Doe`, expiry `01/26`, CVV `123`:
| Card number | Outcome |
| :----------------- | :----------- |
| `4000000000001000` | Frictionless |
| `4000000000001091` | Challenge |
### Checkout.com
| Card number | Outcome |
| :----------------- | :----------- |
| `4485040371536584` | Frictionless |
| `4242424242424242` | Challenge |
For a challenge in the sandbox, complete it with the password `Checkout1!`. See the Checkout.com 3DS test cards documentation for expiry/CVV and additional cards.
# Cancel and Capture Flow
Source: https://docs.y.uno/docs/payment-features/Cancel-and-capture-flow
Configure real-time, manual, or delayed capture and cancel settings for authorized card payments
This guide outlines all available approaches for capture and cancel operations and explains how to interact with our APIs for each scenario.
## In this guide
* [**Capture modes**](#capture-modes)
* [Real-time capture](#real-time-capture)
* [Manual capture](#manual-capture)
* [Delayed capture](#delayed-capture)
* [**Cancel modes**](#cancel-modes)
* [Manual cancel](#manual-cancel)
* [Delayed cancel](#delayed-cancel)
* [**Configuration requirements**](#configuration-requirements)
* [**Example requests**](#example-requests)
* [Example 1: Real-time capture](#example-1-real-time-capture)
* [Example 2: Manual capture only](#example-2-manual-capture-only)
* [Example 3: Delayed capture](#example-3-delayed-capture)
* [Example 4: Delayed cancel](#example-4-delayed-cancel)
* [Example 5: Combined delayed capture and cancel](#example-5-combined-delayed-capture-and-cancel-with-enhanced-validation)
* [**When to use each mode**](#when-to-use-each-mode)
* [**Field reference**](#field-reference)
## Capture modes
Yuno provides three options for capturing payments, determined by the `capture` field and optional `delayed_capture_settings` configuration found in the [create payment API](/reference/create-payment). The actual feature availability or specific implementation details may vary depending on which payment provider you're routing your payments through.
### Real-time capture
This mode processes the payment and transfers the funds without any delay, effectively combining authorization and capture into a single **purchase** operation. When `payment_method.detail.card.capture` is set to `true`, the transaction is executed as a purchase, which means the authorization and capture happen simultaneously.
Depending on the payment provider's API, Yuno may execute this as one direct purchase transaction or as an authorization immediately followed by a capture call.
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"payment_method": {
"detail": {
"card": {
"capture": true,
"card_data": {
// card details
}
}
}
}
}
```
### Manual capture
With this configuration, Yuno won't capture the payment until you call the [capture API](/reference/capture-authorization) or manually capture it in your [Yuno dashboard](https://dashboard.y.uno/). Set `capture: false` to authorize the payment without capturing it.
Manual captures provide maximum flexibility since they give you full control of when the capture is performed. However, it's important to capture as soon as possible since payment providers enforce time limits on how long authorizations can remain uncaptured, and these limits vary by provider and region.
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"payment_method": {
"detail": {
"card": {
"capture": false,
"card_data": {
// card details
}
}
}
}
}
```
**Capturing Different Amounts**
If you need to capture a different amount than originally authorized, you must use manual capture. The real-time and delayed capture modes will always capture the initially authorized amount.
### Delayed capture
Configure `capture: false` along with `delayed_capture_settings` to schedule the capture of the payment for a later time, specified in the `delay` field.
**Full Amount Captures Only**
Delayed capture only applies when capturing the **full amount** of the authorization. If you need to capture a partial amount, you must use [manual capture](/docs/capture-payments) instead.
**`simplified_mode`**
Setting `simplified_mode` to `true` will make Yuno retry the capture operation in case an error occurs during the scheduled capture attempt.
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"payment_method": {
"detail": {
"card": {
"capture": false,
"delayed_capture_settings": {
"delay": "P7D",
"simplified_mode": false
},
"card_data": {
// card details
}
}
}
}
}
```
The `delay` field is required when using delayed capture operations and must follow the ISO 8601 standard. For example:
* `"PT3H"` for 3 hours
* `"P7D"` for 7 days
* `"P1M"` for 1 month
If you call the [capture API](/reference/capture-authorization) before the scheduled time, your call will override the delay and execute the capture immediately. **This action automatically cancels the scheduled Yuno trigger**. Alternatively, you can capture the payment manually through your [Yuno dashboard](https://dashboard.y.uno/).
## Cancel modes
When you authorize a payment without immediately capturing it, those funds are temporarily held on the customer's payment method. If you decide not to capture the payment, it's important to cancel the authorization to release those held funds and provide a better customer experience. Cancel modes give you control over when and how these authorizations are voided.
### Manual cancel
With manual cancel mode, authorized payments stay active until you explicitly cancel them. Yuno will not automatically void these authorizations, giving you full control over when to release the funds. You can cancel authorizations using the [cancel API](/reference/cancel-or-refund-a-payment) or through your Yuno dashboard interface.
It's crucial to cancel authorizations you won't capture as soon as possible to release the held funds. Customer experience is significantly impacted when authorizations aren't canceled, as funds may remain reserved for varying periods depending on the customer's region and card network.
### Delayed cancel
Configure `delayed_cancel_settings` to set a delay when canceling uncaptured authorizations, similar to delayed captures. This feature automates the release of customer funds if you decide not to capture them within a specified timeframe, significantly improving the customer experience by preventing indefinite holds on their payment methods.
The `delay` field is required when using delayed cancel operations and must follow the ISO 8601 standard. For example:
* `"PT3H"` for 3 hours
* `"P7D"` for 7 days
* `"P30D"` for 30 days
**`simplified_mode`**
Setting `simplified_mode` to `true` will make Yuno retry the cancel operation in case an error occurs during the scheduled cancellation attempt.
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"payment_method": {
"detail": {
"card": {
"capture": false,
"delayed_cancel_settings": {
"delay": "P30D",
"simplified_mode": false
},
"card_data": {
// card details
}
}
}
}
}
```
If you call the [capture API](/reference/capture-authorization) or [cancel API](/reference/cancel-or-refund-a-payment) before the scheduled time, your call will override the delay and execute the action immediately. **This action automatically cancels the scheduled Yuno trigger**. Alternatively, you can capture or cancel the payment manually through your Yuno dashboard.
**Delayed Capture and Cancel Settings**
Yuno recommends not using **both** `delayed_capture_settings` and `delayed_cancel_settings` simultaneously to avoid unexpected behaviors. Use only one at a time based on your needs.
## Configuration requirements
* `delayed_capture_settings` and `delayed_cancel_settings` are only valid when `capture = false`
* If `capture = true`, these objects must be omitted or set to `null`
* Manual operations can be performed via API endpoints or through your Yuno dashboard
## Example requests
### Example 1: Real-time capture
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"country": "US",
"amount": {
"currency": "USD",
"value": "20000"
},
"customer_payer": {
"id": "",
"first_name": "John",
"last_name": "Doe",
"email": "johndoe@example.com"
},
"workflow": "DIRECT",
"payment_method": {
"detail": {
"card": {
"capture": true,
"card_data": {
"number": "4111111111111111",
"expiration_month": 11,
"expiration_year": 28,
"security_code": "123",
"holder_name": "John Doe"
}
}
},
"type": "CARD"
},
"account_id": "",
"description": "Real-time capture payment",
"merchant_order_id": "000023"
}
```
### Example 2: Manual capture only
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"country": "US",
"amount": {
"currency": "USD",
"value": "20000"
},
"customer_payer": {
"id": "",
"first_name": "John",
"last_name": "Doe",
"email": "johndoe@example.com"
},
"workflow": "DIRECT",
"payment_method": {
"detail": {
"card": {
"capture": false,
"card_data": {
"number": "4111111111111111",
"expiration_month": 11,
"expiration_year": 28,
"security_code": "123",
"holder_name": "John Doe"
}
}
},
"type": "CARD"
},
"account_id": "",
"description": "Authorization only - manual capture",
"merchant_order_id": "000024"
}
```
### Example 3: Delayed capture
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"country": "US",
"amount": {
"currency": "USD",
"value": "20000"
},
"customer_payer": {
"id": "",
"first_name": "John",
"last_name": "Doe",
"email": "johndoe@example.com"
},
"workflow": "DIRECT",
"payment_method": {
"detail": {
"card": {
"capture": false,
"delayed_capture_settings": {
"delay": "P7D",
"simplified_mode": false
},
"card_data": {
"number": "4111111111111111",
"expiration_month": 11,
"expiration_year": 28,
"security_code": "123",
"holder_name": "John Doe"
}
}
},
"type": "CARD"
},
"account_id": "",
"description": "Authorization with delayed capture",
"merchant_order_id": "000025"
}
```
### Example 4: Delayed cancel
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"country": "US",
"amount": {
"currency": "USD",
"value": "20000"
},
"customer_payer": {
"id": "",
"first_name": "John",
"last_name": "Doe",
"email": "johndoe@example.com"
},
"workflow": "DIRECT",
"payment_method": {
"detail": {
"card": {
"capture": false,
"delayed_cancel_settings": {
"delay": "P30D",
"simplified_mode": false
},
"card_data": {
"number": "4111111111111111",
"expiration_month": 11,
"expiration_year": 28,
"security_code": "123",
"holder_name": "John Doe"
}
}
},
"type": "CARD"
},
"account_id": "",
"description": "Authorization with delayed cancel",
"merchant_order_id": "000026"
}
```
### Example 5: Combined delayed capture and cancel with enhanced validation
This example shows a complete payment request with both delayed capture and cancel settings, along with enhanced customer validation fields:
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"country": "US",
"amount": {
"currency": "USD",
"value": "20000"
},
"customer_payer": {
"merchant_customer_validations": {
"account_is_verified": true,
"email_is_verified": true,
"phone_is_verified": true
},
"id": "",
"first_name": "John",
"last_name": "Doe",
"email": "johndoe@example.com"
},
"workflow": "DIRECT",
"payment_method": {
"detail": {
"card": {
"capture": false,
"delayed_capture_settings": {
"delay": "P20D",
"simplified_mode": true
},
"delayed_cancel_settings": {
"delay": "P40D",
"simplified_mode": true
},
"card_data": {
"number": "4111111111111111",
"expiration_month": 11,
"expiration_year": 28,
"security_code": "123",
"holder_name": "John Doe"
},
"verify": false
}
},
"type": "CARD"
},
"account_id": "",
"description": "Payment with card details",
"merchant_order_id": "000023"
}
```
**Note**
While this example shows both `delayed_capture_settings` and `delayed_cancel_settings` configured together, Yuno recommends using only one at a time to avoid unexpected behaviors.
## When to use each mode
### Use real-time capture when:
* You provide goods or services immediately
* You don't need to validate inventory or fraud checks after authorization
* You want the simplest payment flow
### Use manual capture when:
* You need to verify inventory before finalizing the payment
* You want to capture a different amount than authorized
* You have complex business logic that determines whether to capture or cancel
* You need maximum control over the capture timing
### Use delayed capture when:
* You want automatic capture after a specific time period
* You have a predictable fulfillment process
* You want to reduce manual intervention while maintaining control
### Use delayed cancel when:
* You want to automatically release customer funds if you don't capture within a timeframe
* You want to improve customer experience by not holding funds indefinitely
* You have a maximum time limit for your fulfillment process
## Field reference
| Field | Type | Description |
| ------------------------------------------ | --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `capture` | `boolean` | Determines whether the card payment is captured immediately (`true`, purchase) or only authorized (`false`, requires capture or cancel). |
| `delayed_capture_settings.delay` | `string` | Delay before Yuno captures the payment. Must follow ISO 8601 duration format (e.g., "P7D" for 7 days, "PT3H" for 3 hours). |
| `delayed_capture_settings.simplified_mode` | `boolean` | If `true`, Yuno retries the capture if it fails. |
| `delayed_cancel_settings.delay` | `string` | Delay before Yuno cancels the authorization. Must follow ISO 8601 duration format (e.g., "P30D" for 30 days). |
| `delayed_cancel_settings.simplified_mode` | `boolean` | If `true`, Yuno retries the cancel if it fails. |
# Account Funding Transactions (AFTs)
Source: https://docs.y.uno/docs/payment-features/account-funding-transactions-afts
Load funds into wallets or transfer between accounts using account funding transactions through the Payments API
## Introduction
**Account Funding Transactions (AFT)** are financial transactions that facilitate the transfer of funds between payment accounts. They are widely used to load or top up user accounts, digital wallets, perform internal fund transfers within a payment platform.
AFTs enable efficient and secure movement of money across accounts.
## What is an AFT?
An **AFT (Account Funding Transaction)** is a type of transaction designed for:
* **Loading funds** into user accounts or digital wallets.
* **Transferring funds** between accounts within the same platform.
* **Depositing money** into commercial or personal accounts. Remittances included.
AFTs leverage traditional payment networks (e.g., Visa, Mastercard, ACH) to process transactions quickly and securely while optimizing costs.
### Types of AFT Transactions
1. **Funding transactions**:
* Transfer funds into an account from a debit/credit card or bank account.
* Example: A user loads their digital wallet using their debit card.
2. **Withdrawal transactions**:
* Move funds from a user account back to their bank account or card.
* Example: A user transfers money from their digital wallet to their bank account.
## Integration
To perform an AFT, you will need to send a request to our [Payments API](/reference/create-payment) with the `additional_data.order.account_funding` object specifying the `sender` and `beneficiary` data.
Each credit card scheme might require different information about the recipient and the sender, depending on the operating region and transaction category.
```Text Example theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
[...]
"additional_data": {
"order": {
"account_funding": {
"sender": {
"first_name": "John",
"last_name": "Doe",
"email": "john.doe@mail.com"
},
"beneficiary": {
"first_name": "Chris",
"last_name": "Martin",
"document": {
"document_number": "38192019",
"document_type": "CC"
}
}
}
}
}
[...]
```
For more details, refer to the create [payments API](/reference/create-payment) section.
**Additional Data**
In case you need to define additional information about the seller, such as `merchant_category_code` for example, you can find extra fields in the `seller_details` inside the [`additional_data` struct](/reference/the-payment-object) in the payment.
# Card verification results (AVS & CVV)
Source: https://docs.y.uno/docs/payment-features/card-verification-results
Understand how Yuno surfaces issuer-side address (AVS), postal code, cardholder name, and CVV/CVC check results on every card payment.
When a card payment is authorized, the issuer can return the result of several verification checks the network ran against the card data the customer provided, most importantly **AVS** (Address Verification Service) and the **CVV / CVC** match. Yuno relays those results back to you on every card transaction so you can use them in your own risk, reconciliation, or retry logic.
This guide covers:
* What each verification result means
* Where to find them in the API response and webhooks
* How to interpret the codes
* How to use them in your decision flow
***
## What gets checked
| Check | What it verifies | Field |
| ------------------------------------- | -------------------------------------------------------------------------------------------------------------- | -------------------------- |
| Street address (AVS) | First line of the billing address the customer entered matches what the issuer has on file. | `address_line_1_check` |
| Postal / ZIP code (AVS) | The billing postal code matches the issuer's record. | `zip_code_check` |
| Cardholder name | The cardholder name on the request matches the issuer's record. Coverage varies widely by network and country. | `card_holder_name_check` |
| Card security code (CVV / CVC / CVV2) | The 3- or 4-digit security code on the card matches. | `card_security_code_check` |
All four are issuer-driven: Yuno does not compute them, it forwards exactly what the acquirer / card network returns.
***
## Where to find them in the response
The block lives on the **card detail** of the payment method, and is duplicated on each transaction that ran a verification:
```
payment.payment_method.payment_method_detail.card.verification_services
payment.transactions.payment_method.detail.card.verification_services
payment.transactions_history[].payment_method.detail.card.verification_services
```
It appears on the response of:
* `POST /v1/payments`: Create payment
* `GET /v1/payments/{id}`: Retrieve payment
* `POST /v1/payments/{id}/capture`, `/refund`, `/cancel`, etc.
It is also included in **payment webhook events** (`payment.created`, `payment.updated`, …), inside the same `payment_method.detail.card` path.
### Example response (excerpt)
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"id": "p_01HZK3TJX5W8R7Q2V4N6Y8M1B3",
"status": "SUCCEEDED",
"payment_method": {
"type": "CARD",
"payment_method_detail": {
"card": {
"authorization_code": "123456",
"card_data": {
"brand": "VISA",
"iin": "411111",
"lfd": "1111"
},
"verification_services": {
"address_line_1_check": "PASS",
"zip_code_check": "PASS",
"card_holder_name_check": "UNAVAILABLE",
"card_security_code_check": "PASS"
}
}
}
}
}
```
If none of the checks were performed, the entire `verification_services` object is omitted from the response.
***
## Result values
Yuno normalizes the result of every check returned by the issuer / acquirer into one of four canonical values. Each of the four fields takes the same enum:
| Value | Meaning |
| ------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| `PASS` | The check ran and the value matched the issuer's record. |
| `FAIL` | The check ran and the value did **not** match. |
| `UNAVAILABLE` | The check could not be completed: the issuer is not certified, did not respond, or does not support the check in this region. |
| `UNCHECKED` | The check was not performed for this transaction (e.g. the merchant did not send a CVV, or the provider does not run AVS). |
***
## How to use these results
AVS and CVV results are **not** authorization decisions: the transaction can be approved even when the checks fail. They are advisory signals you can fold into your own risk strategy.
A simple decision matrix many merchants use:
| AVS (address\_line\_1\_check / zip\_code\_check) | CVV (card\_security\_code\_check) | Suggested action |
| ------------------------------------------------ | --------------------------------- | -------------------------------------------------------------------------------------- |
| `PASS` | `PASS` | Accept. |
| `PASS` | `FAIL` | Soft decline / step-up: billing data looks right but the security code is wrong. |
| `FAIL` | `PASS` | Review: billing-data mismatch is a strong fraud signal even with a correct CVV. |
| `FAIL` | `FAIL` | Decline. |
| `UNAVAILABLE` / `UNCHECKED` | any | Treat as unknown: fall back to other risk signals (3DS result, fraud-screening score). |
Because verification coverage varies by issuer and region, any decisioning you build on top should:
1. **Default to the authorization decision.** A `SUCCEEDED` transaction should ship unless your risk policy says otherwise.
2. **Combine signals.** Pair CVV / AVS with `fraud_screening`, the `three_d_secure` result, and `provider_data.iso8583_response_code`.
3. **Tolerate `UNAVAILABLE` and `UNCHECKED`.** Many cards in Latin America and EMEA do not run AVS at all.
***
## Sending verification data on the request
You can also pass `verification_services` **into** Yuno on the create-payment request, for example, when relaying upstream auth results from a system of record. The same four fields are accepted under:
```
payment_method.payment_method_detail.card.verification_services
```
When provided on the request, Yuno forwards the values to the downstream provider where supported.
# Enroll Cards with Payment Links
Source: https://docs.y.uno/docs/payment-features/enrollment/enroll-cards-with-payment-link
Generate a payment link so customers can update an expired or declined card and re-enroll automatically
Yuno provides merchants with the ability to manage overdue or declined payments using secure payment links. When a credit card expires or is reported as stolen or lost, you can generate a payment link to share with customers via email or text message, allowing them to easily update their payment information.
This feature is tailored for merchants who operate their own subscription engine and need to update credit card details to continue processing payments with a new `vaulted_token` for their customers.
## How it works
### 1. Receiving the payment link
When users need to update their payment information, they receive a secure payment link. This link allows them to complete any pending payments using a credit or debit card. To create the payment link for enrollment, make sure to include the following fields:
* `customer_payer.id`: The ID of the previously [generated customer](/reference/create-customer)
* `one_time_use`: Set this to `true` to ensure the payment link can only be used once
* `vault_on_success`: Set this to `true` to enroll the credit card after a successful payment
### 2. Automatic enrollment
Once the payment is successfully completed through the link, Yuno automatically generates a new `vaulted_token` for the customer.
### 3. Continue charging
After obtaining the `vaulted_token`, you can proceed with your subscription schedule. Use the [Get payment methods](/reference/retrieve-enrolled-payment-methods-api) endpoint to access the customer's payment methods.
For more information about creating and managing payment links, refer to the [payment link API reference](/reference/create-payment-link).
# Enroll Payment Methods
Source: https://docs.y.uno/docs/payment-features/enrollment/enroll-payment-methods
Store a customer's payment method in Yuno's vault to enable recurring charges and retries across providers
Enrollment allows you to securely store a customer's payment method in Yuno's vault for future use. When you enroll a payment method, Yuno generates a `vaulted_token` that references the payment details without exposing sensitive information. This enables recurring payments, subscriptions, and retries across providers while maintaining PCI compliance.
**Vaulted Token**
A Vaulted Token is created once a payment method is enrolled and stored with the customer information. You can use the created Vaulted Token to identify the payment method in future payments.
## Available payment methods for enrollment
| Payment method | Type |
| -------------------------- | ---------------------- |
| **Cards** | `CARD` |
| **Nupay** | `NU_PAY_ENROLLMENT` |
| **PayPal** | `PAYPAL_ENROLLMENT` |
| **Daviplata** | `DAVIPLATA_ENROLLMENT` |
| **MercadoPago Wallet** | `WALLET_CONNECT` |
| **dLocal Yape** | `YAPE_ENROLLMENT` |
| **dLocal Smart PIX** | `SMART_PIX` |
| **Astropay** | `ASTROPAY_ENROLLABLE` |
| **Nequi**\* | `NEQUI` |
| **Bancolombia Tokenbox**\* | `BANCOLOMBIA_TOKENBOX` |
| **Adyen PIX Biométrico** | `PIX_BIOMETRICO` |
| **DolarApp** | `DOLARAPP` |
(\*) SDK only. Consult the [SDK documentation](/docs/sdks/overview/quickstart) for integration details.
## Requirements
* Gather your [API credentials](/docs/developers-credentials) from the [Yuno Dashboard](https://dashboard.y.uno/developers):
* `public-api-key`
* `private-secret-key`
* `account_id`
* [Set up connections](/docs/connections) on your Yuno Dashboard. Add a payment method that requires enrollment.
* [Build a route](/docs/routing#configuring-the-dynamic-routing) for the payment method to define how it will be processed.
* [Configure the checkout builder](/docs/checkout-builder) to make your connected payments available.
## Steps summary
To enroll a payment method into a customer account:
1. [Create a Customer](/reference/create-customer)
2. [Create Customer Session](/reference/create-customer-session) (Only for Checkout workflow)
3. (Optional) Retrieve Payment Methods Available to Enroll - [Checkout workflow](/reference/retrieve-payment-methods-to-enroll-checkout)
4. Enroll Payment Method [Checkout workflow](/reference/enroll-payment-method-checkout)/[Direct workflow](/reference/enroll-payment-method-api)
5. Retrieve Payment Methods - [Direct workflow](/reference/retrieve-enrolled-payment-methods-api)
## Enroll a payment method
### Step 1: Create a customer
Register customer info through the [Create Customer](/reference/create-customer) endpoint. Also, supply the `merchant_customer_id`, a unique identifier for the customer used on your system.
**Customer complementary information**
Optional details like phone, billing address, and shipping address are not required to enroll a payment method, but some providers use them for fraud checks. If you include these fields, certain sub-fields become required.
After creating the customer, you'll receive an `id` that identifies them in Yuno. If your customer already has an `id`, skip this step.
### Step 2: Create a customer session
**Workflow Requirements**
The enrollment workflow varies by payment method type:
* **Checkout workflow**: Requires customer session for most payment methods (Cards, Nupay, PayPal, Daviplata, dLocal methods, Astropay, Adyen PIX Biométrico)
* **Direct workflow**: Available for Cards only (PCI compliant merchants). Proceed directly to Step 3 using the customer `id` generated in Step 1.
* **SDK workflow**: Payment methods like Nequi and Bancolombia Tokenbox require SDK implementation. WALLET\_CONNECT (MercadoPago) supports both SDK and Checkout workflows. Consult the [SDK documentation](/docs/sdks/overview/quickstart) for details.
* **SDK Seamless workflow**: You can enroll payment methods during the seamless payment flow by setting `vault_on_success: true` when creating the payment. The payment method will be automatically enrolled if the payment succeeds. For wallets (Apple Pay / Google Pay), the instrument is vaulted as a hidden record: the `vaulted_token` is returned in the payment response but does not appear in the customer's payment-methods listing — see the note in [Step 5](#step-5-retrieve-payment-methods).
Create a customer session to store the customer's payment preferences using the [Create Customer Session](/reference/create-customer-session) endpoint. Use the `id` from Step 1 as the `customer_id`.
The response returns a `customer_session`, which you'll use to enroll the payment method.
### Step 3: Retrieve payment methods to enroll
This **optional step** lists all available payment methods the customer can enroll. If you already know which payment method to enroll, proceed to [Step 4](#step-4-enroll-a-payment-method).
To list available payment methods, use the Retrieve Payment Methods To Enroll endpoint. For the [Checkout workflow](/reference/retrieve-payment-methods-to-enroll-checkout), include the `customer_session` in the request. The Direct workflow doesn't currently support retrieving payment methods to enroll.
The response returns a `payment_methods` array containing all available payment methods to enroll. Use the `type` field from this response in the next step.
**Available Payment Methods**
Only payment methods that you've connected, routed, and added to your checkout will appear in the response.
### Step 4: Enroll a payment method
Enroll the payment method using one of the following endpoints:
* [**Checkout workflow**](/reference/enroll-payment-method-checkout): Pass the payment method `type` to the `payment_method_type` parameter. Supported types include: `CARD`, `NU_PAY_ENROLLMENT`, `PAYPAL_ENROLLMENT`, `DAVIPLATA_ENROLLMENT`, `WALLET_CONNECT`, `YAPE_ENROLLMENT`, `SMART_PIX`, `ASTROPAY_ENROLLABLE`, `PIX_BIOMETRICO`.
* [**Direct workflow**](/reference/enroll-payment-method-api): Pass the payment method `type` to the `type` parameter. (Only available for `CARD` payment methods used by PCI compliant merchants)
* [**SDK workflow**](/docs/sdks/overview/quickstart): Payment methods like `NEQUI` and `BANCOLOMBIA_TOKENBOX` require SDK implementation. `WALLET_CONNECT` (MercadoPago) supports both SDK and Checkout workflows.
The enrollment response includes a redirect URL to the payment provider page. Step 5 explains where to find it and how to complete enrollment.
### Step 5: Retrieve payment methods
The customer must provide authorization on the payment provider page. Retrieve the authorization URL based on your workflow:
* **Checkout workflow**: The enrollment URL appears in the enrollment response from Step 4. Find it in `provider.redirect.init_url`.
* **Direct workflow**: You'll receive the final status in Step 4 (cards only).
Redirect the user to complete authorization. Once enrollment is complete, proceed to the next step.
To confirm enrollment, retrieve the enrolled payment methods and verify the `status` is `ENROLLED`.
**Wallet-vaulted instruments are not listed**
Instruments vaulted through a wallet payment (Apple Pay / Google Pay with `vault_on_success: true`) are stored as hidden records: they do not appear in the enrolled payment methods listing, even though their `vaulted_token` is valid and chargeable. Store that token from the payment response, and resolve it individually with [Retrieve Enrolled Payment Method by ID](/reference/retrieve-enrolled-payment-method-by-id-api) if needed. See [Stored Credentials](/docs/payment-features/stored-credentials#wallet-originated-tokens-apple-pay-and-google-pay).
**Fingerprint**
When a credit card is enrolled, the response includes a `fingerprint` field that represents your customer's card across your organization. If a customer enrolls the same card multiple times, multiple `vaulted_token` values are generated, but the `fingerprint` remains the same, allowing you to deduplicate on your side. See [Card Fingerprint](/docs/fingerprint).
The fingerprint is available after enrollment but can be `null` for some providers. Always check for its presence before using it for deduplication.
The fingerprint also appears in payment responses when a transaction uses an enrolled credit card.
# Installments
Source: https://docs.y.uno/docs/payment-features/installments/index
Offer card payments in installments through merchant-defined or provider-defined plans for flexible checkout
In this section, you'll discover how Yuno supports payments in installments, offering you and your customers the flexibility to make large purchases more affordable. Explore the benefits of this feature and understand the difference between "Merchant" and "Provider" installments for a tailored payment solution.
## Accept card payments in installments
Yuno supports payments in installments, which allows you to spread out the cost of a purchase over a longer period of time. This is a great way to make a large purchase more affordable or to free up cash flow for other expenses.
### Merchant vs. Provider Installments
Installment implementation varies depending on the origin and your commercial agreements. There are two options merchants can use, one defined by themselves and the other according to the providers' definition:
* **[Merchant](/docs/merchant-installments)**: In this case, the merchant manages its own installment options through individual payment processors, determining the available installment choices for customers within Yuno.
* **[Provider](/docs/provider-installments)**: When the merchant lacks predefined installment agreements, they rely on the payment processor's installment options. We work with your chosen provider to access the available installments to offer your customers for each transaction.
To have additional information regarding how to configure each option, you can access the [Merchant Installments](/docs/merchant-installments) or the [Provider Installments](/docs/provider-installments) pages.
# Merchant Installments
Source: https://docs.y.uno/docs/payment-features/installments/merchant-installments
Configure installment options yourself when your commercial agreements with payment processors already define the available plans
You can use the Merchant Installments options when you, the merchant, have your own commercial agreements and installment capabilities defined within your payment processors. In this case, you are responsible for handling the logic behind the installment options available for each transaction. When creating the payment, you will inform Yuno of the available number of installments that customers can choose from.
## How to use merchant installments?
Depending on the way you are connected to Yuno, the process of configuring the installments may vary. Next, we present how you can inform Yuno of the installment option for the Direct workflow and the SDK integration.
### Direct workflow
When using a [Direct integration](/docs/direct-flow), you manage the front-end checkout experience. In this case, you will inform Yuno about the number of installments when creating the payment using the [Create Payment](/reference/create-payment) endpoint. The number of installments will be defined through the `payment_method.detail.card.installments` parameter.
### SDK Integration
When you use Yuno's SDK, Yuno is responsible for presenting to the customer the installment options available for each payment. As a result, you need to inform Yuno which installments will be available for your account. In this case, the installment configurations are performed through [Yuno's Dashboard](https://auth.y.uno/u/login?). To perform this configuration, execute the two steps described below.
1. First, when configuring your provider [Connection](/docs/connections) in Yuno Dashboard, you need to enable the installments option. Thus, Yuno will show the installment option when the customer chooses the Credit card option form of the SDK checkout.
2. After enabling the installments, you need to create an installment plan using the [Create Installments Plan](/reference/create-installments-plan) endpoint. When creating a plan, you will specify the accepted currency, amounts, card brands, dates, etc. Once the plan is active, Yuno applies it automatically to matching payments and presents the corresponding installment options to the customer.
**Secure Fields SDK Integration**
When using Secure Fields SDK integration, you will need to [enable the installments option](/docs/sdks/customization/secure-fields/payment-secure-fields) while starting the checkout process.
For merchant-created installments, you also have the possibility of specifying the plan for every session by either using:
* the `plan_id` while [creating the session](/reference/create-checkout-session).
* a `plan structure` while [creating the checkout session](/reference/create-checkout-session).
**Routing with Fallback Providers**
When setting up your [route](/docs/using-yuno/dashboard-overview/routing) for the Card payment method, it's important to remember that if you have a fallback provider while using installments, we will try to make a fallback payment if the first transaction is rejected. Therefore, it's crucial to ensure that both providers support the amount of installments set for your account. If they do not, you can set up different routes for each scenario to avoid issues.
# Provider Installments
Source: https://docs.y.uno/docs/payment-features/installments/provider-installments
Let Yuno consult the payment provider for available installment plans when no merchant agreement exists
**Provider** installment is when the merchant does not have a commercial agreement for a defined set of installments, so they use the installments defined by the payment processor. Yuno consults the provider of your choosing in order to get the installments available to offer your customers for each transaction.
### How to use provider installments?
While configuring your provider [Connection](/docs/connections) in Yuno Dashboard, you can enable the installments available for the provider so we can use them in the Credit card form of the SDK for the customer to select from. For this scenario, there is no need to create a plan, as Yuno will use the plan defined by your payment processor.
**Secure Fields SDK**
When using Secure Fields SDK integration, you will need to [enable the installments option](/docs/sdks/customization/secure-fields/payment-secure-fields) while starting the checkout process.
This option is not enabled for all providers, only the ones that have Installment services that Yuno can access to get the information from. If you consider that a provider should have this feature enabled, please reach out to your account manager.
**Routing Configuration Warning**
While setting your [route](/docs/using-yuno/dashboard-overview/routing) for the Card payment method, remember that having a fallback for a provider that has "Provider installments" is not supported, as different providers handle different types of installment plans. It can cause a processing error in the fallback.
# Network Token Authentication
Source: https://docs.y.uno/docs/payment-features/network-token-authentication
Authenticate card-on-file payments with network passkeys to raise approval rates and shift fraud liability to the issuer
Network Token Authentication (NTA) is Yuno's unified solution for authenticating card payments through **Network Token Passkeys** — the passkey-backed authentication experiences offered by the card networks on top of their tokenization services. It consolidates every network's passkey integration under a single Yuno product, providing merchants with a consistent flow, configuration point, and shopper experience regardless of the underlying network.
The purpose of NTA is simple: allow merchants to turn card-on-file payments into authenticated, passkey-backed transactions without integrating network-specific SDKs. Yuno handles the cryptography, redirects, and network-specific plumbing, while the merchant controls when a payment follows the passkey flow through routing rules.
## What the product solves
Card-on-file payments traditionally rely on a stored PAN and, at best, a static CVC re-entry. This often leads to:
* **Low approval rates**: Issuers treat unauthenticated card-on-file as higher risk.
* **High friction**: Fallbacks usually involve a full 3DS challenge.
Network Token Passkeys address both issues. The transaction is submitted as a network token with a cryptogram, and the shopper authenticates once against the network using a device passkey (biometric or one-time passcode). This results in a transaction that is both tokenized and authenticated, shifting liability where applicable.
## Benefits for the merchant
* **Higher authorization approval rates**: Passkey-authenticated transactions carry a strong authentication signal rewarded by issuers.
* **Liability shift**: Fraud liability moves to the issuer on authenticated transactions, reducing chargeback exposure.
* **SCA compliance**: Satisfies Strong Customer Authentication (SCA) requirements with a lighter shopper experience than standalone 3DS.
* **Smoother repeat-purchase experience**: Once a passkey is registered, future purchases on the same device are frictionless and faster.
* **Reduced friction-driven drop-off**: The passkey step is network-hosted and optimized for mobile, cutting abandonment.
* **One integration for every network**: Merchants inherit new network integrations automatically as Yuno onboards them.
* **Merchant-controlled via routing**: Decide exactly when to apply NTA (e.g., per country, amount, payment method, BIN) using standard Yuno routing rules.
## Supported brands
| Brand | Passkey product | Status |
| ---------- | -------------------------- | --------- |
| Mastercard | Secure Card on File (SCOF) | Supported |
Additional networks will be added as their passkey integrations are productized. The merchant-facing flow remains identical across brands.
## How it works at Yuno
Network Token Authentication is **opt-in per merchant** and driven entirely by routing configuration. There is no change to the payment creation call; the passkey flow is triggered based on the routing rules for that specific transaction.
### Setup steps
Before triggering a passkey flow, complete the following setup:
1. **Onboard in Network Tokens**: Enable your account for [Network Tokens](/docs/security-and-compliance/network-tokens).
2. **Create a Network Token Authentication connection**: In the Yuno Dashboard, create a dedicated connection of type **Network Token Authentication**.
3. **Load 3DS information**: Ensure the payment provider connection processing the authorization has its 3DS credentials/configuration loaded.
4. **Configure routing**: Place the NTA connection as a step that runs **prior** to the payment provider step in your routing configuration.
### Runtime behavior
1. When a payment is created, Yuno evaluates the routing rules **before** sending the transaction to the acquirer.
2. If the route includes the Network Token Authentication step, Yuno triggers the passkey flow with the corresponding network.
3. If not, the payment proceeds as a standard card authorization.
Yuno handles routing evaluation, passkey triggering, redirect handling, and returning the authenticated result.
## Integration
When NTA is triggered, Yuno surfaces it as a standard `REDIRECT_URL` continue action. This matches the pattern used by redirect-based APMs, requiring no network-specific frontend code.
### 1. Initialize Yuno
```js theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
const yuno = await Yuno.initialize(PUBLIC_API_KEY)
```
### 2. Start the payment client
```js theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
const apiClientPayment = await yuno.apiClientPayment({
country_code: "US",
checkout_session: "",
})
```
### 3. Generate the one-time token
```js theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
const oneTimeToken = await apiClientPayment.generateToken({
checkout_session: "",
payment_method: {
type: "CARD",
vaulted_token: "",
card: { detail: { security_code: "123" } },
},
})
```
### 4. Create the payment
From your backend, call Yuno's [Create Payment](https://docs.y.uno/reference/payments/create-payment) endpoint with `payment_method.token` set to the one-time token. If NTA is triggered, the response contains `sdk_action_required: true`.
### 5. Get the continue action
```js theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
const data = await apiClientPayment.getContinuePaymentAction({
checkoutSession: "",
})
```
`data.action` will be `REDIRECT_URL` and `data.redirect` contains the network-hosted authentication URL:
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"action": "REDIRECT_URL",
"redirect": {
"init_url": "https://...",
"success_url": "https://...",
"error_url": "https://..."
}
}
```
### 6. Redirect the shopper
Use a full-page browser redirect to send the shopper to `redirect.init_url`.
```js theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
if (data.action === "REDIRECT_URL") {
window.location.href = data.redirect.init_url
}
```
After authentication, the network redirects the shopper back to your site. Use [Yuno Webhooks](/docs/webhooks/configure-webhooks) or [Retrieve Payment by ID](https://docs.y.uno/reference/payments/retrieve-payment-by-id) to read the final status.
## When authentication is triggered
NTA runs **only** when:
1. The merchant is onboarded in Network Tokens.
2. An NTA connection exists with 3DS info on the payment provider connection.
3. The NTA connection is correctly placed in the routing before the payment step.
## Handling the final status
The flow is asynchronous. Wait for the outcome via webhook or poll the payment status. Terminal states are standard Yuno statuses (`SUCCEEDED`, `DECLINED`, `CANCELLED`, `EXPIRED`).
# Payment Details
Source: https://docs.y.uno/docs/payment-features/payment-amount-details
Break down a payment's total into fee, shipping, tips, taxes, and discount components for transparency
The API lets you break down a payment's total into individual components, such as base charges, taxes, fees, tips, and discounts.
* [Fee](#fee-amount)
* [Shipping](#shipping-amount)
* [Tips](#tips)
* [Taxes](#taxes)
* [Discounts](#discounts)
* [Customer validations](#customer-validations)
These fields are informational: each component is already included in the payment's total `amount.value` and isn't added on top of it.
## Fee amount
A dedicated field (`additional_data.order.fee_amount`) allows you to specify the fee amount for your services that is included in the transaction.
In the following example you can see a request that clarifies that a 180 JPY fee amount is part of a 5000 JPY final transaction. This field is for informational purposes, the `fee_amount` is already included in the final transaction amount and is not added separately.
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
curl --request POST \
--url https://api-sandbox.y.uno/v1/payments \
--header 'X-Idempotency-Key: ' \
--header 'accept: application/json' \
--header 'content-type: application/json' \
--header 'private-secret-key: ' \
--header 'public-api-key: ' \
--data '
{
"description": "Test",
"account_id": "{{account-code}}",
"merchant_order_id": "0000023",
"country": "JP",
"merchant_reference" : "reference-{{$randomUUID}}",
"amount": {
"currency": "JPY",
"value": 5000.00
},
"customer_payer": {
"id":"967ecd18-d898-4b88-9400-dd5b01b18edc"
},
"additional_data": {
"order": {
"fee_amount": 180.00
}
},
"workflow": "DIRECT",
"payment_method": {
"type":"CARD",
"vaulted_token": "eb8caa17-6407-457b-960e-125d8d7a90c1",
"detail": {
"card": {
"stored_credentials":{
"reason":"CARD_ON_FILE",
"usage": "USED"
}
}
}
}
}
'
```
## Shipping amount
A dedicated field (`additional_data.order.shipping_amount`) allows you to specify the shipping amount that is included in the transaction.
In the following example you can see a request that clarifies that a 270 JPY shipping amount is part of a 5000 JPY final transaction. This field is for informational purposes, the `shipping_amount` is already included in the final transaction amount and is not added separately.
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
curl --request POST \
--url https://api-sandbox.y.uno/v1/payments \
--header 'X-Idempotency-Key: ' \
--header 'accept: application/json' \
--header 'content-type: application/json' \
--header 'private-secret-key: ' \
--header 'public-api-key: ' \
--data '
{
"description": "Test",
"account_id": "{{account-code}}",
"merchant_order_id": "0000023",
"country": "JP",
"merchant_reference" : "reference-{{$randomUUID}}",
"amount": {
"currency": "JPY",
"value": 5000.00
},
"customer_payer": {
"id":"967ecd18-d898-4b88-9400-dd5b01b18edc"
},
"additional_data": {
"order": {
"shipping_amount": 270.00
}
},
"workflow": "DIRECT",
"payment_method": {
"type":"CARD",
"vaulted_token": "eb8caa17-6407-457b-960e-125d8d7a90c1",
"detail": {
"card": {
"stored_credentials":{
"reason":"CARD_ON_FILE",
"usage": "USED"
}
}
}
}
}
'
```
## Tips
A dedicated field (`additional_data.order.tip_amount`) allows you to specify the tips amount that is included in the transaction.
In the following example you can see a request that clarifies that a 50 JPY tip amount is part of a 5000 JPY final transaction. This field is for informational purposes, the `tip_amount` is already included in the final transaction amount and is not added separately.
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
curl --request POST \
--url https://api-sandbox.y.uno/v1/payments \
--header 'X-Idempotency-Key: ' \
--header 'accept: application/json' \
--header 'content-type: application/json' \
--header 'private-secret-key: ' \
--header 'public-api-key: ' \
--data '
{
"description": "Test",
"account_id": "{{account-code}}",
"merchant_order_id": "0000023",
"country": "JP",
"merchant_reference" : "reference-{{$randomUUID}}",
"amount": {
"currency": "JPY",
"value": 5000.00
},
"customer_payer": {
"id":"967ecd18-d898-4b88-9400-dd5b01b18edc"
},
"additional_data": {
"order": {
"tip_amount": 50.00
}
},
"workflow": "DIRECT",
"payment_method": {
"type":"CARD",
"vaulted_token": "eb8caa17-6407-457b-960e-125d8d7a90c1",
"detail": {
"card": {
"stored_credentials":{
"reason":"CARD_ON_FILE",
"usage": "USED"
}
}
}
}
}
'
```
## Taxes
A dedicated array of objects (`additional_data.order.taxes`) allows you to specify the taxes amounts for your services that are included in the transaction.
| Field | Type | Description | Example |
| :--------- | :---- | :--------------------------------- | :------- |
| type\* | enum | Tax Type. | VAT |
| tax\_base | float | Taxed base amount for the payment. | 10000.00 |
| value\* | float | Tax amount value for the payment. | 2100.00 |
| percentage | float | Tax rate | 21.00 |
| Tax Type | Availability | Description |
| :--------------- | :----------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| VAT | COL, ECU | Value Added Tax. Also known as IVA. |
| CONSUMPTION\_TAX | COL | Also known as "Impuesto al consumo". In Colombia, the National Consumption Tax is an indirect tax applied to the sale of specific goods and services, such as alcoholic beverages, cigarettes, mobile phone services, among others. The rate varies depending on the good or service. |
| AIRPORT\_TAX | COL, BRL | This tax is a fee charged to passengers for the use of airport facilities. This tax varies depending on the airport and may include national and international rates. |
| VAT\_LAW\_17934 | UYU | In Uruguay, Law No. 17.934 refers to the regulations that establish specific modifications and provisions related to the Value Added Tax (VAT). This law may include regulations on exemptions, special rates, and administrative procedures. |
| VAT\_LAW\_19210 | UYU | In Uruguay, Law No. 19.210 establishes additional regulations or modifications to VAT rules. This law may focus on aspects such as the digitization of tax processes, new tax rates, or adjustments in exemptions and tax treatments of certain goods and services. |
| VAT\_EXEMPTION | COL, ECU | Value Added Tax Exemption |
| ISV | DOM | Sales Tax. Also known as "Impuesto Sobre las Ventas". In the Dominican Republic, the ISV, commonly known as ITBIS (Impuesto a la Transferencia de Bienes Industrializados y Servicios), is a value-added tax applied to the transfer of goods and services. The ITBIS is similar to the VAT in other countries, where the tax is levied at each stage of the production and distribution process. |
In the following example, you can see a request that clarifies what taxes are part of a 1000.00 USD final transaction. This field is for informational purposes; the `taxes` struct is already included in the final transaction amount and has not been added separately.
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
curl --request POST \
--url https://api-sandbox.y.uno/v1/payments \
--header 'X-Idempotency-Key: ' \
--header 'accept: application/json' \
--header 'content-type: application/json' \
--header 'private-secret-key: ' \
--header 'public-api-key: ' \
--data '
{
"description": "Test",
"account_id": "{{account-code}}",
"merchant_order_id": "0000023",
"country": "US",
"merchant_reference" : "reference-{{$randomUUID}}",
"amount": {
"currency": "USD",
"value": 1000.00
},
"customer_payer": {
"id":"967ecd18-d898-4b88-9400-dd5b01b18edc"
},
"additional_data": {
"order": {
"taxes": [
{
"type": "AIRPORT_TAX",
"tax_base":400000.00
},
{
"type": "VAT",
"value": 320000.00,
"tax_base":2000000.00
}
]
}
},
"workflow": "DIRECT",
"payment_method": {
"type":"CARD",
"vaulted_token": "eb8caa17-6407-457b-960e-125d8d7a90c1",
"detail": {
"card": {
"stored_credentials":{
"reason":"CARD_ON_FILE",
"usage": "USED"
}
}
}
}
}
'
```
## Discounts
A dedicated array of objects (`additional_data.order.discounts`) allows you to specify the discounts that are included in the transaction.
In the following example you can see a request that clarifies that a 500 USD discount amount is part of a 5000 USD final transaction. This field is for informational purposes, the `discounts` is already included in the final transaction amount and is not added separately.
```json Example theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
curl --request POST \
--url https://api-sandbox.y.uno/v1/payments \
--header 'X-Idempotency-Key: ' \
--header 'accept: application/json' \
--header 'content-type: application/json' \
--header 'private-secret-key: ' \
--header 'public-api-key: ' \
--data '
{
"description": "Test",
"account_id": "{{account-code}}",
"merchant_order_id": "0000023",
"country": "US",
"merchant_reference" : "reference-{{$randomUUID}}",
"amount": {
"currency": "USD",
"value": 5000.00
},
"customer_payer": {
"id":"967ecd18-d898-4b88-9400-dd5b01b18edc"
},
"additional_data": {
"order": {
"discounts": [
{
"id": "10OFF",
"name":"Offer",
"unit_amount":500.00
}
]
}
},
"workflow": "DIRECT",
"payment_method": {
"type":"CARD",
"vaulted_token": "eb8caa17-6407-457b-960e-125d8d7a90c1",
"detail": {
"card": {
"stored_credentials":{
"reason":"CARD_ON_FILE",
"usage": "USED"
}
}
}
}
}
'
```
## Customer validations
A dedicated object (`customer_payer.merchant_customer_validations`) allows you to specify certain customer validations rules for fraud prevention inquiries.
| field | type | description |
| :-------------------- | :--- | :------------------------------------------------------------------------------------------ |
| account\_is\_verified | bool | If the customer's account has been validated before on the merchant's side. True by default |
| email\_is\_verified | bool | If the customer's email has been validated before on the merchant's side. True by default |
| phone\_is\_verified | bool | If the customer's phone has been validated before on the merchant's side. True by default |
In the following example you can see a request that clarifies that customer has been previously verified outside Yuno.
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
[...]
"description": "Test PIX",
"account_id":"{{account-code}}",
"merchant_order_id": "0000022",
"country": "BR",
"amount": {
"currency": "BRL",
"value": 50
},
"customer_payer": {
"merchant_customer_id": "AA001",
"first_name": "VALERIO",
"last_name": "DE AGUIAR ZORZATO",
"email": "test_user_1431202421@testuser.com",
"phone": {
"number": "11992149494",
"country_code": "55"
},
"document": {
"document_type": "CPF",
"document_number": "96050176876"
},
"merchant_customer_validations":{
"phone_is_verified":true,
"account_is_verified":true,
"email_is_verified":true
}
},
[...]
```
# SCA Exemptions
Source: https://docs.y.uno/docs/payment-features/sca-exemptions
Request PSD2 exemptions from Strong Customer Authentication for eligible low-risk or recurring card transactions
## Understanding SCA Exemptions
Under the European Union's Payment Services Directive 2 (PSD2), Strong Customer Authentication (SCA) is mandated for electronic payments to enhance security and reduce fraud. However, PSD2 provides specific scenarios—known as SCA exemptions—where transactions can bypass the standard authentication requirements. These exemptions are designed to streamline the payment process for low-risk transactions, improving the user experience without compromising security.
## Challenge Request Indicator
The `strong_customer_authentication_exemptions` array enables merchants to specify their preference regarding the application of Strong Customer Authentication (SCA) exemptions during a transaction. By utilizing this field, merchants can request that certain transactions be exempted from the standard authentication challenges, thereby enhancing the customer experience and reducing friction during the payment process.
## Allowed Values
The `strong_customer_authentication_exemptions` array accepts the following values, each corresponding to a specific SCA exemption:
* **`LOW_VALUE`**: Indicates that the transaction amount is below the low-value threshold defined by PSD2 (typically under €30).
* **`TRANSACTION_RISK_ANALYSIS`**: Signifies that a Transaction Risk Analysis (TRA) has been conducted, and the transaction is deemed low-risk.
* **`STRONG_CUSTOMER_AUTHENTICATION`**: Signifies that the authentication responsibility has been delegated to a trusted third party who has already performed SCA.
* **`OUT_OF_SCOPE`**: Signifies that the authentication responsibility shouldn't be taken into account.
* **`SECURE_CORPORATE`**: Indicates that the payment is made using a secure corporate card not assigned to an individual.
* **`TRUSTED_BENEFICIARY`**: Denotes that the merchant has been added to the customer's list of trusted beneficiaries after an initial SCA.
* **`RECURRING_PAYMENT`**: Indicates that the transaction is a fixed-amount recurring payment to the same beneficiary.
**Cartes Bancaires Safe'R (France)**
Safe'R is a Cartes Bancaires (CB) program built on top of EMV 3DS 2.x and TRA. There is no dedicated `SAFER` flag in Yuno's API. To request Safe'R-eligible flows, use the `TRANSACTION_RISK_ANALYSIS` exemption and include the CB risk data fields in your payment request.
Provide as much of the following as possible to maximize eligibility:
* `customer_payer.ip_address`
* `customer_payer.email`
* `customer_payer.phone`
* `customer_payer.billing_address.*`
* `customer_payer.shipping_address.*`
* `customer_payer.browser_info.*` (for web flows)
## Implementation Example
The Strong Customer Authentication exemptions come from either:
* **\[Recommended]** - The previous analysis of a fraud provider in your payment route:
*
* Defining it when creating payment requests via API. Ensure that the selected value accurately reflects the nature of the transaction. For example:
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
[...],
"payment_method": {
"type": "CARD",
"detail": {
"card": {
"card_data": {
"holder_name": "Paco",
"number": "4871049999999910",
"expiration_month": 3,
"expiration_year": 30,
"security_code": "737"
},
"three_d_secure": {
"strong_customer_authentication_exemptions": ["LOW_VALUE"]
}
}
}
}
[...]
}
```
In this example, the `strong_customer_authentication_exemptions` is set to LOW\_VALUE, indicating that the transaction qualifies for the low-value payment exemption.
### Considerations
* *Issuer's Final Decision*: While merchants can request an exemption using the `strong_customer_authentication_exemptions` field, the card issuer has the final authority to accept or decline the exemption based on their risk assessment and compliance policies.
* *Liability Implications*: Requesting an exemption may impact liability in cases of fraudulent transactions. It's essential to understand that if an exemption is granted, the liability shift associated with SCA may not apply. The payment response reflects this in the `three_d_secure.liability_shift` field — see [3DS Standalone: Response fields](/docs/payment-features/3ds-standalone#response-fields).
* *Regulatory Compliance*: Ensure that the use of this field aligns with regional regulations, such as PSD2 in Europe, and that your implementation adheres to the specific requirements and thresholds defined for each exemption type.
# Split Payments Marketplace
Source: https://docs.y.uno/docs/payment-features/split-payments-marketplace
Onboard recipients and split a marketplace payment among multiple sellers, fees, and commissions
This feature allows **merchants to split payments among multiple recipients**, which is particularly useful for marketplace models where transactions need to be divided among different sellers or stakeholders. Merchants can specify how the payment is split, including the amounts, recipients, and any applicable fees.
The split payment functionality depends on the support of the selected payment provider. Yuno acts solely as the orchestrator of the payment, not the processor. Ensure your provider supports split payments before using this functionality.
## Key features
The key features of the split payments marketplace include:
* **Split payments**: Define how the total payment amount is distributed among different recipients.
* **Flexible configuration**: Supports both absolute-based and auto-calculation splits.
* **Auto Split Configuration**: Define rules at the recipient level (percentage, fixed, or mixed) to automate split calculations without specifying amounts in each payment request.
* **Integration with providers**: Splits can be executed by payment providers that support this functionality.
* **Detailed handling of fees**: The system allows for fine-tuning of how transaction fees and chargebacks are managed.
* **Onboarding transfer**: Allows the transfer of onboardings between different recipients.
To use this feature, you must **first onboard your recipients** for the payment split, and **then create the payment** specifying the necessary information.
## 1. Onboarding
Yuno's onboarding model is crafted to assist marketplaces in seamlessly connecting and managing their **submerchants** across **multiple payment providers**. Central to this system is the **recipient object**, which represents each individual submerchant within the marketplace ecosystem.
* Each **marketplace owner** is represented in **Yuno as an organization**.
* Within an organization, one or more accounts can be created, each configured with its own set of **connections** to payment providers (e.g., Stripe, Adyen, dLocal).
* For every account, the marketplace can register one or more **recipients** — these are the submerchants to be onboarded.
* Each **recipient** is then linked individually to one or more **connections**, depending on which payment processors they will use.
This **architecture** enables:
* A single, unified onboarding process.
* Independent status tracking per provider.
* Easy scaling of submerchant operations across providers.
This design ensures flexibility, transparency, and full traceability throughout the onboarding lifecycle. The [recipients endpoint](/reference/create-recipient-1) is used to create and manage each submerchant profile and to trigger the corresponding provider-specific onboarding workflows.
### Onboarding flows
Yuno offers two onboarding flows for submerchants, providing flexibility based on the submerchant's current status with payment providers.
1. **Pre-onboarded accounts**: If a submerchant has already completed the onboarding process with a specific provider (e.g., through an external dashboard or platform), the marketplace can supply the corresponding `recipient_id` during creation. In this scenario, no further onboarding is required, and the status will be immediately set to `SUCCEEDED` (`onboardings.type`=`PREVIOUSLY_ONBOARDED`).
2. **Dynamic onboarding**: If no credentials are provided, Yuno will initiate the onboarding process for the chosen provider (`onboardings.type`=`ONE_STEP_ONBOARDING` or `TWO_STEP_ONBOARDING`). This process may include:
1. Form submission or redirection to a hosted onboarding page.
2. Uploading legal or financial documentation.
3. Completing KYC/KYB validation steps.
Throughout the onboarding lifecycle, a recipient may experience various statuses that reflect the current state of the process:
| Status | Description |
| ----------- | ---------------------------------------------------------------------------- |
| `CREATED` | Initial state after creation; onboarding process not yet started. |
| `PENDING` | Awaiting provider review after data submission. |
| `SUCCEEDED` | The recipient is fully onboarded and active. |
| `DECLINED` | The onboarding was rejected by the provider and cannot be retried. |
| `BLOCKED` | The provider has explicitly blocked the onboarding due to compliance issues. |
| `CANCELED` | The onboarding process was voluntarily canceled before completion. |
| `REJECTED` | The onboarding failed due to incorrect data or failed validations. |
| `ERROR` | A technical error occurred during the onboarding flow. |
These statuses assist the marketplace in understanding the onboarding lifecycle and implementing appropriate retry, alert, or fallback mechanisms when necessary.
This flexible approach allows marketplaces to tailor the onboarding process to their operational needs, maintaining control and visibility.
### Workflow
The onboarding workflow follows a structured process that ensures submerchants are properly integrated into the marketplace ecosystem. The diagram below illustrates the complete flow from initial setup to payment processing.
**Workflow Steps:**
1. **Organization & Account Setup**: The marketplace owner creates an organization in Yuno and configures accounts with payment provider connections.
2. **Recipient Creation**: For each submerchant, the marketplace creates a recipient using the [Create Recipients API](/reference/create-recipient-1) endpoint, specifying either:
* `provider_recipient_id` for pre-onboarded submerchants
* Provider connection details for new onboarding
3. **Onboarding Execution**:
* **Pre-onboarded**: Status immediately becomes `SUCCEEDED`
* **New onboarding**: Yuno initiates provider-specific flow with status progression from `CREATED` → `PENDING` → `SUCCEEDED`
4. **Payment Creation**: Once recipients are successfully onboarded (`SUCCEEDED` status), the marketplace can create payments with the `split_marketplace` object.
5. **Split Processing**: The payment provider executes the split according to the defined distribution, transferring funds to each recipient's designated share.
## 2. Auto Split Configuration
Yuno allows you to define **automatic split rules** at the recipient level. When a payment is created without an explicit `amount` for a recipient in the `split_marketplace` array, Yuno uses these rules to calculate the split automatically.
### Calculation types
The `split_configuration` object supports three calculation methods:
| Type | Description | Formula |
| :----------- | :---------------------------------------------- | :---------------------------------------------------- |
| `PERCENTAGE` | A percentage of the total payment amount. | `Split = Total * (Percentage / 100)` |
| `FIXED` | A constant fixed amount in a specific currency. | `Split = fixed_amount` |
| `MIXED` | Combines a percentage and a fixed amount. | `Split = (Total * (Percentage / 100)) + fixed_amount` |
### Rounding mode
To ensure precision across different currencies, Yuno supports three rounding strategies for automatic calculations:
| Mode | Description | Strategy |
| :----------- | :----------------------------------------------------- | :---------- |
| `STANDARD` | Rounds to the nearest even number (Bankers' Rounding). | `HALF_EVEN` |
| `ROUND_UP` | Always rounds away from zero. | `CEILING` |
| `ROUND_DOWN` | Always rounds towards zero. | `FLOOR` |
### Implementation
You can define the `split_configuration` when [creating](/reference/create-recipient-1) or [updating](/reference/update-recipient-1) a recipient.
| Field | Type | Description | Required |
| :----------------- | :-------------- | :---------------------------------------------------------------------- | :--------- |
| `calculation_type` | `string` (enum) | The method used to calculate the split: `PERCENTAGE`, `FIXED`, `MIXED`. | **Yes** |
| `currency` | `string` | ISO 4217 currency code. Must match the payment currency. | **Yes** |
| `percentage` | `number` | Percentage of the total payment. | Optional\* |
| `fixed_amount` | `number` | Flat amount to be split. | Optional\* |
| `rounding_mode` | `string` (enum) | Rounding strategy: `STANDARD`, `ROUND_UP`, `ROUND_DOWN`. | Optional\* |
\*Requirement depends on `calculation_type`:
* **PERCENTAGE**: `percentage` and `rounding_mode` are required.
* **FIXED**: `fixed_amount` is required.
* **MIXED**: `percentage`, `fixed_amount`, and `rounding_mode` are required.
```json Example Recipient with Auto Split theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"merchant_recipient_id": "seller-123",
"split_configuration": {
"calculation_type": "PERCENTAGE",
"percentage": 10.5,
"rounding_mode": "STANDARD",
"currency": "USD"
}
}
```
## 3. Payment split integration
In this section, we explore how the `split_marketplace` object is used to divide a [payment](/reference/payments/create-payment) among multiple recipients. This object is an array where each entry specifies a recipient and their corresponding share of the payment.
In this step, reference recipients created in Step 1 (Onboarding).
For `type` = `PURCHASE` or `MARKETPLACE`, include the `recipient_id` of that recipient.
For `PAYMENTFEE`, `VAT` and `COMMISSION`, `recipient_id` is optional.
Field
Type
Description
Mandatory
Example Value
`recipient_id`
`string`
The unique identifier for the recipient within the marketplace.
Use the ID of a recipient created in Step 1 (Onboarding) when `type` is `PURCHASE` or `MARKETPLACE`.
Conditional
`rec_test123`
`provider_recipient_id`
`string`
The recipient's ID as provided by the payment provider, if applicable.
Conditional
`prov_rec_abc`
**Note:**
You must provide either `recipient_id` or `provider_recipient_id`.
For marketplace owners (`type`=`COMMISSION`), `provider_recipient_id` is optional if not required by the provider.
`type`\*
`enum`
The transaction detail item type. Options include `PURCHASE`, `PAYMENTFEE`, `VAT`, `COMMISSION`, `MARKETPLACE`.
`recipient_id` is mandatory for `PURCHASE` and `MARKETPLACE`.
Conditional
`PURCHASE`
**Note:**
**Propagation considerations**
* Items are sent to the provider only if it supports transmitting details
* These types do not affect fund disbursement, they are merely informational when the provider allows it
`merchant_reference`
`string`
An identifier for the payment transaction. This is optional. If not specified, the main payment's merchant reference will be used for all split transactions. (MAX 255; MIN 3 characters).
No
`AAB01-432245`
`amount`
`struct`
Specifies the amount for the split. **Optional** if the recipient has a `split_configuration` defined.
Conditional
`value`
`number`
The monetary value of the split (e.g., 7500 for 75.00). Required if `amount` is provided.
Conditional
`7500`
`currency`
`enum`
The currency in which the payment is made (ISO 4217, 3 characters). Required if `amount` is provided.
Conditional
`COP`
`liability`
`struct`
Information about the recipient's liability for fees and chargebacks, if applicable.
No
`processing_fee`
`enum`
Specifies who is responsible for the transaction fee: `MERCHANT`, `RECIPIENT`, `SHARED`.
No
`MERCHANT`
`chargebacks`
`boolean`
Indicates if the recipient is liable for chargebacks (`true` if they are responsible).
No
`false`
**Note:**
**Auto Split Calculation**
If `amount` is omitted, Yuno will use the recipient's `split_configuration` to calculate the share. If both are present, the `amount` in the request takes precedence.
```json Example using provider recipients directly theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"split_marketplace": [
{
"provider_recipient_id": "recipient_123",
"type": "PURCHASE",
"amount": {
"value": 750,
"currency": "EUR"
}
},
{
"type": "COMMISSION",
"amount": {
"value": 30,
"currency": "EUR"
}
}
]
}
```
```json Example using Yuno recipients theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"split_marketplace": [
{
"recipient_id": "4b31a9b8-4cd2-4e47-93cf-03729241bd68",
"type": "PURCHASE",
"amount": {
"value": 750,
"currency": "EUR"
}
},
{
"recipient_id": "9104911d-5df9-429e-8488-ad41abea1a4b",
"type": "COMMISSION",
"amount": {
"value": 30,
"currency": "EUR"
}
}
]
}
```
```json Example with Implicit Auto-calculation theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"split_marketplace": [
{
"recipient_id": "4b31a9b8-4cd2-4e47-93cf-03729241bd68",
"type": "PURCHASE"
// The amount is omitted, Yuno uses the recipient's split_configuration
},
{
"recipient_id": "9104911d-5df9-429e-8488-ad41abea1a4b",
"type": "COMMISSION",
"amount": {
"value": 50,
"currency": "USD"
}
}
]
}
```
## 3. Onboarding transfer
The goal of this flow is to allow the transfer of onboardings between recipients in a controlled and reversible way.
The process has several stages. First, the initial recipient is created with its onboarding (a prior step). Later, when a transfer is required, follow the steps to create the new recipient, use the transfer service, and, if needed, reverse the operation.
1. **Recipient and onboarding (before any transfer)**: [Create recipient](/reference/create-recipient-1), then [create onboarding](/reference/create-onboarding).
This step happens in advance when a new recipient is created and its onboarding is assigned. It is not part of the transfer itself.
If you decide to transfer the onboarding to another recipient, continue the flow:
2. **Create the new recipient and onboarding**: Use the [create recipient](/reference/create-recipient-1) and [create onboarding](/reference/create-onboarding) endpoints to set up the recipient and onboarding that will receive the transfer.
3. **Transfer the onboarding**: Use [transfer onboarding](/reference/transfer-onboarding) and include:
* `recipient_id`: the target recipient ID
* `onboarding_id`: the onboarding to transfer
The onboarding will be transferred to the new recipient.
4. **Reverse the transfer (optional)**: Use [reverse onboarding](/reference/reverse-onboarding) to revert the previous transfer, providing the same `recipient_id` and `onboarding_id`.
The `onboarding` object includes a `history` element that stores the complete traceability of the onboarding. This history includes not only updates to the object but also events related to transfers between recipients, ensuring full lifecycle visibility.
## 4. Standalone Transfers
Merchants often need to send funds to recipients (sellers, vendors, contractors) independently of a payment lifecycle, directly from their organization balance. This is known as a **Standalone Transfer** or **Forward Transfer**.
This feature allows you to:
* Distribute sales proceeds to sellers in a Marketplace.
* Pay contractors after completed jobs (Gig Economy).
* Manage revenue sharing for subscriptions or commission payments for affiliates.
* Execute bulk payouts to multiple recipients.
### Transfer Statuses
A standalone transfer flow goes through multiple states depending on the provider's response and any subsequent reversals:
| Status | Description | Terminal? |
| ----------- | ------------------------------------------------ | --------- |
| `CREATED` | Transfer flow created, not yet sent to provider. | No |
| `PENDING` | Sent to provider, awaiting confirmation. | No |
| `SUCCEEDED` | Forward transfer completed successfully. | No |
| `DECLINED` | Provider declined the transfer. | Yes |
| `ERROR` | Provider error during processing. | Yes |
| `REVERSED` | Reverse transaction completed successfully. | Yes |
### Transactions and Reversals
In the Standalone Transfer Flow, forward and reverse operations are treated as identical independent transactions to maintain an explicit audit trail. This means:
1. **Forward Transfer (`SPLIT_TRANSFER`):** You create a transfer moving funds from your balance to the recipient's connection.
2. **Reverse Transfer (`SPLIT_TRANSFER_REVERSE`):** You can fully or partially reverse the `SPLIT_TRANSFER` to return the funds to your balance. The original forward transfer *must be* in `SUCCEEDED` status for a reverse to take place.
### Idempotency
Both the creation and reversal of standalone transfers require an **Idempotency Key** via the `X-Idempotency-Key` header. This allows you to safely retry requests without accidentally duplicating fund distribution. These keys are retained for 24 hours. Duplicate requests using the same combination of `account_id` and idempotency key will return the original transfer object.
## Validations
To ensure successful split payments, the following validations are enforced:
* **Total Split Matching**: The sum of all splits must match the overall payment amount.
* **Recipient Existence**: Every `recipient_id` included in the split must correspond to a successfully onboarded recipient.
* **Auto Split Currency**: If a recipient has a `split_configuration`, its `currency` must exactly match the payment's `amount.currency`.
* **Amount Consistency**: If you provide an `amount.value` for a recipient with `split_configuration`, it must match the result of the automatic calculation.
* **Individual Split Limits**: Each individual split's resolved value must be greater than zero and less than or equal to the total payment amount.
* **Minimum Precision**: For `PERCENTAGE` splits, the calculated value must be at least `0.0001` (platform minimum).
* **Required Fields**:
* For manual splits (no `split_configuration`): `amount.value` and `amount.currency` are mandatory.
* If `split_configuration` is provided during recipient creation: `calculation_type` and `currency` are always mandatory.
* **Exclusion Rule**: You must include either `recipient_id` or `provider_recipient_id` for each split item, but never both.
* **Multiple Providers**: For recipients linked to multiple payment providers, use the [recipients object](/reference/recipients-for-marketplace/create-recipient-1) to manage the split logic across connections.
## API endpoints involved
This section lists the API endpoints involved in managing split payments.
* **[Create recipients](/reference/create-recipient-1)**: **POST**: `https://api-sandbox.y.uno/v1/recipients`
* **[Create onboarding](/reference/create-onboarding)**: **POST**: `https://api-sandbox.y.uno/v1/recipients/{recipient_id}/onboardings`
* **[Continue onboarding](/reference/continue-onboarding)**: **POST**: `https://api-sandbox.y.uno/v1/recipients/{recipient_id}/onboardings/{onboarding_id}/continue`
* **[Create payment](/reference/create-payment)**: **POST**: `https://api-sandbox.y.uno/v1/payments`
* **[Capture authorization](/reference/capture-authorization)**: **POST**: `https://api-sandbox.y.uno/v1/payments/{id}/transactions/{transaction_id}/capture`
* **[Refund payment](/reference/refund-payment)**: **POST**: `https://api-sandbox.y.uno/v1/payments/{id}/transactions/{transaction_id}/refund`
* **[Cancel or refund a payment](/reference/cancel-or-refund-a-payment)**: **POST**: `https://api-sandbox.y.uno/v1/payments/{id}/cancel-or-refund`
* **[Cancel or refund a payment with transaction](/reference/cancel-or-refund-payment-with-transaction)**: **POST**: `https://api-sandbox.y.uno/v1/payments/{id}/transactions/{transaction_id}/cancel-or-refund`
* **[Transfer onboarding](/reference/transfer-onboarding)**: **POST**: `https://api-sandbox.y.uno/v1/recipients/{recipient_id}/onboardings/{onboarding_id}/transfer`
* **[Reverse onboarding transfer](/reference/reverse-onboarding)**: **POST**: `https://api-sandbox.y.uno/v1/recipients/{recipient_id}/onboardings/{onboarding_id}/reverse-transfer`
* **[Create standalone transfer](/reference/create-standalone-transfer)**: **POST**: `https://api-sandbox.y.uno/v1/split-marketplace/transfers`
* **[Get standalone transfer](/reference/get-standalone-transfer)**: **GET**: `https://api-sandbox.y.uno/v1/split-marketplace/transfers/{transfer_id}`
* **[Reverse standalone transfer](/reference/reverse-standalone-transfer)**: **POST**: `https://api-sandbox.y.uno/v1/split-marketplace/transfers/{transfer_id}/reverse`
# Stored Credentials
Source: https://docs.y.uno/docs/payment-features/stored-credentials
Store and reuse card details for customer-initiated or merchant-initiated transactions while complying with scheme rules
Depending on how and when a payment is processed, it can originate from either customer-initiated transactions (CIT) or merchant-initiated transactions (MIT).
To ensure the responsible storage and use of cardholder information, Visa and Mastercard have established guidelines and regulations for stored credentials.
Yuno has streamlined the process for you to comply with these scheme rules, enabling you to securely store card details in Yuno for future use while maintaining compliance.
**Important: This is not the same as Subscriptions**
Think of who's in control of recurrence:
* **Stored Credentials**: You control recurrence and are responsible for sending each transaction according to your own schedule and recurrence logic.
* **Subscription API**: Yuno controls it. You provide instructions once, then Yuno automatically sends transactions on your behalf. See [Subscriptions](/docs/subscriptions).
* Categorization
* General considerations
* Create a payment
* Subscription agreement ID
* Network transaction ID
* Wallet-originated tokens (Apple Pay and Google Pay)
## Categorization
| Category | Customer-initiated transactions (CIT) | Merchant-initiated transactions (MIT) |
| :----------------- | :------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Definition** | Transactions initiated by the customer, such as online and in-store purchases, or ATM withdrawals. | Transactions initiated by the merchant or service provider without the customer's active involvement. |
| **Examples** | Includes online purchases, in-store purchases, and ATM withdrawals. | Includes recurring payments, automatic subscription renewals, and recurring billing. |
| **Authentication** | Typically requires cardholder authentication to ensure security. | Requires initial customer authentication to set up, with potential additional authentication based on security regulations and card issuer policies for subsequent transactions. |
Determining whether a transaction is initiated by the merchant or the customer has significant implications for security, user experience, fraud prevention, and regulatory compliance.
## General considerations
* **Responsibility**: In the context of strong customer authentication (SCA) under PSD2 regulation in the European Union, CIT generally requires higher authentication compared to MIT.
* **Frequency**: MIT transactions are often recurring and periodic, while CIT are more ad hoc events based on customer actions.
## Create a payment with processing type
To specify a [payment](/reference/create-payment) with a processing type, use the `stored_credentials` structure inside the `payment_method.detail.card` when creating a payment.
| Parameter | Type | Description |
| --------------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `reason` | enum | Indicates the reason for storing credentials for the transaction. `CARD_ON_FILE` `SUBSCRIPTION` `UNSCHEDULED_CARD_ON_FILE` |
| `usage` | enum | A credit card can be stored with or without an initial payment. This field indicates if this is the first time the vaulted\_token/network\_token is used or reused. `FIRST` `USED` |
| `subscription_agreement_id` | string | The ID of the agreement with the customer, mandatory for certain markets (e.g., MX). |
| `network_transaction_id` | string | The ID provided by Visa/Mastercard in the response of the initial payment, which is highly recommended for future use in merchant-initiated transactions (MIT). |
**Critical: Complete All Required Fields**
* When working with CIT and MIT transactions, it's essential to correctly populate the `usage`, `reason`, and `network_transaction_id` fields. Failing to complete these fields properly can result in **decreased approval rates** and **loss of chargeback disputes**.
* Some providers (e.g., Adyen) require that the `reason` field remains consistent across the transaction lifecycle. If your first transaction (`usage=FIRST`) uses `reason=SUBSCRIPTION`, all subsequent transactions (`usage=USED`) must also use `reason=SUBSCRIPTION`.
Store credential reasons
| Reason | Description |
| :------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `CARD_ON_FILE` | A customer-initiated payment using a previously enrolled credit card where the cardholder is present. Allows customers one-click payment for a frictionless payment experience. |
| `SUBSCRIPTION` | Used for merchant-initiated payments as part of a subscription. This does not create a new subscription - use the [Subscription API](/docs/subscriptions) for automated recurring billing. |
| `UNSCHEDULED_CARD_ON_FILE` | A merchant-initiated payment using stored credit card details that is not related to a subscription schedule or amount. Payment can occur at any given time. |
### Request example
```sh Request (cURL) theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
curl --request POST \
--url https://api-sandbox.y.uno/v1/payments \
--header 'X-Idempotency-Key: ' \
--header 'accept: application/json' \
--header 'content-type: application/json' \
--header 'private-secret-key: ' \
--header 'public-api-key: ' \
--data '
{
"description": "Test",
"account_id": "{{account-code}}",
"merchant_order_id": "0000023",
"country": "DE",
"merchant_reference" : "reference-{{$randomUUID}}",
"amount": {
"currency": "EUR",
"value": 5000
},
"customer_payer": {
"id":"967ecd18-d898-4b88-9400-dd5b01b18edc"
},
"workflow": "DIRECT",
"payment_method": {
"type":"CARD",
"vaulted_token": "eb8caa17-6407-457b-960e-125d8d7a90c1",
"detail": {
"card": {
"stored_credentials":{
"reason":"CARD_ON_FILE",
"usage": "USED",
"network_transaction_id":"583103536844189"
}
}
}
}
}
'
```
## Wallet-originated tokens (Apple Pay and Google Pay)
A wallet CIT with `vault_on_success: true` also produces a `vaulted_token`: Apple Pay and Google Pay decrypt to a card network token, so the stored instrument is a `CARD` record with `parent_payment_method_type` set to the wallet type.
**Store the token from the payment response**
The `vaulted_token` is returned only in the CIT payment response. Wallet-vaulted instruments are intentionally not included in [Retrieve Enrolled Payment Methods](/reference/retrieve-enrolled-payment-methods-api) — an empty `payment_methods` list for a wallet-only customer is expected, even though the token is valid and chargeable. Persist the `vaulted_token` (plus any display metadata you need, such as brand and last four digits) on your side when the CIT succeeds. A stored token can still be resolved individually with [Retrieve Enrolled Payment Method by ID](/reference/retrieve-enrolled-payment-method-by-id-api).
Charges on a stored wallet token always use `detail.card.stored_credentials` — not `detail.wallet`:
| Scenario | `reason` | `usage` |
| :------------------------------------------------------ | :------------- | :------ |
| First charge (wallet sheet shown, instrument vaulted) | `SUBSCRIPTION` | `FIRST` |
| Later charges in the same recurring series (MIT) | `SUBSCRIPTION` | `USED` |
| Customer-present one-click purchase on the stored token | `CARD_ON_FILE` | `USED` |
Yuno attaches the `network_transaction_id` from the `usage: FIRST` payment automatically, exactly as for cards. Keep `reason` consistent within a series. See the "Critical: Complete All Required Fields" note under [Create a payment with processing type](#create-a-payment-with-processing-type).
## Subscription agreement
For certain markets (MX for example) and payment processors, when a subscription-related payment is made, the ID of the agreement with the customer needs to be specified in the payment request to ensure correct processing. To facilitate this, Yuno has enabled the `subscription_agreement_id` field inside the `stored_credentials` struct, allowing you to share the agreement made with the customer.
**Note**
The `subscription_agreement_id` and `network_transaction_id` are independent fields. Including a `subscription_agreement_id` does not replace the need for a `network_transaction_id`. Both should be provided when applicable to ensure optimal approval rates and chargeback protection.
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
"payment_method": {
"type":"CARD",
"vaulted_token": "eb8caa17-6407-457b-960e-125d8d7a90c1",
"detail": {
"card": {
"stored_credentials":{
"reason":"CARD_ON_FILE",
"usage": "USED",
"subscription_agreement_id":"AA0001",
"network_transaction_id":"583103536844189"
}
}
}
}
```
## Network transaction ID
A network transaction ID is a unique identifier assigned to a transaction by the card network. It is used to track and reference specific transactions, particularly in recurring payment scenarios, ensuring consistency and traceability across the payment lifecycle.
If the transaction is customer-initiated (CIT), the network transaction reference will be available in the `card.stored_credentials.network_transaction_id` field. This field represents the transaction ID for Visa and the trace ID for Mastercard, which are recommended for future subscription payments.
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
"payment_method": {
"type":"CARD",
"vaulted_token": "eb8caa17-6407-457b-960e-125d8d7a90c1",
"detail": {
"card": {
"stored_credentials":{
"reason":"CARD_ON_FILE",
"usage": "USED",
"network_transaction_id":"583103536844189"
}
}
}
}
```
### Use
Yuno associates the `network_transaction_id` with the `vaulted_token` for future transactions, so you don't have to manage the logic for each case. Yuno performs the association when a payment is created with:
* *Payment method*:
* A card `vaulted_token`, or
* Card data with `vault_on_success` set to `true`
* *Stored credentials*:
* `usage` set to `FIRST`
When using `vault_on_success = true` in a direct integration, you must create the customer first and pass its `customer_payer.id` in the payment request. Sending customer details inline does not create the customer on Yuno's side, so the card cannot be stored and no `vaulted_token` will be returned.
If you already have the `network_transaction_id` for the card, you can include it in the payment in the corresponding field. If not, for MIT payments (with `stored_credentials.usage=USED`), Yuno sends the `network_transaction_id` associated with the `vaulted_token` to the provider.
Remember to specify the `usage` in the `stored_credentials` section, as Yuno triggers the `network_transaction_id` logic based on those fields.
# Subscriptions
Source: https://docs.y.uno/docs/payment-features/subscriptions/index
Automate recurring billing by letting Yuno's engine create, pause, resume, and cancel subscriptions on schedule
Yuno's subscription service lets you manage recurring payments and automate subscription billing for your customers.
**Subscriptions vs Stored Credentials**
* **Subscriptions** (this page): Yuno's recurrence engine. You provide instructions and frequency once, then Yuno automatically sends transactions on your behalf.
* **Stored Credentials**: You control the recurrence. You're responsible for sending each transaction according to your own schedule. See [Stored Credentials](/docs/stored-credentials).
## Yuno subscriptions
A subscription in Yuno's environment can go through several stages, starting with its creation status. When a subscription is created, it automatically receives the **CREATED** status. However, it is a transitory status that is active while the payment isn't processed. After that, the subscription will be **ACTIVE** or **CANCELED**, depending on the payment confirmation.
When the payment related to the subscription is confirmed, the subscription status changes to **ACTIVE**. It remains with this status while the subscription is within its availability data range and the customer pays the bills. An active subscription can change to three different statuses:
* **COMPLETED**: The subscription finish date was reached. In this case, the current subscription is terminated, and it is not possible to reactivate it. If your client wants to continue using your product/service using recurring payments, you need to create a new subscription.
* **PAUSED**: At any moment, you can pause the subscription. Use this option in case your customer has delayed a payment, for example. You can always activate a paused subscription.
* **CANCELED**: If your customer decides to cancel the recurring payment, you can cancel the subscription. After canceling it, the subscription is terminated, and it is not possible to reactivate it.
Learn more about the status of the subscription on the [Subscription Status](/reference/status-subscriptions) page.
## Subscription integration
To start using the subscriptions feature, you need a Yuno account and integration with the Yuno API. The Yuno API provides the following operations to manage your subscriptions:
* **Create**: Use the [Create a Subscription endpoint](/reference/create-subscription) to subscribe a customer.
* **Pause**: Pause an active subscription with the [Pause Subscription endpoint](/reference/pause-subscription).
* **Resume**: Resume a previously paused subscription with the [Resume Subscription endpoint](/reference/resume-subscription).
* **Cancel**: Cancel an active subscription with the [Cancel Subscription endpoint](/reference/cancel-subscription).
* **Retrieve**: Use the [Retrieve Subscription endpoint](/reference/retrieve-subscription) to get the details of a subscription.
## New concepts
* **Subscriptions**: A subscription involves recurring charges directly tied to a customer and a particular payment method. When stopping or updating, the impact is solely on the same.
* **Payment methods available**
* **Enrolled**: Customers can pay with a previously enrolled payment method. Only the vaulted token is needed when creating the subscription to associate it with the charges.
* **Capabilities**:
* **Frequency**: Define the frequency at which subscription charges will occur, whether daily, weekly, or monthly, specifying the amount that needs to be charged for the next billing cycle.
* **Billing cycles**: The number of billing cycles (following the frequency criterion) that will be completed to fulfill the subscription. If neither an `end_date` is sent nor defined, we will continue attempting charges until it is stopped.
* **Billing date**: By specifying the `billing_date` object, the merchant can define the logic behind the exact date for the billing of the subscription. This is mutually exclusive with the frequency object.
* **Availability**: The start and end dates of the subscription. If they are not defined, nor the billing cycles, charges will continue until it is stopped.
* The fields `billing_cycles` and `availability.finish_at` impact each other. If both are completed during the subscription creation, it will transition to the COMPLETED state upon reaching the nearest event defined in these fields, whether it is the billing cycle or the corresponding `finish_at`.
* **Trial periods**: This feature lets you define a period where your customers can benefit from a reduced amount. It could be partial or total (for example, a free trial). You need to determine the value to be reduced from the total amount of each subscription charge and the billing cycles it should apply to.
* **Initial payment validation**: A flag to identify if the subscription should wait for the first payment to continue. False by default. If the field is set to true, the subscription should remain in the CREATED status while waiting for the first payment of the subscription.
* If the first payment succeeds (SUCCEEDED), the subscription transitions to ACTIVE.
* If the first payment fails (DECLINED/REJECTED), the subscription transitions to CANCELED.
## Using Yuno subscription solution
Yuno provides subscription management functionalities through its API. You can use this API to create, update, and manage subscriptions, as well as retrieve subscription details and usage.
To use the subscription solution, normally, you will follow the steps described below:
1. To begin, [Create a Customer](/reference/create-customer). You will need to provide personal customer information and the `merchant_customer_id`, a unique identifier for the customer used in your system. Upon completing the customer creation process, you will receive an `id` that identifies the user within the Yuno system. This `id` will be used to create the subscription.
2. After creating the customer, you will need to [enroll a credit card](/docs/enroll-payment-methods) to generate a `vaulted_token` for use in the subscription creation.
3. [Create a Subscription](/reference/create-subscription) for your customer and the enrolled card. At this step, you will configure the subscription and define the payment method. When creating the subscription, you can customize:
* The amount the subscription charges.
* The billing frequency (daily, monthly, or yearly).
* The total number of billing cycles.
* The subscription availability to define the start and end date.
**Available Payment Methods**
Currently, only Cards can be used as payment methods for subscriptions.
**Declined Payments**
If a payment from a subscription is declined (including the first payment attempt), the subscription will continue its schedule for future payment attempts, giving the merchant the possibility to charge the client the pending amount through a different process and continue with the ongoing subscription. If you want to cancel a subscription, feel free to use the [cancel subscription endpoint](/reference/cancel-subscription).
In the response to the [Create Subscription](/reference/create-subscription) endpoint, you receive an `id` which is used to identify the created subscription. You will use the `id` if you decide to pause, resume, or cancel the subscription.
## Renewal events
`subscription.active` is sent once, when the subscription first becomes active (at `billing_cycles.current` = 2); it is not re-sent on subsequent renewals, and no other `subscription.*` webhook fires for a renewal charge. Track each renewal via the per-cycle `payment.purchase` webhook (outcome in `status`/`sub_status`). `$0`/trial cycles generate no payment webhook by design.
**`code` vs `id` mapping**
Subscription webhook payloads use `code` while the API uses `id`, and they are the same values: `subscription.code` equals the `id` returned from `POST /v1/subscriptions`, and `customer_payer.code` equals the customer `id`.
# Plans
Source: https://docs.y.uno/docs/payment-features/subscriptions/plans
Define a reusable pricing catalog once, then subscribe customers to it instead of setting amount and frequency per subscription
A plan is a reusable pricing definition — name, price (optionally per country), billing frequency, and an optional trial phase ladder. Instead of specifying `amount`/`frequency` on every [subscription](/docs/payment-features/subscriptions/index) you create, subscribe the customer to a plan and Yuno resolves the price for their country automatically.
**Plans vs raw subscriptions**
Raw subscriptions (`amount` + `frequency`, no `plan_id`) remain fully supported — plans are additive, not a replacement. A subscription created without a plan simply omits the plan fields (`plan_id`, `billing_phases`, `current_phase`, …) from its responses — they're absent, not `null`.
## Creating and using a plan
Say you're launching a "Streaming Pro" tier that costs \$20/month in the US, but you want to charge R\$99.90 in Brazil instead of a straight currency conversion. Here's the whole flow:
1. **Create the plan once.** Call [Create a Plan](/reference/plans/create-plan) with a name, a `base_amount` (the default price — \$20 USD in our example), a `frequency` (monthly), and, if you need country-specific pricing, a `country_prices` list (`BR` → R\$99.90). This gives you back a `plan_id`.
2. **Subscribe customers to it, as many as you want.** When you call [Create Subscription](/reference/subscriptions/create-subscription), send that `plan_id` instead of an `amount`. Yuno looks up the subscriber's `country` and charges them the right price automatically — no need to compute or send the amount yourself on every subscription.
3. **The price resolves per subscriber, in this order:** does the plan have an explicit price for their country? Use that. If not, fall back to `base_amount`. So in our example, a US customer pays \$20, a Brazilian customer pays R\$99.90, and a customer anywhere else also pays \$20 (the `base_amount` fallback covers every country you didn't list explicitly).
**`plan_id` takes over pricing and cadence — but not all conflicting fields are rejected the same way**
* `amount` is mutually exclusive with `plan_id` — send exactly one of the two.
* `trial_period` and `billing_date` sent alongside `plan_id` are rejected with `400 BAD_REQUEST` — the plan already defines the trial ladder and cadence, so these would conflict with it.
* `frequency` sent alongside `plan_id` is **not** rejected — it's silently ignored and overridden by the plan's own frequency. If you send one anyway expecting it to apply, it won't; nothing will tell you that.
Simplest rule: when subscribing with `plan_id`, just omit `amount`, `frequency`, `trial_period`, and `billing_date` entirely — the plan supplies all of them. (Raw subscriptions without a plan still work exactly as before — plans are an addition, not a replacement.)
## Plans are immutable — here's why that matters
You can't edit a plan's price after creating it — there's no update endpoint. This is deliberate: it means every subscriber keeps the exact price they signed up for, forever, even if you change your pricing later. Nobody gets a surprise price increase because you tweaked the plan.
In practice, this means a "price change" is really "create a new plan": if Streaming Pro goes from \$20 to \$25/month, you create a new plan for \$25 and start pointing new signups at it — your existing \$20 subscribers keep paying \$20 until you move them or they cancel. To migrate existing subscribers onto the new plan, use [Change Subscription Plan](/reference/subscriptions/change-subscription-plan) (immediate replacement) or the `plan_change` object on [Update Subscription](/reference/subscriptions/update-subscription) (scheduled, same `id`). When you're ready to stop offering the old price entirely, see **Canceling a plan** below.
## Trial phases — offering a discounted or free intro period
If you want new subscribers to pay less (or nothing) for a while before the regular price kicks in — a 14-day free trial, or \$9.99/month for the first 3 months before jumping to \$20/month — that's what `phases` on the plan are for.
Think of it as a short ladder the subscriber walks through: one or more `TRIAL` steps (any price you want, including \$0), followed by exactly one `REGULAR` step at the end, which is always priced from the plan's normal `base_amount`/`country_prices`. For example, a 3-month-then-regular plan has two phases: phase 1 is `TRIAL`, 3 months, \$9.99; phase 2 is `REGULAR` with no set duration — it just runs at the plan's normal price from then on.
While a subscriber is inside a `TRIAL` phase, their subscription's `status` reads `TRIALING` (instead of `ACTIVE`) and `current_phase` reads `TRIAL`, so you can tell at a glance that they're still in the discounted period. The moment they reach the `REGULAR` phase, both flip automatically — `status` becomes `ACTIVE`, `current_phase` becomes `REGULAR` — with no action needed on your end.
If you don't need a trial or intro discount at all, just omit `phases` — the plan charges its regular price from the first bill.
See [The Plan Object](/reference/plans/the-plan-object) for every field on a phase, and [The Subscription Object](/reference/subscriptions/the-subscription-object) for how a subscription reports back which phase it's in (`plan_id`, `billing_phases`, `current_phase`). To see what was actually charged for each phase — provider, per-charge amounts, which phase a payment belonged to — use [List Subscription Payments](/reference/subscriptions/list-subscription-payments).
## Canceling a plan
**This cancels every subscriber on the plan immediately — there is no way to opt out of that.**
Calling [Cancel Plan](/reference/plans/cancel-plan) does two things at once, synchronously, in the same request:
1. Blocks anyone new from subscribing to this plan.
2. **Cancels every subscription currently on it, right now.** Not "on their next renewal," not "after a grace period" — immediately, as part of this same API call.
There is no soft-cancel, no grandfathering, and no way to retire a plan for new signups while letting existing subscribers keep paying on it. If that's what you need, don't cancel the plan — just stop pointing new signups at it (step 2 above) and leave it active for as long as its current subscribers should keep billing.
Before you call this, check the plan's `subscribers_count` (via [List Plans](/reference/plans/list-plans) — this field isn't on the single-plan [Retrieve Plan](/reference/plans/retrieve-plan) response) so you know exactly how many active subscriptions are about to be canceled — the response also echoes back `affected_subscriptions` so you can confirm afterward that the number matches what you expected.
If you're not sure a previous cancel call fully finished canceling every subscriber, it's safe to call it again — re-canceling an already-canceled plan re-runs the cascade and returns `200`, it does not error.
# Smart Retries
Source: https://docs.y.uno/docs/payment-features/subscriptions/retries
Recover declined recurring card charges by retrying them on an optimized, customizable schedule
Yuno's Smart Retries help recover declined recurring credit card payments by retrying them on an optimized schedule. By retrying at the right moments, Smart Retries increase the likelihood of payment success, ensuring a consistent revenue stream and reducing involuntary subscriber churn.
### Key advantages
Yuno's Smart Retries offer several benefits that enhance payment processes and revenue recovery:
* **Data-driven decision-making**: Uses a proven retry schedule, or machine-learning-based retry timing via the `SMART` strategy.
* **Enhanced revenue retrieval**: Increases the chances of successfully collecting payments.
* **Decreased subscriber turnover**: Minimizes disruptions and involuntary subscriber departures.
* **Flexible logic**: Allows customization of retry schedules to maximize success opportunities.
* **Comprehensive approach**: Works in conjunction with other revenue recovery strategies.
### Retry schedule
By default, Yuno applies the fixed retry schedule below. Each delay is measured **from the previous attempt**, not cumulatively from the first attempt. You can also switch to machine-learning-based retry timing, which adapts the moment of each retry per transaction, by setting `strategy` to `SMART` — see [Machine-learning retry timing](#machine-learning-retry-timing).
| Attempt | Delay after the previous attempt | Total time after the first attempt |
| :------------------------- | :------------------------------- | :--------------------------------- |
| First try (initial charge) | - | - |
| Retry 1 | 5 hours | \~5 hours |
| Retry 2 | 12 hours | \~17 hours |
| Retry 3 | 24 hours | \~41 hours |
| Retry 4 | 36 hours | \~77 hours (\~3.2 days) |
| Retry 5 | 48 hours | \~125 hours (\~5.2 days) |
| Retry 6 | 96 hours | \~221 hours (\~9.2 days) |
The last retry is attempted roughly 9.2 days after the initial failed charge.
### Customization
Every business model is unique, so we allow merchants to define specific rules to enhance the flexibility of our retry schedule. When creating the subscription object, you can use the `retries` structure to make adjustments:
| Parameter | Type | Description | Example |
| :---------------------------- | :----- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------- |
| `retry_on_decline` | bool | Indicates whether to retry a payment after a first decline. Defaults to false. This flag is the only switch that enables retries; there is no dashboard toggle. | TRUE |
| `amount` | number | Number of retries the subscription will attempt. The maximum equals your environment's configured retry schedule length — 6 in production. A value above the cap is rejected with `400` (`Max retries attempts exceeded`). This cap is set per environment and is not configurable per account via the API. | 4 |
| `strategy` | string | The retry strategy. Allowed values: DEFAULT, SMART and CUSTOM\_SCHEDULE. DEFAULT uses the fixed schedule above. SMART uses machine-learning-based retry timing — see [Machine-learning retry timing](#machine-learning-retry-timing). CUSTOM\_SCHEDULE uses the per-attempt schedule you provide. | `CUSTOM_SCHEDULE` |
| `stop_on_hard_decline` | bool | When true and a hard decline is detected, retries stop for the current cycle only. On its own, the subscription stays ACTIVE, billing advances to the next cycle, and no cancel/pause or subscription webhook is emitted. If `cancel_on_exhausted_retries` is also true, the subscription is canceled instead — see [Canceling a subscription when retries run out](#canceling-a-subscription-when-retries-run-out). | TRUE |
| `cancel_on_exhausted_retries` | bool | When true, the subscription is canceled once retries for a billing cycle end without a successful payment, instead of rolling forward to the next cycle. Defaults to false. Can be set at creation or changed later with [Update Subscription](/reference/subscriptions/update-subscription). See [Canceling a subscription when retries run out](#canceling-a-subscription-when-retries-run-out). | TRUE |
| `schedule` | object | Contains attempt and delay\_seconds fields | Attempt: 2, `delay_seconds`: 86400 |
The maximum number of retries equals your environment's configured retry schedule length: 6 in production. Sandbox is currently limited to 5 and is being aligned to match production.
`strategy`: `DEFAULT` applies the fixed schedule above. Use `SMART` for machine-learning-based retry timing, or `CUSTOM_SCHEDULE` together with the `schedule` array to define your own delays.
### Machine-learning retry timing
Set `strategy` to `SMART` to have Yuno's machine-learning model choose **when** each retry is attempted, instead of using the fixed schedule. The model weighs signals such as the decline reason, the country, the card issuer and the payment provider to pick the moment most likely to succeed.
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"retries": {
"retry_on_decline": true,
"amount": 4,
"strategy": "SMART"
}
}
```
`SMART` changes retry **timing** only. It does not change how many retries you get: `amount` still controls that, and the same per-environment maximum applies. Any `schedule` array sent alongside `strategy: SMART` is ignored.
Machine-learning timing is applied **from the second retry onward**. The first retry always uses the standard delay from the fixed schedule above.
If a timing decision is not available in time, the retry falls back to the fixed schedule above. Retries are never skipped or dropped because of this — only their timing changes.
`SMART` is available to all accounts.
### Canceling a subscription when retries run out
By default, when every retry for a billing cycle has been attempted and none succeeded, the subscription stays `ACTIVE` and billing rolls forward to the next cycle. A subscription backed by a permanently dead card therefore keeps generating failed charges indefinitely.
Set `cancel_on_exhausted_retries` to `true` — at creation or via [Update Subscription](/reference/subscriptions/update-subscription) — to change that:
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"retries": {
"retry_on_decline": true,
"amount": 3,
"cancel_on_exhausted_retries": true
}
}
```
When retries for a cycle end without a successful payment, Yuno then:
1. Sets the subscription status to `CANCELED`.
2. Sets `cancellation_source` to `RETRIES_EXHAUSTED`.
3. Stops all future scheduled billing for the subscription.
4. Sends one `SUBSCRIPTION.CANCEL` webhook.
This applies whichever way the retries ended — the schedule running to its last attempt, or `stop_on_hard_decline` ending the cycle early after a hard decline. In both cases `cancellation_source` is `RETRIES_EXHAUSTED`.
`cancel_on_exhausted_retries` defaults to `false`. If you omit it, subscriptions behave exactly as they do today. No existing subscription changes behavior.
**This cancellation is final.** A canceled subscription is no longer billable, so [Retry Subscription](/reference/subscriptions/retry-subscription) is rejected for it. Without this flag you can manually rescue a subscription whose retries were exhausted; with it enabled, that option is gone once the cancellation happens. Enable it only if an exhausted retry schedule should genuinely end the customer's subscription.
`cancel_on_exhausted_retries` can be set at creation or changed afterward with [Update Subscription](/reference/subscriptions/update-subscription).
This flag applies to renewal cycles. Subscriptions created with `initial_payment_validation: true` already cancel themselves when their first payment fails, and that path reports `cancellation_source` as `SYSTEM` rather than `RETRIES_EXHAUSTED`.
# Statement descriptor on recurring payments
Source: https://docs.y.uno/docs/payment-features/subscriptions/soft-descriptor
Control the soft (statement) descriptor that appears on the cardholder's bank statement for subscription and merchant-initiated recurring charges.
The soft descriptor (also called the statement descriptor) is the text a cardholder sees on their bank statement next to a charge. A clear descriptor reduces confusion and the disputes that follow from it, which matters most on recurring charges where the customer is billed without re-entering the checkout.
Where you set the descriptor depends on which recurring mechanism you use. The two paths are independent, so pick the one that matches how the charge is generated.
**Which path applies to you**
* **Yuno subscription engine**: Yuno generates each rebill from a subscription object. Set the descriptor on the subscription.
* **Merchant-initiated (MIT)**: You generate each rebill yourself with a Create Payment call using stored credentials. Set the descriptor on each payment.
The same merchant can use both for different products. Wallet rebills (Apple Pay / Google Pay) ride the card / network-token rail in both cases, so the rules below apply to them too.
## Subscription-engine rebills
When Yuno's [subscription engine](/docs/payment-features/subscriptions) charges the customer on each cycle, set the descriptor once with the `soft_descriptor` field on the subscription. Yuno persists it on the subscription and applies it to every rebill the engine generates.
* Set it on [Create Subscription](/reference/subscriptions/create-subscription) (`soft_descriptor`, string, max 255).
* Change it later on [Update Subscription](/reference/subscriptions/update-subscription); the new value applies to subsequent rebills.
```json Create Subscription (excerpt) theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"name": "Streaming plan",
"account_id": "493e9374-510a-4201-9e09-de669d75f256",
"country": "US",
"soft_descriptor": "ACME STREAMING",
"amount": { "currency": "USD", "value": 15000 },
"payment_method": {
"type": "CARD",
"vaulted_token": "{{vaulted_token}}"
}
}
```
## Merchant-initiated (MIT) rebills
When you drive recurrence yourself — sending each charge as a merchant-initiated payment with `stored_credentials.usage = USED` and `reason = SUBSCRIPTION` — there is no subscription object to carry the descriptor. Set it per payment instead.
On [Create Payment](/reference/payments/create-payment), the descriptor lives on the payment method detail:
* `payment_method.detail.card.soft_descriptor`
* `payment_method.detail.wallet.soft_descriptor`
* `payment_method.detail.bank_transfer.soft_descriptor`
For Apple Pay and Google Pay rebills, the saved method is a card-type network token, so use `payment_method.detail.card.soft_descriptor`.
```json Create Payment (excerpt) theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"amount": { "currency": "USD", "value": 15000 },
"payment_method": {
"type": "CARD",
"vaulted_token": "{{vaulted_token}}",
"detail": {
"card": {
"soft_descriptor": "ACME STREAMING",
"stored_credentials": {
"reason": "SUBSCRIPTION",
"usage": "USED"
}
}
}
}
}
```
See [Stored Credentials](/docs/payment-features/stored-credentials) for the full CIT/MIT flow.
## Provider behavior
Yuno forwards `soft_descriptor` to each provider's equivalent field (for example, Stripe `statement_descriptor` / `statement_descriptor_suffix`, Unlimit `dynamic_descriptor`, Airwallex `descriptor`, Inovio `PMT_DESCRIPTOR`, Nuvei `dynamicDescriptor.merchantName`). Behavior differs by provider:
| Provider | Behavior |
| :-------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Stripe | Sends only the suffix (`statement_descriptor_suffix`) by default. The full descriptor is sent only for organizations enabled for full statement descriptors — contact your technical account manager. |
| Unlimit | Truncates to 22 characters. |
| Airwallex | Truncates to 30 characters. |
| Inovio | Strips non-alphanumeric characters. |
| Worldpay | Does not read `soft_descriptor`. The statement narrative comes from the generic `payment_description` field instead. |
Length and allowed characters vary by provider. Keep descriptors short and alphanumeric so they survive truncation and sanitization, and test with your provider before relying on a specific format.
# Transaction Retries
Source: https://docs.y.uno/docs/payment-features/transaction-retries
Automatically retry failed capture or refund transactions up to seven times over a 96-hour window
Yuno provides merchants with the ability to retry capture and refund transactions that have encountered errors or been declined by the provider. This feature aims to enhance transaction success rates and improve the user experience. By setting the `simplified_mode` field to `true` in [capture](/reference/capture-authorization) and [refund](/reference/refund-payment) requests, Yuno will automatically retry failed transactions up to seven times within a 96-hour period. The system handles the following scenarios during the retry process:
#### Capture transactions
Capture transactions can encounter various statuses during and after the retry process. The table below details these statuses:
| Payment while retry is ongoing | Payment after successful retries | Payment after failed retries |
| :-------------------------------------- | :------------------------------------------------------------------- | :------------------------------------------ |
| SUCCEEDED / CAPTURE\_RETRY\_IN\_PROCESS | SUCCEEDED / CAPTURED or PARTIALLY\_CAPTURED depending on the amount. | SUCCEEDED / CAPTURE\_RETRY\_PROCESS\_FAILED |
#### Refund transactions
Refund transactions also have specific statuses during and after the retry process. The table below outlines these statuses:
| Payment while retry is ongoing | Payment after successful retries | Payment after failed retries |
| :------------------------------------- | :------------------------------------------------------------------------------ | :--------------------------- |
| SUCCEEDED / REFUND\_RETRY\_IN\_PROCESS | REFUNDED / REFUNDED or SUCCEEDED / PARTIALLY\_REFUNDED depending on the amount. | SUCCEEDED / APPROVED |
## Benefits
This feature provides several advantages:
* **Improved transaction success rates**: Automatic retries enhance the likelihood of successful transaction completions, leading to higher approval rates.
* **Enhanced user experience**: By automatically retrying failed transactions, user friction is reduced, improving overall customer satisfaction and retention.
* **Operational efficiency**: Automating retry attempts optimizes time and resources by minimizing manual intervention for failed transactions, allowing teams to focus on strategic tasks.
## Retry scheme
The retry scheme is crafted to maximize transaction success by scheduling retries at strategic intervals.
The table below describes the intervals between each retry. Note that each retry is scheduled based on the timing of the last attempt, meaning the time between retries is cumulative:
| Event | Deadline after the first try |
| :---------- | :--------------------------- |
| First try | - |
| Second try | 5 minutes |
| Third try | 50 minutes |
| Fourth try | 6 hours |
| Fifth try | 24 hours |
| Sixth try | 48 hours |
| Seventh try | 96 hours |
This table illustrates that each retry is performed based on the time elapsed since the previous attempt, not the initial attempt. For example, the fourth retry occurs 6 hours after the third retry rather than 6 hours after the first attempt. The entire schedule spans 7 days and 7 hours in total.
## Examples
Below are examples of capture authorization and refund requests using the simplified mode.
```Text Capture theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
curl --request POST \
--url https://api-sandbox.y.uno/v1/payments/id/transactions/transaction_id/capture \
--header 'X-Idempotency-Key: ' \
--header 'accept: application/json' \
--header 'charset: utf-8' \
--header 'content-type: application/json' \
--header 'private-secret-key: ' \
--header 'public-api-key: ' \
--data '
{
"amount": {
"currency": "JPY",
"value": 300
},
"simplified_mode": true,
"description": "Confirmed",
"reason": "PRODUCT_CONFIRMED",
"merchant_reference": "AAB01-432245"
}
'
```
```sh Refund theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
curl --request POST \
--url https://api-sandbox.y.uno/v1/payments/id/transactions/transaction_id/refund \
--header 'X-Idempotency-Key: ' \
--header 'accept: application/json' \
--header 'charset: utf-8' \
--header 'content-type: application/json' \
--header 'private-secret-key: ' \
--header 'public-api-key: ' \
--data '
{
"simplified_mode": true,
"description": "Refund",
"reason": "REQUESTED_BY_CUSTOMER",
"merchant_reference": "AAB01-432245"
}
'
```
# Chargeback Management
Source: https://docs.y.uno/docs/payouts-and-disputes/chargeback-management
Explains chargeback and dispute states, evidence submission, and predispute deflection handling across providers
Yuno offers a unified and automated solution for handling disputes, allowing you to manage chargebacks across all providers from a single dashboard. Yuno's platform automates workflows, helps you recover revenue, and keeps you audit-ready.
## What is a chargeback?
A chargeback is a claim initiated by a customer through their issuing bank due to a transaction they find problematic. Common reasons include unauthorized payments, incorrect amounts, or merchant disputes.
In Yuno, a **chargeback** and a **dispute** are technically the same: they both represent a contested transaction.\
The conceptual difference lies in the merchant's response: when a merchant provides documentation to contest the chargeback, it becomes an **active dispute**. However, the transaction remains the same, and only its state evolves based on the actions taken.
## Chargeback workflow
1. **Chargeback creation**
* The customer raises a claim with their issuing bank
* The bank notifies the payment provider
* The provider informs Yuno about the claim
* Yuno logs the chargeback, and its initial transaction state is `CREATED`
2. **Merchant notification**
* Yuno notifies the merchant about the chargeback and updates the payment's status
3. **Merchant actions**
* The merchant can:
* **Submit evidence**: Provide documentation supporting the validity of the transaction, turning the chargeback into an active dispute
* **Accept the chargeback**: Acknowledge the claim without disputing it and lose the funds (`LOST`)
4. **Evidence review**
* If evidence is submitted, the issuing bank reviews the documentation and issues a final decision (`PENDING_REVIEW`)
5. **Chargeback/dispute resolution**
* **Dispute Won** (`WON`): The customer's claim is rejected, and the transaction remains valid
* **Dispute Lost** (`LOST`): The customer's claim is accepted, resulting in a refund to the customer
## Chargeback states
The states of chargebacks in Yuno represent the various stages of the process:
| **State** | **Description** |
| ---------------- | ------------------------------------------------------------------------------------------------------------ |
| `CREATED` | A chargeback has been received; the merchant can take action or submit evidence if the provider supports it. |
| `PENDING_REVIEW` | Evidence has been submitted and is under review by the issuing bank. |
| `WON` | The dispute was resolved in favor of the merchant. |
| `LOST` | The claim was accepted, resulting in a refund to the customer. |
| **Payment Status** | **Payment Substatus** | **Transaction Type** | **Transaction Status** | **Description** |
| ------------------ | --------------------- | -------------------- | ---------------------- | ---------------------------------------------------------------------------------------------------------- |
| `SUCCEEDED` | APPROVED | Chargeback | Won | Chargeback dispute won |
| `IN_DISPUTE` | RECEIVED | Chargeback | Created | Chargeback or Inquiry received. Decision or documentation must be provided in order to initiate a dispute. |
| | PENDING\_REVIEW | Chargeback | Pending\_review | Dispute in review by the provider |
| `CHARGEBACK` | LOST | Chargeback | Lost | Expired/Closed/Review\_lost |
## Predisputes (deflections)
When a provider/network explicitly reports a predispute deflection, Yuno:
* Creates a `CHARGEBACK` transaction with `status = PREVENTED` so you can audit that a chargeback was prevented
* Sets the payment to `status = CHARGEBACK` and `sub_status = LOST` to reflect the financial outcome
* Emits only the chargeback webhook for the `CHARGEBACK / PREVENTED` transaction (no separate refund webhook)
* Enforces idempotency to avoid duplicate transactions and notifications
Additional details:
* No evidence required: predispute deflections do not require evidence submission
* Dispute ID mapping: the Dispute ID equals the chargeback transaction ID
* Optional fields: chargeback webhooks may include `provider_dispute_id` and `is_pre_dispute` to indicate predispute-origin cases
`PREVENTED` is used only on transactions of type `CHARGEBACK` and is a terminal state for that transaction.
### Example predispute
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"transaction": {
"id": "tx_cb_001",
"type": "CHARGEBACK",
"status": "PREVENTED",
"category": "CARD",
"amount": 19700,
"provider_id": "STRIPE",
"provider_dispute_id": "du_1S2umUCXdfp1jQhWSW3lALH2"
},
"payment": {
"id": "pay_123",
"status": "CHARGEBACK",
"sub_status": "LOST",
"amount": { "currency": "USD", "value": 19700, "refunded": 0, "captured": 19700 }
}
}
```
## Key benefits of managing chargebacks with Yuno
Yuno simplifies and optimizes your chargeback management through several key advantages:
### All your disputes in one integrated workflow
Consolidate chargeback data from all your payment providers into one dashboard. Whether it's Visa, Mastercard, or a local acquirer, you can track, respond, and manage disputes centrally.
### Streamlined chargeback response
Automate chargeback responses with the right supporting documentation to ensure every dispute is addressed quickly and efficiently.
### Ensure compliance
Every chargeback, every response, every update is logged and accessible. With built-in audit trails and exportable records, compliance and internal reviews are faster and easier.
## Understand the reason code
Understanding the reason code behind each chargeback is crucial, as it explains why the customer initiated the dispute. Familiarity with these codes allows you to tailor your response more effectively and gather the necessary information for each case. In the [Chargeback Response Codes section](/docs/reason-codes), you can find a comprehensive list of all possible codes provided by acquirers. In each chargeback transaction you'll be able to find the reason code in the `response_code` field.
## Evidence management
To dispute a chargeback, the merchant must submit evidence supporting their case. In the context of dispute resolution services, evidence refers to any information or documentation that substantiates your position in a disagreement or claim. Providing compelling evidence is crucial for achieving a favorable outcome. Examples of such evidence include:
* *Proof of delivery*: Documents confirming that a product was shipped and received by the customer, such as tracking numbers or delivery confirmations
* *Customer communications*: Records of emails, text messages, or any exchanges that demonstrate agreements or clarifications made with the customer
* *Refund and return policies*: Copies of the policies that the customer agreed to at the time of purchase, outlining the conditions for returns or refunds
* *Proof of authenticity*: Documentation verifying the legitimacy of a transaction, like signed receipts or authentication records
It's essential that the evidence presented is clear, relevant, and directly pertains to the issue at hand. Additionally, organizing and presenting the evidence professionally and concisely will aid in its assessment by the parties involved in resolving the dispute.
**Evidence requirements**
The uploaded files must meet the following criteria:
* *Format*: File must be in PDF format, encoded as base64
* *Size*: File must be no larger than 1 MB in size
* *Language*: Dispute should be written in English or the country's local language
### Example request to submit evidence
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
POST https://api-sandbox.y.uno/v1/payments/:payment_id/transactions/:transaction_id/dispute
Headers:
X-Idempotency-Key:
X-Public-Api-Key:
X-Private-Secret-Key:
Body:
{
"account_id":"",
"evidence": [
{
"file_name": "signed_receipt.pdf",
"content_type": "application/pdf",
"content_category": "RECEIPT",
"content": "JVBERi0xLjMKJcTl8uXrp/Og0MT..."
}
]
}
```
The endpoint returns a standard payment response structure containing the updated payment information, including the chargeback/dispute status.
### Updating dispute evidence
If you need to add additional evidence to an existing dispute, you can use the [Update Dispute](/reference/update-dispute) endpoint. This allows you to provide supplementary documentation after the initial dispute has been submitted.
**Important Notes**
* **Status unchanged**: Adding additional evidence does not change the chargeback status. The status remains the same regardless of updates.
* **Provider support**: Not all providers support updating disputes. If a provider doesn't support updates, you'll receive a controlled error response, and the chargeback status will remain unchanged.
* **Retrieving dispute information**: Use the [Retrieve Payment by ID](/reference/retrieve-payment-by-id) endpoint to check the current status of a chargeback/dispute. The response includes transaction details with chargeback information.
Please refer to the [Disputes API](/reference/disputes) and [Update Dispute API](/reference/update-dispute) reference sections for more information.
# Payouts
Source: https://docs.y.uno/docs/payouts-and-disputes/payouts
Sends secure payouts to beneficiaries via bank, card, or wallet withdrawal methods across multiple providers
Yuno Payouts is an API solution designed to streamline the process of sending secure payouts to various beneficiaries, such as users, merchants, providers, and customers. With Yuno Payouts, you can efficiently distribute funds to multiple recipients while ensuring their security and taking complete control of your payout operations.
The Yuno Payout solution enables you to create payout requests without restrictions on the number of records. You can perform payouts to any bank, card, or wallet. The payout options are only limited by the provider you choose to use.
## Benefits of using Yuno Payouts
* **Centralization**: The Payout service saves you time and costs by centralizing all your payment operations in one place. You no longer need to manage payments across multiple systems or interfaces.
* **Information**: Stay informed about payment statuses with Yuno's customizable notifications. You can receive real-time updates on any changes in the payment order status tailored to your preferences.
* **Localization**: By depositing funds directly into your partners' local bank accounts, you can pay them in their preferred currency, eliminating the need for foreign currency conversions and saving them from extra fees and taxes.
## How Payouts work
A payout in Yuno can go through a few different states, starting with its creation. When you create a payout, it automatically receives the **CREATED** status. However, the **CREATED** status is temporary. As Yuno checks and transfers the information to the provider, the payout status changes to **PENDING**.
When the payout changes to the **PENDING** status, a series of actions are performed, defining if the payout will succeed, transfer the funds, or if it will be blocked. Below, you find the description for each of the possible ending states:
* **SUCCEEDED**: The provider validates the transaction, and the funds are successfully transferred to the beneficiary’s account. You'll receive a confirmation notification.
* **REJECTED**: The payout was not processed due to problems Yuno identified before attempting the transfer. Possible reasons for a rejected payout include insufficient funds or incorrect payout details, like a wrong account number. You'll need to create a new payout to perform the transaction.
* **DECLINED**: The payout was attempted, but the provider refused to accept it. Reasons for a declined payout include a frozen or closed beneficiary account or the transaction being flagged as a potential fraud. You'll need to create a new payout to perform the transaction.
Learn more about the payout status on the [Payouts Status](/reference/payouts/payout-workflow) page.
## New Concepts
* **Beneficiary**: This is equivalent to the customer for payins. It is the object that receives beneficiary information for the payout. Example: If the payout is for salary payments, the beneficiary would be the employee receiving their salary.
* **Withdrawal Method**: The payment method's counterpart for payouts. Just as payins require payment method information, payouts require withdrawal method information. Send the fields for the category you're using: cards, bank transfers, or wallets.
## Using Yuno Payouts
The Yuno Payouts feature is available through Yuno API. You can use the API to create and retrieve payout information. To use the Payouts solution, you need to fulfill the following requirements:
* You need a Yuno account.
* You need to integrate with [Yuno API](/reference/payouts/create-payout).
* Have an account with an external provider that supports payouts.
To use the Payouts solution, you'll need to follow the steps below:
1. Configure the provider credentials in the [Connections section](/docs/using-yuno/dashboard-overview/connections) in your Yuno dashboard.
* (Optional) Add a [Webhook URL](/docs/webhooks/configure-webhooks) to get notifications about updates to the payout transactions.
2. Create the payout using the [Create Payout](/reference/payouts/create-payout) endpoint. You need to provide the beneficiary information, the amount, and the withdrawal method to make the payout.
3. Yuno will verify the information and then send the payout request to the provider. The provider will analyze the available funds to authorize the payment.
4. To check the current status of payouts, you can use one of the following options:
* The [Retrieve Payout by ID](/reference/payouts/retrieve-payout-by-id) endpoint, informing the `id` received after creating the payout.
* The [Retrieve Payout by Merchant Reference](/reference/payouts/retrieve-payout-by-merchant-reference) endpoint, informing the `merchant_reference` provided when creating the payout.
**Yuno Payouts availability**
Yuno Payouts requires a security and risk analysis. To learn more about the Yuno Payouts, check the provider's support or request the activation, contact [Yuno's support team](mailto:support@y.uno).
## Referenced Payouts
Payouts could be made to different payment methods, such as bank accounts and even card, depending on the provider. For Payouts to a card payment method where the merchant does not have the credit card information (not being PCI compliant) Yuno lets them send the Payout if the card was previously used in a payment. This is called a "Referenced Payout."
To use this, you'll need to first charge the customer using one of Yuno's PCI compliant solutions (any [Yuno SDK](/docs/sdks/overview/quickstart)) and then make a Payout indicating the original transaction where Yuno can find the credit card information.
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
"withdrawal_method": {
"type": "STP_PAYOUT",
"provider_id": "STP",
"original_transaction_id":"9104911d-5df9-429e-8488-ad41abea1a4b"
}
```
# Chargeback Response Codes
Source: https://docs.y.uno/docs/payouts-and-disputes/reason-codes
Lists chargeback response codes and their meanings by category across card networks
A chargeback reason code is a short alphanumeric code assigned by the issuing bank to explain why a customer disputed a transaction. These codes help merchants understand the issue and respond accordingly. While merchants can challenge chargebacks by providing evidence, the reason code might change if new information arises during the dispute process. Major card networks like Visa, Mastercard, American Express, Discover, and Diners each have their own set of reason codes.
The following table shows the possible reason codes for each Chargeback that you'll find in each transaction. You'll be able to find the associated `response_code` in each [transaction](/reference/transaction#chargebacks-specific-response_codes) webhook. Also, in each chargeback transaction you'll find the raw reason code from the card schemes in the response data.
| **Category** | **Response\_code** | **Description** |
| :---------------- | :----------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Fraud | `EMV_LIABILITY_SHIFT_COUNTERFEIT` EMV Liability Shift Counterfeit Fraud | The cardholder is claiming that they did not authorize or participate in a transaction that you processed. |
| Fraud | `EMV_LIABILITY_SHIFT_NOT_COUNTERFEIT` EMV Liability Shift Non-Counterfeit Fraud | The cardholder is claiming that they did not authorize or participate in a transaction that you processed. |
| Fraud | `CARD_PRESENT_FRAUD` Other Fraud – Card-Present Environment | The cardholder is claiming that they did not authorize or participate in a key-entered or unattended transaction conducted in a card-present environment. |
| Fraud | `NON_CARD_PRESENT_FRAUD` Other Fraud – Card-Absent Environment | The cardholder did not authorize or participate in a transaction conducted in a card-not-present environment, such as internet, mail-order, phone-order, and others. |
| Fraud | `SCHEME_MONITORING_PROGRAM` Other Fraud - Scheme Monitoring Program | Scheme Fraud Monitoring program |
| Authorization | `NO_AUTHORIZATION` No Authorization | Correct and valid authorization was not obtained by the merchant. |
| Authorization | `DECLINED_AUTHORIZATION` Declined Authorization | Authorization request received a Decline response and the merchant completed the transaction. |
| Processing Errors | `LATE_PRESENTMENT` Late Presentment | The transaction was not sent within the timeframe required. |
| Processing Errors | `INCORRECT_TRANSACTION_CODE` Incorrect Transaction Code | The cardholder is claiming that the converted amount of charge on an international transaction is incorrect. |
| Processing Errors | `INCORRECT_CURRENCY` Incorrect Currency | The merchant made one or more errors related to the transaction currency. |
| Processing Errors | `INCORRECT_ACCOUNT_NUMBER` Incorrect Account Number | The account number in the authorization does not match the account number used in the transaction. |
| Processing Errors | `INCORRECT_AMOUNT` Incorrect Amount | The cardholder is claiming that the amount they agreed to pay differs from the amount charged. |
| Processing Errors | `DUPLICATE_PROCESSING` Duplicate Processing/Paid by Other Means | A single transaction was processed two or more times. |
| Processing Errors | `INVALID_DATA` Invalid Data | The authorization was obtained using invalid or incorrect data. |
| Customer Disputes | `PRODUCT_OR_SERVICE_NOT_RECEIVED` Merchandise/Services Not Received | The cardholder is claiming that merchandise or services that they ordered were not received. |
| Customer Disputes | `CANCELED_RECURRING_TRANSACTION` Cancelled Recurring Transaction | A recurring transaction was processed after it was cancelled. |
| Customer Disputes | `PRODUCT_OR_SERVICE_ISSUE` Not as Described or Defective Merchandise/Services | The cardholder is claiming the goods were not as described. |
| Customer Disputes | `COUNTERFEIT_MERCHANDISE` Counterfeit Merchandise | The merchandise was identified as counterfeit. |
| Customer Disputes | `MISREPRESENTATION` Misrepresentation | The cardholder’s bank received a notice from the cardholder is claiming misrepresented terms of sale. |
| Customer Disputes | `CREDIT_NOT_PROCESSED` Credit Not Processed | The cardholder’s bank received a notice from the cardholder claiming that they received authorization, credit or voided transaction receipt that has not been processed. |
| Customer Disputes | `PRODUCT_OR_SERVICE_CANCELED` Cancelled Merchandise/Services | The cardholder’s bank received a notice from the cardholder stating that they returned merchandise or cancelled services, but the credit has not appeared on the cardholder’s statement. |
| Customer Disputes | `ORIGINAL_TRANSACTION_NOT_ACCEPTED` Original Credit Transaction Not Accepted | The original credit was not accepted. |
| Customer Disputes | `CASH_TRANSACTION_VALUE` Non-Receipt of Cash or Load Transaction Value | Cardholder did not receive the full cash withdrawal at an ATM. |
| Customer Disputes | `CUSTOMER_AGREEMENT` Proof of customer transaction or agreement required | The issuer asks the merchant for a copy of the receipt signed by the cardholder or any other documentation that verifies the customers agreement for the purchase. Usually to verify a card-present transaction the cardholder disputes or doesn’t recognize. |
# Apple Pay & Google Pay enhanced experience
Source: https://docs.y.uno/docs/plugins/vtex/apple-pay-google-pay-enhanced-experience
Enable a direct wallet experience on VTEX checkout and unlock Apple Pay installments.
The Apple Pay & Google Pay enhanced experience is an optional add-on for stores already using the Yuno VTEX plugin. It improves the checkout experience for shoppers by removing an intermediate screen between the VTEX checkout and the device's native wallet sheet, which is known to reduce conversion on wallet payments.
## What it is
By default, when a shopper selects Apple Pay or Google Pay, the Yuno Payment App opens an intermediate screen inside the VTEX checkout before the device's native confirmation sheet (Face ID, fingerprint, or PIN) appears.
The **enhanced experience** removes that intermediate screen: the Apple Pay and Google Pay buttons appear **directly inside the VTEX checkout payment step**, and tapping a button opens the device's native sheet immediately.
This integration also unlocks the optional **Apple Pay installments** feature.
## How it works
When a shopper reaches the checkout, the Yuno SDK quietly prepares a payment session in the background. By the time they reach the payment step, the Apple Pay and Google Pay buttons appear instantly.
* **Fast confirmation**: Tapping a button opens the native wallet sheet immediately.
* **Auto-recalculation**: If the shopper changes their cart (adds an item, applies a coupon, changes shipping), the SDK recalculates the session automatically.
* **Error handling**: If a payment fails, the shopper can try again without reloading the page.
***
## Integration guide
Setting up the enhanced experience involves adding a small JavaScript snippet to your VTEX checkout and finding the values to fill into it.
The snippet is added to your store's `checkout6-custom.js` file from the VTEX dashboard.
1. In the **VTEX dashboard**, search for **Checkout** in the top bar.
2. Select the website your store uses (usually **Default**).
3. Open the **Code** tab and select `checkout6-custom.js` from the file list on the right.
4. Add the snippet below at the end of the file, then click **Save**.
```javascript theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
(function () {
window.addEventListener('yuno-sdk-vtex-io-ready', function (event) {
var YunoVTEXIO = event.detail.YunoVTEXIO;
YunoVTEXIO.initialConfiguration({
paymentMethods: ['Google Pay', 'Apple Pay'],
affiliationName: 'YOUR_AFFILIATION_NAME'
});
});
var script = document.createElement('script');
script.src = 'https://sdk-web-vtex-io.y.uno/v1/main.js';
document.head.appendChild(script);
})();
```
Replace `YOUR_AFFILIATION_NAME` with the affiliation name from your Yuno provider configuration. In `paymentMethods`, list the wallets you want to enable: `'Apple Pay'`, `'Google Pay'`, or both.
The `affiliationName` value is the same one you set when configuring Yuno as a payment provider.
1. In the **VTEX dashboard** search bar, type `providers` and select the **Providers** result.
2. Find the Yuno provider configured for this store and open it.
3. In the provider's detail view, copy the value from the **Affiliation Name** field and use it in the snippet.
After saving the snippet, the enhanced experience is live. Apple Pay and Google Pay buttons will
appear directly inside the VTEX checkout payment step
***
## Apple Pay installments
Apple Pay installments is an optional feature within the enhanced experience that lets shoppers split their purchase into installments.
### What shoppers see
Once enabled, an **Installments** selector appears above the Apple Pay button. Tapping it opens a panel listing every installment option.
If the plan includes interest, a **Payment details** panel appears below showing the breakdown (number of installments, financing cost, etc.).
### How to enable
Apple Pay installments are enabled from the Yuno dashboard, by creating installment plans for the
Apple Pay payment method. **The snippet doesn't change**: a store running the enhanced experience with
`'Apple Pay'` in `paymentMethods` already asks Yuno for the available plans on every order.
1. In the **Yuno dashboard**, go to **Installments** and click **Create installment**.
2. In **Payment method type**, select **Apple Pay**.
3. Set the number of installments, the rate, the amount range, and the availability window.
Card plans are not reused. Apple Pay only sees plans created for the Apple Pay payment method, so
a store with installment plans already set up for cards still needs its own Apple Pay plans.
The plan appears with **Apple Pay** in the **Payment method** column. Create one plan per amount
band if you want different options for different cart sizes.
Open the payment step with a cart inside the plan's amount range and select Apple Pay. The
**Installments** selector appears above the button.
You can also create plans with the [Create Installments Plan](/reference/installments/create-installments-plan)
endpoint, sending `payment_method_type: APPLE_PAY`.
### Eligibility rules
Yuno resolves the plan for each order from the cart total, so the shopper always sees the options that
apply to what's in their cart. If the cart changes, the options are recalculated.
Each plan you create defines:
* **Payment method type**: must be Apple Pay.
* **Currency and country**: must match the order.
* **Amount range**: minimum and maximum order total the plan covers.
* **Availability window**: start and end date for the plan.
The selector shows one entry per number of installments. If two plans cover the same order and both
offer the same count, only one of them is used, so keep the amount ranges apart if you want a
predictable result.
If no plan covers the order, the selector is hidden and Apple Pay renders as a plain button — the
payment still goes through, at one installment.
Check the minimum amount of your lowest plan against your typical order total. If the plan starts
above it, most shoppers never see the selector, and the feature looks broken when it's only out of
range.
# Headless SDK integration
Source: https://docs.y.uno/docs/plugins/vtex/direct-sdk-integration
Render the Yuno checkout experience directly on your own front-end, including headless and mobile WebView setups, using the SDK Web for VTEX.
Most stores integrate Yuno through the standard plugin flow described in [Set up Yuno on VTEX](/docs/plugins/vtex/set-up-yuno-on-vtex). For stores that need to render the Yuno checkout experience directly on their own front-end instead, Yuno provides the **Yuno SDK Web for VTEX** npm package.
## When this applies
If your store has standard requirements, you do not need this page. The standard plugin flow already handles everything. Use the headless SDK integration only when your store has specific needs that require the Yuno checkout experience to be rendered directly by your front-end. This applies, for example, to headless or highly customized checkouts.
A **headless** store in VTEX is one where the merchant runs its own front-end outside VTEX's native storefront. It still uses VTEX's commerce capabilities (catalog, cart, checkout, orders) through APIs. Because the front-end is fully under your control, the Yuno checkout experience is no longer rendered for you by the standard plugin. Instead, your front-end mounts the **Yuno SDK Web for VTEX** itself. For background on this architecture, see VTEX's [Headless commerce guide](https://developers.vtex.com/docs/guides/headless-commerce).
## What stays the same
The setup in your **VTEX dashboard** and **Yuno dashboard** does not change:
* You still configure Yuno as a payment provider in VTEX.
* You still configure the webhook in your Yuno dashboard.
* The **Yuno Payment Connector** remains the backbone of the integration. Every payment continues to flow through it.
## What's different
Instead of letting the standard flow render the Yuno checkout for you, your front-end mounts the **Yuno SDK Web for VTEX** directly and provides it with the configuration it needs to render the checkout experience for the current shopper.
## Before you mount: run the authorization first
The SDK does not generate its own payment context. It renders the checkout from a `payload` produced by the **Yuno Payment Connector**. That `payload` only exists once the **authorization step** of the transaction has run.
Authorization is **step 1** of the VTEX [payment transaction flow](https://help.vtex.com/docs/tutorials/transaction-flow-in-payments). When the shopper places the order, VTEX calls the Payment Connector with the order details (items, amounts, shopper, shipping). The Connector processes that request and returns a response that includes the `payload`. The SDK needs this payload to configure and mount itself for that specific order.
Always trigger the authorization step **before** mounting the SDK. If you mount it without the `payload` returned by the Connector, the SDK has no payment context to render and the checkout will not load.
***
## Integration steps
The Yuno SDK Web for VTEX is published on npm as `@yuno-payments/sdk-web-vtex`. Install it in your project using your preferred package manager:
```bash npm theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
npm install @yuno-payments/sdk-web-vtex
```
```bash yarn theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
yarn add @yuno-payments/sdk-web-vtex
```
Mount the SDK on the page where the shopper completes the payment. Initialize it by calling the `mount` method with a configuration object:
```javascript theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
import { loadScript } from '@yuno-payments/sdk-web-vtex'
import type { YunoVTEXInterface, MountProps, OnPaymentDoneParams } from '@yuno-payments/sdk-web-vtex'
// Load the SDK
const yunoVTEX: YunoVTEXInterface = await loadScript()
// Example of payload received from the connector
const payload = "{\"isVTEXCard\":true,\"checkoutSessions\":[\"bd0c0a6e\"],\"paymentIds\":[\"ABC\"],\"orderId\":\"123\"}"
// SDK Props
const mountProps: MountProps = {
// Required properties
elementRoot: 'yuno-sdk-root',
payload,
language: 'en',
// Optional VTEX configuration (Recommended)
domainVTEX: 'https://mystore.myvtex.com',
proxyUrlVTEX: 'https://proxy.mystore.com',
// Event handlers
onPaymentDone: (paymentData: OnPaymentDoneParams) => {
// Continue to your order confirmation flow.
console.log('Payment completed:', paymentData)
if (paymentData.success) {
// Handle successful payment
paymentData.payments?.forEach(payment => {
console.log(`Order ${payment.orderId}: ${payment.status}`)
})
}
},
onError: (message: string, error?: any) => {
// Handle and surface the error to the shopper.
console.error('Payment error:', message, error)
},
onLoading: (loading: boolean) => {
// Show or hide a loading indicator.
console.log('Loading state:', loading)
},
// Device fingerprinting for fraud prevention
deviceFingerprints: [
{
provider_id: 'RISKIFIED',
session_id: 'riskified-session-123'
}
]
}
// Mount the payment interface
await yunoVTEX.mount(mountProps);
```
Keep the SDK mounted while the shopper is paying. Call `unmount` **only when you tear the checkout down**, for example, when the component is destroyed or the shopper navigates away:
```javascript theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
// Later, when the checkout is no longer needed:
await yunoVTEX.unmount()
```
| Field | Description |
| :------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `elementRoot` | **Required.** ID of the DOM element where the SDK renders the checkout UI (for example, `yuno-sdk-root`). |
| `payload` | **Required.** The payment context for the current shopper, returned by the Yuno Payment Connector during authorization. It is a serialized JSON string. Pass it as received, without parsing it. |
| `language` | **Required.** Language the SDK is displayed in (for example, `en`, `es`, `pt-BR`). |
| `domainVTEX` | Optional (recommended). Your VTEX store domain (for example, `https://mystore.myvtex.com`). |
| `proxyUrlVTEX` | Optional. URL of a proxy to VTEX, if your setup routes VTEX calls through one. |
| `onPaymentDone` | Optional. Callback invoked when the payment finishes. Receives a result object with `success` and a `payments` array. |
| `onError` | Optional. Callback invoked when an error occurs during the payment. |
| `onLoading` | Optional. Callback invoked when the SDK changes its loading state. |
| `deviceFingerprints` | Optional. Device fingerprinting identifiers for fraud prevention, each with a `provider_id` and a `session_id`. |
***
## Using the Headless SDK inside a mobile app
The Yuno SDK Web for VTEX is a **web** library. To use it inside a mobile app, you load your front-end page (the one that mounts the SDK) inside a **WebView**. The WebView is what gives the SDK the browser environment it needs to run.
### What a WebView is and why you need one
A **WebView** is an embeddable browser component that renders web content inside a native app (`WebView` on Android, `WKWebView` on iOS, and wrappers such as `react-native-webview`). Because the SDK runs in the browser, the WebView is what gives it that browser environment. Your app loads the URL that mounts the SDK, and the SDK renders the checkout inside the WebView.
The implementation details below are **suggestions**. How you build the WebView and the bridge is entirely up to you. The goal is only to show what needs to be in place for the SDK to work.
### The bridge between your app and the WebView
Your app and the page inside the WebView need to communicate in both directions:
* **Web → App:** the page reports results back to the native app (for example, payment completed, error, or loading state). Every WebView platform exposes a message channel for this: `window.ReactNativeWebView.postMessage(...)`, a JavaScript interface on Android, or a `WKScriptMessageHandler` on iOS.
* **App → Web:** the app injects/evaluates JavaScript in the page (for example, to deliver the `payload` after the page loads).
We recommend defining a small **message contract** that the page emits and the app listens for. For example:
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{ "type": "paymentDone", "paymentData": { "success": true, "payments": [] } }
{ "type": "error", "message": "..." }
{ "type": "loading", "loading": true }
```
When the SDK calls `onPaymentDone`, `onError`, or `onLoading`, your page forwards a message in this shape through the bridge. The app then reacts by closing the WebView, showing the result, or toggling a spinner. The exact field names are yours to define.
### Technical considerations
For the SDK to work inside a WebView, make sure the WebView has:
* **JavaScript enabled.**
* **DOM storage enabled** (the SDK uses browser storage).
* **Third-party / shared cookies enabled**, so the payment session is preserved across the requests the SDK makes.
* A bridge wired up (see above) so results can flow back to the app.
### Wallets: Apple Pay and Google Pay
Wallets have extra requirements on top of the general setup, because the device's native payment surface is involved.
#### Google Pay (Android WebView)
Google Pay inside an Android WebView relies on the Chromium **Payment Request API** and on opening the Google Pay sheet. To make it work:
* **Enable the Payment Request API** on the WebView. On Android this is done through `androidx.webkit` (`WebSettingsCompat.setPaymentRequestEnabled(...)`) when the feature is supported.
* **Allow the wallet sheet to open.** Google Pay opens its sheet via `window.open()`. A default WebView may block it (you may see an `OR_BIBED_15` / "pop-ups turned off" error). Configure the WebView so the new window loads in the same WebView instead of requiring a blocked popup.
* **Declare the Google Pay intents** your app can query, in the Android manifest, so the WebView can reach the Google Pay service:
```xml theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
```
Some conditions are not about your app's code but about the **device where the payment is made**. They apply both to a shopper's device and to any device you use to test the flow. The device needs an up-to-date **Android System WebView** and **Google Play services**, and a **Google account with a valid payment method** added. For full details, see Google's [Using Google Pay with an Android WebView](https://developers.google.com/pay/api/android/guides/recipes/using-android-webview) guide.
#### Apple Pay (iOS WebView)
Apple Pay has a hard requirement on **where the page is served from**: it cannot run from a **static local HTML file** loaded into the WebView. The page that mounts the SDK must be served from a **hosted URL whose domain is registered and verified in your Apple Developer account**. That domain must also be configured in your **Yuno dashboard** so that every domain involved matches. If the domains do not match, Apple Pay will not become available.
### Examples
The snippets below are **reference examples only**. They show one possible way to wire the WebView and the bridge in each stack. They are not a required or recommended technology choice; use whatever fits your app.
Load the hosted page in a `WebView`, enable the wallet-friendly settings, and listen for messages from the page. Delivering the `payload` to the page (after the authorization step) and the message contract are up to you.
```jsx theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
import { WebView } from 'react-native-webview'
function CheckoutWebView({ uri, onResult }) {
return (
{
const data = JSON.parse(event.nativeEvent.data)
// { type: 'paymentDone' | 'error' | 'loading', ... }
onResult(data)
}}
/>
)
}
```
> Enabling the Android Payment Request API (`setPaymentRequestEnabled`) is not exposed by `react-native-webview` out of the box; it requires a small native adjustment to the WebView settings.
Enable JavaScript, register a JavaScript interface for the Web → App channel, and inject the `payload` once the page has loaded.
```kotlin theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
WebView(context).apply {
settings.javaScriptEnabled = true
// Web -> App: the page calls Android.receiveMessageFromJS("...")
addJavascriptInterface(object {
@JavascriptInterface
fun receiveMessageFromJS(message: String) {
// Parse the message contract and react (e.g. paymentDone / error).
}
}, "Android")
webViewClient = object : WebViewClient() {
override fun onPageFinished(view: WebView?, url: String?) {
// App -> Web: deliver the payload returned by the connector.
evaluateJavascript("window.postMessage('$payloadJson', '*');", null)
}
}
loadUrl(hostedUrl)
}
```
> For Google Pay, also enable the Payment Request API on `settings` via `WebSettingsCompat.setPaymentRequestEnabled(...)` and add the `` intents shown above to your manifest.
Register a `WKScriptMessageHandler` for the Web → App channel and inject the `payload` when the page finishes loading. Remember Apple Pay requires a hosted, verified URL (not a local file).
```swift theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
let contentController = WKUserContentController()
contentController.add(coordinator, name: "iosListener") // Web -> App
let config = WKWebViewConfiguration()
config.userContentController = contentController
let webView = WKWebView(frame: .zero, configuration: config)
webView.navigationDelegate = coordinator
webView.load(URLRequest(url: hostedURL))
// In the navigation delegate, after the page loads:
// App -> Web: deliver the payload returned by the connector.
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
webView.evaluateJavaScript("window.postMessage(\(payloadJson), '*');")
}
```
***
**Resources**
* [NPM Package: @yuno-payments/sdk-web-vtex](https://www.npmjs.com/package/@yuno-payments/sdk-web-vtex)
# FAQs
Source: https://docs.y.uno/docs/plugins/vtex/faqs
Answers to the most common questions about the Yuno VTEX integration.
Yuno automatically tracks the expiration of every Pix payment based on the configuration in your integration. Before a Pix payment expires, Yuno proactively checks whether it has been completed. If the shopper does not pay in time, Yuno notifies VTEX, which automatically cancels the order.
Saved-card flows and Click to Pay both rely on a customer record being created in Yuno. To enable them, set the **Create Customer** field to **Yes** in your Yuno provider configuration. With this option enabled, the plugin creates or updates a Yuno customer record on every payment.
Yes. Orders created with VTEX's [subscriptions](https://help.vtex.com/docs/tutorials/how-subscriptions-work) feature are supported out of the box. The first purchase is processed like any other card payment. The automatic renewals that follow are charged even though the shopper is not present and no security code (CVV) is entered. Yuno processes them as stored-credential, merchant-initiated (MIT) payments, a classification that lets recurring charges go through instead of being declined.
There is nothing extra to configure on the Yuno side: as long as you have set up subscriptions in VTEX, the integration handles them automatically, and your regular checkout is unaffected. Subscriptions apply to card payments only.
The environment is determined by the prefix of your Yuno **Public API Key**:
* `dev_*`, `staging_*`, and `sandbox_*` prefixes connect to test environments.
* `prod_*` prefixes connect to production.
To switch to production, simply replace your API keys in the VTEX dashboard with your production credentials from the Yuno dashboard.
Use the **Soft Descriptor** field in your Yuno provider configuration. The text you enter is sent to the acquirer and shown on the shopper's card statement. We recommend using your store name to help shoppers identify the purchase and reduce chargebacks.
Not necessarily. If your VTEX accounts share the same Yuno credentials (e.g., a franchise model), you can use the **Main Account** fields in the provider configuration to share catalog and order data. If each account uses its own credentials, you should configure them independently.
Yes. You can connect a single VTEX account to multiple Yuno integrations. Configure Yuno as a provider once for each integration with a distinct **Affiliation Name**, then select the correct affiliation when activating each payment method.
When a shopper's cart contains products from different sellers or franchises, VTEX splits the purchase into multiple suborders and charges each one independently. Yuno processes every suborder so the whole order is paid — not just the first part — sharing a single antifraud session across all of them. You can control which antifraud providers receive that shared session with the **Antifraud Providers for Split Orders** field. See [Advanced Scenarios](/docs/plugins/vtex/set-up-yuno-on-vtex#advanced-scenarios) for details.
Yes. VTEX lets you modify an order after it has been placed — useful when the final amount is only known later, such as products sold by weight. If the final total is the same or lower, Yuno captures only the final amount. If it is higher, Yuno charges the difference automatically against the card used on the original order, without the shopper needing to re-enter it.
Automatic charges for **increased** totals apply to **credit cards** and must be enabled in advance: set **Vault Card for Order Modification** and **Create Customer** to **Yes** in your provider configuration before the orders are placed. See [Advanced Scenarios](/docs/plugins/vtex/set-up-yuno-on-vtex#order-modifications-changed-order-totals) for the full setup.
Open the order in your **Yuno dashboard** to see the full lifecycle of every payment attempt, including provider responses and errors. Cross-reference the VTEX order ID with the Yuno payment ID to follow the transaction end-to-end.
# VTEX Plugin Overview
Source: https://docs.y.uno/docs/plugins/vtex/index
Understand how the Yuno VTEX plugin works and the payment methods available for your store.
Yuno and VTEX have joined forces to simplify payment processes for merchants worldwide. By integrating Yuno's payment orchestration platform with VTEX's e-commerce platform, businesses gain access to a wide variety of payment methods and advanced security features.
With Yuno, your VTEX store can offer shoppers credit and debit cards and alternative payment methods such as Pix and Boleto Bancário. It also supports digital wallets like Apple Pay, Google Pay, and Click to Pay, plus Buy Now, Pay Later options, all through a single integration. Yuno's orchestration layer handles the routing and processing behind the scenes, so you can scale across markets without rebuilding the payment stack each time.
Yuno is also PCI compliant, meeting rigorous security standards when handling card data. The integration is designed to keep shoppers inside your VTEX checkout from start to finish. There are no redirects to external payment pages, which removes friction at the most sensitive point of the purchase journey and helps lift conversion.
## Payment methods available
Through Yuno, your VTEX store can accept payments across the following categories:
| Category | Examples |
| :----------------------- | :-------------------------------------------------------------------------------------------------------------- |
| **Credit cards** | Visa, Mastercard, American Express, Diners, Elo, Hipercard, Alelo, and other regional brands. |
| **Debit cards** | Visa Electron, Maestro, Mastercard Debit, Elo Débito, and other regional brands. |
| **Instant payments** | Pix (Brazil). |
| **Bank transfers** | PSE (Colombia) and other bank-transfer methods supported by Yuno. |
| **Digital wallets** | Apple Pay, Google Pay, Click to Pay, Nubank, PicPay, Mercado Pago, and other regional wallets. |
| **Cash vouchers** | Boleto Bancário (Brazil), Safetypay, PagoEfectivo, and other voucher methods supported by Yuno. |
| **Buy Now, Pay Later** | BNPL methods supported by Yuno. |
| **Generic Yuno methods** | Category-level methods (Yuno Card, Yuno Wallet, Yuno Bank Transfer, Yuno BNPL, Yuno Ticket, Yuno Payment Link). |
Which methods are actually offered to your shoppers depends on the methods you activate in the **VTEX dashboard** and the providers you have enabled in your **Yuno dashboard**.
## How the plugin works
The plugin is composed of three pieces that work together behind the scenes:
* **Yuno Payment Connector**: The component you configure in your VTEX dashboard. It handles the communication between VTEX and Yuno: authorizing transactions, capturing or refunding them, and reporting status back to VTEX.
* **Yuno Payment App**: Renders the Yuno checkout experience inside the VTEX checkout. When a shopper picks a payment method, the Payment App displays the right form (card form, Pix QR, wallet button) and submits the payment.
* **Yuno SDK Web for VTEX**: The library used by the Payment App to render the Yuno UI where the shopper enters their payment data.
You configure the **Payment Connector** in VTEX. The **Payment App** is installed afterward, and the **SDK Web** is loaded automatically during checkout. There is no separate setup for it.
## Recurring payments, multi-seller & modified orders
Beyond one-off checkout, the Yuno integration also handles three common VTEX scenarios automatically:
* **VTEX subscriptions (recurring payments)**: for products sold on a recurring basis, Yuno processes both the first purchase and the automatic renewals that follow. See the [FAQs](/docs/plugins/vtex/faqs) for details.
* **Multi-seller (split) orders**: when a cart combines products from different sellers or franchises, VTEX splits it into separate orders and Yuno charges every one of them, not just the first. See [Advanced Scenarios](/docs/plugins/vtex/set-up-yuno-on-vtex#advanced-scenarios).
* **Modified orders (changed totals)**: when an order's total changes after checkout (for example, products sold by weight), Yuno adjusts to the final amount. If it goes **down**, only the final (lower) amount is captured; if it goes **up**, the difference is charged automatically (when enabled). See [Advanced Scenarios](/docs/plugins/vtex/set-up-yuno-on-vtex#order-modifications-changed-order-totals).
***
## Where to next?
Step-by-step setup in the VTEX and Yuno dashboards.
Enable Apple Pay and Google Pay buttons directly in VTEX checkout.
For stores that need to render the Yuno checkout on their own front-end, including mobile WebViews.
Answers to the questions merchants ask most often.
# Set up Yuno on VTEX
Source: https://docs.y.uno/docs/plugins/vtex/set-up-yuno-on-vtex
Start accepting payments with Yuno on your VTEX store by following this end-to-end configuration guide.
This page walks you through every step needed to start accepting payments with Yuno on your VTEX store. The setup happens in two places. Your **VTEX dashboard** is where you register Yuno as a payment provider, install the Payment App, and activate payment methods. Your **Yuno dashboard** is where you configure the webhook that keeps order status in sync.
### Before you start
Have the following ready:
* A user with administrator access to your VTEX dashboard.
* Your Yuno credentials, which you can find in your Yuno dashboard under **Developers → API Credentials**: **Account ID**, **Public API Key**, and **Private Secret Key**.
***
1. In the **VTEX dashboard**, open the left-hand menu and go to **Store Settings → Payment → Providers**, then click **New Provider** at the top right.
2. In the **Select a provider** dialog, type `Yuno` in the search box and select **Yuno** from the results.
3. Fill in the provider configuration form and save. Once saved, the provider is registered, but no payment methods are active yet.
| Field | Required | What it does |
| :--------------------------------------- | :------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Application Key / Application Token** | Yes | VTEX admin credentials the plugin uses to interact with VTEX on your behalf. See VTEX's guide on [generating Application Keys](https://help.vtex.com/docs/tutorials/api-keys#generating-internal-application-keys). |
| **Automatic Settlement** | Yes | Defines when the payment is captured automatically after authorization. Applies to card and wallet payments only. |
| **Affiliation Name** | Yes | A human-readable name for this Yuno integration. |
| **Account ID** | Yes | Your Yuno **Account ID**, available in your Yuno dashboard. |
| **Public API Key** | Yes | Your Yuno **Public API Key**. The prefix determines the environment. |
| **Private Secret Key** | Yes | Your Yuno **Private Secret Key**. |
| **Main Account Name** | Optional | For multi-account setups. |
| **Main Account App key** | Optional | Application Key of the main VTEX account. |
| **Main Account App token** | Optional | Application Token of the main VTEX account. |
| **Soft Descriptor** | Optional | Custom text that appears on the shopper's card statement. |
| **Create Customer** | Optional | When set to **Yes**, the plugin creates a corresponding customer record in Yuno. |
| **VTEX IO orderPlaced page URL** | Optional | A custom URL where shoppers should be redirected after payment. |
| **Payment Mode** | Optional | **Payment App** (modern) or **Legacy** (redirect). |
| **Transaction Identification From** | Optional | **Yuno TID** or **Provider TID**. |
| **Antifraud Providers for Split Orders** | Optional | Comma-separated antifraud providers (`RISKIFIED`, `CYBERSOURCE`, `SIGNIFYD`, `CIELO_CYBERSOURCE_FRAUD`) that receive the shared session for split orders. Defaults to `RISKIFIED` + `CYBERSOURCE` when left empty. |
| **Vault Card for Order Modification** | Optional | When set to **Yes** (and **Create Customer** is also **Yes**), the plugin securely stores the card used on each order so that, if the order total later increases, the additional amount can be charged automatically. See [Order modifications](#order-modifications-changed-order-totals). |
The **Automatic Settlement** field determines the timing of the capture for card and wallet payments.
| Option | Practical Behavior |
| :------------------------------------------------------------ | :------------------------------------------------------------------------------------------------------------ |
| **Use behavior recommended by payment processor** | **Immediate Capture**: The transaction is captured immediately after authorization. (Default) |
| **Automatic capture immediately after payment authorization** | **Immediate Capture**: The transaction is captured immediately after authorization. Same as default. |
| **Automatic capture immediately after anti-fraud analysis** | **Immediate Capture**: The transaction is captured immediately after authorization. |
| **Disabled** | **Authorize Only**: The transaction is only authorized. Capture happens later when the order is **invoiced**. |
**Environments**: The Yuno environment is determined by the prefix of your **Public API Key**: `dev_`, `staging_`, `sandbox_`, or `prod_`.
We suggest using **Use behavior recommended by payment processor** unless your business specifically requires capture after invoicing.
After saving the provider configuration, install the Yuno Payment App from your VTEX dashboard.
1. In the **VTEX dashboard**, go to **Apps → App Management**.
2. Search for **Yuno** and select the **Yuno Payment App** in the list of available apps and open its **Settings**.
3. Click **Install** to complete the setup.
Once installed, the Payment App takes care of rendering the Yuno checkout experience inside your VTEX checkout.
Now choose which payment methods you want to offer to your shoppers and route them through Yuno.
1. In the **VTEX dashboard**, go to **Store Settings → Payment → Settings → Payment Conditions**. Click the **+** button to add a payment condition.
2. Select the payment method you want to activate (for example, Visa, Mastercard, Pix, Apple Pay, or any of the generic **Yuno** methods, such as Yuno Card or Yuno Wallet).
3. In the **Process with provider** field, select the Yuno affiliation you configured in Step 1. Set the **Status** to **Active** and save.
Repeat for every method you want to offer. You can review the full list of available methods in the [Overview](/docs/plugins/vtex) page.
The webhook keeps your VTEX orders in sync with Yuno's payment status updates.
1. In the **Yuno dashboard**, open **Developers → Webhooks** and click **Add webhook**.
2. Fill in the form:
* **Name**: For example `VTEX webhook`.
* **Endpoint URL**: `https://{store_name}.myvtex.com/_v/yunopartnerbr.yuno/v4/webhook`, replacing `{store_name}` with your VTEX account name.
* **x-api-key** and **x-secret**: Enter any placeholder value (for example, `VTEX`).
3. Select all events and click **Add**.
***
## Advanced Scenarios
### Multi-affiliation
A single VTEX account can be connected to **more than one Yuno integration** when you need to process different payment methods through different Yuno accounts. For example, you can assign one Yuno account to credit cards and a different one to wallets.
To set this up, repeat Step 1 once per integration, giving each one a distinct **Affiliation Name**. Then, when activating payment methods, use the **Process with affiliation** field to choose which account should process it.
### Multi-account
If your business runs **multiple VTEX accounts** (for example, a franchise model sharing the same Yuno credentials), use the **Main Account** fields in the provider configuration:
* **Main Account Name**: The name of the main VTEX account.
* **Main Account App key** and **Main Account App token**: Application credentials of that main account.
When these fields are set, the plugin reads catalog and order data from the main account instead of the current one.
### Split orders (multiple sellers)
When a shopper's cart contains products from **different sellers or franchises**, VTEX splits the purchase into multiple suborders and authorizes each one independently. The Yuno integration detects this and processes **every** suborder, so the entire order is paid, not just the first part. A single antifraud session is shared across all of them.
This works automatically; no extra setup is required. If you want to control which antifraud providers receive the shared session, use the **Antifraud Providers for Split Orders** field in the provider configuration (see the field reference in Step 1). Valid values are `RISKIFIED`, `CYBERSOURCE`, `SIGNIFYD`, and `CIELO_CYBERSOURCE_FRAUD`; when left empty, it defaults to `RISKIFIED` + `CYBERSOURCE`.
### Order modifications (changed order totals)
VTEX lets you **change an order after checkout**, when the final total turns out to be different from the amount that was authorized. This applies, for example, if you sell products **by weight**, where the exact total is only known once the order is picked and packed.
* If the final total is the **same or lower**, VTEX captures only the final amount. No extra setup is required.
* If the final total is **higher**, VTEX charges the difference as a **separate, automatic charge**. Since the shopper is no longer present and does not re-enter their card, Yuno charges the difference against the card they already used on the original order.
To enable automatic charges when an order total **increases**, configure the following in your provider settings **before** the orders you expect to modify are placed:
| Field | Value |
| :------------------------------------ | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Vault Card for Order Modification** | **Yes**: stores the card on the original order so it can be charged again for the difference. |
| **Create Customer** | **Yes**: required, so the card is stored against a Yuno customer. Both fields must be enabled together. |
| **Automatic Settlement** | **Disabled** (recommended). The original payment is authorized at checkout and captured at invoicing. If the final total is **lower** than the authorized amount, only that lower amount is captured (a partial capture). If it is higher, the difference is charged as a separate additional charge. |
Order-total **increases** are supported for **credit cards only** (a VTEX restriction). The card is stored at the time of the original payment, so **Vault Card for Order Modification** and **Create Customer** must be enabled **before** the order is placed. Turning them on later does not apply to orders that already exist.
**Franchises / multiple accounts:** enable **Vault Card for Order Modification** and **Create Customer** on **every** affiliation you use (each franchise or sub-account), and set the **Main Account** fields as described under [Multi-account](#multi-account).
# Installments
Source: https://docs.y.uno/docs/sdks/additional-features/installments
Get notified when the shopper selects an installment option in the card form on Web, iOS, and Android
Register the optional `onInstallmentSelected` callback to keep your cart total in sync with the installment plan the shopper picks in the card form. The SDK notifies you when a default installment is pre-selected, every time the shopper changes the selection, and when the plan is recalculated (for example, after a BIN change).
The callback is optional on all platforms: if you don't register it, the SDK behavior is unchanged. Exceptions thrown inside your callback are caught by the SDK and never interrupt the payment flow.
| Platform | Available from | Where to register |
| -------- | -------------- | ---------------------------------------------------- |
| Web | SDK `1.6.7` | `card.onInstallmentSelected` in `startCheckout` |
| iOS | SDK `2.21.0` | `onInstallmentSelected(_:)` on `YunoPaymentDelegate` |
| Android | SDK `2.20.0` | `onInstallmentSelected` parameter of `startCheckout` |
## Implementation
Pass the callback inside the `card` options of `startCheckout`:
```javascript theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
await yuno.startCheckout({
checkoutSession: session.checkout_session,
elementSelector: '#payment-form',
countryCode: 'BR',
card: {
onInstallmentSelected: ({ installment, label, amount, isMerchantInstallment }) => {
// Update your cart total, e.g. with amount?.total_value
console.log('Installment selected:', { installment, label, amount, isMerchantInstallment })
},
},
// ...
})
```
The callback receives a single object argument:
```typescript theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
type OnInstallmentSelected = (args: {
installment: number
label: string
amount?: {
currency: string
value: string
total_value: string
}
additionalData?: Record
isMerchantInstallment: boolean
}) => void
```
| Field | Type | Description |
| ----------------------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| `installment` | `number` | Number of installments selected (e.g. `3`). |
| `label` | `string` | The exact installment label rendered in the form, localized (e.g. `3x de R$875.00 - Total R$2,625.00`). |
| `amount` | `object` | Optional. `currency`, `value`, and `total_value` as raw strings, exactly as reported by the installments plan. |
| `additionalData` | `object` | Reserved for future use. Currently always `undefined`. |
| `isMerchantInstallment` | `boolean` | `true` when the selected option was supplied by your own `onGetInstallments` callback (merchant installments); `false` for Yuno-provided plans. |
Firing semantics:
* Fires with the current selection as soon as the plan renders and a default installment is pre-selected, so your total is correct from first paint.
* Fires on every selection the shopper makes.
* Re-fires the current selection when the available options change (for example, a BIN change recalculates the plan).
* Does not fire when installments stop being available — there is no clear notification on Web.
* Works across all card flows, including secure fields and Click to Pay.
Implement the optional `onInstallmentSelected(_:)` method of `YunoPaymentDelegate`:
```swift theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
class ViewController: UIViewController, YunoPaymentDelegate {
// ... required YunoPaymentDelegate implementation ...
func onInstallmentSelected(_ installmentSelected: YunoInstallmentSelected?) {
guard let installmentSelected else {
// Installments are no longer available — restore your base total
return
}
// Update your cart total, e.g. with installmentSelected.amount?.totalValue
}
}
```
The method receives a `YunoInstallmentSelected?` payload:
```swift theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
@objc public final class YunoInstallmentSelected: NSObject {
@objc public let installment: Int
@objc public let label: String
@objc public let amount: YunoInstallmentAmount?
@objc public let additionalData: [String: Any]?
}
@objc public final class YunoInstallmentAmount: NSObject {
@objc public let currency: String
@objc public let value: String
@objc public let totalValue: String
}
```
| Field | Type | Description |
| ---------------- | ------------------------ | --------------------------------------------------------------------------------------------------------- |
| `installment` | `Int` | Number of installments selected (e.g. `3`). |
| `label` | `String` | The exact installment label rendered in the form, localized (e.g. `3x of R$ 500,31 - Total R$ 1.500,93`). |
| `amount` | `YunoInstallmentAmount?` | `currency`, `value`, and `totalValue` as raw strings, exactly as reported by the installments plan. |
| `additionalData` | `[String: Any]?` | The `additional_data` object of the selected option, when the installments service provides it. |
Firing semantics:
* Fires once when a default installment is pre-selected as the plan loads, so your total is correct from first paint.
* Fires on every selection the shopper makes, and with the recalculated default after the plan changes (for example, a BIN change).
* Fires once with `nil` when a previously reported selection no longer applies (for example, the shopper switches to a card without installments) — restore your base total. It is never called with `nil` before the first selection is reported.
* Delivered on the main thread. The method is optional — omitting it keeps the SDK behavior unchanged.
Pass the callback when calling `startCheckout`:
```kotlin theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
startCheckout(
checkoutSession = "checkout_session",
countryCode = "country_code_iso",
callbackPaymentState = { state, subState -> /* ... */ },
onInstallmentSelected = { selection ->
if (selection != null) {
// Update your cart total, e.g. with selection.amount?.totalValue
} else {
// Installments are no longer available — restore your base total
}
},
)
```
The callback receives an `InstallmentSelected?` payload:
```kotlin theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
data class InstallmentSelected(
val installment: Int,
val label: String,
val amount: InstallmentAmount? = null,
val additionalData: Map? = null,
)
data class InstallmentAmount(
val currency: String,
val value: String,
val totalValue: String,
)
```
| Field | Type | Description |
| ---------------- | -------------------- | ------------------------------------------------------------------------------------------------------- |
| `installment` | `Int` | Number of installments selected (e.g. `3`). |
| `label` | `String` | The exact installment label rendered in the form, localized (e.g. `3x de R$875.00 - Total R$2,625.00`). |
| `amount` | `InstallmentAmount?` | `currency`, `value`, and `totalValue` as raw strings, exactly as reported by the installments plan. |
| `additionalData` | `Map?` | Reserved for future use. Currently always `null`. |
Firing semantics:
* Fires once when a default installment is pre-selected as the plan renders, so your total is correct from first paint.
* Fires on every selection the shopper makes, and with the recalculated default after the plan changes (for example, a BIN change).
* Fires once with `null` when installments stop being available after a selection was already reported (for example, the shopper switches to a card without installments) — restore your base total.
* Does not fire when the card form renders without installments. The callback runs on the main thread, and registering no callback keeps the SDK behavior unchanged.
# Flutter
Source: https://docs.y.uno/docs/sdks/additional-platforms/flutter
Integrate Yuno's Flutter SDK for payment and enrollment flows, including styling, customization, and troubleshooting
Integrate Yuno's Flutter SDK Lite payment and enrollment flows by following these steps.
## Requirements
* Flutter SDK installed (Dart included).
* iOS 14.0 or above.
* Android minSdkVersion 21 or above.
* Java 8 enabled and AndroidX enabled.
* Android Gradle plugin 4.0.0 or above.
* Proguard 6.2.2 or above.
* Kotlin Gradle plugin 1.4.0 or above.
* `FlutterFragmentActivity` for `MainActivity` on Android.
## Adding the SDK to your project
This section applies to both Payment and Enrollment flows. Complete these steps before implementing either flow.
### Flutter package
Add the Yuno package to your Flutter project:
```bash theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
flutter pub add yuno
```
### Android configuration
Add the Yuno Maven repository to your project-level `android/build.gradle`:
```groovy theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
allprojects {
repositories {
google()
mavenCentral()
maven { url "https://yunopayments.jfrog.io/artifactory/snapshots-libs-release" }
}
}
```
Use `FlutterFragmentActivity` in `MainActivity.kt`:
```kotlin theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
class MainActivity: FlutterFragmentActivity()
```
Create a custom `Application` and initialize the native SDK:
```kotlin theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
import android.app.Application
import com.yuno_flutter.yuno_sdk_android.YunoSdkAndroidPlugin
class MyApp : Application() {
override fun onCreate() {
super.onCreate()
YunoSdkAndroidPlugin.initSdk(this, "YUNO_API_KEY")
}
}
```
Then register the application class in `AndroidManifest.xml`:
```xml theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
```
### iOS configuration
No additional iOS-specific configuration is required beyond the Flutter package installation. iOS appearance customization is configured through `IosConfig` during SDK initialization (see customizations section).
## Payment
Follow these steps to integrate the Yuno payment flow in your Flutter application.
Before initiating a payment, create a customer and checkout session using Yuno's server-side API.
* Use [Create customer](/reference/customers/create-customer) to represent the person making the payment.
* Use [Create checkout session](/reference/checkout-sessions/create-checkout-session) to define transaction details.
Keep the returned `checkout_session` ID for the next steps.
Initialize the Yuno SDK in your Flutter app, typically before `runApp` in `main.dart`.
```dart theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
await Yuno.init(
apiKey: 'YOUR_PUBLIC_API_KEY',
countryCode: 'CO',
yunoConfig: const YunoConfig(),
iosConfig: const IosConfig(),
);
```
Set up a payment listener (e.g., `YunoPaymentListener`) in your widget tree to receive events.
```dart theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
YunoPaymentListener(
listener: (context, state) {
final ott = state.token;
if (ott.isNotEmpty) {
// Send ott to your backend
}
},
child: YourWidget(),
)
```
Start the Lite payment flow by calling `startPaymentLite` with the selected payment method.
```dart theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
await Yuno.startPaymentLite(
arguments: StartPayment(
checkoutSession: checkoutSessionId,
methodSelected: const MethodSelected(
paymentMethodType: 'CARD',
),
),
);
```
After the user completes the form, the SDK generates an OTT delivered to your `YunoPaymentListener`.
```dart theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
listener: (context, state) {
final ott = state.token;
if (ott.isNotEmpty) {
// Send ott to your backend
}
}
```
Use the OTT from Step 5 to create the payment in your backend via the [Create payment](/reference/payments/create-payment) endpoint.
If the response includes `sdk_action_required: true`, call `continuePayment` to handle 3DS or redirects.
```dart theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
await Yuno.continuePayment(showPaymentStatus: true);
```
### Payment status validation
The SDK manages the relationship between frontend SDK status and backend payment status when users interact with payment flows. Understanding this distinction helps you handle payment states correctly in your application.
#### Sync payment methods (Apple Pay and Google Pay)
For synchronous payment methods like Apple Pay and Google Pay, when a user cancels or closes the wallet UI before a payment service provider (PSP) response is received:
* **SDK status**: Returns `cancelByUser` (CANCELLED\_BY\_USER)
* **Backend payment status**: Remains `PENDING` until PSP timeout or merchant cancellation
* **Important**: The SDK will not return `reject` or `processing` in this scenario
This ensures that the backend payment remains in a pending state and can be properly handled by the merchant's system.
#### Async payment methods (PIX and QR-based methods)
For asynchronous payment methods like PIX, when a user closes the QR code window before completing the payment:
* **SDK status**: Returns `processing`, optionally with a sub-status such as `CLOSED_BY_USER`
* **Backend payment status**: Remains `PENDING` and the QR code remains valid until expiry
* **Checkout session reuse**: Re-opening the same checkout session can display the same valid QR code
* **No automatic cancellation**: The PIX payment is not automatically cancelled when the user closes the QR window
This behavior allows users to return to the payment flow and complete the transaction using the same QR code before it expires.
#### Expired async payments
If a PIX QR code expires naturally:
* **Backend status**: Updated to `EXPIRED`
* **SDK status**: SDK callbacks and polling endpoints return `EXPIRED` consistently
This ensures merchants receive accurate status information when a payment method has expired.
## Enrollment
Follow these steps to enroll payment methods in your Flutter application.
Create a customer and a `customer_session` in your backend using the [Create customer session](/reference/customer-sessions-enrollment/create-customer-session) endpoint.
Ensure the SDK is initialized with your API key and configuration.
```dart theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
await Yuno.init(
apiKey: 'YOUR_PUBLIC_API_KEY',
countryCode: 'CO',
);
```
Set up a `YunoEnrollmentListener` to receive status updates.
```dart theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
YunoEnrollmentListener(
listener: (context, state) {
final status = state.enrollmentStatus;
// Handle status updates
},
child: YourWidget(),
)
```
Call `enrollmentPayment` with the customer session ID.
```dart theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
await Yuno.enrollmentPayment(
arguments: EnrollmentArguments(
customerSession: customerSessionId,
showPaymentStatus: true,
),
);
```
Monitor the enrollment status through your listener callback.
```dart theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
listener: (context, state) {
final status = state.enrollmentStatus;
// Handle completion or errors
}
```
For methods using external authentication, pass the redirect URL to the SDK. See [Handling the deeplink return](#handling-the-deeplink-return) for how to capture `uri`.
```dart theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
await Yuno.receiveDeeplink(url: uri);
```
## Handling the deeplink return
Redirect-based methods (some APMs, external 3DS, and enrollment with external authentication) send the user out of your app and bring them back through a deeplink. Capture that returning URL and pass it to `Yuno.receiveDeeplink`. This applies to both the Payment and Enrollment flows.
Listen for incoming links (for example with the [`app_links`](https://pub.dev/packages/app_links) package) and pass the URL to `Yuno.receiveDeeplink`. Handle both the cold-start link (app opened by the deeplink) and links received while the app is already running.
```dart theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
late AppLinks _appLinks;
StreamSubscription? _linkSubscription;
Future _initDeepLinks() async {
_appLinks = AppLinks();
// App opened from a deeplink (cold start)
final initialLink = await _appLinks.getInitialLink();
if (initialLink != null) _handleDeepLink(initialLink);
// App already running
_linkSubscription = _appLinks.uriLinkStream.listen(_handleDeepLink);
}
void _handleDeepLink(Uri uri) {
// Forward the redirect back to the SDK
// (optionally gate on your own callback scheme/host)
Yuno.receiveDeeplink(url: uri);
}
```
## Parameters
For the full list of parameters and options, see the subsections that follow.
### `Yuno.init`
| Parameter | Description |
| :------------ | :----------------------------------------------------------------------------------------------------- |
| `apiKey` | Your Yuno public API key. |
| `countryCode` | Country where the payment is performed. See [Country coverage](/docs/sdks/resources/country-coverage). |
| `yunoConfig` | SDK configuration options. See `YunoConfig` below. |
| `iosConfig` | iOS appearance configuration. See `IosConfig` below. |
### `YunoConfig`
| Parameter | Description |
| :--------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `lang` | Defines the language used in the payment forms. Set it to one of the available options: en (English), es (Spanish), pt (Portuguese), ms (Malay), id (Indonesian), th (Thai), ar (Arabic), hi (Hindi), bn (Bengali), ml (Malayalam), ur (Urdu). See [Supported languages](#supported-languages) for more details. |
| `saveCardEnable` | Enables the Save card checkbox on card flows, allowing users to save their card for future payments. Default: `false`. |
| `keepLoader` | Keeps the SDK loader visible during the flow so you can hide it manually with `Yuno.hideLoader()`. Default: `false`. |
### `IosConfig`
| Parameter | Description |
| :----------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `appearance` | iOS-only appearance customization. See [`Appearance`](#appearance-ios) below and the [customizations](#customizations) section for detailed styling options. |
### `Appearance` (iOS)
| Parameter | Description |
| :------------------------------------ | :----------------------------------------------- |
| `fontFamily` | iOS font family name. |
| `accentColor` | Accent color for highlights and active elements. |
| `buttonBackgrounColor` | Primary button background color. |
| `buttonTitleBackgrounColor` | Primary button title color. |
| `buttonBorderBackgrounColor` | Primary button border color. |
| `secondaryButtonBackgrounColor` | Secondary button background color. |
| `secondaryButtonTitleBackgrounColor` | Secondary button title color. |
| `secondaryButtonBorderBackgrounColor` | Secondary button border color. |
| `disableButtonBackgrounColor` | Disabled button background color. |
| `disableButtonTitleBackgrounColor` | Disabled button title color. |
| `checkboxColor` | Checkbox color. |
### `StartPayment` (Lite)
| Parameter | Description |
| :------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `checkoutSession` | The `checkout_session` ID created in your backend using the [Create checkout session](/reference/checkout-sessions/create-checkout-session) endpoint. This session identifier is required to initialize the payment flow. |
| `methodSelected` | The selected payment method information. See `MethodSelected` below for details on specifying the payment method type and optional vaulted token. |
| `showPaymentStatus` | Controls whether the SDK displays its built-in payment status screens after payment completion. Set to `false` if you want to handle status display in your own UI. Default: `true`. |
### `MethodSelected`
| Parameter | Description |
| :------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `paymentMethodType` | Payment method type selected by the user. Common values include: `CARD`, `PIX`, `PAYPAL`, `MERCADO_PAGO`, `GOOGLE_PAY`, `APPLE_PAY`. This value must match one of the payment methods available in your checkout session. |
| `vaultedToken` | Optional vaulted token to reuse a previously saved payment method. When provided, the SDK will use the saved payment method instead of prompting for new payment details. Leave empty for new payment methods. |
### `EnrollmentArguments`
| Parameter | Description |
| :------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `customerSession` | The `customer_session` ID created in your backend using the [Create customer session](/reference/customer-sessions-enrollment/create-customer-session) endpoint. This session is used to associate the enrolled payment method with a specific customer. |
| `showPaymentStatus` | Controls whether the SDK displays its built-in enrollment status screens after enrollment completion. Set to `false` if you want to handle status display in your own UI. Default: `true`. |
| `countryCode` | Optional country code override for this enrollment. If not provided, the SDK uses the country code from `Yuno.init()`. See [Country coverage](/docs/sdks/resources/country-coverage) for supported countries. |
## customizations
You can customize SDK behavior and appearance using the configuration options:
* `YunoConfig` for language, save card, and loader handling
* `IosConfig.appearance` for iOS UI styling
* Android styling through native configuration (see below)
### iOS customization
iOS appearance is fully customizable through the `IosConfig.appearance` parameter in `Yuno.init()`. You can modify visual styling to match your brand identity, including colors, fonts, and button designs.
#### Available iOS customization options
| Parameter | Type | Description |
| ------------------------------------- | ------ | ----------------------------------------------------------------------------------------------------------- |
| `fontFamily` | String | Custom font family name for all SDK text. Use the font name as registered in your iOS project's Info.plist. |
| `accentColor` | Color | Primary accent color used for highlights, active states, and interactive elements throughout the SDK. |
| `buttonBackgrounColor` | Color | Background color for primary action buttons (e.g., "Pay", "Confirm"). |
| `buttonTitleBackgrounColor` | Color | Text color for primary button labels. |
| `buttonBorderBackgrounColor` | Color | Border color for primary buttons. Set to match background for borderless buttons. |
| `secondaryButtonBackgrounColor` | Color | Background color for secondary/cancel buttons. |
| `secondaryButtonTitleBackgrounColor` | Color | Text color for secondary button labels. |
| `secondaryButtonBorderBackgrounColor` | Color | Border color for secondary buttons. |
| `disableButtonBackgrounColor` | Color | Background color for disabled buttons (when user cannot proceed). |
| `disableButtonTitleBackgrounColor` | Color | Text color for disabled button labels. |
| `checkboxColor` | Color | Color for checkboxes like "Save card for future payments". |
When using `Color(0xFF...)` for iOS appearance customization, add `import 'dart:ui';` at the top of your file.
For more iOS customization options, see [SDK customizations (iOS)](/docs/sdks/customization/ios).
### Android customization
For Android, the Flutter SDK uses the native Android SDK's styling system. customization is performed in the native Android layer using Kotlin/Java code when initializing the SDK through `YunoSdkAndroidPlugin.initSdk()`.
#### YunoConfig (Android)
The Android SDK supports comprehensive styling through the `YunoConfig` data class:
**cardFlow removed from YunoConfig (Android 2.11.0+)**
Card flow configuration is now handled exclusively through the **CheckoutBuilder** in the Dashboard. Omit `cardFlow` from `YunoConfig`.
```dart theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
class YunoConfig {
bool saveCardEnable;
YunoConfig({
this.saveCardEnable = false,
});
}
```
#### YunoStyles
Control the visual appearance of SDK components:
```kotlin theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
data class YunoStyles(
val buttonStyles: YunoButtonStyles? = null,
val fontFamily: FontFamily? = null
)
```
| Parameter | Type | Description |
| -------------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `buttonStyles` | YunoButtonStyles | Customizes all primary action buttons displayed in the SDK including background, text, borders, and state colors. See YunoButtonStyles below for detailed options. |
| `fontFamily` | FontFamily | Sets a custom font family for all text elements throughout the SDK. Use a FontFamily registered in your Android app. |
#### YunoButtonStyles
Fine-tune button appearance with these options:
```kotlin theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
data class YunoButtonStyles(
val backgroundColor: Color? = null,
val contentColor: Color? = null,
val cornerRadius: Dp? = null,
val elevation: Dp? = null,
val padding: Dp? = null,
val fontFamily: FontFamily? = null,
val fontSize: TextUnit? = null,
val fontStyle: FontStyle? = null
)
```
| Parameter | Type | Description |
| ----------------- | ---------- | ------------------------------------------------------------------------ |
| `backgroundColor` | Color | Background color for buttons. |
| `contentColor` | Color | Text and icon color for buttons. |
| `cornerRadius` | Dp | Button corner radius for rounded corners. Use `0.dp` for square buttons. |
| `elevation` | Dp | Shadow elevation for Material Design elevation effect. |
| `padding` | Dp | Internal padding inside buttons. |
| `fontFamily` | FontFamily | Font family specifically for button text (overrides global fontFamily). |
| `fontSize` | TextUnit | Font size for button text. |
| `fontStyle` | FontStyle | Font style (normal, italic, bold) for button text. |
Configure styles in your `Application` class during SDK initialization in `MyApp.kt`. For more Android customization options including XML themes and drawable customization, see [SDK customizations (Android)](/docs/sdks/customization/android).
## Environment variables (recommended)
Use `--dart-define` to avoid hardcoding keys:
```bash theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
flutter run --dart-define="YUNO_API_KEY=apiKey"
```
Then read it in Dart:
```dart theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
const apiKey = String.fromEnvironment('YUNO_API_KEY', defaultValue: '');
```
If you also need the key on the Android native side, map `dart-defines` into `BuildConfig` and read `BuildConfig.YUNO_API_KEY` in `MyApp` (see the Flutter SDK README for the full snippet).
## Troubleshooting
| Issue | Cause | Fix |
| :--------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Country code has not been initialized. Call Yuno.init() first.` | `Yuno.init()` was not called or failed before calling payment/enrollment methods. | Ensure `Yuno.init()` completes before any SDK call, and avoid hot reload for Android configuration changes. Perform a full restart after initialization changes. |
| Android native initialization fails silently | The Android native SDK was not initialized in the `Application` class, or the custom `Application` class was not registered in `AndroidManifest.xml`. | Verify that: 1) `YunoSdkAndroidPlugin.initSdk()` is called in your custom `Application` class `onCreate()`, 2) The custom `Application` class is registered in `AndroidManifest.xml` with `android:name=".MyApp"`, 3) The API key is correct. |
| Hot reload causes Android initialization issues | Flutter's hot reload does not re-execute native platform initialization code. | Perform a full app restart (stop and restart) instead of hot reload when making changes to `Yuno.init()` or Android native configuration. |
| Payment status listener not triggered | Listener widget is not in the widget tree above the point where payment is initiated, or the listener is recreated during navigation. | Ensure `YunoPaymentListener` or `YunoMultiListener` wraps the relevant part of your widget tree and persists across navigation. Place it high in the widget tree (e.g., wrapping `MaterialApp` or a top-level screen). |
| Android build fails with Maven repository error | Yuno Maven repository not added or added in wrong location in `build.gradle`. | Add `maven { url "https://yunopayments.jfrog.io/artifactory/snapshots-libs-release" }` to the `repositories` block in your project-level `android/build.gradle` (not in the app-level `build.gradle`). Ensure it is inside the `allprojects` section. |
| `MainActivity` crashes on Android | `MainActivity` does not extend `FlutterFragmentActivity` as required by the Yuno SDK. | Change your `MainActivity` to extend `FlutterFragmentActivity` instead of `FlutterActivity`: `class MainActivity: FlutterFragmentActivity()` |
| Token is empty or null in payment listener | Payment form validation failed, or the user canceled before completing the form. | Check for validation errors in the payment form. Ensure all required fields are filled correctly. Add null/empty checks in your listener before using the token. |
| customization not applied | Platform-specific customization not configured correctly or cached build artifacts. | For iOS: Verify `IosConfig.appearance` is properly set in `Yuno.init()`. For Android: Check native styling in XML or programmatic configuration. Clear build cache with `flutter clean` and rebuild. |
## Notes
* The Lite payment flow requires you to render the payment method list and pass the selected `paymentMethodType`.
* Use `YunoPaymentListener`/`YunoEnrollmentListener` to receive OTT/status updates and drive backend calls.
## Supported languages
The Flutter SDK supports the following `YunoLanguage` values:
`en` (English), `es` (Spanish), `pt` (Portuguese), `ms` (Malay), `id` (Indonesian), `th` (Thai), `ar` (Arabic), `hi` (Hindi), `bn` (Bengali), `ml` (Malayalam), `ur` (Urdu).
# Advanced Features
Source: https://docs.y.uno/docs/sdks/additional-platforms/react-native/advanced-features
Performance optimization, deep linking, and platform-specific configurations for React Native.
**Orientation: Choosing Your Integration Flow**, before you begin, please review the [Official Integration Flow](/docs/sdks/overview/understanding-flows).
* **Standard Flow ([Full Checkout](/docs/sdks/full-checkout/web-payments))**: Recommended for most merchants. Yuno handles the UI, security, and automatic updates for payment methods.
* **Custom Flow (This SDK)**: Use this only if you require full control over the UX. **Note**: You will be responsible for manually handling payment statuses, 3DS transitions, and fraud routing data collection.
Explore advanced configurations and custom integrations for the React Native SDK.
## Deep linking / external browser return
Handle users returning to your app after external payment flows like 3DS authentication challenges, bank transfer redirects, PIX payments, and alternative payment methods that redirect to external browsers.
### 1. Set callback\_url in checkout session
Include `callback_url` when creating the checkout session on your backend:
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"callback_url": "myapp://return"
}
```
### 2. Configure deep links
**iOS - Info.plist:**
```xml theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
CFBundleURLTypesCFBundleTypeRoleEditorCFBundleURLNamecom.yourappCFBundleURLSchemesmyapp
```
**Android - AndroidManifest.xml:**
```xml theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
```
### 3. Handle deep links in react-native
```typescript theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
import { YunoSdk } from '@yuno-payments/yuno-sdk-react-native';
import { Linking } from 'react-native';
import { useEffect } from 'react';
function App() {
useEffect(() => {
// Handle initial URL (app opened from closed state)
Linking.getInitialURL().then((url) => {
if (url) {
handleDeepLink(url);
}
});
// Handle URL changes (app is running)
const subscription = Linking.addEventListener('url', (event) => {
handleDeepLink(event.url);
});
return () => {
subscription.remove();
};
}, []);
const handleDeepLink = async (url: string) => {
// Check if it's a payment return URL
if (url.startsWith('myapp://return')) {
try {
await YunoSdk.receiveDeeplink(url);
} catch (error) {
console.error('Error processing deep link:', error);
}
}
};
}
```
### 4. Continue payment after return
After handling the deep link, continue the payment flow:
```typescript theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
const handleDeepLink = async (url: string) => {
if (url.startsWith('myapp://return')) {
try {
await YunoSdk.receiveDeeplink(url);
// Continue payment flow
await YunoSdk.continuePayment(
checkoutSessionId,
'US',
true // show payment status
);
} catch (error) {
console.error('Error:', error);
}
}
};
```
## Performance
### Lazy loading
Initialize the SDK only when the user enters the payment flow to save resources.
```typescript theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
const PaymentScreen = () => {
const [yunoLoaded, setYunoLoaded] = useState(false);
useEffect(() => {
if (!yunoLoaded) {
YunoSdk.initialize({
apiKey: 'pk_test_key',
countryCode: 'US',
});
setYunoLoaded(true);
}
}, []);
};
```
## Error handling
Listen to the `onPaymentStatus` event to handle failures gracefully.
```typescript theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
const subscription = YunoSdk.onPaymentStatus((state) => {
if (state.status === 'FAILED') {
Alert.alert('Error', 'Payment failed. Please try again.');
}
});
```
## Platform-specific configuration
Handle differences between iOS and Android in your React Native app.
### Conditional configuration
```typescript theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
import { Platform } from 'react-native';
await YunoSdk.initialize({
apiKey: 'your-api-key',
countryCode: 'US',
...(Platform.OS === 'ios' && {
iosConfig: { /* iOS settings */ },
}),
...(Platform.OS === 'android' && {
androidConfig: { /* Android settings */ },
}),
});
```
### Platform differences
| Feature | iOS | Android |
| ------------- | --------------- | -------------- |
| Card scanning | Not available | Available |
| Deep links | Universal Links | Intent Filters |
| Minimum OS | iOS 14.0+ | API 21 (5.0)+ |
# Code Examples
Source: https://docs.y.uno/docs/sdks/additional-platforms/react-native/code-examples
Ready-to-use React Native code examples for common scenarios.
**Orientation: Choosing Your Integration Flow**, before you begin, please review the [Official Integration Flow](/docs/sdks/overview/understanding-flows).
* **Standard Flow ([Full Checkout](/docs/sdks/full-checkout/web-payments))**: Recommended for most merchants. Yuno handles the UI, security, and automatic updates for payment methods.
* **Custom Flow (This SDK)**: Use this only if you require full control over the UX. **Note**: You will be responsible for manually handling payment statuses, 3DS transitions, and fraud routing data collection.
Explore these examples to quickly implement Yuno in your React Native application.
## Basic payment flow
The simplest way to integrate Yuno using the pre-built payment method selection component.
```typescript theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
import React, { useState, useEffect } from 'react';
import { View, Button, Text, StyleSheet, ScrollView } from 'react-native';
import { YunoSdk, YunoPaymentMethods } from '@yuno-payments/yuno-sdk-react-native';
export default function PaymentScreen() {
const [checkoutSession, setCheckoutSession] = useState(null);
const [paymentMethodSelected, setPaymentMethodSelected] = useState(false);
useEffect(() => {
initCheckout();
const subscription = YunoSdk.onPaymentStatus((state) => {
if (state.status === 'SUCCEEDED') {
Alert.alert('Success', 'Payment successful!');
}
});
return () => subscription.remove();
}, []);
const initCheckout = async () => {
const session = await fetch('https://api.example.com/checkout', {
method: 'POST',
body: JSON.stringify({ amount: { currency: 'USD', value: 2500 } }),
}).then(r => r.json());
setCheckoutSession(session.checkoutSession);
};
const processPayment = async () => {
await YunoSdk.startPayment(true);
};
return (
$25.00
{checkoutSession && (
{
setPaymentMethodSelected(event.isSelected);
}}
/>
)}
);
}
const styles = StyleSheet.create({
container: { flex: 1, padding: 20 },
amount: { fontSize: 32, fontWeight: 'bold', textAlign: 'center', marginBottom: 24 },
});
```
## React Navigation integration
```typescript theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import { YunoSdk, YunoPaymentMethods } from '@yuno-payments/yuno-sdk-react-native';
const Stack = createStackNavigator();
function CheckoutScreen({ navigation }) {
const [checkoutSession, setCheckoutSession] = useState(null);
const [paymentMethodSelected, setPaymentMethodSelected] = useState(false);
useEffect(() => {
initCheckout();
const subscription = YunoSdk.onPaymentStatus((state) => {
if (state.status === 'SUCCEEDED') {
navigation.navigate('Success');
}
});
return () => subscription.remove();
}, []);
const handlePayment = async () => {
await YunoSdk.startPayment(true);
};
return (
{checkoutSession && (
{
setPaymentMethodSelected(event.isSelected);
}}
/>
)}
);
}
export default function App() {
useEffect(() => {
YunoSdk.initialize({ apiKey: 'pk_test_key', countryCode: 'US' });
}, []);
return (
);
}
```
## One-click payment (Vaulted Tokens)
```typescript theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
const payWithCard = async (card) => {
const session = await createCheckoutSession();
await YunoSdk.startPaymentLite({
checkoutSession: session.id,
methodSelected: {
vaultedToken: card.vaultedToken,
paymentMethodType: 'CARD',
},
showPaymentStatus: true,
}, 'US');
};
```
## Subscription enrollment
```typescript theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
const enrollCard = async () => {
const customerSession = await createCustomerSession('cus_123');
await YunoSdk.enrollmentPayment({
customerSession: customerSession.id,
countryCode: 'US',
showPaymentStatus: true,
});
};
```
## Context API integration
```typescript theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
import React, { createContext, useContext, useState, useEffect } from 'react';
const PaymentContext = createContext(null);
export function PaymentProvider({ children }) {
const [isProcessing, setIsProcessing] = useState(false);
useEffect(() => {
const subscription = YunoSdk.onPaymentStatus((state) => {
setIsProcessing(false);
if (state.status === 'SUCCEEDED') { /* ... */ }
});
return () => subscription.remove();
}, []);
const processPayment = async () => {
setIsProcessing(true);
await YunoSdk.startPayment(true);
};
return (
{children}
);
}
```
# React Native Enrollment
Source: https://docs.y.uno/docs/sdks/additional-platforms/react-native/enrollment
Save customer payment methods for future use.
**Orientation: Choosing Your Integration Flow**, before you begin, please review the [Official Integration Flow](/docs/sdks/overview/understanding-flows).
* **Standard Flow ([Full Checkout](/docs/sdks/full-checkout/web-payments))**: Recommended for most merchants. Yuno handles the UI, security, and automatic updates for payment methods.
* **Custom Flow (This SDK)**: Use this only if you require full control over the UX. **Note**: You will be responsible for manually handling payment statuses, 3DS transitions, and fraud routing data collection.
Yuno allows you to save payment methods (enrollment) either during a payment flow or as a standalone step.
## Save during payment
To save a card during a regular payment flow, include the `vault_on_success` flag when creating the payment on your backend.
```typescript theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
// When creating payment on backend, include vault_on_success flag
async function createPayment(token: string, checkoutSession: string) {
await fetch('/api/payment/create', {
method: 'POST',
body: JSON.stringify({
one_time_token: token,
checkout_session: checkoutSession,
vault_on_success: true, // Save after successful payment
}),
});
}
```
## Separate enrollment
Use the enrollment flow to save a payment method without processing a payment.
```typescript theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
// 1. Create customer session on backend
const customerSession = await createCustomerSession('cus_123');
// 2. Set up listener
const enrollmentSubscription = YunoSdk.onEnrollmentStatus((state) => {
if (state.status === 'SUCCEEDED') {
console.log('Card saved successfully');
}
});
// 3. Start enrollment flow
await YunoSdk.enrollmentPayment({
customerSession: customerSession.id,
countryCode: 'US',
showPaymentStatus: true,
});
// 4. Clean up
enrollmentSubscription.remove();
```
## Listeners
Use `onEnrollmentStatus` to track the progress of the enrollment flow.
| Status | Description |
| ----------- | ------------------------------------------ |
| `SUCCEEDED` | The payment method was saved successfully. |
| `FAILED` | The enrollment failed. |
| `CANCELED` | The user closed the enrollment flow. |
# React Native Headless
Source: https://docs.y.uno/docs/sdks/additional-platforms/react-native/headless
Build a completely custom UI for your payments with the Headless integration.
**Orientation: Choosing Your Integration Flow**, before you begin, please review the [Official Integration Flow](/docs/sdks/overview/understanding-flows).
* **Standard Flow ([Full Checkout](/docs/sdks/full-checkout/web-payments))**: Recommended for most merchants. Yuno handles the UI, security, and automatic updates for payment methods.
* **Custom Flow (This SDK)**: Use this only if you require full control over the UX. **Note**: You will be responsible for manually handling payment statuses, 3DS transitions, and fraud routing data collection.
Build completely custom payment forms with full UI control when you need complete control over every UI element, highly custom checkout experiences, or have development resources for custom UI.
## Integration workflow
```typescript theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
import { YunoSdk } from '@yuno-payments/yuno-sdk-react-native';
const CustomPaymentForm = () => {
const [cardNumber, setCardNumber] = useState('');
const [expiry, setExpiry] = useState('');
const [cvv, setCvv] = useState('');
const processPayment = async () => {
try {
// 1. Use headless API to generate a one-time token
const result = await YunoSdk.generateToken({
checkoutSession: 'session_id',
paymentMethod: {
type: 'CARD',
card: {
number: cardNumber,
expirationMonth: parseInt(expiry.split('/')[0]),
expirationYear: parseInt(expiry.split('/')[1]),
securityCode: cvv,
holderName: 'John Doe',
type: 'CREDIT',
},
},
}, 'session_id', 'US');
// 2. Create payment with token on your backend
await createPayment(result.token);
// 3. Handle 3DS if needed - use getThreeDSecureChallenge
const challengeResult = await YunoSdk.getThreeDSecureChallenge('session_id', 'US');
if (challengeResult.type === 'URL') {
// Open 3DS URL in WebView, then continue payment
await YunoSdk.continuePayment('session_id', 'US', true);
}
} catch (error) {
console.error('Payment error:', error);
}
};
return (
);
};
```
## Handling 3DS
For headless integrations, you must manually trigger the 3DS challenge if the payment requires authentication.
1. After creating the payment on your backend, if the status is `WAITING_FOR_ACTION`, call `YunoSdk.getThreeDSecureChallenge`.
2. If a URL is returned, display it to the user.
3. Once the user completes the challenge, call `YunoSdk.continuePayment` to finalize the transaction.
# React Native SDK
Source: https://docs.y.uno/docs/sdks/additional-platforms/react-native/index
Integrate Yuno into your React Native application to accept payments and save payment methods.
**Orientation: Choosing Your Integration Flow**, before you begin, please review the [Official Integration Flow](/docs/sdks/overview/understanding-flows).
* **Standard Flow ([Full Checkout](/docs/sdks/full-checkout/web-payments))**: Recommended for most merchants. Yuno handles the UI, security, and automatic updates for payment methods.
* **Custom Flow (This SDK)**: Use this only if you require full control over the UX. **Note**: You will be responsible for manually handling payment statuses, 3DS transitions, and fraud routing data collection.
The Yuno React Native SDK provides a set of components and methods to integrate Yuno's payment features into your mobile app. It supports both iOS and Android.
## Install
```bash theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
npm install @yuno-payments/yuno-sdk-react-native
```
**iOS setup**:
```bash theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
cd ios && pod install
```
**Requirements**:
* react-native 0.70+
* Node.js 16+
* Android Min SDK 21
* iOS 14.0+
The SDK includes TypeScript definitions out of the box.
## Initialize
Initialize the SDK as early as possible in your application, typically in `App.tsx`.
```typescript theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
import { YunoSdk } from '@yuno-payments/yuno-sdk-react-native';
import { useEffect } from 'react';
export default function App() {
useEffect(() => {
YunoSdk.initialize({
apiKey: 'your-public-api-key',
countryCode: 'US', // Default country
});
}, []);
return ;
}
```
## Basic payment flow (Full Checkout)
The simplest integration uses the `YunoPaymentMethods` component to display available payment methods and `startPayment` to process the transaction.
```typescript theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
import { YunoSdk, YunoPaymentMethods } from '@yuno-payments/yuno-sdk-react-native';
export default function PaymentScreen() {
const [checkoutSession, setCheckoutSession] = useState(null);
const [isReady, setIsReady] = useState(false);
useEffect(() => {
// 1. Subscribe to payment events
const subscription = YunoSdk.onPaymentStatus((state) => {
if (state.status === 'SUCCEEDED') {
// Handle success
}
});
// 2. Fetch checkout session from your backend
createCheckoutSession().then(session => {
setCheckoutSession(session);
setIsReady(true);
});
return () => subscription.remove();
}, []);
const handlePayment = async () => {
// 3. Start payment flow
await YunoSdk.startPayment(true); // true = show payment status screen
};
return (
{checkoutSession && (
)}
);
}
```
## Integration options
Choose the integration level that best fits your needs:
Control the payment method selection UI while Yuno handles the payment process.
Build a completely custom UI and handle the payment flow manually.
Allow customers to save their payment methods for future use.
Customize the appearance of the SDK components to match your brand.
## Next steps
* Check out the [Code Examples](/docs/sdks/additional-platforms/react-native/code-examples) for common scenarios.
* Learn about [Advanced Features](/docs/sdks/additional-platforms/react-native/advanced-features) like deep linking and performance.
# React Native Lite
Source: https://docs.y.uno/docs/sdks/additional-platforms/react-native/lite
Use the Lite SDK for a semi-customized integration where you control the payment method selection UI.
**Orientation: Choosing Your Integration Flow**, before you begin, please review the [Official Integration Flow](/docs/sdks/overview/understanding-flows).
* **Standard Flow ([Full Checkout](/docs/sdks/full-checkout/web-payments))**: Recommended for most merchants. Yuno handles the UI, security, and automatic updates for payment methods.
* **Custom Flow (This SDK)**: Use this only if you require full control over the UX. **Note**: You will be responsible for manually handling payment statuses, 3DS transitions, and fraud routing data collection.
The Lite SDK allows you to build your own payment method selection screen while Yuno handles the actual payment process and security.
## Alternative mounting options
The basic flow uses automatic payment method display. For more control, use these alternatives:
### Custom payment method selection (`startPaymentLite`)
Select which payment method to display:
```typescript theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
// 1. Fetch available methods
const methods = await fetchPaymentMethods(sessionId);
// 2. Display in your UI
// 3. Start payment with selected method
await YunoSdk.startPaymentLite(
{
checkoutSession: session.checkoutSession,
methodSelected: {
paymentMethodType: selectedMethod, // 'CARD', 'PIX', etc.
vaultedToken: null, // or saved token
},
showPaymentStatus: true,
},
'US' // Optional country code override
);
```
### Simplified flow (`startPaymentSeamlessLite`)
Similar to Lite but with automatic payment creation:
```typescript theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
await YunoSdk.startPaymentSeamlessLite({
checkoutSession: session.checkoutSession,
methodSelected: {
paymentMethodType: 'CARD',
vaultedToken: null, // or saved token
},
showPaymentStatus: true,
countryCode: 'US',
});
```
## Vaulted token payments
Use saved payment methods for a faster checkout experience.
```typescript theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
await YunoSdk.startPaymentLite({
checkoutSession: session.checkoutSession,
methodSelected: {
paymentMethodType: 'CARD',
vaultedToken: 'vtok_saved_card_123',
},
showPaymentStatus: true,
});
```
## Parameters
| Parameter | Description |
| ---------------------------------- | --------------------------------------------------- |
| `checkoutSession` | Checkout session ID from your backend. |
| `methodSelected.paymentMethodType` | Payment method type (e.g. `CARD`, `PIX`). |
| `methodSelected.vaultedToken` | Saved payment method token, or `null` for new card. |
| `showPaymentStatus` | When `true`, SDK shows payment result UI. |
| `countryCode` | Optional ISO country code override (e.g. `US`). |
# React Native Styling
Source: https://docs.y.uno/docs/sdks/additional-platforms/react-native/styling
Customize the appearance of the Yuno SDK in your React Native app.
**Orientation: Choosing Your Integration Flow**, before you begin, please review the [Official Integration Flow](/docs/sdks/overview/understanding-flows).
* **Standard Flow ([Full Checkout](/docs/sdks/full-checkout/web-payments))**: Recommended for most merchants. Yuno handles the UI, security, and automatic updates for payment methods.
* **Custom Flow (This SDK)**: Use this only if you require full control over the UX. **Note**: You will be responsible for manually handling payment statuses, 3DS transitions, and fraud routing data collection.
You can customize the look and feel of the Yuno SDK components to match your app's brand.
## Configuration
Styling configuration is passed during the SDK initialization.
```typescript theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
import { YunoSdk } from '@yuno-payments/yuno-sdk-react-native';
YunoSdk.initialize({
apiKey: 'your-public-api-key',
countryCode: 'US',
yunoConfig: {
// Global configuration
language: 'en',
theme: {
// Customize colors, fonts, etc.
// Note: Specific theme options depend on the native SDK versions
}
},
});
```
## Platform-specific styling
Since the React Native SDK wraps native iOS and Android SDKs, some styling options might be platform-specific.
```typescript theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
import { Platform } from 'react-native';
YunoSdk.initialize({
apiKey: 'your-key',
countryCode: 'US',
...(Platform.OS === 'ios' && {
iosConfig: {
// iOS-specific settings
},
}),
...(Platform.OS === 'android' && {
androidConfig: {
// Android-specific settings
},
}),
});
```
For a full list of available styling tokens, refer to the [Android Customization](/docs/sdks/customization/android) and [iOS Customization](/docs/sdks/customization/ios) documentation.
# Android Enrollment
Source: https://docs.y.uno/docs/sdks/card-enrollment/android-enrollment
Enroll payment methods on Android using full-checkout with pre-built UI and ProGuard configuration
The Android SDK makes it easy to implement enrollment flows for saving payment methods to a customer account.
Include the library in your project by following the same steps as in [full-checkout](/docs/sdks/full-checkout/android-payments#include-the-library-in-your-project).
## Additional resources
* See [Choose the right integration for you](/docs/sdks/overview/choose-integration) if you're unsure which flow to follow.
* Access the [Release notes](/changelog/android) or the [Yuno Android SDK repository](https://github.com/yuno-payments/yuno-sdk-android) to verify the latest SDK version available.
* [full-checkout Enrollment (Android)](#full-checkout-enrollment-android): Automatic enrollment with pre-built UI components
## Requirements
* **Minimum SDK Version**: `minSdkVersion` 21 or above
* **Java**: Java 8 enabled
* **AndroidX**: Use AndroidX instead of older support libraries
* **Android Gradle Plugin**: 4.0.0 or above
* **ProGuard**: 6.2.2 or above
* **Kotlin Gradle Plugin**: 1.4.0 or above
* **ELF Page Size Support**: Compliant with Google's 16 KB ELF page alignment requirements (Android 15 / ARMv9 ready)
### ProGuard / R8 Configuration
If your project has `minifyEnabled = true`, add these rules to your `proguard-rules.pro` file to ensure the SDK works correctly, especially with **AGP 8.x+ R8 full mode**.
```proguard theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
# Preserve generic type signatures and annotations
-keepattributes Signature
-keepattributes *Annotation*
# Yuno SDK
-keep class com.yuno.** { *; }
-dontwarn com.yuno.**
# Gson — R8 full mode compatibility
-keep class com.google.gson.** { *; }
-keep,allowobfuscation,allowshrinking,allowoptimization class * extends com.google.gson.reflect.TypeToken
-dontwarn com.google.gson.**
# Retrofit — R8 full mode compatibility
-keep,allowobfuscation,allowshrinking interface retrofit2.Call
-keep,allowobfuscation,allowshrinking class retrofit2.Response
-keep,allowobfuscation,allowshrinking class kotlin.coroutines.Continuation
-dontwarn retrofit2.**
# OkHttp + Okio — Suppress warnings
-dontwarn okhttp3.**
-dontwarn okio.**
```
### Why are these rules necessary?
AGP 8.x+ enables **R8 full mode** by default, which aggressively strips generic type signatures. Without `-keepattributes Signature`, Gson’s `TypeToken` can fail at runtime with `java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType`.
## Parameters
For the full list of parameters, see the [Android SDK Common Reference](/docs/sdks/resources/references/android).
| Parameter | Description |
| ------------------------- | ------------------------------------------------------------------------------- |
| `customerSession` | Customer session ID from Create customer session API. Required. |
| `countryCode` | ISO country code. Required. |
| `showEnrollmentStatus` | Show enrollment result screen. Optional; default true. |
| `callbackEnrollmentState` | Callback: enrollment state. Optional; requires `initEnrollment` in onCreate. |
| `keepLoader` | If `true`, the SDK loader persists during enrollment, preventing UI flickering. |
| `requestCode` | Optional; use if capturing result via `onActivityResult`. |
| `countryCode` | Country for the enrollment. Required for `apiClientEnroll`. |
| `customerSession` | Customer session ID. Required for `apiClientEnroll`. |
## full-checkout Enrollment (Android)
Yuno full-checkout for Android provides enrollment with pre-built UI, card enrollment, status handling, and basic error management. See [Requirements](#requirements) above.
### Step 1: Create a customer
Create a customer in Yuno's system using the [Create customer endpoint](/reference/customers/create-customer) before enrolling payment methods. This endpoint returns a `customer_id`. Then create a customer session using the [Create Customer Session](/reference/customer-sessions-enrollment/create-customer-session) endpoint; use the returned `customer_session` when calling the enrollment methods.
### Step 2: Include the library in your project
Add the Yuno library to your Android project:
#### Add the Repository
Add Yuno's Maven repository to your project's Gradle configuration:
```kotlin theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
maven { url "https://yunopayments.jfrog.io/artifactory/snapshots-libs-release" }
```
Add the dependency in `build.gradle`:
```kotlin theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
dependencies {
implementation 'com.yuno.payments:android-sdk:2.11.0'
}
```
#### Permissions
The Yuno SDK includes the `INTERNET` permission by default, which is required to make network requests.
```xml theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
```
### Step 3: Initialize SDK with the public key
Initialize the SDK:
1. Get your Public API Key from the [Yuno Dashboard](https://dashboard.y.uno/)
2. Create a custom application class if you haven't already done so
3. In the `onCreate()` method of your application class, call `Yuno.initialize()` with your API key:
```kotlin theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
class CustomApplication : Application() {
override fun onCreate() {
super.onCreate()
Yuno.initialize(
this,
PUBLIC_API_KEY,
config = YunoConfig(
keepLoader = true,
),
)
}
}
```
Use the data class `YunoConfig` to customize the SDK's behavior. Include this configuration when calling `Yuno.initialize()`. The available options are:
```kotlin theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
data class YunoConfig(
val saveCardEnabled: Boolean = false,
val keepLoader: Boolean = false,
val language: YunoLanguage? = null,
val styles: YunoStyles? = null
)
```
For a detailed explanation of the `keepLoader` parameter and mandatory error handling, see the [Android Reference Guide](/docs/sdks/resources/references/android#keeploader-parameter).
**cardFlow removed from YunoConfig**
Starting from version **2.11.0**, `cardFlow` is no longer part of `YunoConfig`. Card flow configuration is now handled exclusively through the **CheckoutBuilder**.
### Step 4: Enroll a new payment method
The enrollment process is a two-step flow. First, initialize the process to set up the necessary components. Then, start the UI flow to allow the user to enroll a payment method.
#### 4.1 Initialize the enrollment process
Call the `initEnrollment` method within your activity's `onCreate` method to prepare your app to handle the enrollment flow. This is a mandatory setup step required by the Android operating system to register the contract that allows the SDK to send the final enrollment status back to your app.
```kotlin theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
fun ComponentActivity.initEnrollment(
callbackEnrollmentState: ((String?) -> Unit)? = null
)
```
#### 4.2 Start the enrollment flow
Call the `startEnrollment` method to launch the user interface and begin the enrollment of a new payment method. You can call this method at any point after `initEnrollment` has been executed, such as when a user taps an "Enroll New Payment Method" button.
```kotlin theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
fun Activity.startEnrollment(
customerSession: String,
countryCode: String,
showEnrollmentStatus: Boolean = true,
callbackEnrollmentState: ((String?) -> Unit)? = null,
requestCode: Int
)
```
`startEnrollment` parameters:
| Parameter | Description |
| ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `customerSession` | The session customer associated with the current enrollment process. |
| `countryCode` | Country code where the payment is performed. See [Country coverage](/docs/sdks/resources/country-coverage) for a complete list of supported countries and their codes. |
| `showEnrollmentStatus` | Indicates whether the enrollment status should be shown. This parameter is optional and defaults to `true`. |
| `callbackEnrollmentState` | A function that returns the current state of the enrollment process. This parameter is optional and defaults to `null`. To register this callback, you must call `initEnrollment` method in the `onCreate` method of the activity. Check the possible states that can be returned. |
| `requestCode` | It is an optional parameter you must inform if you are going to use the `onActivityResult` method to capture the enrollment states. |
## Common reference
For full parameter and customization details, see the [Android SDK Common Reference](/docs/sdks/resources/references/android).
# iOS Enrollment
Source: https://docs.y.uno/docs/sdks/card-enrollment/ios-enrollment
Enroll payment methods on iOS using full-checkout with the enrollment delegate and result handling
The iOS SDK makes it easy to implement enrollment flows for saving payment methods to a customer account.
Include the library in your project by following the same steps as in [full-checkout](/docs/sdks/full-checkout/ios-payments#include-the-library-in-your-project).
## Additional resources
* See [Choose the right integration for you](/docs/sdks/overview/choose-integration) if you're unsure which flow to follow.
* Access the [Release notes](/changelog/ios) or the [Yuno iOS SDK repository](https://github.com/yuno-payments/yuno-sdk-ios) to verify the latest SDK version available.
* [full-checkout Enrollment (iOS)](#full-checkout-enrollment-ios): Automatic enrollment with pre-built UI components
## Requirements
* CocoaPods or [Swift Package Manager](https://www.swift.org/package-manager/)
* iOS 14.0 or later
* Active Yuno account; API credentials (obtain from the [Yuno Dashboard](https://dashboard.y.uno/) → **Developers** > **Credentials**)
* Create a customer using the [Create customer endpoint](/reference/customers/create-customer) before enrolling
## Parameters
For the full list of parameters, see the [iOS SDK Common Reference](/docs/sdks/resources/references/ios).
| Parameter | Description |
| -------------------------- | -------------------------------------------------------------------------- |
| `customerSession` | Customer session ID from Create customer session API. Required. |
| `countryCode` | ISO country code (e.g. `BR`). Required. |
| `language` | Language code for the UI. Optional. |
| `viewController` | UIViewController that presents the enrollment flow. Required for delegate. |
| `yunoEnrollmentResult(_:)` | Delegate: enrollment finished with result. |
| `YunoConfig` (initialize) | Optional: `appearance`, `saveCardEnabled`. See Common Reference. |
## full-checkout Enrollment (iOS)
The Yuno full-checkout iOS SDK provides enrollment with pre-built UI, card enrollment, status handling, and basic error management. See [Requirements](#requirements) above.
### Step 1: Create a customer and customer session
Create a customer in Yuno's system using the [Create customer endpoint](/reference/customers/create-customer) before enrolling payment methods. This endpoint will return a `customer_id` that you'll use to associate enrolled payment methods with the specific customer.
Then create a customer session using the [Create Customer Session](/reference/customer-sessions-enrollment/create-customer-session) endpoint. The session information will be used when calling the enrollment methods.
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
POST /v1/customer-session
{
"country": "BR",
"customer_id": "6c85a4e3-0a6c-423d-a12a-10045320ab4a"
}
```
The response includes a `customer_session` ID that you'll use in the next step.
### Step 2: Include the library in your project
Including the library in your project is done in the same way as in payment flows. Follow the steps in [Include the library in your project](/docs/sdks/full-checkout/ios-payments#include-the-library-in-your-project) there.
#### CocoaPods
```ruby theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
pod 'YunoSDK', '~> 2.11.1'
```
Run:
```ruby theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
pod install
```
#### Swift Package Manager
```swift theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
dependencies: [
.package(url: "https://github.com/yuno-payments/yuno-sdk-ios.git", .upToNextMajor(from: "2.11.1"))
]
```
Check the [Release notes](/changelog/ios) or [Yuno iOS SDK repository](https://github.com/yuno-payments/yuno-sdk-ios) for the current SDK version.
### Step 3: Initialize SDK with the public key
Initialize the SDK:
1. Get your Public API Key from the [Yuno Dashboard](https://dashboard.y.uno/)
2. Initialize the SDK by calling `Yuno.initialize()` with your API key:
```swift theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
import YunoSDK
Yuno.initialize(
apiKey: "PUBLIC_API_KEY",
config: YunoConfig(),
callback: { (value: Bool) in }
)
```
Use the `YunoConfig` data class to customize the SDK's behavior. Include this configuration when calling `Yuno.initialize()`. For example:
```swift theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
struct YunoConfig {
var appearance: Appearance? = nil
var saveCardEnabled: Bool = false
}
```
### Step 4: Implement the enrollment delegate
Create a class that adopts the `YunoEnrollmentDelegate` protocol:
**Swift 6 Concurrency Requirements**
If you're using Swift 6, you'll need to implement the `YunoEnrollmentDelegate` protocol with specific concurrency considerations. See the [Swift 6 Concurrency](/docs/sdks/resources/swift-6-concurrency) guide for detailed implementation options and best practices.
```swift theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
protocol YunoEnrollmentDelegate: AnyObject {
var customerSession: String { get }
var countryCode: String { get }
var language: String? { get }
var viewController: UIViewController? { get }
func yunoEnrollmentResult(_ result: Yuno.Result)
}
class ViewController: UIViewController, YunoEnrollmentDelegate {
var customerSession: String { "cus_ses_123456" }
var countryCode: String { "BR" }
var language: String? { "en" }
var viewController: UIViewController? { self }
func yunoEnrollmentResult(_ result: Yuno.Result) {
switch result {
case .succeeded:
print("Enrollment successful")
case .fail:
print("Enrollment failed")
case .processing:
print("Enrollment processing")
case .reject:
print("Enrollment rejected")
case .userCancelled:
print("User canceled")
case .internalError:
print("Internal error")
}
}
}
```
#### Options
| Parameter | Description |
| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| `customerSession` | The unique identifier for the customer session. |
| `countryCode` | Country code where the enrollment is performed. See [Country Coverage](/docs/sdks/resources/country-coverage) for supported countries. |
| `language` | Language code for the enrollment forms (e.g., `"en"`, `"es"`, `"pt"`). See [Supported languages](/docs/sdks/resources/languages-supported). |
| `viewController` | The `UIViewController` used to present the enrollment flow. Required for proper UI presentation. |
| `yunoEnrollmentResult(_:)` | Called when the enrollment process completes with the final result. |
### Step 5: Start the enrollment process
Call the `enrollPayment()` method to display the enrollment flow:
```swift theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
func startEnrollment() {
Yuno.enrollPayment(with: self, showPaymentStatus: true)
}
```
The SDK presents a full-screen `UIViewController` modally using the `viewController` provided in your delegate. In SwiftUI, wrap a `UIViewController` and return it via the `viewController` property.
#### Options
| Parameter | Type | Description |
| ------------------- | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `delegate` | `YunoEnrollmentDelegate` | The delegate object that handles enrollment callbacks. |
| `showPaymentStatus` | `Bool` | Whether to display status views during the enrollment process. When `true`, the SDK displays default status screens. When `false`, you handle status display through callbacks. |
In SwiftUI, wrap a `UIViewController` and return it from the `viewController` property so the SDK can present the UI.
### Step 6: Handle deep link return (Optional)
Only needed when the enrollment flow uses deep links. If your payment method does not use deep links, skip this step. Otherwise, handle the return in your `AppDelegate`:
```swift theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
func application(_ app: UIApplication,
open url: URL,
options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool {
guard url.scheme == "yunoexample" else { return false }
return Yuno.receiveDeeplink(url, showStatusView: true)
}
```
Make sure the `url.scheme` matches the `callback_url` used when creating the `customer_session`.
### Step 7: Handle enrollment result
The SDK calls your `yunoEnrollmentResult(_:)` delegate method with the final status:
```swift theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
func yunoEnrollmentResult(_ result: Yuno.Result) {
switch result {
case .succeeded:
print("Enrollment successful")
// Navigate to success screen or update UI
case .fail:
print("Enrollment failed")
// Show error message
case .processing:
print("Enrollment still processing")
// Show processing message
case .reject:
print("Enrollment rejected")
// Show rejection message
case .userCancelled:
print("User canceled")
// Handle cancellation
case .internalError:
print("Internal error occurred")
// Show error message
}
}
```
#### Enrollment Result States
| State | Description | Action Required |
| --------------- | --------------------------------------------------------- | ------------------------------------- |
| `succeeded` | Enrollment completed successfully | No |
| `fail` | Enrollment failed due to validation or technical issues | Yes - Investigate and retry |
| `processing` | Enrollment in progress, awaiting approval | No |
| `reject` | Enrollment rejected (invalid data, fraud detection, etc.) | Yes - Inform user and suggest actions |
| `internalError` | Unexpected internal error occurred | Yes - Technical intervention required |
| `userCancelled` | User canceled the enrollment | No |
`Yuno.Result` does not include tokens or error messages; it only returns a high-level status.
### Complementary features
For styling, themes, form options, and additional configurations, see [SDK customizations](/docs/sdks/customization/ios).
## Common reference
For full parameter and customization details, see the [iOS SDK Common Reference](/docs/sdks/resources/references/ios).
# Web Enrollment
Source: https://docs.y.uno/docs/sdks/card-enrollment/web-enrollment
Enroll payment methods on Web using full-checkout, mounting the enrollment form and handling callbacks
The Web SDK makes it easy to implement enrollment flows for saving payment methods to a customer account.
Include the library in your project by following the same steps as in [payment flows](/docs/sdks/full-checkout/web-payments#include-the-library-in-your-project). This lets you complete [step 1](#step-1-include-the-library-in-your-project) and continue with the enrollment flow below.
## Additional resources
* Yuno offers a [TypeScript library](https://www.npmjs.com/package/@yuno-payments/sdk-web-types) that complements the SDK.
* See [Choose the right integration for you](/docs/sdks/overview/choose-integration) if you're unsure which flow to follow.
* See the [Demo App](https://github.com/yuno-payments/yuno-sdk-web) for a complete implementation (clone from the repository).
## Requirements
* A [customer](/reference/customers/create-customer) created in Yuno, a [customer session](/reference/customer-sessions-enrollment/create-customer-session), and an [enrollment payment method object](/reference/payment-methods-checkout/enroll-payment-method-checkout): reference each API when setting up your backend.
* Public API key (obtain from the [Yuno Dashboard](https://dashboard.y.uno/) → **Developers** > **Credentials**)
## Parameters
For the full list of parameters and callbacks, see the [Web SDK Common Reference](/docs/sdks/resources/references/web).
| Parameter | Description |
| ---------------------- | ------------------------------------------------------------------------------ |
| `customerSession` | Customer session ID from your backend (Create customer session API). Required. |
| `countryCode` | ISO country code (e.g. `US`). |
| `language` | Language code for the UI (e.g. `en`). Optional. |
| `showLoading` | Show loading spinner. Optional. |
| `onLoading` | Callback: loading state updates. Optional. |
| `elementSelector` | CSS selector where the enrollment form mounts. Optional. |
| `card` | Card form options. Optional. |
| `yunoEnrollmentStatus` | Callback: enrollment ended; receives `vaultedToken` and `status`. |
| `issuersFormEnable` | Show issuer (bank) list. Optional. |
| `texts` | Custom button/label text. Optional. |
## full-checkout Enrollment (Web)
Use full-checkout for a seamless integration with pre-built UI. Implement enrollment as follows.
### Step 1: Include the library in your project
Including the library in your project is done in the same way as in [payment flows](/docs/sdks/full-checkout/web-payments#include-the-library-in-your-project).
### Step 2: Initialize the SDK
See [Quickstart guide](/docs/sdks/overview/quickstart#web-sdk-integration) for initialization.
### Step 3: Create a customer session and an enrollment payment method object
Create a [customer session](/reference/customer-sessions-enrollment/create-customer-session) and an [enrollment payment method object](/reference/payment-methods-checkout/enroll-payment-method-checkout) on your **server-side** to keep private API keys secure; define which payment method the customer can enroll when creating the payment method object.
#### Server-side example
Create a customer session and enrollment payment method on your backend. This keeps your private API keys secure.
```javascript theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
// 1. Create customer session
const customerSession = await fetch(
"https://api-sandbox.y.uno/v1/customers/sessions",
{
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${PRIVATE_SECRET_KEY}`,
},
body: JSON.stringify({
customer_id: "your-customer-id",
country: "US",
}),
}
).then((res) => res.json());
// 2. Create enrollment payment method
const enrollment = await fetch(
`https://api-sandbox.y.uno/v1/customers/sessions/${customerSession.id}/payment-methods`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${PRIVATE_SECRET_KEY}`,
},
body: JSON.stringify({
type: "CARD",
}),
}
).then((res) => res.json());
// Return customerSession to your client
return customerSession;
```
#### Client-side example
After receiving the `customerSession` from your server, initialize the Yuno SDK and mount the enrollment form on the client-side.
```javascript theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
// Initialize Yuno SDK
const yuno = await Yuno.initialize(PUBLIC_API_KEY);
// Mount the enrollment form
await yuno.mountEnrollment({
customerSession, // Received from your server
countryCode: "US",
language: "en",
showLoading: true,
onLoading: (args) => {
console.log(args);
},
});
```
To verify cards (zero-value authorization) before enrollment, add the `verify` struct when defining the payment method object on the server.
### Step 4: Mount the enrollment
Use `await yuno.mountEnrollment()` with the parameters below.
| Parameter | Description |
| --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `customerSession` | Refers to the current enrollment's [customer session](/reference/customer-sessions-enrollment/create-customer-session). Example: `e15648b0-fcd5-4799-a14c-cc463ae8a133`. |
| `countryCode` | Country for the payment process. Use an `ENUM` value; see [Country Coverage](/docs/sdks/resources/country-coverage). |
| `language` | Language for payment forms. Use any code listed in [Supported languages](/docs/sdks/resources/languages-supported). Example: `en-US`. Defaults to browser language when available. |
| `showLoading` | Controls visibility of the Yuno loading/spinner page during the payment process. |
| `onLoading` | Required to receive notifications about server calls or loading events. |
| `elementSelector` | HTML element where the Yuno SDK is mounted. |
| `card` | Define specific settings for the credit card form. |
| `yunoEnrollmentStatus` | Callback after enrollment ends; receives `vaultedToken` and `status`. Status options: `CREATED`, `EXPIRED`, `REJECTED`, `READY_TO_ENROLL`, `ENROLL_IN_PROCESS`, `UNENROLL_IN_PROCESS`, `ENROLLED`, `DECLINED`, `CANCELED`, `ERROR`, `UNENROLLED`. |
| `issuersFormEnable` | Enable the issuer's form (bank list). |
| `texts` | Custom text for payment form buttons to match your application's language or branding. |
| `card.isCreditCardProcessingOnly` | Optional. Forces card transactions to process as credit only—useful where cards act as both credit and debit. |
The next code block presents an example of the Enrollment parameter configuration and mounting.
```javascript theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
await yuno.mountEnrollment({
customerSession: 'e15648b0-fcd5-4799-a14c-cc463ae8a133',
/**
* The complete list of country codes is available on /docs/sdks/resources/country-coverage
*/
countryCode: country,
/**
- Language for payment forms (see Supported languages)
- Defaults to browser language when available
*/
language: 'en-US',
/**
* Hide or show the Yuno loading/spinner page
* Default is true
* @optional
*/
showLoading: true,
/**
* Required if you'd like to be informed if there is a server call
* @param { isLoading: boolean, type: 'DOCUMENT' | 'ONE_TIME_TOKEN' } data
* @optional
*/
onLoading: (args) => {
console.log(args);
}
/**
* API card
* @optional
*/
card: {
/**
* Mode render card can be step or extends
* Default extends
*/
type: "extends",
/**
* Write custom CSS to style the card form. Your CSS will be injected into the iframe.
* Example:
* `@import url('https://fonts.googleapis.com/css2?family=Luckiest+Guy&display=swap');
* .Yuno-front-side-card__name-label {
* color: red !important;
* font-family: 'Luckiest Guy' !important;
* }`
*/
styles: '',
/**
* Show checkbox for save/enroll card
* Default is false
*/
cardSaveEnable: false,
/**
* Custom texts in Card forms buttons
* Example:
*
* texts: {
* cardForm?: {
* enrollmentSubmitButton?: string;
* paymentSubmitButton?: string;
* }
* cardStepper?: {
* numberCardStep?: {
* nextButton?: string;
* },
* cardHolderNameStep?: {
* prevButton?: string;
* nextButton?: string;
* },
* expirationDateStep?: {
* prevButton?: string;
* nextButton?: string;
* },
* cvvStep?: {
* prevButton?: string;
* nextButton?: string;
* }
* }
* }
*/
texts: {},
/**
* Hide or show the document fields into card form
* Default is true
* @optional
*/
documentEnable: true,
},
/**
* Call back is called with the following object
* @param {{
* status: 'CREATED'
* | 'EXPIRED',
* | 'REJECTED',
* | 'READY_TO_ENROLL',
* | 'ENROLL_IN_PROCESS',
* | 'UNENROLL_IN_PROCESS',
* | 'ENROLLED',
* | 'DECLINED',
* | 'CANCELED',
* | 'ERROR',
* | 'UNENROLLED',
* vaultedToken: string,
* }}
*/
yunoEnrollmentStatus: ({ status, vaultedToken}) => {
console.log('status', { status, vaultedToken})
},
/**
* If this is called the SDK should be mounted again
* @param { error: 'CANCELED_BY_USER' | any }
* @optional
*/
yunoError: (error) => {
console.log('There was an error', error)
},
});
```
## Common reference
For full parameter and customization details, see the [Web SDK Common Reference](/docs/sdks/resources/references/web).
# Android Styling
Source: https://docs.y.uno/docs/sdks/customization/android
Customize Android SDK fonts, buttons, colors, and text styles to match your brand
Modify Yuno Android SDK styles (colors, text, buttons) to align payment forms and checkout with your brand. Element structure stays uniform. For all Android SDK parameters and config options, see [Android SDK Common Reference](/docs/sdks/resources/references/android).
## General guidelines
Yuno Android SDK supports XML themes and styles, which should be defined within your application's styles. Android customizations are a work in progress and are continuously updated.
## Customizable elements
Elements you can modify for a personalized style. Some customizations require version 1.13.0 or higher.
* [Font styles](#font-styles)
* [Button styles](#button-styles)
* [Color styles](#color-styles)
* [Text styles](#text-styles)
### Font styles
You can override Yuno Android SDK fonts if you want to use your font family. You can override the following font styles:
* `YunoRegularFont`
* `YunoMediumFont`
* `YunoBoldFont`
Example (font style):
```xml theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
```
### Button styles
Override button styles; available options depend on SDK version. Buttons you can customize:
| Versions before v1.10.0 | Version v1.10.0 and higher | Version v1.13.0 and higher |
| -------------------------- | ---------------------------------- | ---------------------------------- |
| `Button.Normal.White` | `Button.Small.NeutralB` | `Button.Normal` |
| `Button.Normal.Green` | `Button.Normal.NeutralB` | `Button.Small` |
| `Button.Normal.Purple` | `Button.Normal.Green` | `Button.Normal.NeutralW` |
| `Button.Normal.Purple.Big` | `Button.Normal.NeutralW.TextGrey4` | `Button.Normal.NeutralW.TextGrey4` |
| | `Button.Normal.NeutralW` | `Button.Normal.Green` |
| | `Button.Small` | `Button.Normal.NeutralB` |
| | `Button.Normal` | `Button.Small.NeutralB` |
For each style, you can set the following attributes:
```kotlin theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
```
Example (`Button.Normal.NeutralB` and button font):
```kotlin theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
```
### Color styles
Override color styles to personalize the SDK; options depend on SDK version. Color styles by version:
| Versions before v1.10.0 | Version v1.10.0 and higher | Version v1.13.0 and higher |
| ----------------------- | -------------------------- | ----------------------------- |
| `yuno_purple_light` | `neutral_b` | `on_focus_outlined_text_view` |
| | `neutral_b_60_alpha` | `primary_4` |
| | `neutral_w` | `primary_5` |
| | `neutral_w_30_alpha` | `secondary_1` |
| | `grey_0` | `secondary_2` |
| | `grey_1` | `secondary_3` |
| | `grey_2` | `secondary_4` |
| | `grey_3` | `secondary_5` |
| | `grey_4` | `secondary_6` |
| | `grey_5` | `tertiary_1` |
| | `primary_1` | `tertiary_2` |
| | `primary_2` | `tertiary_3` |
| | `primary_3` | `tertiary_4` |
Example (colors, SDK v1.13.0+):
```xml theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
#fff000#282A30
```
### Text styles
You can override Yuno Android SDK text styles to personalize the SDK's appearance.
> This feature is only available for SDK version 1.13.0 or higher.
Customization attributes per text style:
| Text Style | Parent Style | Customizable Attributes |
| -------------------- | ----------------- | ----------------------- |
| `YunoRegularFont` | | `android:fontFamily` |
| `TextMicro` | `YunoRegularFont` | `android:textSize` |
| `TextSmall` | `YunoRegularFont` | `android:textSize` |
| `TextBody` | `YunoRegularFont` | `android:textSize` |
| `TextSubTitle` | `YunoRegularFont` | `android:textSize` |
| `TextH4` | `YunoRegularFont` | `android:textSize` |
| `TextH3` | `YunoRegularFont` | `android:textSize` |
| `TextH2` | `YunoRegularFont` | `android:textSize` |
| `TextH1` | `YunoRegularFont` | `android:textSize` |
| `TextH1Super` | `YunoRegularFont` | `android:textSize` |
| `TextMicro.NeutralB` | `TextMicro` | `android:textColor` |
| `TextMicro.NeutralB` | `TextMicro` | `android:textColorHint` |
| `TextSmall.NeutralB` | `TextSmall` | `android:textColor` |
| `TextSmall.NeutralB` | `TextSmall` | `android:textColorHint` |
Example (text customizations):
```kotlin theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
```
## Create your own card form flow
The first step to creating your card form flow is to create a new layout resource file called `screen_payment_card_form.xml` to override the current XML and implement your design.
After creating the `screen_payment_card_form.xml` file, you can define your own design. You need to use the Yuno secure-fields components, which ensures that the Yuno SDK can retrieve credit card information during the checkout. Below, you will find a list of all the components you can use to change the design:
**Changing Components**
When changing the Yuno Android SDK components, you must use them with their defined Android `id`.
### v1.10.0 or higher
Additional components are available for the Yuno SDK version v1.10.0 or higher. These components are listed in the [subsection below](#components-available-for-v1100-and-higher).
* `CloseButton`: Button to close the form.
```xml theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
```
* `CardNumberEditText`: Field where the user can enter the credit card number.
```xml theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
```
* `CardDataStackView`: Field where the user can enter the credit card's expiration date and verification code (CVV/CVC).
```xml theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
```
* `TextView` for Voucher card type: This is a copy Yuno SDK shows when the card is `VOUCHER `type, you must set it below the CVV field.
```xml theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
```
* `TextFieldItemView `for card holder's name: Field where the user can enter the credit card holder's name.
```xml theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
```
* `SpinnerFieldItemView` for identification document type: A selector where the credit card holder can choose their identification document type.
```xml theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
```
* `TextFieldItemView` for identification document number: Field where the user can enter the credit card holder's identification document number.
```xml theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
```
* `PhoneInformationView `for customer's phone number: Field where the user can enter his phone number if required. In addition to providing the Android `id`, it's required to have `gone` visibility.
```xml theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
```
* `Installments`: Component that shows the spinner of card installments. In addition to providing the Android `id`, it's required to have `gone` visibility, and you need to add the `ShimmerFrameLayout` dependency: `implementation 'com.facebook.shimmer:shimmer:0.5.0'`.
```xml theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
```
* Yuno's `TextView`: A text to show that Yuno verified the form.
```xml theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
```
* `CustomYunoSwitch`: It's a switch component that lets the user choose if the card will be used as credit or debit. In addition to providing the Android `id`, it's required to have `gone` visibility.
```xml theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
```
* `CustomYunoSwitch`: A tooltip to show how the switch works. In addition to providing the Android `id`, it's required to have `gone` visibility. Yuno recommends positioning this component next to the switch.
```xml theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
```
* `AppCompatCheckBox`: A check box users can use to choose whether to save the credit card for future purchases.
```xml theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
```
* `Button`: It validates the card form and continues the payment process. When the user clicks this button, the SDK submits the form and sends the credit card information to Yuno.
```xml theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
```
### Components available for v1.10.0 and higher
Available only for SDK v1.10.0 or higher.
* `TextFieldItemView` for customer's address: It is used to input the customer's address when required. Ensure it is utilized with its specified Android `id` (`@+id/textField_address`) and is set to have `gone` visibility by default.
```xml theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
```
* `TextFieldItemView` for customer's state: It allows the customer to enter their state if needed. It must be used with the defined Android `id` (`@+id/textField_state`) and should have `gone` as the default visibility.
```xml theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
```
* `TextFieldItemView` for customer's city: It is designated for the input of the customer's city. It should be used with the provided Android `id` (`@+id/textField_city`) and maintain a default visibility setting of `gone`.
```xml theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
```
* `TextFieldItemView` for customer's zip code: This is where the customer can input their zip code. Ensure it is implemented using the specified Android `id` (`@+id/textField_zip_cod`) and has `gone` visibility by default:
```xml theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
```
* `SpinnerFieldItemView` for customer's country: This SpinnerFieldItemView selects the customer's country when necessary. It must be utilized with the defined Android `id` (`@+id/spinner_country`) and should have a default visibility of `gone`.
```xml theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
```
* `SpinnerFieldItemView` for customer's gender: It is used to select the customer's gender if required. Ensure it is used with its defined Android `id` (`@+id/spinner_gender`) and is set to `gone` visibility by default.
```xml theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
```
## Address autocomplete
Merchants can enable or disable address autocomplete functionality in the Android SDK. When enabled, the SDK automatically fills address fields based on postal code lookup. When disabled, users must manually enter all address information.
# iOS Styling
Source: https://docs.y.uno/docs/sdks/customization/ios
Customize iOS SDK appearance, including fonts, colors, and button styles, to match your brand
Modify Yuno iOS SDK styles (font, button, color) by setting appearance fields. Use these to match your app brand and improve consistency. For all iOS SDK parameters and config options, see [iOS SDK Common Reference](/docs/sdks/resources/references/ios).
## Appearance configuration
Available customization fields:
| Field | Description |
| -------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| `fontFamily` | Specifies the font family used in the SDK. Provide the font file name used in your app, ensuring it matches your application's assets. |
| `accentColor` | Defines the accent color used in several SDK elements. |
| `buttonBackgroundColor` | Sets the background color for the primary buttons. |
| `buttonTitleColor` | Determines the text color for the primary buttons. |
| `buttonBorderColor` | Specifies the border color for the primary buttons. |
| `secondaryButtonBackgroundColor` | Sets the background color for the secondary buttons. |
| `secondaryButtonTitleColor` | Determines the text color for the secondary buttons. |
| `secondaryButtonBorderColor` | Specifies the border color for the secondary buttons. |
| `disableButtonBackgroundColor` | Sets the background color for the disabled-buttons. |
| `disableButtonTitleColor` | Determines the text color for the disabled-buttons. |
**Color Configuration**
Ensure all colors are specified as UIColor to maintain compatibility. Colors can be sourced from Xcode's predefined palette or the merchant's assets, but they must always be of type UIColor.
Use the `Yuno.Appearance()` function to define a variable with all your customizations to control the appearance. Then inform it when initializing the SDK:
```swift theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
let appearance = Yuno.Appearance(
fontFamily: "Climate Crisis",
accentColor: UIColor.orange,
buttonBackgroundColor: UIColor.yellow,
buttonTitleColor: UIColor.black,
buttonBorderColor: UIColor.black,
secondaryButtonBackgroundColor: UIColor.yellow,
secondaryButtonTitleColor: UIColor.black,
secondaryButtonBorderColor: UIColor.black,
disableButtonBackgroundColor: UIColor.gray,
disableButtonTitleColor: UIColor.black
)
Yuno.initialize(
apiKey: apiKey,
config: YunoConfig(appearance: appearance)
)
```
### Usage examples
Example (two appearance customizations):
```swift Example 1 (left) theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
let appearance = Yuno.Appearance(
fontFamily: "Climate Crisis",
accentColor: UIColor.black,
buttonBackgroundColor: UIColor.black,
buttonTitleColor: UIColor.white
)
Yuno.initialize(
apiKey: apiKey,
config: YunoConfig(appearance: appearance)
)
```
```swift Example 2 (right) theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
let appearance = Yuno.Appearance(
fontFamily: "Climate Crisis",
accentColor: UIColor.orange,
buttonBackgroundColor: UIColor.orange,
buttonTitleColor: UIColor.white
)
Yuno.initialize(
apiKey: apiKey,
config: YunoConfig(appearance: appearance)
)
```
## Address autocomplete
Merchants can enable or disable address autocomplete functionality in the iOS SDK. When enabled, the SDK automatically fills address fields based on postal code lookup. When disabled, users must manually enter all address information.
# Payment Link White Label
Source: https://docs.y.uno/docs/sdks/customization/web/payment-link-white-label
Serve Yuno's hosted Payment Link checkout under your own domain, with no Yuno branding and all traffic routed through your infrastructure.
By default, a Yuno [Payment Link](/docs/using-yuno/dashboard-overview/payment-links) redirects the customer to Yuno's hosted checkout on a Yuno domain:
```
https://checkout.sandbox.y.uno/payment?session={session_id}
```
There, the checkout SDK loads from a `*.y.uno` origin and calls Yuno services directly. White-labeling lets you serve that same hosted checkout **under your own domain** (e.g. `pay.yourbrand.com`) with the Yuno branding removed and every subsequent request — SDK bundle, assets, API, WebSocket, 3DS — routed through your infrastructure.
This is the hosted-checkout counterpart to the SDK-level [White Label](/docs/sdks/customization/web/white-label) page. It reuses the same `apiUrl` / `assetUrl` overrides, applied to the Payment Link redirect instead of a direct `
```
## Verifying a white-label setup
After loading the SDK from a non-Yuno origin, none of the following should appear in the merchant page:
* Elements with `class="yuno-*"` or `id="yuno-*"`.
* A resolved font family of `Yuno-Inter`.
* Network requests to `*.y.uno` hosts — including the static CDNs `icons.prod.y.uno` and `sdk.prod.y.uno` for icons, brand logos, and flags. These are host-swapped onto your origin only on recent SDK builds; older builds still fetch them straight from the CDN.
And these should be present:
* `window.SdkPayments` resolves to the SDK instance factory.
* `'sdk-payments-ready'` fires once on bundle load.
* DOM nodes use `class="sdk-payments-*"` / `id="sdk-payments-*"`.
## Local test harness
A throwaway proxy server lives in the [`yuno-payments/yuno-sdk-web`](https://github.com/yuno-payments/yuno-sdk-web/tree/main/white-label-proxy-server) repo under `white-label-proxy-server/`. It listens on `http://localhost:9090`, serves a landing page from a non-Yuno origin, and transparently proxies SDK asset / API / WebSocket traffic upstream — point a partner test page's `
```
### 2. Initialize and process payment
```javascript theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
import { Yuno } from '@yuno-payments/sdk-web';
// Initialize SDK
const yuno = await Yuno.initialize('your-public-api-key');
// Create checkout session on your backend
// Your backend calls: POST https://api-sandbox.y.uno/v1/checkout/sessions
const session = await fetch('/api/create-session', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
customer_id: 'customer-123',
amount: { currency: 'USD', value: 1000 },
country: 'US'
})
}).then(r => r.json());
// Configure checkout
await yuno.startCheckout({
checkoutSession: session.checkout_session,
elementSelector: '#payment-form',
countryCode: 'US',
async yunoCreatePayment(oneTimeToken) {
// Your backend calls: POST https://api-sandbox.y.uno/v1/payments
// with { payment_method: { token: oneTimeToken }, checkout_session: ... }
const payment = await fetch('/api/process-payment', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
one_time_token: oneTimeToken,
checkout_session: session.checkout_session
})
}).then(r => r.json());
// Required for async payment methods (3DS, PIX, etc.)
await yuno.continuePayment();
}
});
// Mount payment form
await yuno.mountCheckout();
```
### 3. Add HTML container and trigger payment
```html theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
```
**Test with**: Card `4111 1111 1111 1111`, any future date, any CVV
For a comprehensive overview of all Web SDK parameters, see [Web SDK Common Reference](/docs/sdks/resources/references/web).
[Complete Web guide →](/docs/sdks/full-checkout/web-payments)
### 1. Install
**CocoaPods**:
```ruby theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
pod 'YunoSDK', '~> 2.11.1'
```
**Swift Package Manager**:
```swift theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
dependencies: [
.package(url: "https://github.com/yuno-payments/yuno-sdk-ios", from: "2.11.1")
]
```
### 2. Initialize and implement delegate
```swift theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
import YunoSDK
// Initialize in AppDelegate or App struct
Yuno.initialize(
apiKey: "your-public-api-key",
config: YunoConfig()
)
// In your view controller - implement YunoPaymentDelegate
class PaymentViewController: UIViewController, YunoPaymentDelegate {
// Required delegate properties
var checkoutSession: String { "session-from-backend" }
var countryCode: String { "US" }
var language: String? { "en" }
var viewController: UIViewController? { self }
override func viewDidLoad() {
super.viewDidLoad()
displayPaymentMethods()
}
func displayPaymentMethods() async {
// Get payment methods view
let paymentView = await Yuno.getPaymentMethodViewAsync(delegate: self)
view.addSubview(paymentView)
// Add constraints...
}
// Required: Create payment with one-time token
func yunoCreatePayment(with token: String) {
// Call your backend: POST /v1/payments
createPaymentOnBackend(token: token) { result in
// After payment creation, continue for async methods
Yuno.continuePayment()
}
}
// Required: Handle payment result
func yunoPaymentResult(_ result: Yuno.Result) {
switch result {
case .succeeded:
print("Payment succeeded!")
case .fail:
print("Payment failed")
case .processing:
print("Payment processing")
default:
break
}
}
}
// Start payment when user taps pay button
@IBAction func payButtonTapped(_ sender: UIButton) {
Yuno.startPayment(showPaymentStatus: true)
}
```
**Test with**: Card `4111 1111 1111 1111`, any future date, any CVV
For a comprehensive overview of all iOS SDK parameters, see [iOS SDK Common Reference](/docs/sdks/resources/references/ios).
[Complete iOS guide →](/docs/sdks/full-checkout/ios-payments)
### 1. Install
**build.gradle**:
```kotlin theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
repositories {
maven { url "https://yunopayments.jfrog.io/artifactory/snapshots-libs-release" }
}
dependencies {
implementation 'com.yuno.payments:android-sdk:2.9.0'
}
```
### 2. Initialize and process payment
**Initialize in Application**:
```kotlin theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
Yuno.initialize(
this,
publicApiKey = "your-public-api-key",
config = YunoConfig(
keepLoader = true,
)
)
}
}
```
For a detailed explanation of the `keepLoader` parameter and mandatory error handling, see the [Android Reference Guide](/docs/sdks/resources/references/android#keeploader-parameter).
**In Activity/Fragment**:
```kotlin theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
import com.yuno.payments.Yuno
class PaymentActivity : ComponentActivity() {
private var checkoutSession: String? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Create checkout session on your backend first
// Your backend calls: POST https://api-sandbox.y.uno/v1/checkout/sessions
lifecycleScope.launch {
val session = createCheckoutSession() // Your backend call
checkoutSession = session.id
// Start checkout with session
startCheckout(
checkoutSession = session.id,
countryCode = "US",
callbackPaymentState = { state, subState ->
when (state) {
"SUCCEEDED" -> println("Payment succeeded!")
"FAILED" -> println("Payment failed")
"PROCESSING" -> println("Payment processing")
"REJECT" -> println("Payment rejected")
else -> println("Payment state: $state")
}
}
)
}
setContent {
var paymentMethodSelected by remember { mutableStateOf(false) }
Column(
modifier = Modifier
.fillMaxSize()
.verticalScroll(rememberScrollState())
) {
// Display payment methods
PaymentMethodListViewComponent(
activity = this@PaymentActivity,
onPaymentSelected = { isSelected ->
paymentMethodSelected = isSelected
}
)
// Pay button
Button(
onClick = {
startPayment(
showStatusYuno = true,
callbackOTT = { token ->
token?.let { ott ->
// Call your backend: POST /v1/payments
// with { payment_method: { token: ott }, checkout_session: ... }
createPayment(ott, checkoutSession!!)
// Required for async payment methods
continuePayment()
}
}
)
},
enabled = paymentMethodSelected
) {
Text("Pay Now")
}
}
}
}
}
```
**Test with**: Card `4111 1111 1111 1111`, any future date, any CVV
For a comprehensive overview of all Android SDK parameters, see [Android SDK Common Reference](/docs/sdks/resources/references/android).
[Complete Android guide →](/docs/sdks/full-checkout/android-payments)
## Backend integration
Your backend must implement two API endpoints to work with Yuno:
### 1. Create checkout session
Before displaying the payment UI, your backend creates a checkout session:
* **Endpoint**: `POST https://api-sandbox.y.uno/v1/checkout/sessions`
* **Required**: Customer ID, amount, country
* **Returns**: `checkout_session` ID (used in SDK)
* **Reference**: [Create checkout session API](/reference/checkout-sessions/create-checkout-session)
**Example request**:
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"country": "US",
"customer_payer": {
"id": "customer-123"
},
"amount": {
"currency": "USD",
"value": "2500"
}
}
```
### 2. Create payment
In the One-Time Token (OTT) callback, your backend creates the payment:
* **Endpoint**: `POST https://api-sandbox.y.uno/v1/payments`
* **Required**: One-time token (from SDK callback), checkout session
* **Returns**: Payment status and `sdk_action_required` field
* **Reference**: [Create payment API](/reference/payments/create-payment)
**Example request**:
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"payment_method": {
"token": "one-time-token-from-sdk"
},
"checkout": {
"session": "checkout-session-id"
}
}
```
**Important**: If the API response has `sdk_action_required: true`, you must call the SDK's `continuePayment()` method to complete async payment methods (3DS authentication, PIX, bank redirects, etc.).
## Parameters
Primary parameters used in this quickstart:
| Parameter | Description |
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------ |
| `publicKey` / `apiKey` | Your Yuno public API key (frontend). From [Yuno Dashboard](https://dashboard.y.uno/) → **Developers** > **Credentials**. |
| `checkoutSession` | Checkout session ID returned by your backend (create session endpoint). Required to start payment. |
| `countryCode` | ISO country code for the payment (e.g. `US`, `CO`). See [Country coverage](/docs/sdks/resources/country-coverage). |
| `elementSelector` (Web) | CSS selector for the element where the payment form is mounted (e.g. `#payment-form`). |
Full parameter reference: [Payment flows (Web)](/docs/sdks/full-checkout/web-payments), [Payment flows (iOS)](/docs/sdks/full-checkout/ios-payments), [Payment flows (Android)](/docs/sdks/full-checkout/android-payments).
## Alternative integration methods
If you need more control over the user interface or specific payment flows, Yuno provides alternative integration methods:
### Lite SDK
A lightweight integration that gives you full control over the payment method display while Yuno handles the secure payment processing.
* [Web Implementation](/docs/sdks/lite-web/payment)
* [Android Implementation](/docs/sdks/lite-android/checkout)
* [iOS Implementation](/docs/sdks/lite-ios/checkout)
### Secure Fields
Build your own payment forms from scratch using our UI components for maximum customization (Web Only).
* [Secure Fields Guide](/docs/sdks/customization/secure-fields/index)
## Test cards
| Card Number | Scenario |
| ------------------- | ------------- |
| 4111 1111 1111 1111 | Success |
| 4000 0000 0000 0002 | Declined |
| 4000 0000 0000 3220 | 3DS Challenge |
# Understanding Flows
Source: https://docs.y.uno/docs/sdks/overview/understanding-flows
Understand payment, enrollment, vaulted token, and Headless SDK flows with diagrams and step sequences
In Yuno SDKs, **payment flows** and **enrollment flows** are separate. Payment is the process of completing a transaction; enrollment is the process of saving a payment method (e.g. a card) to a customer account for future use. This page explains both flows at a high level with diagrams and step sequences. Use the Quickstart guide and platform flow pages for implementation details.
## Payment flow
The SDK provides a unified payment experience: customers complete transactions using multiple payment methods within a single integration. The diagram below illustrates the main payment workflow.
RequestResponseSuccess
### Payment flow steps
1. Merchant Server: `Create Customer` → Yuno Server: `Creates Customer`
2. Merchant Client: `Initiate Checkout` → Merchant Server: `Create Checkout session`
3. Merchant Server: `Create Checkout session` → Yuno Server: `Creates Checkout session`
4. Merchant Client: `Initiate Checkout` → `Initiate SDK` to continue payment flow
5. Merchant Client: `Initiate SDK` to continue payment flow → Yuno SDK: `Receive checkout session`
6. Yuno SDK: `Receive checkout session` → `List payment methods`
7. Yuno SDK: `List payment methods` → User selects payment methods
8. Yuno SDK: User selects payment methods → Callback with the `one-time token`
9. Yuno SDK: Callback with the `one-time token` → Merchant Client: Receive `one-time token` (single use)
10. Merchant Client: Receive `one-time token` (single use) → `Initiate payment`
11. Merchant Client: `Initiate payment` → `Initiate SDK` to continue payment flow
12. Merchant Client: `Initiate SDK` to continue payment flow → Yuno SDK: `Continue with the payment flow`
13. Yuno SDK: `Continue with the payment flow` → Show screen for the user to complete payment
14. Yuno SDK: Show screen for the user to complete payment → Display `payment result` (optional)
15. Merchant Client: `Initiate payment` → Merchant Server: `Create payment`
16. Merchant Server: `Create payment` → Yuno Server: `Creates payment` in the payment provider
### Payment flow using a vaulted token
If a customer has an enrolled payment method, they can use a **vaulted token** to pay without entering payment details again.
RequestResponseSuccess
#### Vaulted token flow steps
1. Merchant Client: `Initiate checkout` → Merchant Server: `Create Customer`
2. Merchant Server: `Create Customer` → Yuno Server: `Create Customer`
3. Merchant Client: `Initiate SDK` with the `checkout session` → Yuno SDK: `Receive checkout session`
4. Yuno SDK: `Receive checkout session` → `List payment methods`
5. Yuno SDK: `List payment methods` → User selects payment methods
6. Yuno SDK: User selects payment method → Callback with the `one-time token`
7. Yuno SDK: Callback with the `one-time token` → Merchant Client: `Initiate payment`
8. Merchant Client: `Initiate payment` → Merchant Server: `Create payment`
9. Merchant Server: `Create payment` → Yuno Server: `Creates payment` in the payment provider
10. Merchant Client: Show `payment result` → Merchant Server: `Receive payment result`
11. Merchant Server: `Receive payment result` → Yuno Server: Provides `payment result`
## Enrollment flow
**Enrollment** is the process of saving a payment method (e.g. a card) to a customer’s account so it can be used later (e.g. with a vaulted token). full-checkout supports enrollment; the diagram below describes the enrollment workflow.
RequestResponseSuccess
### Enrollment flow steps
1. Merchant Server: `Create Customer` → Yuno Server: `Creates Customer`
2. Merchant Client: `Add payment method` → Merchant Server: `Create customer session`
3. Merchant Server: `Create customer session` → Yuno Server: `Creates customer session`
4. Merchant Client: `Display payment methods to enroll` → Merchant Server: `Request available payment methods to enroll`
5. Merchant Server: `Request available payment methods to enroll` → Yuno Server: `Returns available payment method`
6. Merchant Client: `Display payment methods to enroll` → Merchant Client: User selects payment method to enroll
7. Merchant Client: User selects payment method to enroll → Merchant Client: `Initiate enrollment`
8. Merchant Client: `Initiate enrollment` → Merchant Client: `Initiate SDK` to continue enrollment
9. Merchant Client: `Initiate SDK` to continue enrollment → Yuno SDK: `Continue enrollment flow`
10. Yuno SDK: `Continue enrollment flow` → Yuno SDK: Shows screens for the user to complete enrollment
11. Merchant Server: Receive `enrollment result` via webhook → Yuno Server: Receive `enrollment results` from payment provider
12. Yuno Server: Receive `enrollment results` from payment provider → Yuno SDK: Display `enrollment result` (optional)
## Headless SDK flow
The **Headless SDK** provides maximum flexibility by allowing you to manage the entire user interface while Yuno handles the complex payment logic and security (like 3DS).
RequestResponseSuccess
### Headless flow steps
1. **Merchant Server**: `Create Customer` → **Yuno Server**: `Creates Customer`
2. **Merchant Client**: `Initiate Checkout` → **Merchant Server**: `Create Checkout session`
3. **Merchant Client**: `Collect Information` → User enters card/payment details in your custom UI.
4. **Merchant Client**: `Generate Token` → **Yuno SDK**: Call `generateToken(details)` to receive a `one-time token`.
5. **Merchant Client**: `Process Payment` → **Merchant Server**: Send `one-time token` to your backend.
6. **Merchant Server**: `Create Payment` → **Yuno Server**: Call [Create Payment](/reference/payments/create-payment) API.
7. **Merchant Client**: `Handle Actions` → If API response returns `sdk_action_required: true`, use the SDK to handle 3DS or other [Payment Actions](/docs/sdks/headless-web/payment#step-7-get-payment-actions).
# Country Coverage
Source: https://docs.y.uno/docs/sdks/resources/country-coverage
Reference supported countries and their codes for Yuno SDK payment and enrollment flows
Yuno is dedicated to expanding its coverage of solutions worldwide. Use the buttons to check the countries by region supported by Yuno's SDKs. If you require access to a Yuno SDK in a country that is not yet supported, reach out to our commercial team.
## Quick navigation
* [Americas](#americas)
* [Africa](#africa)
* [Asia Pacific](#asia-pacific)
* [Europe](#europe)
* [Middle East](#middle-east)
## Americas
The table below lists all supported American countries and provides the respective country code.
| Country | Country code |
| -------------------------------- | :----------: |
| Anguilla | AI |
| Antigua and Barbuda | AG |
| Argentina | AR |
| Aruba | AW |
| Bahamas | BS |
| Barbados | BB |
| Belize | BZ |
| Bermuda | BM |
| Bolivia | BO |
| Bonaire | BQ |
| Brazil | BR |
| Canada | CA |
| Cayman Islands | KY |
| Chile | CL |
| Colombia | CO |
| Costa Rica | CR |
| Cuba | CU |
| Curaçao | CW |
| Dominica | DM |
| Dominican Republic | DO |
| Ecuador | EC |
| El Salvador | SV |
| Falkland Islands | FK |
| French Guiana | GF |
| Grenada | GD |
| Guadeloupe | GP |
| Guatemala | GT |
| Guyana | GY |
| Haiti | HT |
| Honduras | HN |
| Jamaica | JM |
| Martinique | MQ |
| Mexico | MX |
| Montserrat | MS |
| Nicaragua | NI |
| Panama | PA |
| Paraguay | PY |
| Peru | PE |
| Puerto Rico | PR |
| Saint Barthélemy | BL |
| Saint Kitts and Nevis | KN |
| Saint Lucia | LC |
| Saint Martin | MF |
| Saint Pierre and Miquelon | PM |
| Saint Vincent and the Grenadines | VC |
| Sint Maarten | SX |
| Suriname | SR |
| Trinidad and Tobago | TT |
| Turks and Caicos Islands | TC |
| United States | US |
| Uruguay | UY |
| Venezuela | VE |
| Virgin Islands British | VG |
| Virgin Islands US | VI |
For further information on standard codes for country identification, currencies, document types, and phone codes for each country, refer to the [Country reference](/reference/country-reference) page.
## Africa
The table below lists all supported African countries and provides the respective country code.
| Country | Country code |
| -------------------------------------------- | ------------ |
| Algeria | DZ |
| Angola | AO |
| Benin | BJ |
| Botswana | BW |
| Burkina Faso | BF |
| Burundi | BI |
| Cameroon | CM |
| Cape Verde | CV |
| Central African Republic | CF |
| Chad | TD |
| Comoros | KM |
| Democratic Republic Of Congo | CD |
| Djibouti | DJ |
| Egypt | EG |
| Equatorial Guinea | GQ |
| Eritrea | ER |
| Ethiopia | ET |
| French Southern Territories | TF |
| Gabon Republic | GA |
| Gambia | GM |
| Ghana | GH |
| Guinea-Bissau | GW |
| Guinea | GN |
| Kenya | KE |
| Lesotho | LS |
| Liberia | LR |
| Libya | LY |
| Madagascar | MG |
| Malawi | MW |
| Mali | ML |
| Mauritania | MR |
| Mauritius | MU |
| Mayotte | YT |
| Morocco | MA |
| Mozambique | MZ |
| Namibia | NA |
| Niger | NE |
| Nigeria | NG |
| Republic Of Congo | CG |
| Reunion | RE |
| Rwanda | RW |
| Saint Helena, Ascension And Tristan Da Cunha | SH |
| São Tomé and Príncipe | ST |
| Senegal | SN |
| Seychelles | SC |
| Sierra Leone | SL |
| Somalia | SO |
| South Africa | ZA |
| South Sudan | SS |
| Sudan | SD |
| Swaziland | SZ |
| Tanzania | TZ |
| Togo | TG |
| Tunisia | TN |
| Uganda | UG |
| Western Sahara | EH |
| Zambia | ZM |
For further information on standard codes for country identification, currencies, document types, and phone codes for each country, refer to the [Country reference](/reference) page.
## Asia Pacific
The table below lists all supported Asia Pacific countries and provides the respective country code.
| Country | Country code |
| ------------------------ | ------------ |
| Afghanistan | AF |
| Armenia | AM |
| Australia | AU |
| Azerbaijan | AZ |
| Bangladesh | BD |
| Bhutan | BT |
| Brunei Darussalam | BN |
| Cambodia | KH |
| China | CN |
| Christmas Island | CX |
| Cocos (Keeling) Islands | CC |
| Cook Islands | CK |
| Fiji | FJ |
| French Polynesia | PF |
| Guam | GU |
| Hong Kong | HK |
| India | IN |
| Indonesia | ID |
| Japan | JP |
| Kazakhstan | KZ |
| Kiribati | KI |
| Kyrgyzstan | KG |
| Macao | MO |
| Malaysia | MY |
| Maldives | MV |
| Marshall Islands | MH |
| Micronesia | FM |
| Mongolia | MN |
| Myanmar | MM |
| Nauru | NR |
| Nepal | NP |
| New Caledonia | NC |
| New Zealand | NZ |
| Niue | NU |
| Norfolk Island | NF |
| Northern Mariana Islands | MP |
| Pakistan | PK |
| Palau | PW |
| Papua New Guinea | PG |
| Philippines | PH |
| Pitcairn Islands | PN |
| Samoa | WS |
| Singapore | SG |
| Solomon Islands | SB |
| South Korea | KR |
| Sri Lanka | LK |
| Taiwan | TW |
| Tajikistan | TJ |
| Thailand | TH |
| Tokelau | TK |
| Tonga | TO |
| Turkmenistan | TM |
| Tuvalu | TV |
| Uzbekistan | UZ |
| Vanuatu | VU |
| Vietnam | VN |
| Wallis and Futuna | WF |
For further information on standard codes for country identification, currencies, document types, and phone codes for each country, refer to the [Country reference](/reference) page.
## Europe
The table below lists all supported European countries and provides the respective country code.
| Country | Country code |
| ---------------------- | ------------ |
| Åland Islands | AX |
| Albania | AL |
| Andorra | AD |
| Austria | AT |
| Belarus | BY |
| Belgium | BE |
| Bosnia & Herzegovina | BA |
| Bulgaria | BG |
| Croatia | HR |
| Cyprus | CY |
| Czech Republic | CZ |
| Denmark | DK |
| Estonia | EE |
| Faroe Islands | FO |
| Finland | FI |
| France | FR |
| Georgia | GE |
| Germany | DE |
| Gibraltar | GI |
| Greece | GR |
| Greenland | GL |
| Guernsey | GG |
| Hungary | HU |
| Iceland | IS |
| Ireland | IE |
| Isle Of Man | IM |
| Italy | IT |
| Jersey | JE |
| Latvia | LV |
| Liechtenstein | LI |
| Lithuania | LT |
| Luxembourg | LU |
| Malta | MT |
| Moldova | MD |
| Monaco | MC |
| Montenegro | ME |
| Netherlands | NL |
| North Macedonia | MK |
| Norway | NO |
| Poland | PL |
| Portugal | PT |
| Romania | RO |
| Russia | RU |
| San Marino | SM |
| Serbia | RS |
| Slovakia | SK |
| Slovenia | SI |
| Spain | ES |
| Svalbard and Jan Mayen | SJ |
| Sweden | SE |
| Switzerland | CH |
| Turkey | TR |
| Ukraine | UA |
| United Kingdom | GB |
| Vatican City State | VA |
For further information on standard codes for country identification, currencies, document types, and phone codes for each country, refer to the [Country reference](/reference) page.
## Middle East
The table below lists all supported Middle East countries and provides the respective country code.
| Country | Country code |
| -------------------- | ------------ |
| Bahrain | BH |
| Iran | IR |
| Iraq | IQ |
| Israel | IL |
| Jordan | JO |
| Kuwait | KW |
| Lebanon | LB |
| Oman | OM |
| Qatar | QA |
| Saudi Arabia | SA |
| Syria | SY |
| United Arab Emirates | AE |
| Yemen | YE |
For further information on standard codes for country identification, currencies, document types, and phone codes for each country, refer to the [Country reference](/reference) page.
# Supported Languages
Source: https://docs.y.uno/docs/sdks/resources/languages-supported
Reference locale codes for setting the display language across Yuno SDK checkout forms
Use these locale codes with Yuno SDKs to specify your desired display language. If you omit the `language` parameter, the SDK defaults to the browser language when available.
## Europe
* German (Germany): `de-DE`
* Greek (Greece): `el-GR`
* English (United Kingdom): `en-GB`
* French (France): `fr-FR`
* Italian (Italy): `it-IT`
* Dutch (Netherlands): `nl-NL`
* Polish (Poland): `pl-PL`
* Romanian (Romania): `ro-RO`
* Russian (Russia): `ru-RU`
* Slovak (Slovakia): `sk-SK`
* Serbian (Latin script): `sr-Latn`
* Swedish (Sweden): `sv-SE`
* Turkish (Turkey): `tr-TR`
* Ukrainian (Ukraine): `uk-UA`
## Middle East & Africa
* Arabic: `ar`
* Hebrew (Israel): `he-IL`
## Asia
* Japanese (Japan): `ja-JP`
* Korean (South Korea): `ko-KR`
* Chinese Simplified (China): `zh-CN`
* Chinese Traditional (Taiwan): `zh-TW`
* Thai (Thailand): `th-TH`
* Vietnamese (Vietnam): `vi-VN`
* Indonesian (Indonesia): `id-ID`
* Malay (Malaysia): `ms-MY`
* Filipino (Philippines): `fil-PH`
## South Asia
* Hindi: `hi`
* Bengali: `bn`
* Malayalam: `ml`
* Urdu: `ur`
* Mongolian: `mn`
## Americas
* English (United States): `en-US`
* English (Canada): `en-CA`
* Spanish (Latin America): `es-CO`
* Portuguese (Brazil): `pt-BR`
# Android Reference
Source: https://docs.y.uno/docs/sdks/resources/references/android
Reference all Android SDK parameters, YunoConfig options, and the keepLoader public methods
Parameters, customizations, and advanced features for all Android SDK flows. Setup: [Payment flows (Android)](/docs/sdks/full-checkout/android-payments), [Enrollment flows (Android)](/docs/sdks/card-enrollment/android-enrollment), [integration modes](/docs/sdks/overview/choose-integration).
## Key parameters (checkout session creation)
When creating a checkout session on your backend for payment flows, the following parameters are commonly used across Android SDKs:
| Parameter | Required | Description |
| -------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `amount` | Yes | The primary transaction amount object containing `currency` (ISO 4217 code) and `value` (numeric amount in that currency). |
| `alternative_amount` | No | An alternative currency representation of the transaction amount with the same structure as `amount` (`currency` and `value`). Useful for multi-currency scenarios, such as displaying prices to customers in their preferred currency (e.g., USD) while processing the payment in the local currency (e.g., COP). |
## Payment parameters (full reference)
Parameters for payment flows. All parameters used in [Payment flows (Android)](/docs/sdks/full-checkout/android-payments) are listed here with full detail.
| Parameter | Type | Required | Description |
| ----------------------- | -------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `checkoutSession` | string | Yes | Checkout session ID from your backend (Create checkout session API). Required for all payment flows. |
| `countryCode` | string | Yes | ISO country code where the payment runs (e.g. `US`, `BR`). Determines available payment methods and compliance. |
| `callbackPaymentState` | function | No | Callback invoked when the payment state changes. Receives the current state: e.g. `SUCCEEDED`, `FAIL`, `PROCESSING`, `REJECT`. Use for UI updates, analytics, or navigation. |
| `merchantSessionId` | string | No | Optional merchant session identifier. Use to correlate the SDK session with your own session or order ID. |
| `onInstallmentSelected` | function | No | Callback invoked when the shopper selects an installment option in the card form (`InstallmentSelected?` payload with `installment`, `label`, and `amount`). Fires for the default pre-selection, every selection, plan recalculations, and once with `null` when installments stop being available. Available from SDK `2.20.0`. See [Full (Android)](/docs/sdks/full-checkout/android-payments#installment-selection-callback-oninstallmentselected). |
## YunoConfig options (initialize)
Runtime behavior and appearance are configured via the `YunoConfig` data class when calling `Yuno.initialize(context, publicApiKey, config)`. All parameters used across Android payment and enrollment flows are listed below. For visual styling (fonts, colors, buttons), see [SDK customizations (Android)](/docs/sdks/customization/android).
| Parameter | Type | Required | Description |
| ----------------- | ------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `saveCardEnabled` | boolean | No | When `true`, allows the user to save or enroll the card during payment. Requires backend support for vaulting (e.g. `payment_method.vault_on_success` in checkout session). |
| `keepLoader` | boolean | No | If `true`, the SDK loader persists from OTT generation until `continuePayment()` is called, preventing UI flickering. If payment creation fails, call `hideLoader()` to manually dismiss it. |
| `language` | string | No | Language code for the SDK UI (e.g. `en`, `es`). Use a code from [Supported languages](/docs/sdks/resources/languages-supported) when available. |
| `styles` | object | No | Custom styles applied to SDK UI elements. Define in your app's styles and reference here, or use theme overrides. See [SDK customizations (Android)](/docs/sdks/customization/android) for font, button, and color options. |
## Enrollment parameters (full reference)
Parameters for enrollment flows. All parameters used in [Enrollment flows (Android)](/docs/sdks/card-enrollment/android-enrollment) are listed here with full detail.
| Parameter | Type | Required | Description |
| ------------------------- | -------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `customerSession` | string | Yes | Customer session ID from Create customer session API. Required. Associates the enrolled payment method with a specific customer. |
| `countryCode` | string | Yes | ISO country code (e.g. `US`, `BR`). Required for enrollment. |
| `showEnrollmentStatus` | boolean | No | When `true`, shows the enrollment result screen after the flow. Default `true`. Set to `false` to handle result only via callback. |
| `callbackEnrollmentState` | function | No | Callback invoked when enrollment state changes. Requires registering `initEnrollment` in your Activity's `onCreate` (or equivalent) so the SDK can deliver results. Optional when using `onActivityResult` with `requestCode`. |
| `requestCode` | int | No | Optional request code used when capturing the enrollment result via `onActivityResult`. Use when you prefer activity-result flow over callbacks. |
## Public methods
The following methods are available globally via the `Yuno` object or as `Activity` extensions.
### `Activity.hideLoader()`
Dismisses the SDK loader when `keepLoader` is active. Use this method when a backend payment creation fails and you cannot proceed with `continuePayment()`.
```kotlin theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
fun Activity.hideLoader()
```
### `Yuno.continuePayment()`
Resumes the payment flow for asynchronous methods (3ds, PIX, etc.) after a payment has been created on your backend.
```kotlin theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
fun continuePayment(
showPaymentStatus: Boolean = true,
checkoutSession: String? = null,
countryCode: String? = null,
callbackPaymentState: ((String?) -> Unit)? = null
)
```
## Enrolling payment methods
You can enroll payment methods (store cards for future use) during the payment flow or via dedicated enrollment flows. For payment flows, enable save card in `YunoConfig` and set `payment_method.vault_on_success` (or equivalent) when creating the checkout session where supported. For dedicated enrollment, see [Enrollment flows (Android)](/docs/sdks/card-enrollment/android-enrollment).
## `keepLoader` parameter
> **Available since Android SDK v2.13.0**
### How it works
The `keepLoader` parameter allows you to persist the SDK's loading indicator across the entire `startPayment` → `continuePayment` flow, providing a seamless visual experience without the loader flickering between steps.
By default, the SDK hides its loader after generating the One-Time Token (OTT) and shows it again when `continuePayment` is called. With `keepLoader` enabled, the loader stays visible continuously from the moment the user submits the payment form until the payment is fully processed (or explicitly dismissed).
```mermaid theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
sequenceDiagram
participant Merchant
participant SDK as Yuno SDK
participant User as Loader Screen
Merchant->>SDK: startPayment(keepLoader: true)
SDK->>User: Show Loader
SDK->>Merchant: callbackOTT(token)
Note over User: Loader remains visible
Merchant->>SDK: continuePayment()
SDK->>User: Dismiss Loader
```
### Integration
#### 1. Enable in YunoConfig
```kotlin theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
Yuno.initialize(
applicationContext = this,
apiKey = "YOUR_PUBLIC_API_KEY",
config = YunoConfig(
keepLoader = true,
),
)
```
#### 2. Handle OTT and call `continuePayment`
When `keepLoader` is enabled, the OTT callback fires while the loader is still visible. Create your payment on your backend and then call `continuePayment` as usual:
```kotlin theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
activity.startCheckout(
checkoutSession = checkoutSession,
countryCode = countryCode,
callbackOTT = { token ->
// The loader is still visible at this point.
// Create payment on your backend using the token,
// then call continuePayment:
activity.continuePayment(showPaymentStatus = true)
},
callbackPaymentState = { state, subState ->
// Handle final payment state
},
)
```
#### 3. Handle errors with `hideLoader`
If your backend call fails and you cannot proceed with `continuePayment`, call `hideLoader()` to dismiss the loader and finish the payment flow:
```kotlin theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
callbackOTT = { token ->
try {
val payment = createPaymentOnBackend(token)
activity.continuePayment(showPaymentStatus = true)
} catch (e: Exception) {
// Dismiss the loader on failure
activity.hideLoader()
}
}
```
**Handling Failures**\
When `keepLoader` is active and payment creation fails, you **must** call `hideLoader()`. Otherwise, the loader will remain on the screen indefinitely (until the built-in timeout triggers).
### Compatibility
* Works with both **Full** and **Lite** payment flows (`startPayment` and `startPaymentLite`).
* Compatible with vaulted tokens.
* The loader respects the SDK's built-in timeout — if neither `continuePayment` nor `hideLoader` is called, the loader will automatically dismiss after the timeout period.
* Not applicable to the **Seamless** flow (`startPaymentSeamlessLite`), which does not use the `startPayment` → `continuePayment` two-step pattern.
# iOS Reference
Source: https://docs.y.uno/docs/sdks/resources/references/ios
Reference all iOS SDK parameters, YunoConfig options, and enrollment delegate configuration
Parameters, customizations, and advanced features for all Yuno iOS SDK flows. For integration setup, see [Payment flows (iOS)](/docs/sdks/full-checkout/ios-payments), [Enrollment flows (iOS)](/docs/sdks/card-enrollment/ios-enrollment), and [integration modes](/docs/sdks/overview/choose-integration).
## Key parameters (checkout session creation)
When creating a checkout session on your backend for payment flows, the following parameters are commonly used across iOS SDKs:
| Parameter | Required | Description |
| -------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `amount` | Yes | The primary transaction amount object containing `currency` (ISO 4217 code) and `value` (numeric amount in that currency). |
| `alternative_amount` | No | An alternative currency representation of the transaction amount with the same structure as `amount` (`currency` and `value`). Useful for multi-currency scenarios, such as displaying prices to customers in their preferred currency (e.g., USD) while processing the payment in the local currency (e.g., COP). |
## Payment parameters (full reference)
Parameters for payment flows. All parameters used in [Payment flows (iOS)](/docs/sdks/full-checkout/ios-payments) are listed here with full detail.
| Parameter | Type | Required | Description |
| -------------------------- | ---------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `checkoutSession` | string | Yes | Checkout session ID from your backend (Create checkout session API). Required for all payment flows. |
| `countryCode` | string | Yes | ISO country code where the payment runs (e.g. `BR`, `US`). Determines available payment methods and compliance. |
| `language` | string | No | Language code for the SDK UI (e.g. `en`, `pt-BR`). Optional. See [Supported languages](/docs/sdks/resources/languages-supported) when available. |
| `viewController` | UIViewController | Yes\* | The view controller that presents the payment flow. The SDK uses it to present modals and capture result. |
| `yunoCreatePayment(with:)` | delegate | Yes | Delegate method: create the payment on your backend using the one-time token provided by the SDK. After creating the payment via the API, inform the SDK so it can continue the flow. |
| `yunoPaymentResult(_:)` | delegate | No | Delegate method: invoked when the payment flow finishes. Receives a `Yuno.Result` enum value (`.succeeded`, `.fail`, `.processing`, `.reject`, `.userCancelled`, `.internalError`). These values map to [payment statuses](/reference/getting-started/response-codes). Use for UI updates or navigation. |
## YunoConfig options (initialize)
Runtime behavior and appearance are configured via `YunoConfig` when calling `Yuno.initialize(apiKey:config:)`. All parameters used across iOS payment and enrollment flows are listed below. For visual styling (fonts, colors, buttons), see [SDK customizations (iOS)](/docs/sdks/customization/ios).
| Parameter | Type | Required | Description |
| ----------------- | ---------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `appearance` | Appearance | No | Custom appearance (fonts, colors, buttons). Use `Yuno.Appearance(...)` to set `fontFamily`, `accentColor`, `buttonBackgroundColor`, `buttonTitleColor`, and related fields. See [SDK customizations (iOS)](/docs/sdks/customization/ios) for all options. |
| `saveCardEnabled` | boolean | No | When `true`, allows the user to save or enroll the card during payment. Requires backend support for vaulting. |
## Enrollment parameters (full reference)
Parameters for enrollment flows. All parameters used in [Enrollment flows (iOS)](/docs/sdks/card-enrollment/ios-enrollment) are listed here with full detail.
| Parameter | Type | Required | Description |
| -------------------------- | ---------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `customerSession` | string | Yes | Customer session ID from Create customer session API. Required. Associates the enrolled payment method with a specific customer. |
| `countryCode` | string | Yes | ISO country code (e.g. `BR`, `US`). Required for enrollment. |
| `language` | string | No | Language code for the SDK UI. Optional. |
| `viewController` | UIViewController | Yes\* | The view controller that presents the enrollment flow. Required for delegate-based enrollment. |
| `yunoEnrollmentResult(_:)` | delegate | No | Delegate method: invoked when enrollment finishes. Receives the result (e.g. vaulted token, status). Use for UI updates or navigation. |
| `YunoConfig` | YunoConfig | No | Same options as payment (e.g. `appearance`, `saveCardEnabled`, `keepLoader`). See [YunoConfig options (initialize)](#yunoconfig-options-initialize) above. |
## Enrolling payment methods
You can enroll payment methods (store cards for future use) during the payment flow or via dedicated enrollment flows. For payment flows, enable save card in `YunoConfig` and set `payment_method.vault_on_success` (or equivalent) when creating the checkout session where supported. For dedicated enrollment, see [Enrollment flows (iOS)](/docs/sdks/card-enrollment/ios-enrollment).
# Web Reference
Source: https://docs.y.uno/docs/sdks/resources/references/web
Reference all Web SDK parameters, SRI integration, payment retry, and enrollment options
Parameters, customizations, and advanced features for all Web SDK flows. See [Quickstart guide](/docs/sdks/overview/quickstart) and [Choose the Right Integration for You](/docs/sdks/overview/choose-integration) for introductory information.
## TypeScript support
TypeScript: Yuno provides a [TypeScript library](https://www.npmjs.com/package/@yuno-payments/sdk-web-types) for all available methods.
## Subresource Integrity (SRI)
This browser security feature lets you ensure a loaded script has not been tampered with. You provide a cryptographic hash alongside the script URL; the browser verifies the downloaded bytes match the declared hash before executing the code.
* **Integrity**: Guarantees the exact code built and published is what runs in the browser.
* **Immutability**: When paired with full semantic version URLs, it ensures stable, reproducible integrations.
* **Defense-in-depth**: Mitigates risks from supply-chain or transport-layer compromise.
### URL formats
When implementing SRI, use the full semantic version URL format to ensure immutable, tamper-evident integrations.
* **Full (immutable) URL with SRI**: Full semantic version path used for locked, tamper-evident integrations with an SRI hash.
* **Partial (mutable) URL**: Version with major and minor (e.g., v1.9). This version will receive patch improvements. This is useful if you like to avoid updates in your code base.
### How to integrate the SDK with SRI
Replace `src` and `integrity` with the environment/version you target. `crossorigin="anonymous"` lets the browser validate the SRI for cross-origin scripts.
The hash can be found in [versions-sri.json](https://sdk-web.y.uno/versions-sri.json) at `latest.integrity` or within the `history` array.\`.
```html theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
```
`src`for production is `https://sdk-web.y.uno/versions-sri.json` .
### Using NPM package
```javascript theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
import { loadScript } from '@yuno-payments/sdk-web'
const yuno = await loadScript({
sri: true
})
```
### Validation notes
* Open DevTools Network tab and confirm main.js returns `200` from the full-version path.
* Verify the response headers allow cross-origin fetches for static assets if served from a distinct origin (`crossorigin="anonymous"` is set).
* Ensure the integrity attribute exactly matches the generated hash, including the sha384- prefix.
* Any change to main.js changes the hash. When changing versions, always regenerate or retrieve the new sha384 value and update the integrity attribute.
### SRI Troubleshooting
* Hash mismatchs cause the script to fail execution with an integrity error (e.g., you updated the file but not the hash). To fix, rebuild, retrieve the new sha384 from [versions-sri.json](https://sdk-web.y.uno/versions-sri.json), and update integrity.
* Browser blocks SRI on cross-origin request when the crossorigin attribute is missing or CORS is restrictive. To fix, add `crossorigin="anonymous"` and configure the static hosting to allow cross-origin fetches for JS assets.
## Key parameters (checkout session creation)
When creating a checkout session on your backend, the following parameters are commonly used across web SDKs:
| Parameter | Required | Description |
| -------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `amount` | Yes | The primary transaction amount object containing `currency` (ISO 4217 code) and `value` (numeric amount in that currency). |
| `alternative_amount` | No | An alternative currency representation of the transaction amount with the same structure as `amount` (`currency` and `value`). Useful for multi-currency scenarios, such as displaying prices to customers in their preferred currency (e.g., USD) while processing the payment in the local currency (e.g., COP). |
## Payment and checkout parameters (full reference)
Parameters for `await yuno.startCheckout()`, `await yuno.mountCheckout()`, and related payment flows. All parameters used in [Payment flows (Web)](/docs/sdks/full-checkout/web-payments) are listed here with full detail.
### Core parameters
| Parameter | Type | Required | Description |
| ------------------- | ------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `checkoutSession` | string | Yes | Checkout session ID returned from your backend (Create checkout session API). Required for all payment flows. |
| `elementSelector` | string | No\* | CSS selector for the element where the SDK mounts (e.g. `#root`). Deprecated when used alone; prefer `renderMode.elementSelector` object to control APM and action areas independently. \*Required when `renderMode.type` is `'element'` and using the object form. |
| `countryCode` | string | Yes | ISO country code where the payment runs (e.g. `FR`, `US`). Determines available payment methods and compliance. |
| `language` | string | No | Language code for the UI (e.g. `fr-FR`, `en-US`). Defaults to browser language when available. See [Supported languages](/docs/sdks/resources/languages-supported). |
| `showLoading` | boolean | No | When `true`, shows the SDK loading spinner. Default `true`. Remains visible until `hideLoader()` or `await yuno.continuePayment()` is called. |
| `showPaymentStatus` | boolean | No | When `true`, shows the payment result screen after the flow completes. Optional. |
| `issuersFormEnable` | boolean | No | When `true`, shows the issuer (bank) list form. Default `true` in source. Optional. |
### Callbacks
| Parameter | Type | Required | Description |
| -------------------------------------- | -------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `yunoCreatePayment(oneTimeToken)` | function | Yes | Callback invoked when the user completes the card/APM step. Receive the one-time token; send it to your backend to create the payment via the API; then `await yuno.continuePayment()` to resume the flow. |
| `yunoPaymentResult(status, subStatus)` | function | No | Callback invoked when the payment flow finishes. Receives the [payment status](/reference/payments/status-and-response-codes/payment) (e.g. `SUCCEEDED`, `DECLINED`, `PENDING`, `REJECTED`, `CANCELED`, `ERROR`) and an optional `subStatus` qualifying it. Use for UI updates or analytics. See [Shopper-cancelled steps](#shopper-cancelled-steps). |
| `yunoError(message, data)` | function | No | Callback invoked when an error occurs during the flow. Receives an error message and optional data object for debugging. |
| `onLoading` | function | No | Callback invoked when loading state changes (e.g. SDK fetching config, processing payment). Use to show or hide your own loader. |
### Shopper-cancelled steps
Some steps render in a modal the shopper can dismiss — the 3DS challenge (closing it with the **X** or pressing the browser back button), and payment-instruction screens such as vouchers or payment codes. When that happens the SDK reports:
```javascript theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
yunoPaymentResult('PENDING', 'CANCELLED_BY_USER')
```
No `yunoError` is emitted for these steps. Dismissing the modal closes the SDK UI, but it does **not** cancel the payment: the payment stays in flight and is resolved by the provider and by Yuno's backend, which remains the source of truth for the final status. A 3DS challenge in particular runs inside the issuer's own iframe, so the SDK cannot determine whether authentication already completed at the moment the shopper closes the modal — reporting a terminal cancellation there could contradict a payment that goes on to be approved.
`CANCELLED_BY_USER` is produced by the SDK to describe the shopper's gesture. It is **not** a payment sub-status and does not appear in the [Payment status reference](/reference/payments/status-and-response-codes/payment).
Branch on `subStatus` to detect this case:
```javascript theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
yunoPaymentResult(status, subStatus) {
if (subStatus === 'CANCELLED_BY_USER') {
// The shopper dismissed the step. The payment is still being resolved —
// wait for the webhook or query the payment before showing a final outcome.
return;
}
// ...handle the final status
}
```
### Card form options (`card`)
| Parameter | Type | Required | Description |
| --------------------------------- | -------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `card.styles` | string | No | Custom CSS string injected into the iframe to style the card form. Use to match your brand. |
| `card.cardSaveEnable` | boolean | No | When `true`, shows a checkbox to save or enroll the card for future use. Default `false`. Requires backend support for vaulting. |
| `card.texts` | object | No | Custom text for card form buttons and labels. Keys depend on SDK version (e.g. placeholders, button labels). |
| `card.onChange` | function | No | Callback when card form state changes (loading, completed, network selected, reset). Receives `{ error, data }`; `data` can include IIN/BIN and instalment options. Use BIN for real-time tax calculations. |
| `card.isCreditCardProcessingOnly` | boolean | No | When `true`, forces card transactions to process as credit only. Useful where the card can act as both credit and debit. |
### Render mode
| Parameter | Type | Required | Description |
| ---------------------------- | ------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `renderMode` | object | No | Controls how payment forms are displayed. Omit to use defaults. |
| `renderMode.type` | string | No | `'modal'` (default) or `'element'`. Modal shows forms in an overlay; element embeds in the given DOM element. |
| `renderMode.elementSelector` | object | No\* | Required if `type` is `'element'`. Provide `apmForm` (selector where APM UI is rendered) and `actionForm` (selector for button/area that opens provider-specific steps, e.g. PIX QR). |
### Custom texts
| Parameter | Type | Required | Description |
| --------- | ------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `texts` | object | No | Custom text for payment form buttons and labels (e.g. `customerForm.submitButton`, `paymentOtp.sendOtpButton`). Use to match your application language or branding. |
### Express button styling (`externalButtons`)
The `externalButtons` property in `startCheckout` and `startSeamlessCheckout` *(SDK 1.6+)* allows merchants to customize the appearance of Google Pay, Apple Pay, and PayPal express buttons. All properties are optional; sensible defaults are used when not provided.
```js theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
await yuno.startCheckout({
// ... other config
externalButtons: {
googlePay: { /* Google Pay options */ },
applePay: { /* Apple Pay options */ },
paypal: { /* PayPal options */ },
},
})
```
The `externalButtons` configuration applies to all flows that render express buttons — including `mountCheckout`, `mountExternalButtons`, and `mountSeamlessExternalButtons` — as long as `startCheckout` or `startSeamlessCheckout` was called first with the configuration.
#### Google Pay
```js theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
externalButtons: {
googlePay: {
buttonColor: 'default',
buttonType: 'pay',
buttonRadius: 30,
buttonLocale: 'en',
buttonSizeMode: 'fill',
buttonWidth: 240,
buttonHeight: 48,
}
}
```
#### Full example
```js theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
const yuno = await window.Yuno.initialize(publicApiKey)
await yuno.startCheckout({
checkoutSession,
elementSelector: '#root',
countryCode: 'CO',
language: 'es',
externalButtons: {
googlePay: {
buttonColor: 'black',
buttonType: 'pay',
buttonRadius: 4,
buttonSizeMode: 'fill',
},
applePay: {
buttonType: 'buy',
buttonStyle: 'black',
buttonBorderRadius: 4,
},
paypal: {
color: 'blue',
shape: 'rect',
label: 'pay',
height: 45,
borderRadius: 4,
},
},
// ... rest of config
})
```
## Payment retry
Payment retry lets a shopper fix and re-submit a **card** payment after it comes back `DECLINED` or `ERROR`, without restarting the checkout. Instead of tearing down the card form, the SDK keeps it open, surfaces the decline (field-level errors and a top error banner), and clones the checkout session so the next attempt reuses the same flow.
Retry is enabled by the Checkout Builder / Dashboard setting `settings.card.enable_payment_retry` under [`styling.settings`](/reference/checkout-builder/publish-checkout-configuration) (default enabled). It is a server-controlled setting, not a `startCheckout()` argument. It applies to non-enrolled card payments only — enrolled/vaulted cards are excluded.
Payment retry is supported across all four Web integrations: **Seamless**, **Full Checkout**, **Lite**, and **Secure Fields**.
### Behavior by integration
| Integration | What you need to do |
| ----------------- | -------------------------------------------------------------------------------------------------------------- |
| **Seamless** | Automatic. The SDK keeps the card form open and drives the retry itself — no extra integration required. |
| **Full Checkout** | Manual. After creating the payment on your backend, check the response and call `continuePayment` (see below). |
| **Lite** | Manual. Same as Full Checkout. |
| **Secure Fields** | Manual. Same as Full Checkout. |
### Triggering retry in Full Checkout, Lite, and Secure Fields
For these three flows, after your backend creates the payment you must inspect the payment response and drive the SDK accordingly:
* **Card payment that failed** (`payment_method.type === 'CARD'` and `status` is `DECLINED` or `ERROR`): call `continuePayment` to run the retry — the card form stays open with the decline shown.
* **Additional action required** (`checkout.sdk_action_required === true`): call `continuePayment` so the SDK can show the required screens (e.g. 3DS or a redirect).
* **Nothing left for the SDK to do** (status is not `DECLINED`/`ERROR` **and** `checkout.sdk_action_required === false`): the SDK will not tear itself down, so you must unmount it manually with `unmountSdk`.
```javascript theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
// In your yunoCreatePayment callback, after creating the payment on your backend:
const payment = await createPaymentOnYourBackend(oneTimeToken);
const isCard = payment.payment_method?.type === 'CARD';
const failed = payment.status === 'DECLINED' || payment.status === 'ERROR';
const actionRequired = payment.checkout?.sdk_action_required === true;
if (isCard && failed) {
// Runs the retry flow: keeps the card form open with the decline shown.
await yuno.continuePayment();
} else if (actionRequired) {
// Additional action needed (e.g. 3DS or redirect).
await yuno.continuePayment({ showPaymentStatus: true });
} else {
// No retry and no action required: clean up the SDK yourself.
await yuno.unmountSdk();
}
```
If the payment method is `CARD` and the status is `DECLINED` or `ERROR`, you **must** call `continuePayment`. If you don't, the card form will **not** close automatically — the shopper is left on the open form with no next step.
When the status is anything other than `DECLINED`/`ERROR` **and** `checkout.sdk_action_required` is `false`, call `unmountSdk` to remove the SDK from the DOM — it does not unmount on its own in these flows.
**Secure Fields:** set the `checkoutSession` on the `secureFields({ ... })` object, and **do not** pass it to `generateTokenWithInformation({ ... })`.
Retry is armed when the SDK initializes the secure fields with a `checkoutSession`, and on each retry the SDK swaps in a freshly cloned session internally. If you also pass `checkoutSession` to `generateTokenWithInformation`, that fixed value overrides the cloned one and breaks the retry attempt.
```javascript theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
// ✅ Correct — checkoutSession only on secureFields
const secureFields = await yuno.secureFields({
checkoutSession,
// ...other options
});
const token = await secureFields.generateTokenWithInformation({ /* no checkoutSession */ });
// ❌ Incorrect — checkoutSession passed to generateTokenWithInformation overrides the cloned session on retry
const token = await secureFields.generateTokenWithInformation({ checkoutSession });
```
## Enrollment parameters (full reference)
Parameters for `await yuno.mountEnrollment()`. All parameters used in [Enrollment flows (Web)](/docs/sdks/card-enrollment/web-enrollment) are listed here with full detail.
| Parameter | Type | Required | Description |
| ---------------------- | -------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `customerSession` | string | Yes | Customer session ID from your backend (Create customer session API). Required. Associates the enrolled payment method with a specific customer. |
| `countryCode` | string | Yes | ISO country code (e.g. `US`, `BR`). Determines available enrollment options. See [Country coverage](/docs/sdks/resources/country-coverage). |
| `language` | string | No | Language code for the UI (e.g. `en`, `en-US`). Defaults to browser language when available. |
| `showLoading` | boolean | No | When `true`, shows the loading spinner during enrollment. Default `true`. |
| `onLoading` | function | No | Callback when loading state changes during enrollment. |
| `elementSelector` | string | No | CSS selector where the enrollment form mounts. Required when not using default modal behavior. |
| `card` | object | No | Card form options (same structure as payment flows: `type`, `styles`, `texts`, `onChange`, `isCreditCardProcessingOnly`, etc.). |
| `yunoEnrollmentStatus` | function | No | Callback when enrollment ends. Receives `vaultedToken` and `status`. Status values: `CREATED`, `EXPIRED`, `REJECTED`, `READY_TO_ENROLL`, `ENROLL_IN_PROCESS`, `UNENROLL_IN_PROCESS`, `ENROLLED`, `DECLINED`, `CANCELED`, `ERROR`, `UNENROLLED`. |
| `issuersFormEnable` | boolean | No | When `true`, shows the issuer (bank) list form. Optional. |
| `texts` | object | No | Custom text for enrollment form buttons and labels. |
## Mount external buttons
Use the `mountExternalButtons` method to render PayPal, Google Pay, and Apple Pay buttons in custom locations within your UI. This gives you control over where these buttons are displayed.
```javascript theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
await yuno.mountExternalButtons([
{
paymentMethodType: 'APPLE_PAY',
elementSelector: '#apple-pay',
},
{
paymentMethodType: 'GOOGLE_PAY',
elementSelector: '#google-pay',
},
{
paymentMethodType: 'PAYPAL',
elementSelector: '#paypal',
},
]);
```
### Parameters
| Parameter | Description |
| :------------------ | :------------------------------------------------------------------------------------------------------------- |
| `paymentMethodType` | The payment method type. Must be `'APPLE_PAY'`, `'GOOGLE_PAY'`, or `'PAYPAL'`. |
| `elementSelector` | The CSS selector for the HTML element where the button should be rendered (e.g., `'#apple-pay'`, `'.button'`). |
### Unmounting buttons
You can unmount a single external button by payment method type:
```javascript theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
await yuno.unmountExternalButton('APPLE_PAY');
```
Or unmount all external buttons at once:
```javascript theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
await yuno.unmountAllExternalButtons();
```
## Enrolling payment methods
You can enroll payment methods (store cards for future use) directly during the payment flow by setting `payment_method.vault_on_success = true` in the [checkout session creation](/reference/checkout-sessions/the-checkout-session-object).
When `vault_on_success` is set to `true`:
* The payment method will be automatically enrolled if the payment status is `SUCCEEDED`
* If the payment does not succeed, no vaulting will occur
* The payment response will include a `vaulted_token` that you can use for future transactions
**Example**:
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"account_id": "...",
...
"payment_method": {
"vault_on_success": true
}
}
```
To generate and receive a `vaulted_token` when `vault_on_success = true`, the payment must reference an existing Yuno customer through `customer_payer.id` in the checkout session. Creating or sending the customer data inline inside the payment request does not create the customer on our side, so no vaulting will occur.
For enrollment flows, see [Enrollment flows (Web)](/docs/sdks/card-enrollment/web-enrollment).
# Swift 6 Concurrency
Source: https://docs.y.uno/docs/sdks/resources/swift-6-concurrency
Handle Swift 6 concurrency requirements when implementing Yuno's payment and enrollment delegate protocols
Swift 6 introduces stricter concurrency requirements that affect how you implement the SDK delegate protocols (e.g., `YunoPaymentDelegate`, `YunoEnrollmentDelegate`). This section explains the challenges and provides solutions for different implementation scenarios.
**Understanding Concurrency in Swift 6**
Concurrency is the ability of your app to manage multiple tasks simultaneously. With Swift 6, concurrency rules have become more stringent to enhance app stability and prevent crashes.
## The problem
With Swift 6, protocols that inherit from `Sendable` require all their implementations to be thread-safe. This generates warnings when implementing the delegate in classes marked as `@MainActor`.
Thread-safe means your code can be safely called from multiple threads without causing crashes or unexpected behavior. `@MainActor` ensures code runs on the main thread (UI thread).
## Our design decision
We do not mark protocols as `@MainActor` because:
* It would force all implementations to be `MainActor` compatible
* It would reduce flexibility for merchants who don't use `MainActor`
* Each implementation has different concurrency needs
## Merchant's responsibility
It's the merchant's responsibility to handle concurrency according to their implementation. Below are three different approaches you can use depending on your specific needs.
### Option 1: Immutable properties
This approach uses immutable properties that are automatically thread-safe, making them ideal for simple configurations. It is best suited for simple apps with fixed configuration values that don't change during runtime.
```swift theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
@MainActor
class MyViewController: UIViewController, YunoPaymentDelegate {
private let _countryCode = "CO"
private let _language = "EN"
private let _checkoutSession = "session_id"
nonisolated var countryCode: String { _countryCode }
nonisolated var language: String? { _language }
nonisolated var checkoutSession: String { _checkoutSession }
nonisolated func yunoPaymentResult(_ result: Yuno.Result) {
Task { @MainActor in
// Handle result on main thread
}
}
}
```
### Option 2: Mutable properties with `MainActor.assumeIsolated`
This approach, best for apps where configuration values might change during runtime (like user preferences), allows for mutable properties while maintaining thread safety by using `MainActor.assumeIsolated`.
```swift theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
@MainActor
class MyViewController: UIViewController, YunoPaymentDelegate {
@Published var configLanguage: String = "EN"
@Published var configCountryCode: String = "CO"
nonisolated var language: String? {
MainActor.assumeIsolated { configLanguage }
}
nonisolated var countryCode: String {
MainActor.assumeIsolated { configCountryCode }
}
}
```
### Option 3: For non `MainActor` classes
This approach is suitable for service classes that don't require `MainActor` isolation, making it best for background services or utility classes that don't interact with the UI.
```swift theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
class MyService: YunoPaymentDelegate {
let countryCode: String
let language: String?
let checkoutSession: String
let viewController: UIViewController?
init(countryCode: String, language: String?, checkoutSession: String, viewController: UIViewController?) {
self.countryCode = countryCode
self.language = language
self.checkoutSession = checkoutSession
self.viewController = viewController
}
func yunoPaymentResult(_ result: Yuno.Result) {
// Handle result
}
}
```
The examples above use `YunoPaymentDelegate`, but the same principles apply to `YunoEnrollmentDelegate`. You should use `customerSession` instead of `checkoutSession` when implementing the enrollment delegate.
## Important considerations
When implementing concurrency in your delegate, keep these key points in mind:
* `MainActor.assumeIsolated`: Only use when you guarantee it's called from `MainActor`. This is a safety mechanism that tells Swift "trust me, I know this is running on the main thread."
* `nonisolated`: Means it can be accessed from any thread, so it must be thread-safe. Use this when your properties or methods don't depend on UI state.
* `viewController`: Remains as `@MainActor` because it should always be accessed from the main thread. UI components must always run on the main thread to prevent crashes.
# Seamless SDK (Payment Android)
Source: https://docs.y.uno/docs/sdks/seamless-sdk/android-payments
Step-by-step guide on integrating Yuno's Seamless Android SDK into your mobile application for a flexible payment experience.
This page provides a guide to the Yuno Seamless SDK for Android payments.
**Recommended SDK**
We recommend using the **Android Seamless SDK** for a smooth integration experience. This option provides a flexible payment solution with pre-built UI components and customization options.
This SDK is ideal for merchants who:
* Want control over the payment flow while leveraging pre-built UI components
* Need to customize the payment experience while maintaining PCI compliance
* Require a balance between implementation speed and customization
The Seamless SDK includes features like:
* Pre-built payment UI components with customization options
* Multiple payment method support
* Advanced payment status handling
* Comprehensive error management
For merchants requiring complete UI control or more advanced features, consider using our [Full SDK](/docs/sdks/full-checkout/android-payments) instead.
## Requirements
Before starting the Yuno Android SDK integration, ensure your project meets the technical requirements. Also, ensure the following prerequisites are in place:
* **Minimum SDK Version**: `minSdkVersion` 21 or above
* **Java**: Java 8 enabled
* **AndroidX**: Use AndroidX instead of older support libraries
* **Android Gradle Plugin**: 4.0.0 or above
* **Kotlin Gradle Plugin**: 1.4.0 or above
* **ProGuard**: 6.2.2 or above
### ProGuard / R8 Configuration
If your project has `minifyEnabled = true`, add these rules to your `proguard-rules.pro` file to ensure the SDK works correctly, especially with **AGP 8.x+ R8 full mode**.
```proguard theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
# Preserve generic type signatures and annotations
-keepattributes Signature
-keepattributes *Annotation*
# Yuno SDK
-keep class com.yuno.** { *; }
-dontwarn com.yuno.**
# Gson — R8 full mode compatibility
-keep class com.google.gson.** { *; }
-keep,allowobfuscation,allowshrinking,allowoptimization class * extends com.google.gson.reflect.TypeToken
-dontwarn com.google.gson.**
# Retrofit — R8 full mode compatibility
-keep,allowobfuscation,allowshrinking interface retrofit2.Call
-keep,allowobfuscation,allowshrinking class retrofit2.Response
-keep,allowobfuscation,allowshrinking class kotlin.coroutines.Continuation
-dontwarn retrofit2.**
# OkHttp + Okio — Suppress warnings
-dontwarn okhttp3.**
-dontwarn okio.**
```
### Why are these rules necessary?
AGP 8.x+ enables **R8 full mode** by default, which aggressively strips generic type signatures. Without `-keepattributes Signature`, Gson’s `TypeToken` can fail at runtime with `java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType`.
**Verify SDK Version**
See the [Release notes](/changelog/android) or the [Yuno Android SDK repository](https://github.com/yuno-payments/yuno-sdk-android) to verify the current SDK version available.
## Step 1: Create a customer
Create a customer using the [Create customer endpoint](/reference/customers/create-customer) before initiating payments. This step is required to:
* Identify the person making the payment
* Enable saved card functionality (if enabled)
* Track payment history
The customer ID returned from this endpoint will be used when creating the `checkout_session`.
## Step 2: Create a checkout session
Create a new `checkout_session` using the [Create checkout session](/reference/checkout-sessions/create-checkout-session) endpoint to initialize the payment flow. Make sure to:
* Include the customer ID obtained from the previous step
* Store the returned `checkout_session` ID for use in Step 6 of the integration
Control auth vs capture by sending `payment_method.detail.card.capture` in the checkout session: `false` = authorize only, `true` = capture immediately.
### Key parameters
| Parameter | Required | Description |
| -------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `amount` | Yes | The primary transaction amount object containing `currency` (ISO 4217 code) and `value` (numeric amount in that currency). |
| `alternative_amount` | No | An alternative currency representation of the transaction amount with the same structure as `amount` (`currency` and `value`). Useful for multi-currency scenarios, such as displaying prices to customers in their preferred currency (e.g., USD) while processing the payment in the local currency (e.g., COP). |
**Checkout session usage**
The `checkout_session` is unique for each payment attempt and cannot be reused.
## Step 3: Add SDK to your project
Add the repository source:
```groovy theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
maven { url "https://yunopayments.jfrog.io/artifactory/snapshots-libs-release" }
```
Include the following code in the `build.gradle` file to add the Yuno SDK dependency to the application:
```kotlin theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
dependencies {
implementation 'com.yuno.payments:android-sdk:{last_version}'
}
```
## Step 4: Configure permissions
The Yuno SDK requires network permissions. Ensure the `INTERNET` permission is included in your `AndroidManifest.xml`:
```xml theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
```
## Step 5: Initialize SDK
Retrieve your public API keys from the [Yuno dashboard](https://dashboard.y.uno/).
If you haven't implemented a custom application, create one. In the `onCreate()` method of your application class, call the initialize function (`Yuno.initialize`):
```kotlin theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
class CustomApplication : Application() {
override fun onCreate() {
super.onCreate()
Yuno.initialize(
this,
PUBLIC_API_KEY,
config = YunoConfig()
)
}
}
```
Use the `YunoConfig` data class to set additional configurations for the SDK. The following table lists and describes the customization options:
| Option | Description |
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **saveCardEnabled** | Enables the save card checkbox for card flows. Check the [Save card](#save-card-for-future-payments) section for more information. |
| **language** | Defines the language to be used in the payment forms. See [Supported languages](/docs/sdks/resources/languages-supported) for options. |
| **styles** | Enables SDK-wide UI customization. Use it to define global visual styles like font family and button appearance through a `YunoStyles` object. For more information, check the [styles](/docs/sdks/resources/references/android#styles) section. |
| **hideCardholderName** | This optional field allows you to hide the cardholder name field in the card form. When set to `true`, the cardholder name field is not rendered. |
The following code block shows an example of `YunoConfig`:
```kotlin theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
data class YunoConfig(
val saveCardEnabled: Boolean = false,
val keepLoader: Boolean = false, // Not applicable to Seamless SDK
val language: YunoLanguage? = null,
val styles: YunoStyles? = null,
val hideCardholderName: Boolean? = null // Optional: Set to true to hide cardholder name field
)
```
## Step 6: Start checkout
Call the `startCheckout` method in the `onCreate()` function of the activity that integrates the SDK to initiate a new payment process with the Seamless SDK:
```kotlin theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
startCheckout(
checkoutSession: "checkout_session",
countryCode: "US",
callbackPaymentState: ((String?) -> Unit)?,
merchantSessionId: String? = null
)
```
| Parameter | Description |
| :--------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `checkoutSession` | The `checkout_session` is related to the payment. |
| `countryCode` | Country code where the payment is performed. See [Country coverage](/docs/sdks/resources/country-coverage) for a complete list of supported countries and their codes. |
| `callbackPaymentState` | A function that returns the current payment process. Optional if you don't need the result. |
| `merchantSessionId` | Optional identifier for merchant session tracking. Default is null. |
The possible payment states returned by `callbackPaymentState` are:
```kotlin theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
const val PAYMENT_STATE_SUCCEEDED = "SUCCEEDED"
const val PAYMENT_STATE_FAIL = "FAIL"
const val PAYMENT_STATE_PROCESSING = "PROCESSING"
const val PAYMENT_STATE_REJECT = "REJECT"
const val PAYMENT_STATE_INTERNAL_ERROR = "INTERNAL_ERROR"
const val PAYMENT_STATE_STATE_CANCELED_BY_USER = "CANCELED"
```
The following table provides additional information about the possible states:
| **State** | **Description** | **Additional action required** |
| ---------------- | ------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
| `SUCCEEDED` | The transaction or payment process was successfully completed without any errors. | No. |
| `FAIL` | The transaction failed due to errors such as data validation issues, server connection failures, or technical/network problems. | Yes. Investigate the cause of failure (validation, network, server) and take corrective measures. |
| `PROCESSING` | The transaction is currently in progress, awaiting approval or verification. | No. |
| `REJECT` | The transaction was rejected due to reasons like insufficient funds or suspected fraudulent activity. | Yes. Inform the user of the rejection, provide the reason if possible, and suggest actions. |
| `INTERNAL_ERROR` | An unexpected internal error occurred within the system handling the payment process. | Yes. Requires technical intervention to review the system, fix internal issues, and retry or inform the user. |
| `CANCELED` | The user voluntarily canceled the transaction or abandoned the payment process. | No. |
### Payment status validation
This section explains how the SDK handles payment status when users cancel or leave payment flows, and how the SDK status relates to the backend payment status in these scenarios.
#### Sync payment methods (Google Pay)
For synchronous payment methods like Google Pay, when a user cancels or closes the wallet UI before a payment service provider (PSP) response is received:
* **SDK Status**: Returns `CANCELED` (CANCELLED\_BY\_USER)
* **Backend payment status**: Remains `PENDING` until PSP timeout or merchant cancellation
* **Important**: The SDK will not return `REJECT` or `PROCESSING` in this scenario
This ensures that the backend payment remains in a pending state and can be properly handled by the merchant's system.
#### Async payment methods (PIX and QR-based methods)
For asynchronous payment methods like PIX, when a user closes the QR code window (clicks X) before completing the payment:
* **SDK Status**: Returns `PROCESSING`, optionally with a sub-status such as `CLOSED_BY_USER`
* **Backend payment status**: Remains `PENDING` and the QR code remains valid until expiry
* **Checkout session reuse**: Re-opening the same checkout session can display the same valid QR code
* **No Automatic Cancellation**: The PIX payment is not automatically cancelled when the user closes the QR window
This behavior allows users to return to the payment flow and complete the transaction using the same QR code before it expires.
#### Expired async payments
If a PIX QR code expires naturally:
* **Backend Status**: Updated to `EXPIRED`
* **SDK Status**: SDK callbacks and polling endpoints return `EXPIRED` consistently
This ensures merchants receive accurate status information when a payment method has expired.
## Step 7: Get payment one-time token (OTT)
Call the method `startPaymentSeamlessLite` to start a payment process:
```kotlin theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
startPaymentSeamlessLite(
paymentSelected: PaymentSelected,
callbackPaymentState: ((String?) -> Unit)?,
showPaymentStatus: Boolean,
)
```
The following table describes the parameters to start the payment:
| Parameter | Description |
| :--------------------- | :--------------------------------------------------------------------------------------- |
| `paymentSelected` | Specifies the payment method, either through a vaulted token or a selected payment type. |
| `callbackPaymentState` | This is an optional parameter. This function handles the state updates. |
| `showPaymentStatus` | This is an optional parameter. When `true`, displays the SDK's default result screen. |
You will receive the payment status via `callbackPaymentState`, which will indicate whether the payment was successful or if an issue occurred.
## Step 8: Create payment
Call the method `startPaymentSeamlessLite` with the selected payment method to complete the payment process:
```kotlin theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
startPaymentSeamlessLite(
paymentSelected: PaymentSelected,
callbackPaymentState: ((String?) -> Unit)?,
showPaymentStatus: Boolean,
)
```
## Complementary features
Yuno Android SDK provides additional services and configurations you can use to improve customers' experience. Use the [SDK customization](/docs/sdks/customization/android) to change the SDK appearance to match your brand or to configure the loader.
### `styles`
With the `styles` customization option, you can define global visual styles through a `YunoStyles` object. It lets you apply consistent branding across the SDK by customizing button appearance and typography.
```kotlin theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
data class YunoStyles(
val buttonStyles: YunoButtonStyles? = null,
val fontFamily: FontFamily? = null
)
```
| Parameter | Description |
| :------------- | :------------------------------------------------------ |
| `buttonStyles` | Customizes the primary buttons displayed in the SDK. |
| `fontFamily` | Sets the font family used across all SDK text elements. |
The `YunoButtonStyles` object lets you define specific settings for button appearance:
```kotlin theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
data class YunoButtonStyles(
val backgroundColor: Color? = null,
val contentColor: Color? = null,
val cornerRadius: Dp? = null,
val elevation: Dp? = null,
val padding: Dp? = null,
val fontFamily: FontFamily? = null,
val fontSize: TextUnit? = null,
val fontStyle: FontStyle? = null
)
```
Use the `YunoConfig` data class, described in Step 5, to use the `styles` customization option.
### Loader
The loader functionality is controlled through the `keepLoader` parameter in the `YunoConfig` data class, which is documented inline in the SDK configuration section above.
### Save card for future payments
You can also display a checkbox to save or enroll cards using `cardSaveEnable: true`. The following examples show the checkbox for both card form renders:
**Demo App Access**
In addition to the code examples provided, you can see the [Yuno repository](https://github.com/yuno-payments/yuno-sdk-android/tree/master) to complete Yuno Android SDKs implementation.
## Error handling
Handle errors returned by the SDK in your app (e.g. failed payments, validation errors). For HTTP status and response codes, see [Status and response codes](/reference/payments/status-and-response-codes/payment) in the API reference.
# Seamless SDK
Source: https://docs.y.uno/docs/sdks/seamless-sdk/index
Yuno's Seamless SDK provides a simple and efficient integration while giving you full control over the payment experience.
Yuno's **Seamless SDK** provides a simple and efficient integration while giving you full control over the payment experience. Like the [Lite SDK](/docs/sdks/overview/quickstart), it allows you to retrieve available payment methods and decide which to display during checkout. Once the selection is made, a single API and SDK call completes the payment process, creating an experience identical to the Lite SDK.
When using the Seamless SDK, you can:
* Execute the payment process.
* Enroll a credit card while making a payment by setting `vault_on_success: true` when creating the payment.
* Use a vaulted token from an enrolled payment method to complete a payment.
Use the following guides to implement each process.
## Payment workflow
The diagram below illustrates the complete payment workflow:
### SDK Headless Payment Flow
This diagram illustrates the headless payment process using the SDK, detailing the interactions between the Merchant Client, Merchant Server, Yuno Server, and Yuno SDK. It outlines the steps from initiating a checkout and requesting payment methods to creating and receiving the payment result.
#### Merchant Client
The Merchant Client represents your frontend application that interacts with both your backend server and the Yuno SDK. It handles the user-facing aspects of the payment flow, including:
* List payment method
* User selects payment methods
* Initiate SDK with checkout session and `payment_method`
#### Merchant Server
The Merchant Server represents your backend application that handles server-side operations and communicates with Yuno's servers. Its key responsibilities include:
* Create `checkout_session`
* Receive webhook with payment result
#### Yuno Server
The Yuno Server handles all backend operations related to customer management, checkout sessions, and payment processing. Its main responsibilities include:
* Creates `checkout_session`
* Create payment
* Sends webhook with payment result
#### Yuno SDK
The Yuno SDK handles the user interface and payment flow on the client side, managing payment method selection, token generation, and payment completion. Its key responsibilities include:
* Initiate SDK with `checkout_session and payment_method`
* Generate OTT
* Continue payment automatic if necessary
* Shows screens for user to complete enrollment
* Display payment method result (optional)
#### Flow
The following steps outline the complete interaction flow between all components of the SDK Headless Payment integration, detailing how each request and response moves through the system:
1. Merchant Server: Create `checkout_session` --> Yuno Server: Creates `checkout_session`
2. Merchant Client: Initiate SDK with checkout session and `payment_method` --> Yuno SDK: Initiate SDK with `checkout_session` and `payment_method`
3. Yuno Server: Create payment --> Yuno SDK: Generate OTT
## Platform-specific SDK setup
To implement the Full SDK integration, follow the platform-specific guides below:
Integrate Seamless SDK for Web applications.
Integrate Seamless SDK for iOS applications.
Integrate Seamless SDK for Android applications.
# Seamless SDK (Payment iOS)
Source: https://docs.y.uno/docs/sdks/seamless-sdk/ios-payments
Step-by-step guide on integrating Yuno's Seamless iOS SDK into your mobile application for a flexible payment experience.
On this page, you will find all the steps to add, configure, and use the Seamless iOS SDK to make payments in your iOS project.
**Recommended SDK**
We recommend using the **iOS Seamless SDK** for a smooth integration experience. This option provides a flexible payment solution with pre-built UI components and customization options.
## Step 1: Include the library in your project
You can add the library using CocoaPods or Swift Package Manager.
### CocoaPods
To add the Yuno SDK to your iOS project, you need to install the Yuno SDK. If you do not have a Podfile, follow the [CocoaPods guide](https://guides.cocoapods.org/using/using-cocoapods.html) to create one. After creating the Podfile, you will integrate the Yuno SDK with Cocoapods by adding the line below to your Podfile.
```ruby theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
pod 'YunoSDK', '~> 1.19.0'
```
After, you need to run the installation:
```ruby theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
pod install
```
### Swift Package Manager
If you are using the [Swift Package Manager](https://www.swift.org/package-manager/), add Yuno SDK as a dependency, as presented in the following code block:
```swift theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
dependencies: [
.package(url: "https://github.com/yuno-payments/yuno-sdk-ios.git", .upToNextMajor(from: "1.1.17"))
]
```
## Step 2: Initialize SDK with the public key
To start running the Yuno iOS Seamless checkout, you first need to get your Yuno app ID and Public API key. Then, import and initialize Yuno as presented in the following code snippet:
```swift theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
import YunoSDK
Yuno.initialize(
apiKey: "PUBLIC_API_KEY",
config: YunoConfig(),
callback: { (value: Bool) in }
)
```
**UISceneDelegate**
Ensure that if your app uses a `UISceneDelegate`, the Yuno initialization code is placed within your `SceneDelegate`.
The Seamless checkout enables you to configure the appearance of the SDK. It is an optional step that you configure through the class `YunoConfig`. To set up configurations, use the following code block to configure the available elements:
```swift theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
final class YunoConfig {
let appearance: Yuno.Appearance,
let saveCardEnabled: Bool
}
```
Configure the SDK with the following options:
| Parameter | Description |
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `appearance` | This optional field defines the appearance of the checkout. By default, it uses Yuno styles. See [SDK customizations](/docs/sdks/customization/ios) for more information. |
| `saveCardEnabled` | This optional field lets you choose whether the **Save Card** checkbox is shown on card flows. It is false by default. |
| `hideCardholderName` | This optional field allows you to hide the cardholder name field in the card form. When set to `true`, the cardholder name field is not rendered. |
**Accessing Your API Key**
You can retrieve your API Key from the [Developers section](/docs/using-yuno/settings/developers-credentials) in the Yuno Dashboard.
### Create a checkout session
Before starting the payment process, you need to create a `checkout_session` using the [Create checkout session](/reference/checkout-sessions/create-checkout-session) endpoint. This session initializes the payment flow and will be used in the next step.
Control auth vs capture by sending `payment_method.detail.card.capture` in the checkout session: `false` = authorize only, `true` = capture immediately.
#### Key Parameters
| Parameter | Required | Description |
| -------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `amount` | Yes | The primary transaction amount object containing `currency` (ISO 4217 code) and `value` (numeric amount in that currency). |
| `workflow` | Yes | Set the value to `SDK_SEAMLESS` so the SDK can complete the payment flow correctly. |
| `alternative_amount` | No | An alternative currency representation of the transaction amount with the same structure as `amount` (`currency` and `value`). Useful for multi-currency scenarios, such as displaying prices to customers in their preferred currency (e.g., USD) while processing the payment in the local currency (e.g., COP). |
## Step 3: Start the checkout and payment process
The seamless checkout and payment process is initiated with a single method `startPaymentSeamlessLite`. In the `ViewController`, where Yuno will be displayed, call the `Yuno.startPaymentSeamlessLite()` method. You can use the method with async/await or using callbacks:
```swift Swift (async/await) theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
func startPaymentSeamlessLite(
with params: SeamlessParams,
paymentSelected: PaymentMethodSelected,
showPaymentStatus: Bool = true
) async -> Result
```
```swift Swift (with callbacks) theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
func startPaymentSeamlessLite(
with params: SeamlessParams,
paymentSelected: PaymentMethodSelected,
showPaymentStatus: Bool = true,
callback: @escaping ((Result) -> Void)
)
```
Additional parameters are required for the seamless version. These include:
* `PaymentMethodSelected`: The vaulted token and/or the payment method the customer will use to make the payment.
```swift theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
protocol PaymentMethodSelected {
var vaultedToken: String? { get }
var paymentMethodType: String { get }
}
```
* `SeamlessParams`
```swift theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
class SeamlessParams {
var checkoutSession: String
var countryCode: String
var language: String?
var viewController: UIViewController?
}
```
Parameters
The following table describes each parameter from `SeamlessParams`:
| Parameter | Description |
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `checkoutSession` | Refers to the current payment's checkout session. |
| `countryCode` | This parameter determines the country for which the payment process is being configured. The complete list of supported countries and their codes is available on the [Country coverage](/docs/sdks/resources/country-coverage) page. |
| `language` | Defines the language to be used in the payment forms. See [Supported languages](/docs/sdks/resources/languages-supported) for options. |
| `viewController` | This property represents the `UIViewController` used to present the payment flow. Even though the property remains optional for backward compatibility, you must supply a visible controller so the SDK can present its UI correctly. |
**Swift 6 Concurrency Requirements**
If you're using Swift 6, you'll need to implement the `YunoPaymentDelegate` protocol with specific concurrency considerations. See the [Swift 6 Concurrency](/docs/sdks/resources/swift-6-concurrency) guide for detailed implementation options and best practices.
## Step 4: Handle payment status (Optional)
**Deep Links and Mercado Pago Checkout Pro**
This step is only required if you're using a payment method that relies on deep links or Mercado Pago Checkout Pro. If your payment methods don't use deep links, you can skip this step.
Some payment methods take users out of your app to complete the transaction. Once the payment is finished, the user is redirected back to your app using a deep link. The SDK uses this deep link to check what happened, checking if the payment was successful, failed, or canceled, and can show a status screen to the user.
To handle this, you need to update your `AppDelegate` to pass the incoming URL back to the Yuno SDK. This lets the SDK read the result and optionally display the payment status. The following code snippet shows how you can add it to your app:
```swift theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
func application(_ app: UIApplication,
open url: URL,
options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
guard url.scheme == "yunoexample" else { return false }
return Yuno.receiveDeeplink(url, showStatusView: true)
}
```
This code listens for deep links that open your app. When a URL is received, it checks if the scheme matches the one you used in the `callback_url` during checkout session setup. If it matches, the URL is passed to the Yuno SDK using `Yuno.receiveDeeplink(...)`. The SDK then reads the payment result and, if `showStatusView` is set to `true`, shows the appropriate status screen to the user.
Make sure the `url.scheme` in this code matches the `callback_url` you provided when creating the `checkout_session`.
## Transaction state
After the payment is completed, the SDK can return different transaction states. The list of all possible states and their descriptions are presented in the following table:
| Transaction state | Description |
| ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `success` | Indicates that the transaction or payment process has been completed successfully. |
| `fail` | This state indicates that the transaction or payment process has failed. It means that there was an error or issue during the payment process that prevented it from being completed successfully. |
| `processing` | Indicates that the transaction or payment process is currently being processed. It is typically used when there is a delay in payment processing, such as waiting for approval from a third-party service or financial institution. |
| `reject` | This state indicates that the transaction has been rejected. The rejection can occur for various reasons, such as insufficient funds, fraudulent activity, or requests that violate specific rules or policies. |
| `internalError` | It means that an unexpected error occurred within the system or infrastructure handling the payment process. This state suggests a problem on the server or backend side rather than an issue with the user's input or request. |
| `userCancell` | This state indicates that the user has voluntarily canceled or aborted the transaction or payment process. It is typically used when the user has the option to cancel or abandon the payment process. |
### Payment status validation
This section explains how the SDK handles payment status when users cancel or leave payment flows, and how the SDK status relates to the backend payment status in these scenarios.
#### Sync payment methods (Apple Pay)
For synchronous payment methods like Apple Pay, when a user cancels or closes the wallet UI before a payment service provider (PSP) response is received:
* **SDK Status**: Returns `userCancell` (CANCELLED\_BY\_USER)
* **Backend payment status**: Remains `PENDING` until PSP timeout or merchant cancellation
* **Important**: The SDK will not return `reject` or `processing` in this scenario
This ensures that the backend payment remains in a pending state and can be properly handled by the merchant's system.
#### Async payment methods (PIX and QR-based methods)
For asynchronous payment methods like PIX, when a user closes the QR code window (clicks X) before completing the payment:
* **SDK Status**: Returns `PENDING`, optionally with a sub-status such as `CLOSED_BY_USER`
* **Backend payment status**: Remains `PENDING` and the QR code remains valid until expiry
* **Checkout session reuse**: Re-opening the same checkout session can display the same valid QR code
* **No Automatic Cancellation**: The PIX payment is not automatically cancelled when the user closes the QR window
This behavior allows users to return to the payment flow and complete the transaction using the same QR code before it expires.
#### Expired async payments
If a PIX QR code expires naturally:
* **Backend Status**: Updated to `EXPIRED`
* **SDK Status**: SDK callbacks and polling endpoints return `EXPIRED` consistently
This ensures merchants receive accurate status information when a payment method has expired.
The transaction state can be handled in two ways when using the `startPaymentSeamlessLite` method:
* **Async/Await**: Use the async/await approach for a more streamlined flow. This method returns a Result asynchronously, making the code easier to read and manage.
* **Callback**: You can handle the transaction state via a callback function, allowing immediate execution once the result is available.
Both options provide flexibility depending on your preferred approach to asynchronous code.
```swift theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
enum Result {
case reject, success, fail, processing, internalError, userCancell
}
```
## Complementary features
Yuno iOS SDK provides additional services and configurations you can use to improve customers' experience. Use the [SDK Customizations](/docs/sdks/customization/ios) to change the SDK appearance to match your brand or to configure the loader.
* **Loader**: Control the use of the loader through the SDK configuration options.
* **Save card for future payments**: In addition, you can display a checkbox for save or enroll cards using `cardSaveEnable: true`. Below, you can find examples of the checkbox for both card form renders.
## Error handling
Handle errors returned by the SDK in your app (e.g. failed payments, validation errors). For HTTP status and response codes, see [Status and response codes](/reference/payments/status-and-response-codes/payment) in the API reference.
# Seamless SDK (Payment Web)
Source: https://docs.y.uno/docs/sdks/seamless-sdk/web-payments
Step-by-step guide on integrating Yuno's Seamless Web SDK for a flexible payment experience with pre-built UI components.
Follow this step-by-step guide to implement and enable Yuno's Seamless Web SDK payment functionality in your application.
**Recommended SDK**
We recommend using the **Web Seamless SDK** for a smooth integration experience. This option provides a flexible payment solution with pre-built UI components and customization options.
**Should I use Lite or Full Seamless SDK?**
Use the Full Seamless SDK for automatic payment method listing and separate display of payment buttons (like PayPal). The Lite Seamless SDK gives you more control over how payment methods are displayed and organized.
## Step 1: Include the library in your project
The integration guide provides [three flexible methods](/docs/sdks/overview/quickstart):
1. Direct HTML script inclusion
2. Dynamic JavaScript injection
3. NPM module installation
Choose the integration method that best suits your development workflow and technical requirements. After completing the SDK integration, you can proceed with the following steps to implement the Seamless functionality.
**TypeScript Library**
If you are using TypeScript, Yuno offers a [library](https://www.npmjs.com/package/@yuno-payments/sdk-web-types) that provides access to all available methods in the Yuno Web SDK.
## Step 2: Initialize SDK with the public key
Initialize the Yuno SDK in your JavaScript application by providing a valid `PUBLIC_API_KEY`:
```javascript theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
const yuno = await Yuno.initialize(PUBLIC_API_KEY);
```
**Credentials**
See the credentials page for more information: [Authentication](/reference/getting-started/authentication)
## Step 3: Create a checkout session
If your workflow requires sending the `additional_data` object, it can be sent as part of the checkout session.
To initialize the payment flow, create a new `checkout_session` using the [Create checkout session](/reference/checkout-sessions/create-checkout-session) endpoint.
* First, [create a customer](/reference/customers/create-customer) or retrieve an existing customer ID
* Include it when creating the `checkout_session`
To control authorization and capture with cards, include `payment_method.detail.card.capture` in the checkout session: set `false` to authorize only, `true` to capture immediately.
### Key parameters
| Parameter | Required | Description |
| -------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `amount` | Yes | The primary transaction amount object containing `currency` (ISO 4217 code) and `value` (numeric amount in that currency). |
| `alternative_amount` | No | An alternative currency representation of the transaction amount with the same structure as `amount` (`currency` and `value`). Useful for multi-currency scenarios, such as displaying prices to customers in their preferred currency (e.g., USD) while processing the payment in the local currency (e.g., COP). |
**`onPaymentMethodSelect` Event**
For all APMs, including Google Pay, Apple Pay, and PayPal, `onPaymentMethodSelected` is triggered as soon as the customer chooses the payment method (before the payment flow begins). Define `onPaymentMethodSelected` in `startSeamlessCheckout` before `mountSeamlessCheckout`.
**Google Pay and Apple Pay Display**
From SDK version 1.5, Google Pay and Apple Pay appear as direct buttons instead of radio buttons in the payment methods list. They are displayed separately from other payment methods.
## Step 4: Start the checkout process
Use the configuration below to provide a seamless and user-friendly payment experience for your customers:
```javascript theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
await yuno.startSeamlessCheckout({
checkoutSession: "438413b7-4921-41e4-b8f3-28a5a0141638",
elementSelector: "#root",
countryCode: "US",
language: "en-US",
showLoading: true,
issuersFormEnable: true,
showPaymentStatus: true,
onLoading: (args) => console.log(args),
renderMode: {
type: "modal",
elementSelector: {
apmForm: "#form-element",
actionForm: "#action-form-element",
},
},
card: {
type: "extends",
styles: "",
cardSaveEnable: false,
texts: {},
hideCardholderName: false, // Optional: Set to true to hide cardholder name field
},
texts: {},
async yunoCreatePayment(oneTimeToken, tokenWithInformation) {
await createPayment({
oneTimeToken,
checkoutSession,
vault_on_success: true
});
await yuno.continuePayment({ showPaymentStatus: true });
},
onPaymentMethodSelected(data) {
console.log("Payment method selected:", data);
},
yunoPaymentResult(data) {
console.log("Payment result:", data);
await yuno.hideLoader();
},
yunoError(error, data) {
console.error("An error occurred:", error);
await yuno.hideLoader();
},
});
```
When using `startSeamlessCheckout`, specify the callbacks to handle payments. You can also customize the checkout interface using the `texts` objects.
### Parameters
Configure the seamless checkout with the following options:
| Parameter | Description |
| ------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `checkoutSession` | Refers to the current payment's [checkout session](/reference/checkout-sessions/the-checkout-session-object). Example: `438413b7-4921-41e4-b8f3-28a5a0141638`. |
| `elementSelector` | The HTML element where the checkout will be rendered. |
| `countryCode` | This parameter specifies the country for which the payment process is being set up. Use an `ENUM` value representing the desired country code. You can find the full list of supported countries and their corresponding codes on the [Country Coverage](/docs/sdks/resources/country-coverage) page. |
| `language` | Language for payment forms. Use any code listed in [Supported languages](/docs/sdks/resources/languages-supported). Example: `en-US`. Defaults to browser language when available. |
| `showLoading` | Controls the visibility of the Yuno loading/spinner page during the payment process. Default: `true`. |
| `onLoading` | Required to receive notifications about server calls or loading events during the payment process. |
| `issuersFormEnable` | Enables the issuer's form (e.g., a list of banks). Default: `true`. |
| `showPaymentStatus` | Shows the Yuno Payment Status page, which is useful when continuing a payment. Default: `true`. |
| `showPayButton` | Controls the visibility of the pay button in the customer or card form. Default: `true`. |
| `renderMode` | Specify how and where the forms will be rendered. The options available are: |
| | ▪️ `type: modal` (default) |
| | ▪️ `type: element` - If you select `element`, you must inform the `elementSelector` to specify where the form should be rendered. |
| `card` | Defines the configuration for the card form. It contains settings like custom styles, save card option, and optional `hideCardholderName` to hide the cardholder name field. When `hideCardholderName` is set to `true`, the cardholder name field is not rendered. When not specified or set to `false`, the cardholder name field is displayed (default behavior). Hiding the field does not affect PAN, expiry, CVV collection, BIN logic, or 3DS/provider validations. |
| `texts` | Allows you to set custom button texts for card and non-card payment forms. |
| `yunoCreatePayment` | Placeholder function for creating a payment. This function will not be called but should be implemented. When creating the payment, you can include `vault_on_success: true` to enroll the payment method after a successful payment. See [Enrolling payment methods](#enrolling-payment-methods-in-seamless-flow) for more details. |
| `onPaymentMethodSelected` | Callback invoked when a payment method is selected, along with the method's type and name. |
| `yunoPaymentResult` | Callback called after the payment is completed, with the [payment status](/reference/payments/status-and-response-codes/payment) (e.g., `SUCCEEDED`, `DECLINED`, `PENDING`, `ERROR`) and an optional `subStatus` qualifying it. See [Shopper-cancelled steps](/docs/sdks/resources/references/web#shopper-cancelled-steps). |
| `yunoError` | Callback invoked when there is an error in the payment process. Receives error type and optional additional data. |
**Customer and Merchant-Initiated Transactions**
Payments can be initiated by the customer (CIT) or by the merchant (MIT). You find more information about their characteristics in [Stored credentials](/docs/payment-features/stored-credentials).
The step-by-step on this page refers to a customer-initiated transaction without the recurrence option. Typically, it's used in one-time online purchases, in-store purchases, ATM withdrawals, etc.
## Step 5: Mount the SDK
To present the checkout process, use the `await yuno.mountSeamlessCheckout()` function. This step ensures the SDK is properly mounted on your chosen HTML element.
```javascript theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
await yuno.mountSeamlessCheckout();
```
After mounting, you must start the checkout flow by calling `await yuno.startPayment()`. If you skip this call, the payment form will not open.
## Step 6: Start the payment flow (Required)
Call `await yuno.startPayment()` immediately after `await yuno.mountSeamlessCheckout()` to open the selected payment method UI:
```javascript theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
await yuno.mountSeamlessCheckout();
await yuno.startPayment();
```
Alternatively, you can trigger the start from a user action such as a button click:
```javascript theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
const payButton = document.querySelector('#button-pay');
payButton.addEventListener('click', async () => {
await yuno.startPayment();
});
```
**Demo App**
In addition to the code examples provided, you can access the [Demo App](https://github.com/yuno-payments/yuno-sdk-web) for a complete implementation of Yuno SDKs (clone from the repository).
## Mount external buttons
You can use the `mountExternalButtons` method to render Google Pay and Apple Pay buttons in custom locations within your UI. This gives you control over where these buttons are displayed.
```javascript theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
await yuno.mountExternalButtons([
{
paymentMethodType: 'APPLE_PAY',
elementSelector: '#apple-pay',
},
{
paymentMethodType: 'GOOGLE_PAY',
elementSelector: '#google-pay',
},
]);
```
### Parameters
| Parameter | Description |
| :------------------ | :------------------------------------------------------------------------------------------------------------- |
| `paymentMethodType` | The payment method type. Must be either `'APPLE_PAY'` or `'GOOGLE_PAY'`. |
| `elementSelector` | The CSS selector for the HTML element where the button should be rendered (e.g., `'#apple-pay'`, `'.button'`). |
### Unmounting buttons
You can unmount a single external button by payment method type:
```javascript theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
await yuno.unmountExternalButton('APPLE_PAY');
```
Or unmount all external buttons at once:
```javascript theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
await yuno.unmountAllExternalButtons();
```
### Unmounting the SDK
For explicit cleanup of the Yuno SDK (e.g., when a user cancels the flow or you need to remove the SDK from the DOM), use the `unmountSdk()` method:
```javascript theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
await yuno.unmountSdk();
```
## Revolut Pay
There are two ways to render the Revolut Pay button:
1. **Full checkout** — the button shows up inside the payment method list rendered by the SDK.
2. **External buttons** (`mountExternalButtons`) — the merchant decides which container on their page the button mounts into.
In both cases, the button configuration goes in `externalButtons.revolutPay` inside `startCheckout`. Unlike other buttons, the widget is rendered by Revolut's own SDK — the configuration maps directly to Revolut's button options.
### External buttons integration
The merchant defines a container in their HTML and mounts the button there:
```html theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
```
```javascript theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
const yuno = await window.Yuno.initialize(PUBLIC_API_KEY);
await yuno.startCheckout({
checkoutSession,
elementSelector: '#root',
countryCode,
language,
// Receives the one-time token when the buyer confirms in the Revolut widget.
// IMPORTANT: create the payment in your backend RIGHT AWAY and call
// continuePayment() — the Revolut widget stays open waiting for the order
// to be completed with the created payment.
async yunoCreatePayment(oneTimeToken, tokenWithInformation) {
await createPaymentInYourBackend({ oneTimeToken, checkoutSession });
yuno.continuePayment();
},
yunoPaymentResult(data) { /* final payment status */ },
yunoError: (error) => { /* flow errors (including widget cancellation) */ },
// Receives { isLoading, type } — Revolut Pay emits type: 'OTT' while the
// token is generated and type: 'CREATE_PAYMENT' in the SDK-driven flow.
onLoading: (data) => { /* show/hide your loader */ },
// Button configuration (see Configuration section below)
externalButtons: {
revolutPay: {
variant: 'dark',
size: 'large',
radius: 'round',
action: 'pay',
locale: 'es',
},
},
});
await yuno.mountExternalButtons([
{
paymentMethodType: 'REVOLUT_PAY',
elementSelector: '#revolut-pay-element',
},
]);
```
To unmount the Revolut Pay button, use the same methods described in [Unmounting buttons](#unmounting-buttons):
```javascript theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
yuno.unmountExternalButton('REVOLUT_PAY'); // this button only
yuno.unmountAllExternalButtons(); // all external buttons
```
### Checkout session requirements
For Revolut Pay to work, the checkout session the merchant creates (backend to backend) must include these fields — the SDK reads them from the session, nothing is configured on the frontend:
* `amount.value` and `amount.currency` — required; used to create the Revolut order shown in the widget.
* `callback_url` — required; used as the mobile redirect URL to return to the merchant page (see [Mobile redirects](#mobile-redirects-callback_url) below).
### Configuration (`externalButtons.revolutPay`)
All configuration is optional. The button is rendered by Revolut, so the options map to Revolut's official button styles:
### Mobile redirects (`callback_url`)
On mobile, the Revolut flow can jump to the Revolut app (or an in-app browser) instead of staying in the popup. To come back to the merchant's page, the SDK needs redirect URLs — it resolves them automatically from the `callback_url` the merchant already sends when creating the checkout session (backend to backend):
* The session's `callback_url` is used for the three outcomes: `success`, `failure`, and `cancel`.
* Nothing extra is needed in the SDK configuration — if the session has a `callback_url`, mobile redirects work; if it doesn't, the flow stays web-only.
* When the buyer returns from the Revolut app, the URL includes a `_rp_fr` query parameter appended by Revolut — harmless, but merchants parsing the return URL strictly should be aware of it.
**Desktop vs. mobile redirects**
Only *mobile* redirect URLs are configured by the SDK. Desktop flows always resolve inside the widget/popup — no redirect happens.
## PayPal REDIRECT Workflow
The Yuno SDK supports a `REDIRECT` workflow for PayPal. This workflow is useful when PayPal was not initialized at the start of the SDK or when using a pre-existing PayPal `orderId`.
* **PaypalButtonModal**: If PayPal is not initialized, the SDK can render the PayPal button inside a modal.
* **Workflow**: The `REDIRECT` workflow skips fraud detection and OTT creation, utilizing the provided `orderId`.
```javascript theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
// Example PayPal configuration
await yuno.startSeamlessCheckout({
// ... other config
paypal: {
workflow: 'REDIRECT',
orderId: 'PAYPAL_ORDER_ID',
}
});
```
## Enrolling payment methods in seamless flow
You can enroll payment methods (store cards for future use) directly during the seamless payment flow by setting `payment_method.vault_on_success = true` in the [checkout session creation](/reference/checkout-sessions/the-checkout-session-object).
When `vault_on_success` is set to `true`:
* The payment method will be automatically enrolled if the payment status is `SUCCEEDED`
* If the payment does not succeed, no vaulting will occur
* The payment response will include a `vaulted_token` that you can use for future transactions
**Example:**
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"account_id": "...",
...
"payment_method": {
"vault_on_success": true
}
}
```
**Vaulting Requirements**
To generate and receive a `vaulted_token` when `vault_on_success = true`, the payment must reference an existing Yuno customer through `customer_payer.id` in the checkout session. Creating or sending the customer data inline inside the payment request does not create the customer on our side, so no vaulting will occur.
For more information about enrolling payment methods, see [Enroll Payment Methods](/docs/payment-features/enrollment/enroll-payment-methods).
## Error handling
Handle errors returned by the SDK in your app (e.g. failed payments, validation errors). For HTTP status and response codes, see [Status and response codes](/reference/payments/status-and-response-codes/payment) in the API reference.
### Payment retry
When a **card** payment comes back `DECLINED` or `ERROR`, payment retry keeps the card form open so the shopper can correct their details and try again without restarting checkout — controlled by `settings.card.enable_payment_retry` under [`styling.settings`](/reference/checkout-builder/publish-checkout-configuration).
In the **seamless** flow this is automatic — the SDK keeps the form open and drives the retry for you. In the Full Checkout, Lite, and Secure Fields flows you must call `continuePayment` on a declined/errored card payment to trigger it. See [Payment retry](/docs/sdks/resources/references/web#payment-retry) in the Web Reference for details.
## Stay updated
Visit the [changelog](/changelog/web#v1-6-0) for the latest SDK updates and version history.
# 3D Secure
Source: https://docs.y.uno/docs/security-and-compliance/3d-secure
Explains 3D Secure 2 authentication flows, configuration requirements, and integration options for card payments.
## What is 3D Secure?
3D Secure, or 3DS, is a security protocol for online payments designed to prevent the fraudulent use of credit cards in card-not-present (CNP) transactions. The protocol, developed in 1999, requires additional verification steps for customers during the purchase process to authenticate themselves and reduce the risk of fraud. The flow below presents a payment process using 3DS:
Where:
* **Merchant Plugin Interface (MPI)** initiates the verification process by facilitating the secure exchange of information between the merchant, scheme Directory Server, and the cardholder’s issuing bank.
* **Scheme Directory Server (DS)** acts as a centralized database and facilitates the identification of the appropriate cardholder’s issuing bank and the corresponding authentication method to be used.
* **Issuer Access Control Server (ACS)** is responsible for verifying and validating the cardholder’s identity during a 3DS transaction. The Issuer ACS receives authentication requests and performs risk assessments and authentication checks based on the bank’s predefined rules and policies.
3D Secure 2, or 3DS2, published in 2016, is an updated version of the original 3DS protocol and uses dynamic authentication methods such as biometrics and token-based authentication, whereas the original 3DS protocol relies on static passwords. 3DS2 aims to provide a better user experience with a more fluid flow for end users during authentication. EMVCo, an organization owned by major card brands, developed and managed both protocols. All major card brands stopped supporting the first version of 3DS in October 2022. Therefore, integrating the 3DS2 verification step is essential to ensure your customers' experience and security. Yuno already provides an easy 3DS2 integration for your business.
## Benefits of 3D Secure 2
As mentioned, 3DS2 was developed to enhance the user experience and adapt the 3DS protocol to the modern payment landscape.
### Prepared for new technologies
3DS2 was designed with the rise of smartphones in mind and allowed banks to offer innovative authentication experiences through their mobile banking apps, such as biometric authentication using fingerprints or facial recognition. Therefore, merchants can offer several authentication methods that align with consumer preferences and technological advancements, resulting in a more convenient and secure authentication process.
### Integration capabilities
Regarding integration, 3DS2 includes an SDK component that enables native integration into mobile apps. As a result, merchants can authenticate transactions within their own apps. Now, the challenge flow happens directly within the mobile checkout flows, eliminating the need for full-page redirects and providing a more seamless user experience.
### Amount of data available for authentication
3DS2 allows businesses to exchange ten times more data on each transaction to the cardholder's bank. This includes payment-specific data, such as shipping address, and contextual data, such as the customer's device ID or previous transaction history. This allows the bank to assess the transaction's risk level and potentially authenticate the payment without additional input from the cardholder. Therefore, a payment using 3DS2 protocols can face a **frictionless flow** or a **challenge flow** to complete the payment.
#### Frictionless flow
In a frictionless flow, the customer's data is confirmed without any manual data entry. It happens when the system recognizes and verifies the customer’s device, and the data is exchanged in the background. As the customer is identified and validated with this information, no additional requests from the payment systems are necessary.
#### Challenge flow
The challenge flow happens when the stored information isn't enough to validate the customer. As the customer's identity is not confirmed, the system requires an additional step to validate the customer, using a one-time password or biometric verification. Depending on the validation system, the customer may be redirected to a card issuer’s page to enter the necessary information.
The use of 3DS2 results in a smoother and more frictionless user experience. The improved data flows and decision-making capabilities enabled by 3DS2 reduce the cart abandonment rate and improve the conversion rates.
## 3D Secure 2 Payment
Adding the 3DS2 verification step to the checkout process changes the normal workflow. Below is a flow chart of the complete checkout and a description of each step to help you better understand the process.
1. The customer provides their card data to initiate the merchant checkout process.
2. The merchant's system checks if it supports 3DS2.
3. If the merchant does not support 3DS2, the checkout process proceeds with the regular payment workflow without using the 3DS2 verification.
4. If the merchant supports 3DS2, Yuno sends the transaction information to the issuer's 3DS service provider to assess the transaction risk. This data includes cardholder and device information upon regional or market law restrictions, such as device ID, MAC address, geo-location, previous transactions, and more.
5. The issuer's 3DS service provider determines if the transaction is high-risk and if a challenge is necessary for additional verification.
6. The payment proceeds to the authorization step if no challenge is necessary (frictionless flow).
7. If a challenge is required (challenge flow), it is presented to the cardholder to verify their identity. This verification can use biometrics and/or two-factor authentication, such as a one-time password or a fingerprint.
8. The system checks if the cardholder successfully completed the challenge.
9. The payment proceeds to the authorization step if the cardholder successfully verifies their identity.
10. If the cardholder fails to verify their identity, the payment is cancelled.
11. The merchant checks with the card issuer if the transaction is authorized.
12. If the transaction is authorized, the payment is processed successfully.
13. If the transaction is not authorized, the payment is cancelled or declined.
## Configuring 3D Secure for your payments
**SDK v1.1 Enhancement**
With SDK v1.1, 3DS logic is handled automatically using the `continuePayment()` method - no separate 3DS setup is required. For more information, see the [Yuno Web SDK documentation](/docs/sdks/full-checkout/web-payments).
You decide if your system will implement the 3DS2 or not. The 3DS2 verification step is added while defining your cards [dynamic routing](/docs/routing#configuring-the-dynamic-routing). When starting your card routes, you can add the 3DS2 step before defining the payment provider. When adding the 3DS2 verification step, when a payment using a card is initialized, the Yuno system will analyze if the card needs an extra challenge. If an extra challenge is necessary, the user will be redirected to the bank environment to complete the authorization. On the other hand, the payment process will proceed normally.
To create payments with the 3DS DIRECT workflow, you need to fulfill some requirements.
### Requirements
Before using 3DS DIRECT, you need to enable 3DS in your [Yuno Dashboard](https://dashboard.y.uno/) and specify the scenarios in which you want your customers to be able to use it. This can be configured in the Yuno Dashboard under: **Routing > Card Routes > 3DS Step**. These scenarios must be indicated on your CARD route. Additionally, you will require the following 3DS setup data in the payment provider connection:
* **Acquirer BIN**: This is the Bank Identification Number (BIN) used to clear and settle the transaction, along with the country in which it is licensed for use. This value is brand-specific — request one per card brand you will authenticate (see the warning below).
* **Merchant ID**: This is the affiliation number provided by the acquirer.
* **Merchant Category Code (MCC)**: The acquirer will provide a specific code representing your merchant category.
* **Merchant's Name**: Refers to the official name or business name of the company or entity conducting the commercial transaction.
* **Merchant URL**: The merchant's website or online platform.
* **Country Code**: The country where the payment needs to be processed, following the [ISO 3166-1](/reference/country-reference) Standard Country Codes.
**The acquirer BIN is brand-specific — and it is not the ICA or Seller ID**
Each card scheme's Directory Server only accepts authentication requests that carry an acquirer BIN registered with that specific scheme. When collecting 3DS credentials from your acquirer, keep in mind:
* Request one acquirer BIN **per card brand** you plan to authenticate (Visa, Mastercard, American Express, Discover/Diners). A BIN registered for one brand does not work for another — for example, a Visa acquiring BIN (starting with 4) is not valid for Mastercard authentications.
* For **Mastercard**, acquirers sometimes share their ICA number (a Mastercard membership identifier, often zero-prefixed) instead of an acquirer BIN. The Mastercard Directory Server does not accept the ICA: authentications fail with EMV 3DS error `303` — "Access denied, invalid endpoint / acquirerBIN not recognized". Ask your acquirer specifically for the **Mastercard acquiring BIN registered for Identity Check (EMV 3DS)** — a value within Mastercard's BIN ranges (2-series or 5-series).
* For **American Express and Discover**, the Seller ID or SE number is your merchant identifier in those networks (it maps to the Acquirer Merchant ID) — it is not the brand's acquirer BIN. Both values are required.
If an authentication fails with error `303` from the Directory Server, the acquirer BIN configured for that brand is wrong or not registered for 3DS — request the correct value from your acquirer, for example: *"For each card network (Visa, Mastercard, American Express, Discover), please provide the acquirer BIN registered with the scheme's Directory Server for EMV 3DS authentication with an external 3DS Server, together with our Acquirer Merchant ID and MCC as registered with the scheme."*
**Using an External MPI for Authentication**
If you are using an external MPI to perform the authentication, the following parameters are required for a successful connection with the provider:
* Acquirer BIN
* Acquirer country code
* Merchant ID
* MCC
## Yuno 3D Secure 2 integration
There are different ways of integrating 3DS in Yuno, depending on your needs.
In general terms, a 3DS integration requires a `setup_id`/`device_fingerprint` for the payment session as the first step for security analysis, and that id can only be obtained by executing a SDK/JS powered by a 3DS authorized provider. While using our SDKs **we take care of all the logic for you**, so you don't have to worry about different provider needs.
Therefore, depending on your Yuno integration, you have three different options:
1. **Checkout integration**: The Checkout workflow is part of the [Checkout](/docs/sdks/overview/quickstart) solution provided by Yuno. Use our SDKs so we can handle all the logic regarding external provider requirements and executions for 3DS. If you want to define specific cases for 3DS analysis, you can define that in the CARD route of your Yuno dashboard.
2. **External integration**: Use your own 3DS and then send the corresponding authorization fields in the [payment creation](/reference/create-payment) (card\_data - eci, cryptogram, etc). Only available for PCI-compliant merchants.
3. **Direct integration**: The Direct workflow is only available for PCI-compliant merchants. It provides a straightforward way to create a payment and validate user information, requiring the merchant to perform just one request to create the payment. To successfully implement the Direct integration, follow the steps outlined in the [integration guideline](/docs/direct-flow) and provide the required information as instructed. For each payment you'll have a:
1. `PENDING/WAITING_ADDITIONAL_STEP` status/sub status.
2. `sdk_action_required` set as `true`.
3. `redirect_url` defined in `payment.payment_method.payment_method_detail.card`.
You are responsible for redirecting your customers to the URL provided by the `redirect_url` so we can gather device information and present the challenge to the customer if necessary. Once the customer successfully completes the 3DS challenge, they will be automatically redirected to the `callback_url`, which you provided when creating the payment with the Create Payment endpoint.
For every scenario the Yuno [webhooks](/docs/configure-webhooks) will promptly notify you about the outcome of the 3DS challenge and the final payment status. This ensures that you receive real-time updates on the progress and completion of the payment transaction. Also, you can always get the payment information by using our [get payment service](/reference/retrieve-payment-by-id).
After executing the 3DS for each scenario, you'll receive all the necessary information in the payment's response inside the `payment_method.detail.card.card_data.three_d_secure` object:
| Field | Description | Example |
| :--------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------- |
| version | Refers to the protocol version of the EMV 3-D Secure specification used. 1.0, 2.0, 2.1.0, 2.2.0, 2.2.1. | 2.2.1 |
| electronic\_commerce\_indicator | This field must be completed with the result of the ECI field provided by the 3d Secure service. The Electronic Commerce Indicator (ECI) informs the card issuer if the transaction was protected by a security protocol like VbV or MCSC. It is mandated by Visa and MasterCard that all 3-D Secure transactions have this value populated in the authorization request (MAX: 2, MIN: 0). | 04 |
| cryptogram | The cryptogram value provided by the 3DSecure service, proving the cardholder was authenticated (MAX: 40, MIN: 0). | BA0BB1Z3N5Q4kjkBU3c3ELGUsJY = |
| transaction\_id | For 3DS v1: This is the Unique Transaction Identifier. It is automatically generated by the MPI. It is typically 28 bytes in length and base64-encoded. Is commonly referred to as XID (MAX: 40, MIN: 0). For 3DS v2: Universally unique transaction identifier assigned by the DS to identify a single transaction. (MAX: 36, MIN:36). | Ex for V1: “TjY0MjAxRjA4MD4987DUzMzYyNjU=” Ex for V2: “c4e59ceb-a382-4d6a-bc87-385d591fa09d” |
| directory\_server\_transaction\_id | Transaction ID generated by the Mastercard directory server during authentication (MAX 255; MIN 3). | f38e6948-5388-41a6-bca4-b49723c19437 |
| pares\_status | Indicates the outcome of the cardholder authentication during the 3-D Secure process. It informs you whether the authentication was successful (Y), failed (N), could not be completed (U), or was only attempted (A). | Y |
| acs\_id | Unique identifier provided by the Access Control Server (ACS) during the 3-D Secure authentication process. | ACS-1234567890 |
| liability\_shift | Boolean indicating whether fraud liability shifted from the merchant to the card issuer as a result of the authentication: `true` when it shifted to the issuer, `false` when the merchant retains it. Can also be `null`, including in some successful-authentication cases — if you see `null` unexpectedly and rely on this field for chargeback handling, contact Yuno support. | true |
In Visa transactions, the `cryptogram` represents the Cardholder Authentication Verification Value (CAVV), a cryptographic value generated by the issuer as evidence of payment authentication during the online purchase, used to qualify for chargeback protection. Mastercard transactions carry an equivalent value called the Accountholder Authentication Value (AAV), or the Universal Cardholder Authentication Field (UCAF). When submitting a transaction for authorization, the merchant must include the CAVV or AAV/UCAF to demonstrate that the cardholder has been authenticated.
```json Example theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
[...]
"payment_method": {
"vaulted_token": "",
"type": "CARD",
"vault_on_success": false,
"token": "",
"detail": {
"card": {
"verify": false,
"capture": false,
"installments": 1,
"installments_plan_id": null,
"first_installment_deferral": 0,
"installments_type": "MERCHANT",
"installment_amount": null,
"soft_descriptor": "",
"authorization_code": "",
"retrieval_reference_number": "",
"acquirer_reference_number": "",
"voucher": null,
"card_data": {
"holder_name": "John Doe",
"iin": "40000000",
"lfd": "1026",
"number_length": 16,
"security_code_length": 3,
"brand": "VISA",
"issuer_name": "",
"issuer_code": null,
"category": "STANDARD",
"type": "CREDIT",
"three_d_secure": {
"version": "2.1.0",
"electronic_commerce_indicator": null,
"cryptogram": null,
"transaction_id": null,
"directory_server_transaction_id": null,
"pares_status": null,
"acs_id": "z1A6ZTh7NopIhdb2R420"
}
}
[...]
```
### Transactions status
A 3DS transaction functions similarly to a regular purchase transaction. It progresses through different states that represent the authorization process. Once the 3DS transaction is marked as SUCCEEDED, Yuno proceeds to the processor and generates a PURCHASE transaction to charge the client. The following table describes all possible states and their descriptions.
| Status | Description |
| :---------- | :--------------------------------------------------------------------- |
| CREATED | Payment is created and waiting for Yuno's SDK session id. |
| PENDING | The challenge is required, and the `redirect_url` is returned by Yuno. |
| IN\_PROCESS | The user is completing the challenge. |
| SUCCEEDED | The challenge was completed correctly. |
| DECLINED | The challenge was completed but declined by the bank. |
| ERROR | An error occurred while redirecting to the user's challenge. |
As mentioned before, if the payment is PENDING/WAITING\_ADDITIONAL\_STEP, the 3DS transaction will be PENDING when a Challenge is required. After the challenge is completed, either successfully or not, the payment and transaction will be updated to the corresponding states (SUCCEEDED or DECLINED).
### Using 3DS for Specific Scenarios
When configuring the CARD route in the Yuno dashboard, you can specify for which situations 3DS should be executed using the [available conditions](/docs/routing#configuring-the-dynamic-routing). As mentioned previously, some preliminary steps will be necessary to execute 3DS depending on the integration method used.
# Card Verification
Source: https://docs.y.uno/docs/security-and-compliance/card-verification
Verify a customer's card is valid at enrollment or payment without charging the customer.
Yuno lets you verify if the customer's credit card is real and is working. Our Credit Card Verification API is designed to empower your applications with a robust mechanism for validating credit card transactions, ensuring a seamless and secure payment experience for your users. This operation does not create any charges for your client.
## Advantages
With the Yuno card verification service, you can protect your business in real time:
* **Real-time Verification**: Instantly validate credit card details to ensure accuracy and authenticity.
* **Fraud Prevention**: Mitigate the risk of fraudulent transactions by verifying the legitimacy of credit card information.
* **Seamless Integration**: Easily integrate our API into your existing payment processing system, minimizing development time and effort.
## Integration
First, you need to define a route to use the card verification feature. When configuring the route, be sure to select:
* **Card** as payment method.
* Define the **Transaction type** **Equal** to **VERIFY**.
With the above configurations, all card verifications will be processed following the configuration of the created route.
**Select the Correct Provider**
* The credit card verification process isn't provided by all providers. Always contact your technical account manager to verify which providers support card verification.
* Yuno uses a zero-dollar authorization for card validations. If the provider does not support this flow, we will internally:
* Authorize the minimum possible amount and then cancel the authorization for credit cards.
* Perform a purchase for the minimum possible amount and then refund it for debit cards.
In addition to creating the route, you need to choose when to use the validation. You can verify cards during the [enrollment process](/reference/enroll-payment-method-checkout) or while making a credit [card payment](/reference/create-payment). Depending on your chosen process, you should use different endpoints or SDK functions.
### Verify the card at the enrollment
You can verify the card at the enrollment whether you are using the Direct or SDK integrations.
#### SDK integration
If you are using an integration based on SDKs, you need to define the `verify` object, informing the `currency` and `vault_on_success = true` when performing the enrollment. The code block below presents an example of card verification requests and responses using the SDK.
```json Request theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"payment_method_type": "CARD",
"country":"DE",
"account_id":"493e9374-510a-4201-9e09-de669d75f256",
"verify": {
"vault_on_success": true,
"currency": "EUR"
}
}
```
```json Response theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"id": "fbc68364-0456-41b6-9743-1acb07d55f14",
"idempotency_key": null,
"account_id": "493e9374-510a-4201-9e09-de669d75f256",
"name": "Card",
"description": "Card",
"type": "CARD",
"category": "CARD",
"country": "BR",
"status": "READY_TO_ENROLL",
"created_at": "2024-01-31T14:44:33.552281Z",
"updated_at": "2024-01-31T14:44:33.552283Z",
"enrollment": {
"session": "232b123d-c4d9-4ddc-b776-e0b0eaa6bb8b",
"sdk_required_action": true
},
"provider": {
"id": "YUNO",
"type": "YUNO",
"provider_status": null
},
"customer_payer": {
"first_name": "Fernando",
"last_name": "Iglesias",
"email": "Anastasia.Kirlin16@yahoo.com",
"gender": null,
"date_of_birth": null,
"document": null,
"phone": null,
"billing_address": null
},
"verify": {
"vault_on_success": true,
"currency": "BRL",
"payment": null
},
"preferred": null
}
```
Access the [SDK integration](/reference/enroll-payment-method-checkout) page for additional information related to the enrollment process.
#### Direct integration
To verify the card at the enrollment with the Direct integration, you will use the [Enroll Payment Method](/reference/enroll-payment-method-api) endpoint. In addition to the `card_data` object, you need to provide the `verify` object. Inside of the `verify` object you define the `currency` and provide `vault_on_success = true`. The code block below presents an example of card verification requests and responses using the [Enroll Payment Method](/reference/enroll-payment-method-api).
```json Request theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"account_id": "493e9374-510a-4201-9e09-de669d75f256",
"country": "DE",
"type": "CARD",
"workflow": "DIRECT",
"card_data": {
"holder_name": "John Smith",
"expiration_month": 10,
"expiration_year": 24,
"number": "4988080000000000",
"security_code": "123"
},
"verify": {
"vault_on_success": true,
"currency": "EUR"
}
}
```
```json Response theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"name": "VISA ****0000",
"description": "VISA ****0000",
"type": "CARD",
"category": "CARD",
"country": "BR",
"status": "ENROLLED",
"sub_status": null,
"vaulted_token": "5d4d8b95-c6f8-4336-b051-9eb06a436139",
"callback_url": null,
"action": "FORM",
"redirect_url": null,
"created_at": "2024-01-31T14:47:39.643700Z",
"updated_at": "2024-01-31T14:47:39.643701Z",
"card_data": {
"iin": "49880800",
"lfd": "0000",
"expiration_month": 10,
"expiration_year": 24,
"number_length": 16,
"security_code_length": 3,
"brand": "VISA",
"issuer": null,
"issuer_code": null,
"category": "BUSINESS ENHANCED",
"type": "DEBIT"
},
"last_successfully_used": null,
"last_successfully_used_at": null,
"preferred": null,
"verify": {
"vault_on_success": true,
"currency": "BRL",
"payment": {
"id": "0aacd66c-6933-4827-813f-8d76637f874d",
"account_id": "493e9374-510a-4201-9e09-de669d75f256",
"description": "VERIFY CARD",
"country": "BR",
"status": "SUCCEEDED",
"sub_status": "VERIFIED",
"merchant_order_id": "VERIFY_CARD_5d4d8b95-c6f8-4336-b051-9eb06a436139",
"created_at": "2024-01-31T14:47:39.717571Z",
"updated_at": "2024-01-31T14:47:41.617945Z",
"amount": {
"currency": "BRL",
"value": 0,
"refunded": 0,
"captured": 0
},
"transactions": [
{
"id": "ead4ed19-5998-4b40-9910-d2dfe25b9fe0",
"type": "VERIFY",
"status": "SUCCEEDED",
"response_code": "SUCCEEDED",
"response_message": "Transaction successful",
"category": "CARD",
"merchant_reference": "VERIFY_CARD_5d4d8b95-c6f8-4336-b051-9eb06a436139",
"provider_data": {
"id": "CIELO",
"transaction_id": "",
"account_id": "",
"status": "true",
"sub_status": "",
"status_detail": "",
"response_message": "Transacao autorizada",
"response_code": null,
"raw_response": {
"ReturnCode": "00",
"ReturnMessage": "Transacao autorizada",
"Valid": true
},
"third_party_transaction_id": null,
"third_party_account_id": null
},
"created_at": "2024-01-31T14:47:39.827470Z",
"updated_at": "2024-01-31T14:47:41.567732Z"
}
]
}
}
}
```
**Verification Feature Availability**
The verify feature at the enrollment is only available for PCI-compliant merchants when using the Direct integration.
### Verify the card at the payment
If you want to verify the card using a payment operation, you need to fulfill two requirements:
* Inform `amount.value=0`.
* Add `verify = true` inside of the `payment_method.detail.card.` object.
Following the above instructions, the resulting operation won't result in any charges for your client.
#### SDK integration
The code block below presents an example of card verification using the payment operation for an SDK integration.
```json Request theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"description": "Test Cards",
"account_id": "493e9374-510a-4201-9e09-de669d75f256",
"merchant_order_id": "0000022",
"merchant_reference": "Test Payment",
"country": "DE",
"amount": {
"currency": "EUR",
"value": 0
},
"checkout": {
"session": "5752d02a-64d2-4953-b8f7-defff1e1b7e6"
},
"customer_payer": {
"id": "9d58f32a-1ec9-4092-94b2-6725363ab447"
},
"payment_method": {
"token": "2c37e3b7-8b06-4e8b-a212-334d7c77e349",
"detail": {
"card": {
"verify":true
}
}
}
}
```
```json Response theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"id": "47646d8b-1f99-4097-9df2-3097bf318bb9",
"account_id": "493e9374-510a-4201-9e09-de669d75f256",
"description": "Test Cards",
"country": "BR",
"status": "SUCCEEDED",
"sub_status": "VERIFIED",
"merchant_order_id": "0000022",
"created_at": "2024-01-31T15:19:03.599525Z",
"updated_at": "2024-01-31T15:19:06.992590Z",
"amount": {
"captured": 0,
"currency": "BRL",
"refunded": 0,
"value": 0
},
"checkout": {
"session": "5752d02a-64d2-4953-b8f7-defff1e1b7e6",
"sdk_action_required": false
},
"payment_method": {
"vaulted_token": "1f275d9f-a60a-4643-a5b0-ae6e40019fd1",
"type": "CARD",
"vault_on_success": true,
"token": "2c37e3b7-8b06-4e8b-a212-334d7c77e349",
"payment_method_detail": {
"card": {
"verify": true,
"capture": true,
"installments": 1,
"installments_plan_id": null,
"installments_total_amount": null,
"first_installment_deferral": 0,
"installments_type": "MERCHANT",
"installment_amount": null,
"soft_descriptor": "",
"authorization_code": "",
"retrieval_reference_number": "",
"acquirer_reference_number": "",
"voucher": null,
"card_data": {
"holder_name": "Pepito Perez2",
"iin": "49880800",
"lfd": "0000",
"number_length": 16,
"security_code_length": 3,
"brand": "VISA",
"issuer_name": "DEUTSCHE BANK AG INDIA",
"issuer_code": null,
"category": "BUSINESS ENHANCED",
"type": "DEBIT",
"three_d_secure": {
"version": null,
"electronic_commerce_indicator": null,
"cryptogram": null,
"transaction_id": null,
"directory_server_transaction_id": null,
"pares_status": null,
"acs_id": null
}
}
}
}
},
"customer_payer": {
"id": "9d58f32a-1ec9-4092-94b2-6725363ab447",
"merchant_customer_id": "1706712254",
"first_name": "Fernando",
"last_name": "Iglesias",
"gender": "",
"date_of_birth": null,
"email": "Anastasia.Kirlin16@yahoo.com",
"nationality": null,
"ip_address": "181.117.11.229",
"device_fingerprint": null,
"browser_info": {
"user_agent": "",
"accept_header": "",
"accept_content": null,
"accept_browser": null,
"color_depth": "",
"screen_height": "",
"screen_width": "",
"javascript_enabled": null,
"java_enabled": null,
"browser_time_difference": null,
"language": ""
},
"document": {
"document_type": "DNI",
"document_number": "38799992"
},
"phone": null,
"billing_address": null,
"shipping_address": null
},
"additional_data": null,
"taxes": null,
"transactions": {
"id": "9be01510-afab-450a-86cc-916d0d4cd8a5",
"type": "VERIFY",
"status": "SUCCEEDED",
"category": "CARD",
"amount": 0,
"provider_id": "CIELO",
"payment_method": {
"vaulted_token": "1f275d9f-a60a-4643-a5b0-ae6e40019fd1",
"type": "CARD",
"vault_on_success": true,
"token": "2c37e3b7-8b06-4e8b-a212-334d7c77e349",
"detail": {
"card": {
"verify": true,
"capture": true,
"installments": 1,
"installments_plan_id": null,
"installments_total_amount": null,
"first_installment_deferral": 0,
"installments_type": "MERCHANT",
"installment_amount": null,
"soft_descriptor": "",
"authorization_code": "",
"retrieval_reference_number": "",
"acquirer_reference_number": "",
"voucher": null,
"card_data": {
"holder_name": "Pepito Perez2",
"iin": "49880800",
"lfd": "0000",
"number_length": 16,
"security_code_length": 3,
"brand": "VISA",
"issuer_name": "DEUTSCHE BANK AG INDIA",
"issuer_code": null,
"category": "BUSINESS ENHANCED",
"type": "DEBIT",
"three_d_secure": {
"version": null,
"electronic_commerce_indicator": null,
"cryptogram": null,
"transaction_id": null,
"directory_server_transaction_id": null,
"pares_status": null,
"acs_id": null
}
}
}
}
},
"response_code": "SUCCEEDED",
"response_message": "Transaction successful",
"reason": null,
"description": "Test Cards",
"merchant_reference": "Pago de test 001",
"provider_data": {
"id": "CIELO",
"transaction_id": "",
"account_id": "",
"status": "true",
"sub_status": "",
"status_detail": "",
"response_message": "Transacao autorizada",
"response_code": "SUCCEEDED",
"raw_response": {
"ReturnCode": "00",
"ReturnMessage": "Transacao autorizada",
"Valid": true
},
"third_party_transaction_id": "",
"third_party_account_id": ""
},
"created_at": "2024-01-31T15:19:03.704095Z",
"updated_at": "2024-01-31T15:19:06.639476Z"
},
"split": [],
"callback_url": "https://google.com/?checkoutSession=5752d02a-64d2-4953-b8f7-defff1e1b7e6",
"workflow": "SDK_CHECKOUT",
"metadata": [],
"fraud_screening": null,
"payment_link_id": "",
"subscription_code": null
}
```
#### Direct Integration
The code block below presents an example of card verification using the payment operation for a Direct integration.
```json Request theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"description": "SUCCESSFUL",
"account_id": "{{account-code}}",
"merchant_order_id": "0000023",
"country": "DE",
"merchant_reference" : "reference-{{$randomUUID}}",
"amount": {
"currency": "EUR",
"value": 0
},
"customer_payer": {
"first_name": "John",
"last_name": "Smith",
"merchant_customer_id": "example00234"
},
"workflow": "DIRECT",
"payment_method": {
"type": "CARD",
"detail": {
"card": {
"capture": true,
"verify":true,
"card_data": {
"number": "4988080000000000",
"holder_name": "JOHN SMITH",
"expiration_month": 10,
"expiration_year": 24,
"security_code": "456"
}
}
}
}
}
```
```json Response theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"id": "bcb42b81-c729-48cb-b782-1a0b6b706b31",
"account_id": "493e9374-510a-4201-9e09-de669d75f256",
"description": "SUCCESSFUL",
"country": "CO",
"status": "SUCCEEDED",
"sub_status": "VERIFIED",
"merchant_order_id": "0000023",
"created_at": "2024-01-31T15:07:04.513703Z",
"updated_at": "2024-01-31T15:07:06.573556Z",
"amount": {
"captured": 0,
"currency": "COP",
"refunded": 0,
"value": 0
},
"checkout": {
"session": "",
"sdk_action_required": false
},
"payment_method": {
"vaulted_token": "",
"type": "CARD",
"vault_on_success": false,
"token": "",
"payment_method_detail": {
"card": {
"verify": true,
"capture": true,
"installments": 1,
"installments_plan_id": null,
"installments_total_amount": null,
"first_installment_deferral": 0,
"installments_type": "MERCHANT",
"installment_amount": null,
"soft_descriptor": "",
"authorization_code": "",
"retrieval_reference_number": "",
"acquirer_reference_number": "",
"voucher": null,
"card_data": {
"holder_name": "JOHN DOE",
"iin": "49880800",
"lfd": "0000",
"number_length": 16,
"security_code_length": 3,
"brand": "VISA",
"issuer_name": "DEUTSCHE BANK AG INDIA",
"issuer_code": null,
"category": "BUSINESS ENHANCED",
"type": "DEBIT",
"three_d_secure": {
"version": null,
"electronic_commerce_indicator": null,
"cryptogram": null,
"transaction_id": null,
"directory_server_transaction_id": null,
"pares_status": null,
"acs_id": null
}
}
}
}
},
"customer_payer": {
"id": null,
"merchant_customer_id": "example00234",
"first_name": "Pepito",
"last_name": "Perez",
"gender": null,
"date_of_birth": null,
"email": null,
"nationality": null,
"ip_address": null,
"device_fingerprint": null,
"browser_info": {
"user_agent": "",
"accept_header": "",
"accept_content": null,
"accept_browser": null,
"color_depth": "",
"screen_height": "",
"screen_width": "",
"javascript_enabled": null,
"java_enabled": null,
"browser_time_difference": null,
"language": ""
},
"document": {
"document_type": "CC",
"document_number": "38799999"
},
"phone": null,
"billing_address": null,
"shipping_address": null
},
"additional_data": null,
"taxes": null,
"transactions": {
"id": "f0da4c61-0c39-493b-a274-16d204fefad9",
"type": "VERIFY",
"status": "SUCCEEDED",
"category": "CARD",
"amount": 0,
"provider_id": "CIELO",
"payment_method": {
"vaulted_token": "",
"type": "CARD",
"vault_on_success": false,
"token": "",
"detail": {
"card": {
"verify": true,
"capture": true,
"installments": 1,
"installments_plan_id": null,
"installments_total_amount": null,
"first_installment_deferral": 0,
"installments_type": "MERCHANT",
"installment_amount": null,
"soft_descriptor": "",
"authorization_code": "",
"retrieval_reference_number": "",
"acquirer_reference_number": "",
"voucher": null,
"card_data": {
"holder_name": "JOHN DOE",
"iin": "49880800",
"lfd": "0000",
"number_length": 16,
"security_code_length": 3,
"brand": "VISA",
"issuer_name": "DEUTSCHE BANK AG INDIA",
"issuer_code": null,
"category": "BUSINESS ENHANCED",
"type": "DEBIT",
"three_d_secure": {
"version": null,
"electronic_commerce_indicator": null,
"cryptogram": null,
"transaction_id": null,
"directory_server_transaction_id": null,
"pares_status": null,
"acs_id": null
}
}
}
}
},
"response_code": "SUCCEEDED",
"response_message": "Transaction successful",
"reason": null,
"description": "SUCCESSFUL",
"merchant_reference": "reference-d3286de8-0c0b-4681-b29c-0a82a67de8ba",
"provider_data": {
"id": "CIELO",
"transaction_id": "",
"account_id": "",
"status": "true",
"sub_status": "",
"status_detail": "",
"response_message": "Transacao autorizada",
"response_code": "SUCCEEDED",
"raw_response": {
"ReturnCode": "00",
"ReturnMessage": "Transacao autorizada",
"Valid": true
},
"third_party_transaction_id": "",
"third_party_account_id": ""
},
"created_at": "2024-01-31T15:07:04.628781Z",
"updated_at": "2024-01-31T15:07:06.512878Z"
},
"split": [],
"workflow": "DIRECT",
"metadata": [],
"fraud_screening": null,
"payment_link_id": "",
"subscription_code": null
}
```
**Important**
The verify feature at the payment is only available for PCI-compliant merchants when using the Direct integration.
# Co-badged Cards Compliance
Source: https://docs.y.uno/docs/security-and-compliance/co-badged-cards-compliance
Explains EU network selection requirements for co-badged cards and Yuno's SDK compliance support.
Co-badged cards are payment cards that support multiple payment networks (e.g., a card that supports both Cartes Bancaires and Visa). To comply with [EU IFR Regulation 2015/751 Article 8](https://eur-lex.europa.eu/eli/reg/2015/751/oj), merchants must allow customers to choose which network to use when processing payments with co-badged cards.
## What are co-badged cards?
Co-badged cards are payment cards that carry multiple network logos and can be processed through different payment networks. Common examples include:
* Cards that support both a domestic network (e.g., Cartes Bancaires in France) and an international network (e.g., Visa or Mastercard)
* Cards that support multiple international networks
When a merchant accepts payments through multiple networks supported by the same card, EU regulations require that customers be given a choice of which network to use.
## When is compliance required?
Compliance with EU IFR Regulation 2015/751 Article 8 is required when:
* A merchant accepts both domestic and international networks (e.g., Cartes Bancaires and Visa)
* The customer's card supports multiple networks that the merchant accepts
* The transaction is processed within the European Economic Area (EEA)
If a merchant only accepts one network, or if the customer's card only supports one network that the merchant accepts, no network selection is required. The regulation applies to transactions processed within the EEA; transactions outside the EEA are not subject to this requirement.
## EU IFR Regulation 2015/751 Article 8
[Regulation (EU) 2015/751](https://eur-lex.europa.eu/eli/reg/2015/751/oj), also known as the Interchange Fee Regulation (IFR), is a European Union regulation on interchange fees for card-based payment transactions. Article 8 specifically addresses co-badged cards and requires that merchants in the EEA allow customers to choose their preferred card network when using co-badged cards.
### Key Requirements
Article 8 requires that when a merchant accepts both domestic and international networks (e.g., Cartes Bancaires and Visa), the merchant must display a choice to EEA consumers allowing them to select which network to use. If a merchant only accepts one of the networks supported by the card, no network selection is required.
### Regulation Scope and Timeline
Regulation (EU) 2015/751 applies to all Member States of the European Union and the European Economic Area (EEA). The regulation entered into force on 8 June 2015, with Article 8 and related provisions applying from 9 June 2016.
## Yuno Solution
Yuno simplifies co-badged card compliance by providing built-in support through our SDKs, so merchants meet regulatory requirements without extra development.
**Automatic Compliance**
When using Yuno SDKs, merchants are compliant with co-badged card regulations out-of-the-box. The SDK automatically handles network detection and selection, see [How It Works](#how-it-works) below for what's automated.
### Supported SDK Versions
Co-badged card compliance is supported in specific versions of each Yuno SDK:
* **Web SDK**: Version 1.1.0 and later
* **iOS SDK**: Version 2.0.0 and later
* **Android SDK**: Version 2.0.0 and later
* **React Native SDK**: Version 1.0.16 and later
### How It Works
The SDK automatically handles compliance with no configuration required. Compliance is enabled by default as soon as a merchant accepts both networks of a co-badged card.
The SDK automatically:
* Detects which networks are supported by the customer's card based on the card IIN (Issuer Identification Number)
* Displays network selection options to customers when multiple networks are available
* Handles the Mastercard-required phrase "Select card brand (optional)" automatically
* Stores the selected network for use in recurring payments
When a co-badged card is detected, the SDK automatically presents network selection options to the customer. The UI is not customizable and is consistently displayed across all platforms (Web, iOS, Android, React Native).
### Recurring Payments
When a customer selects a network for their first payment, the SDK automatically stores this preference. For all subsequent recurring payments with the same card, the SDK automatically uses the initially selected network, ensuring compliance with the regulation requirement that all subsequent purchases be processed through the same network.
The SDK tracks and uses the selected network automatically, without merchant involvement.
## Direct Integration
Direct API integrations require merchants to handle co-badged card compliance themselves. See below for required steps.
**Manual Implementation Required**
For merchants using direct API integrations (not SDKs), additional steps are required to ensure compliance with co-badged card regulations. Merchants must implement network detection, selection UI, and network storage themselves.
### Merchant Requirements
Merchants using direct API integrations must implement compliance measures themselves. To be compliant with EU IFR Regulation 2015/751 Article 8, merchants using direct integrations must:
1. Detect which networks are supported by the customer's card
2. Present network selection options to customers when multiple networks are available
3. Include the selected network in payment requests
4. Store the selected network for recurring payments
5. Display the Mastercard-required phrase "Select card brand (optional)" when applicable
### Card IIN Detection
Yuno provides methods to detect which networks are supported by a card based on the card IIN (Issuer Identification Number). The card IIN is the first 6-8 digits of the card number and identifies the card issuer and supported networks.
### API Requirements
To process payments with the selected network, merchants must include the network selection in their payment API requests. When creating a payment, merchants must include the selected network in the payment request. The following parameters are used:
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"payment_method": {
"detail": {
"card": {
"network": "selected_network_here"
}
}
}
}
```
### Network Selection UI Implementation
Merchants must implement their own UI for network selection. The UI must display all available networks for the customer's card, allow customers to select their preferred network, and display the Mastercard-required phrase "Select card brand (optional)" when applicable. This phrase must be clearly visible and displayed before or alongside network selection options.
The network selection UI shown in the SDK section above provides a reference for how network selection should be presented to customers.
### Recurring Payments (Direct Integration)
For recurring payments, merchants must ensure that the initially selected network is used for all subsequent payments with the same card. This requires:
1. Storing the selected network when the payment method is first used
2. Including the stored network in all subsequent payment requests for that payment method
3. Maintaining this preference across all recurring transactions
## Examples
### Example: Network Selection Required
A French customer uses a co-badged card that supports both Cartes Bancaires and Visa. The merchant accepts both networks. The system detects both networks, presents a selection to the customer, and processes the payment through the selected network. For future recurring payments, the initially selected network is automatically used.
### Example: No Selection Required
A merchant only accepts Visa, and a customer uses a co-badged card that supports both Cartes Bancaires and Visa. Since the merchant only accepts Visa, no network selection is required and the payment is processed through Visa.
## Summary
* **SDK Integration**: Merchants using Yuno SDKs are compliant out-of-the-box (see [How It Works](#how-it-works)).
* **Direct Integration**: Merchants must implement network detection, selection UI, and network storage for recurring payments.
* **Regulatory Requirement**: EU IFR Regulation 2015/751 Article 8 requires network selection for co-badged cards in the EEA. The regulation entered into force on 8 June 2015, with Article 8 applying from 9 June 2016.
* **Mastercard Requirement**: The phrase "Select card brand (optional)" must be displayed when applicable.
* **Recurring Payments**: The initially selected network must be used for all subsequent payments with the same card.
# Exporting Tokens from Yuno
Source: https://docs.y.uno/docs/security-and-compliance/data-migration-processes/exporting-tokens-from-yuno
Explains the requirements and secure process for exporting tokenized card data from Yuno's vault.
Yuno offers a secure and PCI DSS-compliant process to export tokens from our vault to your systems, or a third-party provider. This guide explains the requirements, encryption protocols, data format, and delivery method to ensure safe and compliant migration of sensitive card data.
**Security Requirements**
Token export requests are handled with the same level of rigor and encryption used to protect data in production. Only eligible clients with validated use cases and PCI DSS compliance may initiate this process.
## When to request a token export
You may request an export of your tokenized data from Yuno when:
* You are switching to a different payment processor or tokenization provider.
* You need to manage tokens within your own PCI DSS-certified infrastructure.
## Eligibility and prerequisites
To proceed with an export, the following conditions must be met in this order:
### 1. Formal request
The client must submit a written request that includes:
* A formal request from the third party who wants to receive the merchant data
* Authorization to export the tokenized data.
* Confirmation of the recipient (internal team or third-party provider).
* Legal and compliance approval on the client's side.
Please submit this written request to your primary Yuno point of contact, and also send a copy via email to [security-migrations@y.uno](mailto:security-migrations@y.uno) to ensure both teams are informed.
### 2. PCI DSS certification
Since the exported data contains card data, the receiving entity must be certified under PCI DSS. This certification is required regardless of whether you are:
* Switching to a different payment provider
* Requesting your own data for internal use
We require:
* A valid Attestation of Compliance (AOC) from the receiving entity
* The AOC must be current and valid at the time of the export request
### 3. Technical requirements for secure data transfer
After the formal request is approved and PCI DSS compliance is verified, the following technical requirements must be met:
#### a. PGP public key for encryption
The receiving entity must provide a PGP public key to encrypt the exported files. This ensures that the data remains secure both in transit and at rest.
* The receiving entity must submit the key
* Yuno will validate the key format and compatibility
#### b. SFTP access credentials
Yuno will provision access to a secure Yuno-hosted SFTP server.
**You provide:**
* A static IP address from which the file will be accessed
* An SSH public key for authentication
**Yuno provides:**
* A dedicated SFTP user account for this purpose
## File format
The exported file will be encrypted using the provided PGP key and follow the structure below:
| Field | Description |
| ------------------ | ---------------------------- |
| `holder_name` | Name of the cardholder |
| `number` | Primary Account Number (PAN) |
| `token` | Token stored in Yuno's vault |
| `expiration_year` | Expiration year of the card |
| `expiration_month` | Expiration month of the card |
* The file will be formatted as a `.csv`
* All fields are UTF-8 encoded.
## Secure delivery process
Once all prerequisites are met:
1. Yuno's security team will:
* Prepare the export file with the card data
* Encrypt the file using the provided PGP key
* Create the SFTP user account for file retrieval
* Upload the file to the secure SFTP location
2. You will be notified when:
* The file is ready for download
* The SFTP access is configured
* The access window is active
3. You can then:
* Access the secure SFTP location using your SSH key and whitelisted IP
* Download the encrypted file within the defined time window
* The file will be automatically removed from the server after the access window expires
**Secure Channel Required**
The file is never sent by email or made publicly accessible. Access is strictly limited to the configured secure channel.
## Security and compliance
Yuno is certified under PCI DSS Level 1 and adheres to strict encryption, access control, and data retention practices throughout this process.
We ensure that:
* All exports are logged and monitored.
* Only authorized personnel handle encrypted data.
* Files are never stored longer than the required access window.
# Network Token Migration Process
Source: https://docs.y.uno/docs/security-and-compliance/data-migration-processes/network-token-migration-process
Explains the steps and requirements for migrating network tokens from a provider into Yuno's vault.
Network Token migration is the process of transferring `network_tokens` from an existing provider to Yuno's secure vault. During this process, a new token is generated for each `network_token`, ensuring seamless continuity and security for payment processing. The `network_token` migration process consists of three main steps:
1. The merchant requests the `network_token` migration process from their current payment processor.
2. Yuno and the payment provider collaborate to securely import all `network_token` data into the Yuno vault.
3. The merchant uses Yuno's token migration API to map the `network_tokens` from the payment provider to the `network_vaulted_tokens` of Yuno.
**First step**
To initiate the `network_token` migration process, contact your business advisor at Yuno to assess the viability and schedule of the procedure.
## Importing network token from a gateway account (steps 1 and 2)
Importing `network_token` data from a gateway account involves handling sensitive information, so strict security protocols must be followed. To import `network_token` data into Yuno from an existing gateway, complete the following steps:
1. **Coordinate with the current gateway**: Contact your current third-party vault or gateway and request an export of the payment method data. Ensure you follow their specified protocols.
2. **Complete the formal request**: Submit a formal request to Yuno, ensuring all required details and processes are documented. The gateway's response time and procedures will determine the data transfer process.
**Your responsibilities when migrating tokens**
You are responsible for managing communication with your gateway provider throughout the migration process. The Yuno team will support and collaborate directly with the third-party vault/gateway to facilitate the importing process. Additionally, the customer subscription information, including amounts, dates, etc., must be obtained directly from the exporting entity, as Yuno will not extract this data from encrypted files.
**Data transfer security**
All data throughout the migration process is encrypted using PGP keys and transferred using SFTP (Secure File Transfer Protocol).
## Client-side requirements (step 3)
To successfully complete the network token migration process, it is essential to fulfill the client-side requirements outlined in step 3. This involves providing the necessary user data, including the buyers and their existing payment methods.
You can execute the token migration process using the Yuno API, which is specifically designed for merchants. As a merchant, you will use this API to:
1. **Add customers**: Register customers in the Yuno system.
2. **Enroll payment methods**: Register payment methods obtained from payment processors for each customer in the Yuno system.
For a detailed guide on performing token migration using the API, click the button below:
## Gateway and payment provider requirements
To proceed with the migration process, you will need to provide the following:
* A public SSH key (you can provide one for production and another for testing). You can use the following command to generate it: `ssh-keygen -t rsa -b 4096 -C your_email@example.com`
* The outbound IPs that will be used during the migration.
* A template file of the data to be migrated to understand its structure. It must include the following mandatory data:
* **Cardholder name**: The full name of the cardholder as stored by the current provider.
* **Expiration date**: The expiry date of the token.
* **Network token number**: The complete network token number that will be tokenized by Yuno.
* **FPAN/Card LDF**: Last four digits from the FPAN associated to the card linked to the network token.
* **Network token transaction ID**: Unique identifier assigned by the card network to a specific transaction made using a network token.
* **Parent payment method type**: The underlying funding instrument from which a network token originates (such as Apple Pay, Google Pay).
* **Provider network token**: Unique identifier assigned to each network token by the current provider, used by the client for referencing that network token during transactions.
**Important notice**
In case of migration of multiple parent payment method types it is mandatory to send their corresponding `network_tokens` in different files.
### PGP public key
Use our public key to encrypt the PCI-sensitive files you send to Yuno.
| Property | Value |
| ----------- | ------------------------------------------------------------- |
| Email | [security-migrations@y.uno](mailto:security-migrations@y.uno) |
| Comment | For encrypting sensitive data. Environment: production |
| Created | 22 Nov 2024 |
| Expires | 22 Nov 2026 |
| Key ID | 73D3D88A |
| Length | 4096 |
| Algorithm | RSA |
| Fingerprint | 5160 7134 4C00 D270 93FB C450 19ED AACD 73D3 D88A |
***
```
-----BEGIN PGP PUBLIC KEY BLOCK-----
xsFNBGdAg2sBEAC4NW7xG06SGZcNCFVXreQsW8l3YGdcNo4y2ks0MZw8B1k6BwMJ
LqJjkiRouWAmRMCbP0Qauw4UPhhVlrIx9MsFrvJFgi/cnOGnwujVNIuhNw8S8cUZ
1K1+5ZAsxuc/hKcSQRH0Hp94UNP76seJgC0U6d422fW2EKG7VN2l1BcM4NlBmOuD
cQ+fOds+ACsBAQiQjL5ZA/sh6t/7cjUdCQhNK8eK5vylx1lKhHb6T1IvB+B/a6Pt
5xxEKNkBgwdQAucDFLFA3ypZsksy8/t9Y7AYw82Teo3z91cQxqiv1C6T62N3+YZ/
b48iNzfkml4kxfq15cNgdpxF+HJ/O6EHzSajbPT3KYsCFW9xS5aYOGTFSfgY+1qL
518YP72t9okj5HalUgDp6YCLuSr5ns+Z8t8K+cgGNjy08GwuRJKhDidvZBzgGMw6
bWavl1obnfThjb3VIHe0WEx/FQuQGGvJzi2EFI+Rne5nT0Q1ayv99kUglfXNdVOL
LDsaCwZwefw2Z7+7hNGiF08NQXxUE05tia5ElsmSl9Mo0OeG7UsVuYHVqwDnLs4W
dC6br3S3p9XKG9mopXOn8Y4Iu9WMhW3ZZHOlrFCzHip5PyBIyl3265LWfs/If8dc
vCKDXC/Hgjxdy7yNzgqguqgwJRnMrXrHx6s3MMHw/1YhNM6uwUjg3WADwwARAQAB
zW5zZWN1cml0eS1taWdyYXRpb25zQHkudW5vIChGb3IgZW5jcnlwdGluZyBzZW5z
aXRpdmUgZGF0YS4gRW52aXJvbm1lbnQ6IHByb2R1Y3Rpb24pIDxzZWN1cml0eS1t
aWdyYXRpb25zQHkudW5vPsLBiAQTAQgAMgUCZ0CDbAIbDgUJA8JnAAILCQIVCAIW
AgIeARYhBFFgcTRMANJwk/vEUBntqs1z09iKAAoJEBntqs1z09iKXJQQAIvBv0sa
C9Brd4ylSzznZdQQoGIilsGoeiWLNV6Gh6YEODspWljjeYKQl6SEb3NsoVrpB7A5
5UNYMGykcvly+fR8UvhNEiJO6vTVCRZnYU43MYLgC35CPj1798egw50GusVoSjKu
960tMOz6DUh3yBO2VSxveaOQ6pIYNqi4HtVFIzvcrpgY1/wIV4jpyYnRtJQEt+M4
LjD9rnkl7eGHeYQV6tpMjoMkLSWApdk5aDoUqmkvXae5aa7ab7iH/7p53oXxVQM7
lqjuNGTgmiJ48gcyHp6aF6M1hbNpoekS63FoGgSRr1h+oB1NlqCokhP8tIjbNbAv
rh3371lfPS8dmVq6rUYQwGxHt1XS5682wRw0ZdvsiGY7VjuZAHgGi0f2cEh3dsqy
Xa3+rbQ1vKX6lIvmmqPiv7Ggo2LLJXfRfg3Q8s35CCvccz1qQcuUl+HI8NQLbiyW
mpelG0+sOl7KHYg7c0HpS8756Eax3sSnr57Jb7Rx88NIF+hH8zE8kBL6OHkFnE+L
yLIbCYzmCSxK0ktvcnMjYb1BGmPxfSWgPEyXrI34MtfyRXpeLaDSBfKzGNL8fLLT
olLEABrWmn6Xvj6DeZAA+xoFmTUqdLYsZ/i/RLZ5lzQv3xp8Uks09dy2mm/dAVxS
4lox2wuJRalx5MZkqrSRZAkjyQMu6EwGiiQ1zsFNBGdAg2wBEACutTIUvApmEQkX
EBcAmDFUkQSquiR4EhmW8icPPWTabszNZu3LXLf/ou1v/dcLvkyyDUFZIezYUwdx
UXBYDFrXmPqddSx5TOSCOvY79pKrrx5S//40RTs9PM2eC1ufggT7fGVvNj8irYPh
jUDtI8LzQXedAMWNB5PLXPZEBnEnaE45PU0s5nREoLK14ldEQl1nCAqAFlEPTztQ
C+ILAprwSZ3qnj0pGYy+uRfmIZD51KpriGdRQqWDdbImM28SNh7tv3jPQenm5oCG
cavOZzhA54B+w2Hgc4aGER0qY5eZsd/YEGaVevjGHaEDE/Xm6ctMSuLKgg6A/zNH
F7kKcS1/5uXXQ0mlk15zRgMJcxNctrKFIYW78R1ECY8vIdN0aMd2/fRgaawwuTz2
WcTlLgsG84bAKcccsQnTwCOBxHR8qt3u+GKCEkIcaQVC/FNjP47iSzyWb1a0KeEV
4TJ9RtWdlj1DK3alGkvbexuCzqZ+1p8O+lCIsEiL5Cz3YeLfLebph1Z40o0HdGw3
XS/e0GnaBZpqzo4MCqud26x9fYX9kP+SHzNAacSSLfc/WJvJOLyuIDXvwiJu7QDC
SDMeS4vLiBmfcfYiBxUKXteRcS2g/9B5tkzKVLWv9xkMXIhsxsyIFDiepUoT4uEN
zPvOR8fbpzI+XkNdAOpm6gKyCTRxeQARAQABwsOsBBgBCAAgBQJnQINtAhsMFiEE
UWBxNEwA0nCT+8RQGe2qzXPT2IoCQAkQGe2qzXPT2IrBdCAEGQEIAB0FAmdAg20W
IQRAK7d6Jh6QEsLrtCje87+APhkLfwAKCRDe87+APhkLf9AqD/9QmNmEaSUZ6ujy
7resqaWT4nSMErhT3TNM8B1FPwF63Igt0HUnKqe4XSy840kKJsTY+ssGcLpbTTxv
CX/DLtR7No5G1WBAr3MZos7GfFhnb2tApDzQdmucHliKLVe2zSiyqvMGiK1irvXy
GKi6Dfvoobw54qkCeD7upz+z6eZAQYnDqh2xlGl7uc6OcgaJgctMhOA8jhlmLIrz
gk/MBXRgZXGfJ0/DZe2JTl7vw3XIUB62XnV3vpHU/UxM5UWpA87m14Lh8SNAvT+l
L8Y1wZ5DcQ1g83oO5NI/DwWorlqOeyhRU8a1a3Kd0aZ6bSWCbZadU4c6ciwvwpnS
MQ5nc4iX1bFsuN8z8WGQ/io4cPMXQbNFBQ22OgnSpxEVS3akDkQOJ25hJeUZaFZU
91CJVlknQipwvpVG3RuuOvTJstYxTKJ8Leg1IB0zo7QhlaMNTu/yWyr0WoJO52Jh
IMoykpfPY6gowKBGi6EZpNjiKoyElkBU1js47wMdqONfBZxyupJpAM2GeBWs0cYS
j7pUL68ah/RMslMuC6rKtjDytVChQJz/nXcxDQeBliYMMedDP3a6FksBmmdJKphw
ZbmVGAbNJd2TSFEsiYZjPJ+bH8SafjcRVVqaRw3cGReyJmwv1EhxhZR+dsZAjdnB
RX0jQSGjQjcWfyUTGmnpipgCNnJOkEFrEACm4QErrplv2jIAADFytyk/VL+3D6RB
0XTrhb0FqLgmVEqYJPuh9z3KkMpQQk9spd3uNBkuBGkTehf4WBWIRcGWIChpVNb+
YabmXfqxYhoRKnhoMS4vRfOZJbdzdBZ7tsjsz072kGi03nK9/B5RnBR2Amj2hry/
BdzZd+vuAUiblC7DJ8M9SAMBAHyXAJFKfgoYs9OxBdQqSePVKG8B2B2Vu12yeJWc
p00yrqfc6c5IvamRvKZ73EYAbt6uf/5ED969QngFeB4NhSUCH7L1h+67lKVjELw4
l2wA4kd2ZxEERfTVRx0/ZptxW2nkVm4iK2R/0DDMDyPZ5VfPo+XA6Y794kWJ/C2E
sX9T9ti6GK6taIZ4vdcR04CMFMNfOSrcnMWN4GDP6BQpYEOu2pOHqUpQAinFCSi9
umfNdhaPchGiHk2KjvXAgPJ6j4AYGadfM24qT6m8GLEtanL2pFGFNPOw8D03fGkV
yhsfHiamgAnnL2mz0khePCn8aTyUMrmSwUc2e5Agj1naMJetd//WnzaPFvWViy+l
V+EqUCVP6YPNq8PHD8ZOAy5T8GO+wNahsKiUaxAhn2kjCXhZRqwWDiJLCn3Wge6B
n4nHVHtvlw/ptDFyrDP2fUkk1XwmN2StG5y74eVN6HlvrTkwL5HmxQKGlSwZC1gK
sNugHSYrj1RUuA==
=ik2s
-----END PGP PUBLIC KEY BLOCK-----
```
# Token Migration Process
Source: https://docs.y.uno/docs/security-and-compliance/data-migration-processes/token-migration-process
Explains the steps, data format, and security requirements for migrating tokenized cards into Yuno.
Token migration is the process of transferring card numbers from an existing provider to Yuno's secure vault. During this process, a new token is generated for each card, ensuring seamless continuity and security for payment processing. The token migration process consists of three main steps:
1. The merchant requests the token migration process from their current payment processor.
2. Yuno and the payment provider collaborate to securely import all card data into the Yuno token vault.
3. The merchant uses Yuno's token migration API to map the tokens from the payment provider to the `vaulted_tokens` of Yuno.
**First step**
To initiate the token migration process, contact your business advisor at Yuno to assess the viability and schedule of the procedure.
## Importing cards from a gateway account (steps 1 and 2)
Importing card data from a gateway account involves handling sensitive information, so strict security protocols must be followed. To import card data into Yuno from an existing gateway, complete the following steps:
1. **Coordinate with the current gateway**: Contact your current third-party vault or gateway and request an export of the payment method data. Ensure you follow their specified protocols.
2. **Complete the formal request**: Submit a formal request to Yuno, ensuring all required details and processes are documented. The gateway's response time and procedures will determine the data transfer process.
**Your responsibilities when migrating tokens**
You are responsible for managing communication with your gateway provider throughout the migration process. The Yuno team will support and collaborate directly with the third-party vault/gateway to facilitate the importing process. Additionally, the customer subscription information, including amounts, dates, etc., must be obtained directly from the exporting entity, as Yuno will not extract this data from encrypted files.
**Data transfer security**
All data throughout the migration process is encrypted using PGP keys and transferred using SFTP (Secure File Transfer Protocol).
## Client-side requirements (step 3)
To successfully complete the token migration process, it is essential to fulfill the client-side requirements outlined in step 3. This involves providing the necessary user data, including the buyers and their existing payment methods.
You can execute the token migration process using the Yuno API, which is specifically designed for merchants. As a merchant, you will use this API to:
1. **Add customers**: Register customers in the Yuno system.
2. **Enroll payment methods**: Register payment methods obtained from payment processors for each customer in the Yuno system.
**API migration option**
The API migration option allows merchants to manage their customers and their respective payment data. [Learn more](/docs/security-and-compliance/data-migration-processes/via-api)
For a detailed guide on performing token migration using the API, click the button below:
### Data format
Yuno specifies the required parameters for each customer and credit card to proceed with the migration process. The required parameters are listed below:
* Account ID
* Merchant customer ID
* First name
* Last name
* Email
* Country
* Document number
* Document type
* Payment method type
* Payment method ID
* Payment method token
Refer to the [Customer Object](/reference/the-customer-object) and [Payment Method Object](/reference/the-payment-method-object-api) to explore all possible parameters for importing/creating customers or enrolling payment objects.
Technical limitations associated with alternative payment methods may make them ineligible for migration between service providers. If you are considering migrating alternative payment method tokens, such as Mercado Pago Wallet Connect or Bancolombia Tokenbox, to the Yuno vault, please contact the Yuno support team.
## Data validation
To ensure efficient processing and prevent delays during the token migration process, please provide the following information when communicating with Yuno Support:
* The external identifier name that will be used for the import.
* An approximate count of the expected number of payment methods to be included (a rough estimate is acceptable).
* Any known data gaps, such as missing names or expiration dates.
**Important notice**
Yuno does not validate expiration dates during credit card import.
## Data protection
When processing payments through Yuno, the platform connects to payment processors. Yuno tokenizes and encrypts the data to ensure security, simplifying the PCI compliance process. However, you are responsible for managing and protecting your customer's data. Additionally, you must communicate any additional fees or issues to your customer.
## Gateway and payment provider requirements
To proceed with the migration process, you will need to provide the following:
* A public SSH key (you can provide one for production and another for testing). Use the following command to generate it: `ssh-keygen -t rsa -b 4096 -C your_email@example.com`
* The outbound IPs that will be used during the migration.
* A template file of the data to be migrated to understand its structure. It must include the following mandatory data:
* **Cardholder name**: The full name of the cardholder as stored by the current provider.
* **Expiration date**: The expiry date of the card.
* **Card number**: The complete card number (PAN) that will be tokenized by Yuno.
* **Card ID**: A unique identifier assigned to each card by the current provider, used by the client for referencing that card during transactions.
### PGP public key
Use our public key to encrypt the PCI-sensitive files you send to Yuno.
| Property | Value |
| ----------- | ------------------------------------------------------------- |
| Email | [security-migrations@y.uno](mailto:security-migrations@y.uno) |
| Comment | For encrypting sensitive data. Environment: production |
| Created | 22 Nov 2024 |
| Expires | 22 Nov 2026 |
| Key ID | 73D3D88A |
| Length | 4096 |
| Algorithm | RSA |
| Fingerprint | 5160 7134 4C00 D270 93FB C450 19ED AACD 73D3 D88A |
***
```
-----BEGIN PGP PUBLIC KEY BLOCK-----
xsFNBGdAg2sBEAC4NW7xG06SGZcNCFVXreQsW8l3YGdcNo4y2ks0MZw8B1k6BwMJ
LqJjkiRouWAmRMCbP0Qauw4UPhhVlrIx9MsFrvJFgi/cnOGnwujVNIuhNw8S8cUZ
1K1+5ZAsxuc/hKcSQRH0Hp94UNP76seJgC0U6d422fW2EKG7VN2l1BcM4NlBmOuD
cQ+fOds+ACsBAQiQjL5ZA/sh6t/7cjUdCQhNK8eK5vylx1lKhHb6T1IvB+B/a6Pt
5xxEKNkBgwdQAucDFLFA3ypZsksy8/t9Y7AYw82Teo3z91cQxqiv1C6T62N3+YZ/
b48iNzfkml4kxfq15cNgdpxF+HJ/O6EHzSajbPT3KYsCFW9xS5aYOGTFSfgY+1qL
518YP72t9okj5HalUgDp6YCLuSr5ns+Z8t8K+cgGNjy08GwuRJKhDidvZBzgGMw6
bWavl1obnfThjb3VIHe0WEx/FQuQGGvJzi2EFI+Rne5nT0Q1ayv99kUglfXNdVOL
LDsaCwZwefw2Z7+7hNGiF08NQXxUE05tia5ElsmSl9Mo0OeG7UsVuYHVqwDnLs4W
dC6br3S3p9XKG9mopXOn8Y4Iu9WMhW3ZZHOlrFCzHip5PyBIyl3265LWfs/If8dc
vCKDXC/Hgjxdy7yNzgqguqgwJRnMrXrHx6s3MMHw/1YhNM6uwUjg3WADwwARAQAB
zW5zZWN1cml0eS1taWdyYXRpb25zQHkudW5vIChGb3IgZW5jcnlwdGluZyBzZW5z
aXRpdmUgZGF0YS4gRW52aXJvbm1lbnQ6IHByb2R1Y3Rpb24pIDxzZWN1cml0eS1t
aWdyYXRpb25zQHkudW5vPsLBiAQTAQgAMgUCZ0CDbAIbDgUJA8JnAAILCQIVCAIW
AgIeARYhBFFgcTRMANJwk/vEUBntqs1z09iKAAoJEBntqs1z09iKXJQQAIvBv0sa
C9Brd4ylSzznZdQQoGIilsGoeiWLNV6Gh6YEODspWljjeYKQl6SEb3NsoVrpB7A5
5UNYMGykcvly+fR8UvhNEiJO6vTVCRZnYU43MYLgC35CPj1798egw50GusVoSjKu
960tMOz6DUh3yBO2VSxveaOQ6pIYNqi4HtVFIzvcrpgY1/wIV4jpyYnRtJQEt+M4
LjD9rnkl7eGHeYQV6tpMjoMkLSWApdk5aDoUqmkvXae5aa7ab7iH/7p53oXxVQM7
lqjuNGTgmiJ48gcyHp6aF6M1hbNpoekS63FoGgSRr1h+oB1NlqCokhP8tIjbNbAv
rh3371lfPS8dmVq6rUYQwGxHt1XS5682wRw0ZdvsiGY7VjuZAHgGi0f2cEh3dsqy
Xa3+rbQ1vKX6lIvmmqPiv7Ggo2LLJXfRfg3Q8s35CCvccz1qQcuUl+HI8NQLbiyW
mpelG0+sOl7KHYg7c0HpS8756Eax3sSnr57Jb7Rx88NIF+hH8zE8kBL6OHkFnE+L
yLIbCYzmCSxK0ktvcnMjYb1BGmPxfSWgPEyXrI34MtfyRXpeLaDSBfKzGNL8fLLT
olLEABrWmn6Xvj6DeZAA+xoFmTUqdLYsZ/i/RLZ5lzQv3xp8Uks09dy2mm/dAVxS
4lox2wuJRalx5MZkqrSRZAkjyQMu6EwGiiQ1zsFNBGdAg2wBEACutTIUvApmEQkX
EBcAmDFUkQSquiR4EhmW8icPPWTabszNZu3LXLf/ou1v/dcLvkyyDUFZIezYUwdx
UXBYDFrXmPqddSx5TOSCOvY79pKrrx5S//40RTs9PM2eC1ufggT7fGVvNj8irYPh
jUDtI8LzQXedAMWNB5PLXPZEBnEnaE45PU0s5nREoLK14ldEQl1nCAqAFlEPTztQ
C+ILAprwSZ3qnj0pGYy+uRfmIZD51KpriGdRQqWDdbImM28SNh7tv3jPQenm5oCG
cavOZzhA54B+w2Hgc4aGER0qY5eZsd/YEGaVevjGHaEDE/Xm6ctMSuLKgg6A/zNH
F7kKcS1/5uXXQ0mlk15zRgMJcxNctrKFIYW78R1ECY8vIdN0aMd2/fRgaawwuTz2
WcTlLgsG84bAKcccsQnTwCOBxHR8qt3u+GKCEkIcaQVC/FNjP47iSzyWb1a0KeEV
4TJ9RtWdlj1DK3alGkvbexuCzqZ+1p8O+lCIsEiL5Cz3YeLfLebph1Z40o0HdGw3
XS/e0GnaBZpqzo4MCqud26x9fYX9kP+SHzNAacSSLfc/WJvJOLyuIDXvwiJu7QDC
SDMeS4vLiBmfcfYiBxUKXteRcS2g/9B5tkzKVLWv9xkMXIhsxsyIFDiepUoT4uEN
zPvOR8fbpzI+XkNdAOpm6gKyCTRxeQARAQABwsOsBBgBCAAgBQJnQINtAhsMFiEE
UWBxNEwA0nCT+8RQGe2qzXPT2IoCQAkQGe2qzXPT2IrBdCAEGQEIAB0FAmdAg20W
IQRAK7d6Jh6QEsLrtCje87+APhkLfwAKCRDe87+APhkLf9AqD/9QmNmEaSUZ6ujy
7resqaWT4nSMErhT3TNM8B1FPwF63Igt0HUnKqe4XSy840kKJsTY+ssGcLpbTTxv
CX/DLtR7No5G1WBAr3MZos7GfFhnb2tApDzQdmucHliKLVe2zSiyqvMGiK1irvXy
GKi6Dfvoobw54qkCeD7upz+z6eZAQYnDqh2xlGl7uc6OcgaJgctMhOA8jhlmLIrz
gk/MBXRgZXGfJ0/DZe2JTl7vw3XIUB62XnV3vpHU/UxM5UWpA87m14Lh8SNAvT+l
L8Y1wZ5DcQ1g83oO5NI/DwWorlqOeyhRU8a1a3Kd0aZ6bSWCbZadU4c6ciwvwpnS
MQ5nc4iX1bFsuN8z8WGQ/io4cPMXQbNFBQ22OgnSpxEVS3akDkQOJ25hJeUZaFZU
91CJVlknQipwvpVG3RuuOvTJstYxTKJ8Leg1IB0zo7QhlaMNTu/yWyr0WoJO52Jh
IMoykpfPY6gowKBGi6EZpNjiKoyElkBU1js47wMdqONfBZxyupJpAM2GeBWs0cYS
j7pUL68ah/RMslMuC6rKtjDytVChQJz/nXcxDQeBliYMMedDP3a6FksBmmdJKphw
ZbmVGAbNJd2TSFEsiYZjPJ+bH8SafjcRVVqaRw3cGReyJmwv1EhxhZR+dsZAjdnB
RX0jQSGjQjcWfyUTGmnpipgCNnJOkEFrEACm4QErrplv2jIAADFytyk/VL+3D6RB
0XTrhb0FqLgmVEqYJPuh9z3KkMpQQk9spd3uNBkuBGkTehf4WBWIRcGWIChpVNb+
YabmXfqxYhoRKnhoMS4vRfOZJbdzdBZ7tsjsz072kGi03nK9/B5RnBR2Amj2hry/
BdzZd+vuAUiblC7DJ8M9SAMBAHyXAJFKfgoYs9OxBdQqSePVKG8B2B2Vu12yeJWc
p00yrqfc6c5IvamRvKZ73EYAbt6uf/5ED969QngFeB4NhSUCH7L1h+67lKVjELw4
l2wA4kd2ZxEERfTVRx0/ZptxW2nkVm4iK2R/0DDMDyPZ5VfPo+XA6Y794kWJ/C2E
sX9T9ti6GK6taIZ4vdcR04CMFMNfOSrcnMWN4GDP6BQpYEOu2pOHqUpQAinFCSi9
umfNdhaPchGiHk2KjvXAgPJ6j4AYGadfM24qT6m8GLEtanL2pFGFNPOw8D03fGkV
yhsfHiamgAnnL2mz0khePCn8aTyUMrmSwUc2e5Agj1naMJetd//WnzaPFvWViy+l
V+EqUCVP6YPNq8PHD8ZOAy5T8GO+wNahsKiUaxAhn2kjCXhZRqwWDiJLCn3Wge6B
n4nHVHtvlw/ptDFyrDP2fUkk1XwmN2StG5y74eVN6HlvrTkwL5HmxQKGlSwZC1gK
sNugHSYrj1RUuA==
=ik2s
-----END PGP PUBLIC KEY BLOCK-----
```
# Via API
Source: https://docs.y.uno/docs/security-and-compliance/data-migration-processes/via-api
Walks through migrating customers and enrolling payment methods via the Yuno API endpoints.
This guide provides a step-by-step process for migrating tokens using the Yuno API endpoints. By following the steps outlined, you will compile a list of customers with their enrolled payment methods.
## Requirements
Before proceeding with the steps in this guide, ensure you have:
* Completed the three steps related to the [importing cards from a gateway account](/docs/security-and-compliance/data-migration-processes/token-migration-process#importing-cards-from-a-gateway-account-steps-1-and-2) process.
* Accessed your [API credentials](/docs/using-yuno/settings/developers-credentials) on the Yuno Dashboard, which include:
* `public-api-key`
* `private-secret-key`
* `account_id`
Make sure you have completed these steps and have the necessary data before continuing with the guide.
## Migrate tokens via API
### Step 1: Create customers
To begin the token migration process, you will use the [Create Customer](/reference/create-customer) endpoint to add customers to the Yuno system. It is important to note that payment methods cannot be enrolled for customers who do not exist in the Yuno system. If the customers are already present in Yuno, you may skip this step.
To register new customers, provide their personal information. Additionally, you must supply the `merchant_customer_id`, which is a unique identifier for the customer used in your system.
**Customer complementary information**
When creating a customer, certain information is optional but can enhance the user's payment experience if provided. Examples of non-mandatory data include phone number, billing address, and shipping address.
If you choose to add optional information, ensure that all required mandatory fields are also provided.
Upon completing the customer creation process, you will receive an `id` that identifies the user within the Yuno system. Use this `id` to enroll the existing payment methods.
### Step 2: Check the customer data (optional)
In this step, you have the option to verify the information of each registered customer. Use the [Retrieve Customer](/reference/customers/retrieve-customer) endpoint to access the customer data. To do this, provide the `id` that was generated when the customer was initially created.
### Step 3: Enroll a payment method
To complete the migration process, you need to enroll payment methods for each customer using the third-party vault or gateway data.
Utilize the [Enroll Payment Method](/reference/enroll-payment-method-api) endpoint to register the payment methods. Remember, the `customer_id` required for this request is the `id` obtained during the customer creation in [Step 1](/docs/security-and-compliance/data-migration-processes/via-api#step-1-create-customers). Additionally, include the `provider_data` object containing the external provider's token, as shown in the code snippet below:
```sh Request theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
curl --request POST \
--url https://api-sandbox.y.uno/v1/customers/{{customer_id}}/payment-methods \
--header 'X-Idempotency-Key: ' \
--header 'accept: application/json' \
--header 'charset: utf-8' \
--header 'content-type: application/json' \
--header 'private-secret-key: ' \
--header 'public-api-key: ' \
--data '
{
"country": "BR",
"type": "CARD",
"workflow": "DIRECT",
"provider_data": {
"id": "MERCADO_PAGO",
"payment_method_token": "{{provider_card_token}}"
},
"account_id": "{{account_id}}"
}
'
```
In the response from the endpoint, you will receive a `vaulted_token` that identifies the enrolled payment method. This `vaulted_token` will be used for future payments, eliminating the need for additional payment method details.
### Step 4: Check the enrolled payment method (optional)
Once the payment method is enrolled, you can verify its successful enrollment using the [retrieve enrolled payment methods](/reference/retrieve-enrolled-payment-methods-api) endpoint. Remember, the `customer_id` needed for this request is the `id` obtained during the customer creation in [Step 1](/docs/security-and-compliance/data-migration-processes/via-api#step-1-create-customers).
# Card Fingerprint
Source: https://docs.y.uno/docs/security-and-compliance/fingerprint
Use card fingerprints to detect and deduplicate repeated card enrollments without storing card data.
Card fingerprints are a cryptographic hash of the card's PAN that uniquely identifies a specific payment card. Yuno returns this value as `fingerprint` on the [Payment Method object](/reference/the-payment-method-object-api). When the same card is enrolled multiple times by the same customer, Yuno creates separate enrollments with distinct `vaulted_token` values, and the fingerprint helps you detect duplicates.
**Key Properties:**
* **Remains consistent** across multiple enrollments of the same card
* **Is unique** to each distinct card number
* **Protects PCI compliance** by not exposing the full card number
* **Enables deduplication** without storing or accessing sensitive card data
You cannot check fingerprints before the customer enters their card information. This is a PCI compliance requirement.
**Workaround:** Display existing saved cards before the enrollment form so customers can see what they already have saved.
## How It Works
### Same Card, Multiple Enrollments
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
// First enrollment
{
"vaulted_token": "b82b7682-def1-4d46-ad51-7da446b2966c",
"card_data": {
"fingerprint": "fp_abc123xyz789",
"iin": "41111111",
"lfd": "1111"
}
}
// Second enrollment of the SAME card
{
"vaulted_token": "7ce53292-c402-4e3d-8ddd-a49268633294", // Different token
"card_data": {
"fingerprint": "fp_abc123xyz789", // Same fingerprint!
"iin": "41111111",
"lfd": "1111"
}
}
```
### Different Cards
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"vaulted_token": "...",
"card_data": {
"fingerprint": "fp_different456", // Different fingerprint
"iin": "52222222",
"lfd": "2222"
}
}
```
## Why Duplicate Enrollments Occur
To avoid operational issues, Yuno does not automatically prevent duplicate card enrollments. When a customer enrolls the same card multiple times:
* Each enrollment creates a **new `vaulted_token`**
* **No automatic deduplication** occurs
* This applies **regardless** of whether expiration date or cardholder info changes
Implement deduplication on your side using fingerprints.
## Implementation Guide
### Step 1: Retrieve Existing Payment Methods
Use the [Retrieve Enrolled Payment Methods](/reference/retrieve-enrolled-payment-methods-api) endpoint to list the customer's existing cards.
```bash theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
GET /v1/customers/{customer_id}/payment-methods
```
**Response:**
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"payment_methods": [
{
"vaulted_token": "token_1",
"card_data": {
"fingerprint": "fp_abc123",
"iin": "41111111",
"lfd": "1111",
"brand": "VISA"
}
},
{
"vaulted_token": "token_2",
"card_data": {
"fingerprint": "fp_xyz789",
"iin": "52222222",
"lfd": "2222",
"brand": "MASTERCARD"
}
}
]
}
```
### Step 2: Check for Duplicates After Enrollment
```javascript theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
async function checkForDuplicates(customerId, newCardFingerprint) {
// Get existing payment methods
const existingMethods = await getCustomerPaymentMethods(customerId);
// Extract fingerprints (filter out nulls)
const existingFingerprints = existingMethods
.map(method => method.card_data?.fingerprint)
.filter(Boolean);
// Check for duplicates
const isDuplicate = existingFingerprints.includes(newCardFingerprint);
if (isDuplicate) {
// Handle duplicate (see options below)
console.log('Duplicate card detected');
}
return isDuplicate;
}
```
### Step 3: Handle Duplicates
You have several options when a duplicate is detected:
**Recommended:** Option A (prevent enrollment) for most integrations. Use B or C only if your product intentionally allows multiple saved copies of the same card.
#### Option A: Prevent Enrollment (Recommended for Best UX)
```javascript theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
// Before enrollment, fetch existing cards and display them
// Show user: "You already have these cards saved:"
// - VISA ending in 1111
// - MASTERCARD ending in 2222
//
// This prevents the duplicate enrollment from happening
```
#### Option B: Notify After Enrollment
```javascript theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
yunoEnrollmentStatus: async ({ status, vaultedToken }) => {
if (status === 'ENROLLED' && vaultedToken) {
const newCard = await getPaymentMethodDetails(customerId, vaultedToken);
const isDuplicate = await checkForDuplicates(
customerId,
newCard.card_data?.fingerprint
);
if (isDuplicate) {
// Notify user
showNotification("This card was already saved. We've removed the duplicate.");
// Optionally remove the duplicate
await unenrollPaymentMethod(customerId, vaultedToken);
} else {
showNotification("Card saved successfully!");
}
}
}
```
#### Option C: Keep Both Enrollments
```javascript theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
// Allow duplicates for customer flexibility
// Display all cards with visual indicators:
// - VISA •••• 1111 (Primary)
// - VISA •••• 1111 (Duplicate - added Jan 15)
```
## Complete Implementation Example
```javascript theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
// Enrollment flow with duplicate detection
const enrollmentFlow = {
// 1. Customer completes enrollment via SDK
yunoEnrollmentStatus: async ({ status, vaultedToken }) => {
if (status !== 'ENROLLED' || !vaultedToken) {
return;
}
try {
// 2. Fetch the newly enrolled payment method
const newCard = await fetch(
`/api/payment-methods/${vaultedToken}`
).then(r => r.json());
const newFingerprint = newCard.card_data?.fingerprint;
// 3. Handle cases where fingerprint is not available
if (!newFingerprint) {
console.warn('Fingerprint not available for this card');
showNotification("Card saved successfully!");
return;
}
// 4. Get existing cards for this customer
const existingCards = await fetch(
`/api/customers/${customerId}/payment-methods`
).then(r => r.json());
// 5. Check for duplicates
const duplicates = existingCards.payment_methods.filter(card =>
card.card_data?.fingerprint === newFingerprint &&
card.vaulted_token !== vaultedToken // Exclude the newly enrolled card
);
// 6. Handle duplicate
if (duplicates.length > 0) {
const confirmRemove = await showConfirmDialog(
"This card is already saved to your account. " +
"Would you like to remove the duplicate?"
);
if (confirmRemove) {
await fetch(
`/api/payment-methods/${vaultedToken}`,
{ method: 'DELETE' }
);
showNotification("Duplicate card removed.");
} else {
showNotification("Card saved. You now have multiple copies of this card.");
}
} else {
showNotification("Card saved successfully!");
}
} catch (error) {
console.error('Error checking for duplicates:', error);
// Fail gracefully - card is still enrolled
showNotification("Card saved successfully!");
}
}
};
```
## Important Considerations
### Fingerprint Availability
The `fingerprint` field may be `null` for some payment methods or providers. Always check if the fingerprint exists before using it:
```javascript theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
const fingerprint = card.card_data?.fingerprint;
if (!fingerprint) {
// Handle this case gracefully
// Option 1: Skip duplicate detection
// Option 2: Use alternative matching (IIN + LFD)
// Option 3: Log and notify your team
console.warn('Fingerprint not available');
}
```
**Alternative matching:**
```javascript theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
// Fallback: Match by IIN + LFD + expiration
const isSameCard = (card1, card2) => {
return card1.card_data?.iin === card2.card_data?.iin &&
card1.card_data?.lfd === card2.card_data?.lfd &&
card1.card_data?.expiration_month === card2.card_data?.expiration_month &&
card1.card_data?.expiration_year === card2.card_data?.expiration_year;
};
```
Different cards may share the same IIN and LFD.
### Card Updates
The fingerprint behavior with card updates:
| Change | Fingerprint Behavior |
| ------------------------------- | -------------------------------- |
| **Card number changes** | ✅ **New** fingerprint generated |
| **Expiration date changes** | ❌ Fingerprint **stays the same** |
| **Cardholder name changes** | ❌ Fingerprint **stays the same** |
| **Card reissued (same number)** | ❌ Fingerprint **stays the same** |
### Network token fingerprint
For network tokens, Yuno uses a `network_token_fingerprint` that works like the card fingerprint and is scoped to your organization and the unique identifier of the network token in the PCI vault. This means duplicate enrollments for the same PAN can map to the same network token. For more details, see [Network Tokens](/docs/network-tokens).
## Use Cases
### 1. Prevent Wallet Clutter
Help users avoid saving the same card multiple times:
```javascript theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
// Show before enrollment form
"You already have these cards saved:
- VISA ending in 1111
- MASTERCARD ending in 2222"
```
### 2. Improve User Experience
Automatically clean up duplicates:
```javascript theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
if (isDuplicate) {
await removeOlderDuplicate(vaultedToken);
showMessage("We updated your saved card.");
}
```
### 3. Data Cleanup
Identify and remove duplicate enrollments in batch:
```javascript theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
async function cleanupDuplicates(customerId) {
const cards = await getPaymentMethods(customerId);
const fingerprints = new Map();
for (const card of cards.payment_methods) {
const fp = card.card_data?.fingerprint;
if (!fp) continue;
if (fingerprints.has(fp)) {
// Keep the most recent, remove older duplicates
const existing = fingerprints.get(fp);
const newerCard = new Date(card.created_at) > new Date(existing.created_at)
? card
: existing;
const olderCard = newerCard === card ? existing : card;
await unenrollPaymentMethod(customerId, olderCard.vaulted_token);
fingerprints.set(fp, newerCard);
} else {
fingerprints.set(fp, card);
}
}
}
```
### 4. Analytics and Monitoring
Track duplicate enrollment rates:
```javascript theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
// Log duplicate events for monitoring
if (isDuplicate) {
analytics.track('duplicate_card_enrolled', {
customer_id: customerId,
fingerprint: fingerprint.substring(0, 10), // Partial for privacy
duplicate_count: duplicates.length + 1
});
}
```
# Network Tokens
Source: https://docs.y.uno/docs/security-and-compliance/network-tokens
Explains network tokens, their lifecycle statuses, and how to integrate them for card payments.
Network tokens represent a significant advancement in the payment processing industry, acting as digital surrogates for sensitive payment card details, including credit card numbers. Issued by payment networks such as Visa, Mastercard, and American Express, these tokens are at the forefront of enhancing transaction security within our evolving digital landscape.
### Benefits of network tokens
* **Enhanced security**: By replacing actual card data during transactions, network tokens play a crucial role in strengthening security measures, significantly reducing the risk of exposure to potential fraud.
* **Seamless integration**: With minimal integration efforts adhering to EMVCo's network token standards, our solution ensures a seamless and efficient implementation process, allowing for quick adaptation within various payment scenarios.
* **Automatic updates**: Network tokens, managed and updated automatically by card networks, contribute to a reduction in shopper friction and declined payments. This inherent adaptability ensures a higher authorization rate compared to transactions without network tokens.
* **Authentication support**: For enhanced security and higher approval rates, you can combine network tokens with [Network Token Authentication](/docs/payment-features/network-token-authentication), enabling passkey-backed shopper authentication directly through the card networks.
## One-time use token vs vaulted token vs network token
| One-time use token | Vaulted token | Network token |
| :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| While using Yuno's SDK, we gather all the necessary information to process the payment and store it in a one-time use token, regardless of the customer's chosen payment method. You will use the token when creating the payment. Note that this token only works one time. You will need to generate a new one-time token for each checkout session created. | A vaulted token is created by Yuno once a payment method is enrolled and stored with the customer information. You can use the created vaulted token to identify the payment method in future payments. | Digitized representations of sensitive payment card information, such as credit card numbers, issued by major payment networks like Visa, Mastercard, or American Express. These tokens serve the purpose of substituting actual card data in transactions, thereby enhancing security by minimizing exposure to potential fraudulent activities. |
When the network tokens feature is enabled, Yuno generates network tokens for all cards enrolled and securely stored in our vault. This approach is fully aligned with how network tokenization is intended to work, as defined by Visa and Mastercard after the card validation, ensuring better performance, security, and reliability in recurring and future transactions. Cards not stored in Yuno (such as one-time use cards) are naturally excluded from this process, since network tokenization is not applicable in those cases.
**Duplicate enrollments**
If the same card is enrolled multiple times, each enrollment creates a distinct `vaulted_token`. For network tokens, Yuno uses a `network_token_fingerprint` that works like the card fingerprint and is scoped to your organization and the unique identifier of the network token in the PCI vault. This means duplicate enrollments for the same PAN can map to the same network token. Use the [Card Fingerprint](/docs/fingerprint) to detect vaulted token duplicates on your side.
## Network tokens lifecycle
Network tokens can have the statuses described in the section below.
| Status | Description |
| --------- | ------------------------------------------------------------------------------------------------------------------------------- |
| Created | The initial status of a network token that has been created. |
| Active | The network token is active and can be used to make a payment. |
| Suspended | Tokens may be suspended if the cardholder contacts the issuer and requests that payments from a particular merchant be blocked. |
| Canceled | Tokens may be canceled for various reasons, such as the cardholder account associated with the token being closed. |
## Types of integration
To make payments with network tokens, you have two available options:
1. Let Yuno provision and collect network tokens.
2. Use your existing network tokens.
### 1. Let Yuno provision and collect network tokens
We procure network tokens from leading card networks, including Visa, Mastercard, and American Express. These tokens are securely stored within the Yuno infrastructure and are used instead of the actual cards during the authorization process.
There is no need for additional integration to access the benefits of network tokenization when Yuno manages the solicitation and accumulation of tokens on your behalf. Simply follow the standard payment workflow corresponding to your specific card payment integration. Yuno seamlessly handles the process, substituting card details for a network token, resulting in increased authorization rates.
To activate payments using network tokens, please contact our support team to provision or request the necessary credentials.
#### Response example
During either the enrollment or payment creation, you will receive the basic information of the network token used in the corresponding operation.
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"description": "Test",
"account_id": "{{account-code}}",
"merchant_order_id": "0000023",
"country": "DE",
"merchant_reference" : "reference-{{$randomUUID}}",
"amount": {
"currency": "EUR",
"value": 5000
},
"customer_payer": {
"id":"967ecd18-d898-4b88-9400-dd5b01b18edc"
},
"workflow": "DIRECT",
"payment_method": {
"type":"CARD",
"vaulted_token": "61d49d6e-7c0e-49d0-be79-7eb08871f998",
"detail": {
"card": {
"network_token":{
"network":"MASTERCARD",
"status": "ACTIVE",
"par":"V0010014622074319305424002620",
"token_data":{
"iin":"45079900",
"lfd": "0010",
"expiration_month":"10",
"expiration_year":"2028",
"response":{
"code":"succeeded",
"message": "Transaction Succeeded"
}
}
}
}
}
}
[...]
}
```
### 2. Use your existing network tokens
After setting up the necessary credentials in your Yuno account and contacting our support team, you will be ready to execute tokenized transactions seamlessly.
With this option, Yuno acts only as a passthrough for the network token information. The merchant must provide the necessary information about the network tokens so Yuno can share them with upstream payment partners.
Network token transactions utilize existing payment transaction API requests. Similar to creating a payment with credit card details, when a merchant uses the Yuno API to finalize a payment, they can choose to include the "network\_token" object to use a network token for the transaction.
#### Payment request fields
Along with the `card_data` object, these fields should be added to the `payment_method.detail.card.network_token.token_data` object for sending payments using Yuno's API.
| Field | Type | Description |
| ------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `number` | number | \[Mandatory] - Token's number without any separators. (MAX 19; MIN 8) - only available for PCI certified merchants |
| `holder_name` | string | Cardholder's full name as it appears on the token (MAX 26; MIN 3) - only available for PCI certified merchants |
| `expiration_month` | integer | \[Mandatory] - Token's expiration month - MM (MAX 2; MIN 2) - only available for PCI certified merchants |
| `expiration_year` | integer | \[Mandatory] - Token's expiration year - YYYY (MAX 4; MIN 4) - only available for PCI certified merchants |
| `cryptogram` | string | \[Mandatory] - The unique cryptogram generated by the issuer for the network token in use in the transaction. Optional for recurring transactions |
| `electronic_commerce_indicator` | string | \[Only required for certain providers] - If the token has been authenticated by Mastercard, the field should be set to 02. For Visa or non-authenticated tokens, it is not necessary to send the field. |
| `token_requestor_id` | string | \[Only required for certain providers] - Token requestor ID of the merchant |
#### Request example
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"description": "Test",
"account_id": "{{account-code}}",
"merchant_order_id": "0000023",
"country": "DE",
"merchant_reference" : "reference-{{$randomUUID}}",
"amount": {
"currency": "EUR",
"value": 5000
},
"customer_payer": {
"id":"967ecd18-d898-4b88-9400-dd5b01b18edc"
},
"workflow": "DIRECT",
"payment_method": {
"type":"CARD",
"detail": {
"card": {
"card_data": {
"number": "4000000000001026",
"holder_name": "John Doe",
"expiration_month": 1,
"expiration_year": 26,
"security_code": "123"
},
"network_token":{
"token_data":{
"number":"4000000000001026",
"holder_name":"Jhohn Doe",
"expiration_month":1,
"expiration_year":26,
"cryptogram":"CCADBxYzRTBBXXXXXXXYZa0AbZD"
}
}
}
}
}
[...]
}
```
#### Response example
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"description": "Test",
"account_id": "{{account-code}}",
"merchant_order_id": "0000023",
"country": "DE",
"merchant_reference" : "reference-{{$randomUUID}}",
"amount": {
"currency": "EUR",
"value": 5000
},
"customer_payer": {
"id":"967ecd18-d898-4b88-9400-dd5b01b18edc"
},
"workflow": "DIRECT",
"payment_method": {
"type":"CARD",
"detail": {
"card": {
"card_data": {
"holder_name": "John Doe",
"iin": "48710499",
"lfd": "9910",
"number_length": 16,
"security_code_length": 3,
"brand": "VISABANCONTACT",
"issuer_name": "BNP PARIBAS FORTIS NVSA",
"issuer_code": null,
"country_code": "BE",
"category": "CLASSIC",
"type": "DEBIT",
"expiration_month": 3,
"expiration_year": 30,
"fingerprint": "4d486017-afa0-4f2c-ba51-a09af528bd38"
[...]
},
"network_token":{
"network":"MASTERCARD",
"status": "ACTIVE",
"par":"V0010014622074319305424002620",
"token_data":{
"iin":"45079900",
"lfd": "0010",
"holder_name":"Jhohn Doe",
"expiration_month":10,
"expiration_year":28,
"response":{
"code":"succeeded",
"message": "Transaction Succeeded"
}
}
}
}
}
}
[...]
}
```
# PCI Compliance
Source: https://docs.y.uno/docs/security-and-compliance/pci-compliance
Explains how Yuno's tokenization reduces PCI DSS scope for merchants using its SDKs.
The Payment Card Industry Data Security Standard (PCI DSS) requires any business that stores, processes, or transmits cardholder data to meet a defined set of security controls. Non-compliance can result in fines from card brands and increased liability in the event of a breach.
By integrating with Yuno, your systems never store or transmit raw card data. Yuno's PCI DSS Level 1 solution handles all sensitive payment information through tokenization, replacing card data with a non-sensitive token before it ever reaches your infrastructure. This significantly reduces your PCI scope and the validation effort required.
## How Yuno reduces your PCI scope
When you integrate using Yuno's SDKs (Full Checkout, Lite Checkout, or Secure Fields), sensitive card data flows directly between the customer's browser or app and Yuno's secure environment. Your servers receive only tokens.
This means most merchants using Yuno's SDK qualify for the **SAQ A** (the shortest PCI self-assessment, composed of just 22 questions), rather than the full SAQ D, which has 329 questions and is required when a merchant stores or processes card data directly.
**Direct Flow**
If your integration uses the [Direct Flow](/docs/direct-flow), your business handles card data directly and must provide an Attestation of Compliance (AOC) signed by your company and a certified auditor.
## What tokenization gives you
Beyond compliance, Yuno's tokenization provides practical benefits for your payment operations:
* **One-click checkout**: Returning customers pay with a single tap using their stored vaulted token
* **Recurring and subscription billing**: Tokenized payment methods are reused seamlessly across billing cycles
* **Cross-processor portability**: A single vaulted token works across all processors connected to your Yuno account
* **Reduced declines**: Network tokens automatically update when cards are renewed or reissued
For a full breakdown of token types and how they work, see [Tokens](/docs/tokens).
## Choosing an SDK integration
Yuno's SDK integrations are available for web (JavaScript) and mobile (iOS, Android, Flutter). Refer to the [SDK guide](/docs/sdks/overview/quickstart) to choose the right integration for your use case.
For more on PCI DSS requirements and self-assessment questionnaires, see the [PCI Security Standards Council](https://www.pcisecuritystandards.org/) and the [PCI Document Library](https://www.pcisecuritystandards.org/document_library/?category=saqs#results).
# Destination Allowlist
Source: https://docs.y.uno/docs/security-and-compliance/pci-proxy/allowlist
Register the third-party hosts your PCI Proxy is allowed to call. Every destination must be on your allowlist before the proxy will send card data to it.
The PCI Proxy only sends card data to hosts you have explicitly registered. This is a
deliberate safety control: even if your API credentials were stolen, an attacker could not
forward your stored cards to a server you never approved. There is no "any host" mode.
Managing your allowlist is self-serve — a hostname you add is usable within minutes, no
support ticket required.
**A destination not on your allowlist is rejected**
A proxy request to an unregistered host returns `403 DESTINATION_NOT_ALLOWED`. Register the
host first with the endpoints below.
## How matching works
The proxy only forwards to hosts that are registered **and enabled** on your allowlist.
Matching is exact on the hostname:
* **Case-insensitive:** `API.Stripe.com` and `api.stripe.com` are the same host.
* **No wildcards:** `api.example.com` does not authorize `sandbox.example.com`.
* **Subdomains are registered separately.**
A request to a host that is not registered, or is registered but `DISABLED`, is rejected with
`403 DESTINATION_NOT_ALLOWED` before any card data is read.
## Register a destination
```sh theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
curl -X POST "https://api.y.uno/v1/pci-proxy/destinations" \
-H "public-api-key: $PUBLIC_API_KEY" \
-H "private-secret-key: $PRIVATE_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{
"hostname": "api.example-processor.com",
"purpose": "Direct acquiring — Processor X",
"account_id": null
}'
```
Returns `201` with the created entry, which starts in the `ENABLED` state. A hostname that is
already registered returns `409 DESTINATION_EXISTS`; a value that is not a bare public hostname
(a URL, a host with a port or path, an IP address, or a wildcard) returns `422 INVALID_HOSTNAME`;
an `account_id` that is not a valid account for your organization returns `400 INVALID_ACCOUNT_ID`.
`account_id` is optional. Left `null` (the default), the destination is allowed for **every
account** in your organization. Set it to a specific account id to scope the destination to
that account only — the host is then usable solely on proxy requests made under that account.
The destination object returns `id`, `hostname`, `purpose`, `account_id`, `status`
(`ENABLED` / `DISABLED`), `created_at`, and `updated_at`. When you call via the API the actor
is your API key, so the object does not carry a user email.
## List your destinations
```sh theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
curl "https://api.y.uno/v1/pci-proxy/destinations" \
-H "public-api-key: $PUBLIC_API_KEY" \
-H "private-secret-key: $PRIVATE_SECRET_KEY"
```
Returns `{"destinations": [ ... ]}` — only the destinations registered for your account.
## Remove a destination
```sh theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
curl -X DELETE "https://api.y.uno/v1/pci-proxy/destinations/{id}" \
-H "public-api-key: $PUBLIC_API_KEY" \
-H "private-secret-key: $PRIVATE_SECRET_KEY"
```
Returns `204`. Removing a destination takes effect immediately — the next proxy request to
that host is rejected.
## Enable or disable a destination
Instead of removing a host, you can **disable** it — the record (and its audit history) is kept,
but the forward path stops using it. Re-**enable** it to turn it back on. This is useful for
temporarily suspending a destination without losing its configuration.
```sh theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
# Turn a destination off (keeps the record)
curl -X POST "https://api.y.uno/v1/pci-proxy/destinations/{id}/disable" \
-H "public-api-key: $PUBLIC_API_KEY" \
-H "private-secret-key: $PRIVATE_SECRET_KEY"
# Re-enable a disabled destination
curl -X POST "https://api.y.uno/v1/pci-proxy/destinations/{id}/enable" \
-H "public-api-key: $PUBLIC_API_KEY" \
-H "private-secret-key: $PRIVATE_SECRET_KEY"
```
Each returns `200` with the updated destination object (its `status` set to `DISABLED` or
`ENABLED`). Only `ENABLED` destinations are used by the forward path; a request to a `DISABLED`
host returns `403 DESTINATION_NOT_ALLOWED`.
A destination moves through three states:
```
create
│
▼
┌───────────┐ disable ┌────────────┐
│ ENABLED │ ───────────► │ DISABLED │
│ (usable) │ ◄─────────── │ (blocked) │
└───────────┘ enable └────────────┘
│ │
└──────────── delete ───────┘
│
▼
(removed)
```
## Audit trail
Every allowlist change — **add, remove, enable, and disable** — is written to an append-only
audit log recording who made the change, when, and which hostname. The audit record persists
even after a destination is removed, so a deletion is never invisible: you can always see who
removed a host and when. There is no way to alter or erase these audit records through the API.
**Treat new-destination and deletion alerts seriously**
Adding or removing a destination is a sensitive action: it changes where your cards can be sent.
Yuno recommends restricting who can manage the allowlist, enabling notifications on allowlist
changes, and reviewing any unexpected additions or deletions — they are the tripwire for a
compromised dashboard account.
# Forward Proxy
Source: https://docs.y.uno/docs/security-and-compliance/pci-proxy/forward-proxy
Step-by-step guide to calling third-party APIs with real card data through the Yuno PCI Proxy using vaulted token expressions.
This guide shows how to call a third-party API with real card data through the Yuno PCI Proxy. If you have not read it yet, start with the [PCI Proxy Overview](/docs/security-and-compliance/pci-proxy/overview).
## Requirements
* Your `public-api-key` and `private-secret-key` from the Yuno Dashboard.
* A card stored with Yuno and its `vaulted_token`. See [Enroll Payment Method](/reference/payment-methods-direct-workflow/enroll-payment-method-api).
* The destination API you want to call, reachable over HTTPS on port 443, and registered on your [destination allowlist](/docs/security-and-compliance/pci-proxy/allowlist).
**Server-side only**
Proxy requests detokenize card data and must only be made from your backend. Never expose your `private-secret-key` in client-side code.
Write the request exactly as the destination API expects it — same body shape, same headers — but put vaulted token expressions where the card data belongs:
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"amount": 2500,
"currency": "USD",
"card": {
"number": "{{vaulted_token.1a2b3c4d-5678-90ab-cdef-111213141516.number}}",
"expiration_month": "{{vaulted_token.1a2b3c4d-5678-90ab-cdef-111213141516.expiration_month}}",
"expiration_year": "{{vaulted_token.1a2b3c4d-5678-90ab-cdef-111213141516.expiration_year}}",
"holder_name": "{{vaulted_token.1a2b3c4d-5678-90ab-cdef-111213141516.holder_name}}"
}
}
```
The card fields you can reference are `number`, `expiration_month`, `expiration_year`, and `holder_name` — they resolve to the stored **card (PAN) data**. If the card was enrolled with a security code, you can also reference `security_code`, within a bounded window — see below. If the card has a **network token**, you can also reference `network_token_number` (the DPAN), `network_token_expiration_month`, and `network_token_expiration_year`. And `network_transaction_id` resolves to the card's NTID — the scheme's reference for its original transaction, required by many processors for merchant-initiated transactions. All fields can be mixed in the same request — send your processor whatever it needs: PAN, DPAN + NTID, or a combination. Provider tokens are not resolved, and neither are cryptograms — a cryptogram is generated per transaction, so if your destination requires one, obtain it separately and include the value directly in the body.
Expressions work in the request body and in header values. Everything that is not an expression is forwarded untouched.
**The security code expires — by default 3 hours after enrollment**
`security_code` is the one field with a lifetime. The security code is never stored: it is held briefly after your customer enters it, and Yuno stops serving it once that window closes. Reference it only for a charge that happens shortly after enrollment.
When it is unavailable — expired, or never captured — the forward fails with `EXPRESSION_RESOLUTION_FAILED` naming `security_code`, and **no** partial substitution happens. Your PAN expressions are unaffected: an expired security code costs you that field only.
If your destination requires the CVV outside that window, your customer must supply it and you include it directly in the body yourself; the proxy forwards it without storing it. Transmitting a raw security code keeps that request in your PCI scope.
#### Storing a security code
A card only has a security code to inject if one was supplied when it was enrolled. Send it as `card.security_code` on [Enroll Payment Method](/reference/payment-methods-direct-workflow/enroll-payment-method-api):
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"customer_id": "...",
"card": {
"number": "4111111111111111",
"expiration_month": 12,
"expiration_year": 2030,
"holder_name": "JOHN DOE",
"security_code": "123"
}
}
```
Enroll without it and the card is still usable for every other expression — only `security_code` will be unavailable.
#### Checking how much of the window is left
Read `card_data.security_code_expires_in` from [Retrieve Enrolled Payment Method](/reference/payment-methods-direct-workflow/retrieve-enrolled-payment-method-by-id-api):
| Value | Meaning |
| ----------------- | --------------------------------------------------------------------------------------------------- |
| A positive number | Seconds left before the security code stops being available |
| `-1` | The window has closed; the security code can no longer be injected |
| Field absent | The card was enrolled without a security code, or your organization does not have the proxy enabled |
The enrollment response does **not** include `security_code_expires_in`. Read it from the payment method endpoint above when you need to know where you stand before building a forward.
Send the request to `https://api.y.uno/v1/pci-proxy/forward` with the destination in the `yuno-proxy-destination-url` header:
```sh theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
curl -X POST "https://api.y.uno/v1/pci-proxy/forward" \
-H "public-api-key: $PUBLIC_API_KEY" \
-H "private-secret-key: $PRIVATE_SECRET_KEY" \
-H "yuno-proxy-destination-url: https://api.example-processor.com/charges" \
-H "yuno-account-id: acc_123" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $PROCESSOR_API_KEY" \
-d '{
"amount": 2500,
"currency": "USD",
"card": {
"number": "{{vaulted_token.1a2b3c4d-5678-90ab-cdef-111213141516.number}}",
"expiration_month": "{{vaulted_token.1a2b3c4d-5678-90ab-cdef-111213141516.expiration_month}}",
"expiration_year": "{{vaulted_token.1a2b3c4d-5678-90ab-cdef-111213141516.expiration_year}}",
"holder_name": "{{vaulted_token.1a2b3c4d-5678-90ab-cdef-111213141516.holder_name}}"
}
}'
```
The HTTP method you use is the method the destination receives. Headers you set for the destination (like `Authorization` above) pass through; Yuno's own credential headers and all `yuno-*` headers are stripped before forwarding.
The `yuno-account-id` header is optional: include it when you need to scope the request to a specific account. Like all `yuno-*` headers it is removed before forwarding and never reaches the destination. It narrows **which allowlisted destinations** are permitted for the request; it does not affect token resolution — vaulted tokens are always scoped to your organization.
Put the **complete** destination URL — including its path and any query string — in `yuno-proxy-destination-url` (for example `https://api.example-processor.com/charges/ch_123/capture?expand=true`). Do not add a path or query string to the `/v1/pci-proxy/forward` request itself; a query string on the proxy request is rejected, so that merchant data is never logged.
The destination's status code, headers, and body are returned to you unchanged, except that any card number the destination echoes back is redacted first (see [Card data in responses](#card-data-in-responses) below). Redirects are **not** followed: a `3xx` from the destination is returned to you as-is, so you decide whether to follow it. The proxy adds diagnostic headers:
| Header | Meaning |
| -------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| `yuno-proxy-request-id` | Unique identifier of this proxy invocation. Include it in support requests. |
| `yuno-proxy-destination-status` | The HTTP status returned by the destination. **Present only when the destination was reached** — if it is missing, the failure happened inside Yuno. |
| `yuno-proxy-replacements` | How many expressions were replaced. `0` on a request you expected to be detokenized means your expressions did not match. |
| `yuno-proxy-response-redactions` | How many card numbers were redacted from the destination's response. A non-zero value means the destination returned card data. |
Errors produced by the proxy itself use the standard Yuno error format and never include the `yuno-proxy-destination-status` header:
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"code": "EXPRESSION_RESOLUTION_FAILED",
"messages": ["a vaulted_token expression could not be resolved: network_transaction_id"]
}
```
| HTTP status | Code | Meaning |
| ----------- | ------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `401` | `NOT_AUTHENTICATED` / `AuthenticationFail` | Missing or invalid API credentials |
| `400` | `INVALID_REQUEST` | Missing or invalid `yuno-proxy-destination-url`, an expression or query string in the URL, an invalid `yuno-proxy-timeout`, more than 20 distinct tokens in one request, or an invalid signing setup (unknown `yuno-proxy-auth` value, missing `yuno-proxy-auth-secret-key`, or `DLOCAL_HMAC` without the `X-Login` or `X-Trans-Key` headers) |
| `400` | `EXPRESSION_RESOLUTION_FAILED` | A `vaulted_token` does not exist, does not belong to your organization, or a referenced field is unavailable (for example, a network-token field on a card with no network token provisioned). The message names the field that could not be resolved — the token value is never echoed |
| `400` | `INVALID_ACCOUNT_ID` | The `yuno-account-id` header is not a valid account for your organization |
| `403` | `DESTINATION_NOT_ALLOWED` | The destination is not a public HTTPS hostname (IP addresses, non-443 ports, and internal networks are rejected), or the host is not on your [destination allowlist](/docs/security-and-compliance/pci-proxy/allowlist) |
| `403` | `PRODUCT_NOT_ENABLED` | The PCI Proxy is not activated for your organization. This gate applies in **production** only — contact your Key Account Manager (KAM) to activate it. The sandbox is open for testing |
| `413` | `REQUEST_TOO_LARGE` | Request body over 1 MB |
| `429` | `TOO_MANY_REQUESTS` | Rate limit exceeded |
| `502` | `DESTINATION_UNREACHABLE` | The destination could not be reached or closed the connection |
| `502` | `RESPONSE_BLOCKED` | The destination's response contained card data and Yuno is configured service-wide to reject such responses instead of redacting them (redaction is the default) |
| `504` | `DESTINATION_TIMEOUT` | The destination did not respond within the timeout |
| `500` | `PROXY_ERROR` | An unexpected error inside the proxy |
A `401` is returned before your request reaches the proxy, so it does not carry the `yuno-proxy-request-id` header; every other response does.
Any `4xx`/`5xx` accompanied by `yuno-proxy-destination-status` is the destination's own error, passed through for you to handle as if you had called it directly.
## Content types
The proxy is **content-type agnostic**. It forwards the body verbatim, without parsing or coercing it to JSON. Expression resolution is a text substitution over the raw body bytes, so a `vaulted_token` expression is replaced wherever it appears — JSON, XML, SOAP, or form key-value pairs. Place the expressions inside your payload and send the `Content-Type` your destination expects.
**JSON** is shown above. The examples below cover the other common formats.
**XML**
```sh theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
curl -X POST "https://api.y.uno/v1/pci-proxy/forward" \
-H "public-api-key: $PUBLIC_API_KEY" \
-H "private-secret-key: $PRIVATE_SECRET_KEY" \
-H "yuno-proxy-destination-url: https://api.legacy-processor.com/gateway" \
-H "Content-Type: application/xml" \
-d '2500{{vaulted_token.1a2b3c4d-5678-90ab-cdef-111213141516.number}}{{vaulted_token.1a2b3c4d-5678-90ab-cdef-111213141516.holder_name}}{{vaulted_token.1a2b3c4d-5678-90ab-cdef-111213141516.expiration_month}}/{{vaulted_token.1a2b3c4d-5678-90ab-cdef-111213141516.expiration_year}}123'
```
**SOAP** — an XML envelope plus the destination's own `SOAPAction` header, forwarded unchanged:
```sh theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
curl -X POST "https://api.y.uno/v1/pci-proxy/forward" \
-H "public-api-key: $PUBLIC_API_KEY" \
-H "private-secret-key: $PRIVATE_SECRET_KEY" \
-H "yuno-proxy-destination-url: https://api.legacy-processor.com/soap" \
-H "Content-Type: text/xml; charset=utf-8" \
-H "SOAPAction: \"ProcessPayment\"" \
-d '2500{{vaulted_token.1a2b3c4d-5678-90ab-cdef-111213141516.number}}{{vaulted_token.1a2b3c4d-5678-90ab-cdef-111213141516.holder_name}}{{vaulted_token.1a2b3c4d-5678-90ab-cdef-111213141516.expiration_month}}/{{vaulted_token.1a2b3c4d-5678-90ab-cdef-111213141516.expiration_year}}123'
```
**Form key-value pairs** (`application/x-www-form-urlencoded`):
```sh theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
curl -X POST "https://api.y.uno/v1/pci-proxy/forward" \
-H "public-api-key: $PUBLIC_API_KEY" \
-H "private-secret-key: $PRIVATE_SECRET_KEY" \
-H "yuno-proxy-destination-url: https://api.legacy-processor.com/charge" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d 'amount=2500&card_number={{vaulted_token.1a2b3c4d-5678-90ab-cdef-111213141516.number}}&card_holder={{vaulted_token.1a2b3c4d-5678-90ab-cdef-111213141516.holder_name}}&exp_month={{vaulted_token.1a2b3c4d-5678-90ab-cdef-111213141516.expiration_month}}&exp_year={{vaulted_token.1a2b3c4d-5678-90ab-cdef-111213141516.expiration_year}}&cvv=123'
```
**Special characters in `holder_name`**
Because substitution is literal, a `holder_name` containing markup or delimiter characters can break the payload structure at the destination:
* **XML / SOAP:** a name with `&`, `<`, or `>` (for example `Doe & Sons`) can break well-formedness. The `number`, `expiration_month`, and `expiration_year` fields are digits only, so they are unaffected — the risk is limited to `holder_name`.
* **Form key-value pairs:** a name with `&`, `=`, or spaces can break the key/value structure. Send `holder_name` URL-encoded, or use a JSON/XML payload if the holder name may contain special characters.
## Card data in responses
If a destination echoes a card number back in its response, the proxy redacts it before returning the response to you — keeping only the last four digits — so raw card numbers never reach your systems. The number of redactions is reported in the `yuno-proxy-response-redactions` response header:
```http theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
HTTP/1.1 200 OK
yuno-proxy-request-id: 7b3f...
yuno-proxy-destination-status: 200
yuno-proxy-response-redactions: 1
{ "status": "approved", "card": { "number": "XXXXXXXXXXXX1111" } }
```
A non-zero `yuno-proxy-response-redactions` is a signal that your destination is returning card data you should not receive. Redaction is the default behavior. Yuno can optionally be configured — as a service-wide setting, not per account — to instead **reject** any response containing card data with `502 RESPONSE_BLOCKED`.
## Authenticating to the destination
A proxy request carries two independent sets of credentials:
* **Your Yuno credentials** (`public-api-key` / `private-secret-key`) authenticate you to the proxy. They are consumed by Yuno and never forwarded.
* **The destination's own credentials** are whatever that third-party API expects. Put them on the request and they are forwarded untouched — Yuno only strips its own headers.
Send whatever authentication header your destination requires — it is **not limited to `Authorization`**. The header name is defined by the destination provider's API, not by Yuno; take it from that provider's own documentation.
**What Yuno forwards vs. removes:**
| Header | Forwarded to destination? |
| ------------------------------------------------------------------------------------------------------- | ------------------------- |
| `Authorization` (and any other destination header) | Yes, unchanged |
| `Content-Type` | Yes |
| `public-api-key`, `private-secret-key` | Removed by Yuno |
| Any `yuno-*` header (e.g. `yuno-proxy-destination-url`, `yuno-account-id`) | Removed by Yuno |
| Internal tracing/infrastructure headers (`traceparent`, `x-datadog-*`, `x-envoy-*`, `x-forwarded-*`, …) | Removed by Yuno |
**Common authentication header names by provider** (examples — always check the destination's docs):
| Provider (example) | Authentication header |
| ------------------------- | --------------------------------------------- |
| Stripe and many REST APIs | `Authorization: Bearer ` |
| Some gateways | `X-Api-Key: ` or `apikey: ` |
| Others | `Api-Token: `, `X-Auth-Token: ` |
| Basic auth | `Authorization: Basic base64(user:pass)` |
## Signed destinations (HMAC request signing)
Some destinations require every request to be **signed (HMAC) over the request body**. You cannot pre-compute that signature yourself: it would have to be calculated over the **resolved** body — the one containing the real card number — which only exists inside Yuno's secure environment. Instead, send your signing credentials on the request itself and the proxy signs for you, after resolving your expressions:
| Header | Meaning |
| ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `yuno-proxy-auth` | The signing scheme. Supported: `DLOCAL_HMAC` |
| `yuno-proxy-auth-secret-key` | Your signing secret for this request. Like every `yuno-*` header it is stripped before forwarding and excluded from logs; the proxy uses it in memory and discards it — nothing is stored |
The destination's other identifiers are plain destination headers you send yourself, forwarded verbatim as always. For **dLocal** (`DLOCAL_HMAC`):
```sh theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
curl -X POST "https://api.y.uno/v1/pci-proxy/forward" \
-H "public-api-key: $PUBLIC_API_KEY" \
-H "private-secret-key: $PRIVATE_SECRET_KEY" \
-H "yuno-proxy-destination-url: https://api.dlocal.com/secure_payments" \
-H "yuno-proxy-auth: DLOCAL_HMAC" \
-H "yuno-proxy-auth-secret-key: $DLOCAL_SECRET_KEY" \
-H "X-Login: $DLOCAL_X_LOGIN" \
-H "X-Trans-Key: $DLOCAL_X_TRANS_KEY" \
-H "X-Version: 2.1" \
-H "Content-Type: application/json" \
-d '{ "amount": 100, "currency": "USD", "country": "CO", "payment_method_id": "CARD",
"card": { "number": "{{vaulted_token.1a2b3c4d-5678-90ab-cdef-111213141516.number}}",
"holder_name": "{{vaulted_token.1a2b3c4d-5678-90ab-cdef-111213141516.holder_name}}",
"expiration_month": "{{vaulted_token.1a2b3c4d-5678-90ab-cdef-111213141516.expiration_month}}",
"expiration_year": "{{vaulted_token.1a2b3c4d-5678-90ab-cdef-111213141516.expiration_year}}",
"cvv": "123" } }'
```
Each `yuno-proxy-auth` value identifies a complete, fixed signing scheme — what is signed, how, and which headers the proxy produces — matching that destination's official authentication specification. `DLOCAL_HMAC` implements [dLocal's request-signing scheme](https://docs.dlocal.com/reference/payins-security):
| | `DLOCAL_HMAC` |
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Algorithm | HMAC-SHA256, output in lowercase hexadecimal |
| String to sign | `X-Login` value + `X-Date` value + the **resolved** request body, concatenated with no separators (empty body for requests without one) |
| Secret | Your dLocal secret key, from `yuno-proxy-auth-secret-key` |
| `X-Login`, `X-Trans-Key` | Sent by you as plain destination headers, forwarded verbatim — both required (`X-Login` is also part of the string to sign; `X-Trans-Key` is not signed, but dLocal rejects requests without it) |
| `X-Date` | Generated by the proxy at send time, ISO8601 UTC with milliseconds (e.g. `2026-07-29T21:32:48.676Z`) |
| `Authorization` | `V2-HMAC-SHA256, Signature: ` |
The signature is computed over the exact body bytes the destination receives — after your `{{vaulted_token…}}` expressions are resolved — which is precisely why the proxy must compute it. What the destination receives:
```
X-Login:
X-Trans-Key:
X-Version: 2.1 <- your value, verbatim
X-Date: 2026-07-29T21:32:48.676Z <- generated by Yuno
Authorization: V2-HMAC-SHA256, Signature: afcad672f89d… <- computed by Yuno
```
Do not send `X-Date` or `Authorization` yourself on a signed destination — the proxy's values replace them (a signature you computed over a body still containing `{{vaulted_token…}}` placeholders would be rejected by the destination anyway). All your other headers pass through untouched.
An unknown `yuno-proxy-auth` value, a missing `yuno-proxy-auth-secret-key`, or a `DLOCAL_HMAC` request without the `X-Login` or `X-Trans-Key` headers is rejected with `400 INVALID_REQUEST` before the destination is contacted. A `401` from the destination itself (wrong credentials) comes back as a destination response, with `yuno-proxy-destination-status: 401`.
**Mutual TLS is not yet supported**
Destinations that require **mutual TLS** (a client certificate) are not supported inline: the certificate is presented by Yuno during the TLS handshake, not sent in your request, so it must be configured with Yuno per destination rather than passed in the body or a header. mTLS is planned for a later release.
## Timeouts
The proxy waits up to 30 seconds for the destination by default. Override it with the `yuno-proxy-timeout` header (seconds, maximum 120):
```sh theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
curl -X POST "https://api.y.uno/v1/pci-proxy/forward" \
-H "public-api-key: $PUBLIC_API_KEY" \
-H "private-secret-key: $PRIVATE_SECRET_KEY" \
-H "yuno-proxy-destination-url: https://api.slow-supplier.com/bookings" \
-H "yuno-proxy-timeout: 90" \
-H "Content-Type: application/json" \
-d '{ "card_number": "{{vaulted_token.1a2b3c4d-5678-90ab-cdef-111213141516.number}}" }'
```
## Testing in sandbox
Use `https://api-sandbox.y.uno/v1/pci-proxy/forward` with your sandbox credentials and sandbox `vaulted_token` values. Sandbox tokens resolve to test card numbers, so you can point the proxy at your destination's own sandbox safely.
**Verify your integration**
Check `yuno-proxy-replacements` in the response while integrating: it confirms the proxy found and replaced your expressions before forwarding.
# PCI Proxy Overview
Source: https://docs.y.uno/docs/security-and-compliance/pci-proxy/overview
Send raw card data to any third-party API through Yuno's PCI DSS Level 1 environment, without bringing your own systems into PCI scope.
Some payment operations require sending raw card data to a third party — a processor Yuno does not orchestrate for you, an airline or hotel supplier API, a fraud or issuer service, or your own acquiring connection. Handling that data directly would pull your systems into full PCI DSS scope.
The Yuno PCI Proxy lets your servers make HTTPS requests to any third-party API **through Yuno's PCI DSS Level 1 environment**. You send a normal API request that references your stored cards by `vaulted_token`; Yuno replaces those references with the real card data inside its secure environment and forwards the request to the destination. The raw card number never touches your infrastructure, so your PCI scope does not change.
**Requirements**
The PCI Proxy works with cards you have already stored with Yuno. Cards are stored when a customer saves a payment method during checkout, or when you enroll one through the [Enroll Payment Method](/reference/payment-methods-direct-workflow/enroll-payment-method-api) endpoint.
**Destinations must be allowlisted**
The proxy only calls hosts you have registered on your destination allowlist. A request to an
unregistered host is rejected with `DESTINATION_NOT_ALLOWED`. Registration is self-serve and
takes effect in minutes — see [Destination Allowlist](/docs/security-and-compliance/pci-proxy/allowlist).
## How it works
1. Your server sends an HTTPS request to `https://api.y.uno/v1/pci-proxy/forward`, authenticated with your standard Yuno API credentials.
2. You put the full destination URL (including its path and query) in the `yuno-proxy-destination-url` header, and reference card data in the request body or headers using expressions such as `{{vaulted_token..number}}`.
3. Inside Yuno's PCI environment, the proxy resolves each expression to the real card data, then forwards your request — same method, headers, and body — to the destination over TLS.
4. The destination's response is returned to you, along with diagnostic headers that tell you what the proxy did.
The proxy is a pass-through: Yuno does not store your request or the destination's response, and request and response bodies are never written to logs.
## Card data in responses
If a destination echoes a full card number back in its response, returning it to you would put your systems back in PCI scope. To prevent that, the proxy scans each response for card numbers — the one it just injected, plus any other valid card number.
By default the proxy **redacts** them, leaving only the last four digits, and reports how many in the `yuno-proxy-response-redactions` response header; a non-zero value is a sign your destination is returning card data you should not receive. Yuno can optionally be configured, as a service-wide setting, not per account, to instead **reject** any response that contains card data with `502 RESPONSE_BLOCKED`.
## Card data you can reference
| Expression | Resolves to |
| ---------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `{{vaulted_token..number}}` | The card number (PAN) |
| `{{vaulted_token..expiration_month}}` | Two-digit expiration month (`MM`) |
| `{{vaulted_token..expiration_year}}` | Four-digit expiration year (`YYYY`) |
| `{{vaulted_token..holder_name}}` | The cardholder name |
| `{{vaulted_token..network_token_number}}` | The network token number (DPAN), when the card has a network token |
| `{{vaulted_token..network_token_expiration_month}}` | Network token two-digit expiration month (`MM`) |
| `{{vaulted_token..network_token_expiration_year}}` | Network token four-digit expiration year (`YYYY`) |
| `{{vaulted_token..network_transaction_id}}` | The network transaction ID (NTID): the card scheme's reference for the stored card's original transaction, required by many processors for merchant-initiated transactions |
The `` must be a `vaulted_token` that belongs to your organization. A token that does not exist or belongs to another organization is rejected with `EXPRESSION_RESOLUTION_FAILED`, before any card data is read. A field whose data is unavailable fails the same way — for example, a `network_token_*` field when the card has no network token, or `network_transaction_id` when the card has no NTID. All fields can be mixed in the same request.
**Not provider tokens, not cryptograms**
These expressions resolve a vaulted token to the data stored with it: the card (PAN, expiration, holder name), its network token (DPAN and its expiration), and its network transaction ID. Provider tokens are not resolved. Neither are **cryptograms**: a cryptogram is generated per transaction, so if your destination requires one, obtain it separately and include the value directly in the request body.
**The security code (CVV) expression has a lifetime**
`{{vaulted_token..security_code}}` resolves only while the security code is still available — by default for 3 hours after enrollment. It is never stored: it is held briefly after your customer enters it, and Yuno stops serving it once that window closes. Supply it as `card.security_code` when you enroll the card, and check `card_data.security_code_expires_in` on the payment method before relying on it. Outside that window, include the CVV directly in the request body yourself if your destination requires it; the proxy forwards it without storing it. Note that transmitting a raw security code keeps that request in your PCI scope.
## Your PCI scope
When you use the PCI Proxy together with Yuno's SDKs to collect cards, raw card data never enters your systems — it flows from the customer to Yuno, and from Yuno to the destination you choose. Most merchants operating this way qualify for the **SAQ A** self-assessment. See [PCI Compliance](/docs/security-and-compliance/pci-compliance) for the complete picture of how Yuno reduces your PCI scope.
## Security controls
* **HTTPS only.** The proxy connects to destinations over TLS 1.2 or higher, on port 443 only. Destinations must be public DNS hostnames — IP addresses and internal networks are rejected.
* **Credential isolation.** Your Yuno API credentials and all `yuno-*` headers are stripped before the request is forwarded. The destination only sees the headers you intend it to see.
* **No storage, no logging.** The proxy holds card data in memory only for the lifetime of the request. Request and response bodies are excluded from logs and traces.
* **Full audit trail.** Every invocation produces an audit record (who, when, destination, outcome — never card data).
## Limits
| Limit | Value |
| ----------------------------------- | ---------------------------------------------------------------------------------- |
| Request and response body size | 1 MB |
| Distinct vaulted tokens per request | 20 |
| Destination timeout | 30 seconds by default, configurable up to 120 with the `yuno-proxy-timeout` header |
| Supported methods | `GET`, `POST`, `PUT`, `PATCH`, `DELETE` |
## Get started
Follow the [Forward Proxy guide](/docs/security-and-compliance/pci-proxy/forward-proxy) for a step-by-step integration, or go straight to the [API reference](/reference/pci-proxy/invoke-forward-proxy).
# B2B Organization Management
Source: https://docs.y.uno/docs/using-yuno/b2b-organization-management
Learn how to manage account groups, accounts, and users for whitelabel partnerships.
Yuno provides a suite of B2B Organization Management APIs designed for platforms and whitelabel partners who need to manage multiple sub-organizations and their users. These APIs allow you to automate your merchants' onboarding by creating a hierarchical structure of Account Groups, Accounts, and Users.
**Prerequisites**
To use these APIs, your organization must have the **whitelabel** property enabled in the Yuno Dashboard. Contact your Yuno account manager to enable this feature.
## Core Management Flow
Follow these steps to set up a new merchant environment.
The account group acts as the parent entity for your merchant, centralizing the management of related accounts. Use the [Create Account Group](/reference/organizations/create-account-group) endpoint to initialize this group.
```bash theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
curl --request POST \
--url https://api-sandbox.y.uno/v1/organizations/account-groups \
--header 'PRIVATE-SECRET-KEY: ' \
--header 'PUBLIC-API-KEY: ' \
--header 'Content-Type: application/json' \
--data '{
"name": "Acme Payments",
"merchant_id": "acme_001"
}'
```
**Output & Next Steps**: The response will include a unique `id` for the Account Group. Store this ID, as you will need it to create specific merchant accounts in the next step.
Within the newly created account group, you can create one or more accounts. This structure allows you to separate business logic, regions, or business lines for the same merchant. Use the [Create Account](/reference/organizations/create-account) endpoint.
```bash theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
curl --request POST \
--url https://api-sandbox.y.uno/v1/organizations/account-groups/{account_group_id}/accounts \
--header 'PRIVATE-SECRET-KEY: ' \
--header 'PUBLIC-API-KEY: ' \
--header 'Content-Type: application/json' \
--data '{
"name": "Acme Production"
}'
```
**Output & Next Steps**: You will receive an `id` for the merchant account. This ID is used to scope payments, sessions, and configurations specifically to this merchant environment.
Finally, create a physical user and grant them access to the account or the entire account group. Assigning roles (like `merchant-admin`) ensures the user has the necessary permissions to manage the merchant dashboard. Use the [Create User](/reference/organizations/create-user) endpoint.
```bash theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
curl --request POST \
--url https://api-sandbox.y.uno/v1/organizations/users \
--header 'PRIVATE-SECRET-KEY: ' \
--header 'PUBLIC-API-KEY: ' \
--header 'Content-Type: application/json' \
--data '{
"email": "admin@acmepay.com",
"first_name": "John",
"last_name": "Doe",
"account_group_permissions": [
{
"account_group_id": "{account_group_id}",
"role_id": "merchant-admin"
}
]
}'
```
**Output & Next Steps**: The user will be created in the system. To allow them to log in to your whitelabel portal, use the [Authenticate Whitelabel User](/reference/organizations/authenticate-whitelabel-user) endpoint to generate a secure access token.
## Environment Availability
The B2B Organization Management APIs are available in both **Sandbox** and **Production** environments. For more information on how to manage your API keys and base URLs, visit the [Environments](/docs/using-yuno/environments) page.
## Next Steps
Explore the full API reference for more advanced management options:
* [Account Groups Reference](/reference/organizations/list-account-groups)
* [Accounts Reference](/reference/organizations/list-accounts)
* [Users Reference](/reference/organizations/list-users)
* [User Permissions Reference](/reference/organizations/retrieve-user-account-permissions)
# Checkout Builder
Source: https://docs.y.uno/docs/using-yuno/dashboard-overview/checkout-builder
Configure payment method display conditions, required fields, and checkout styling with a no-code builder
The Checkout Builder is a no-code tool designed to customize your checkout experience. It includes two main modules:
* **Payment method settings**: Enable payment methods with a published route to show to your customers. Additionally, you can define under which circumstances specific payment methods are displayed.
* **Checkout styling**: Adjust the checkout's visual elements for desktop and mobile devices, including colors and typography. This ensures the checkout experience is consistent with your brand.
Any changes made using the Checkout Builder are immediately reflected in the user-facing checkout, providing a straightforward way to manage and adapt the checkout experience to meet your business requirements.
## Advantages of using Checkout Builder
* **Customization with no code**: Enjoy the flexibility of tailoring your checkout experience without the need for complex coding. This empowers you to create a checkout process that aligns with your brand and business objectives.
* **Payment method flexibility**: Easily enable, organize, and display the payment methods that best suit your customer base and market.
* **Intuitive user interface**: Yuno's interface makes it a breeze to configure payment methods, set display conditions, and customize styling.
## Payment method settings
This module lets you configure and customize the payment methods used in the checkout experience. Beyond activating payment methods, you can adjust the order in which they're displayed, customize their appearance, set required fields, and determine conditions for when each payment method is displayed. This breadth of customization ensures the checkout experience fits your audience and specific use case.
You must click **Publish settings** on the Checkout Builder to apply all changes to the checkout.
### Conditions
You can control when a payment method appears at checkout by setting display conditions based on criteria such as the order’s country, amount, currency, or integration metadata. To configure these settings:
Next to the payment method, click the three dots icon and select **Set Conditions**. Click **Add new condition** in the pop-up.
Enter a descriptive name and select parameters like order country, currency, or metadata.
Fill out the fields that appear based on your selected specifications.
### Required fields
Required fields specify the information users must provide when using each payment method. Some payment methods require specific data to process payments, and Yuno may request it even if you didn't specify it. Yuno streamlines the process of adding or removing desired fields through its user interface.
The **Required Fields** panel in the Checkout Builder lets you collect billing and shipping addresses as two independent forms during checkout. Billing address is used for card verification (AVS) and integrations with providers such as Stripe and Adyen, while shipping address is used for physical delivery.
**SDK version requirement**: This feature is only available in **Web SDK v1.7 or later**. Merchants on earlier SDK versions will not see the new address forms even if the configuration is enabled in the Checkout Builder.
#### Where to find it
1. Open the **Checkout Builder** in the Yuno Dashboard.
2. In **Payment method settings**, click the **three dots (⋯)** on the payment method you want to configure and select **Set Required fields**.
3. Find the **Address configuration** section in the **Required Fields** drawer.
This setting is **per payment method**, not global. Repeat the configuration for every payment method that should collect addresses.
#### How to configure
1. In the **Address configuration** section, turn the toggle **on**.
2. Choose the address mode:
* **Billing Address only**
* **Billing & Shipping Address**
3. Click **Save changes**.
4. Return to the Checkout Builder and click **Publish settings** for the changes to take effect in the live checkout.
No additional SDK parameters are required in the merchant's integration: as long as Web SDK v1.7 or later is integrated, the address forms render automatically based on the Checkout Builder configuration.
#### Available configuration
| Setting | Description | What the customer sees in the SDK |
| ------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Address configuration toggle: OFF** | Master switch disabled. | No address form is rendered in the checkout. |
| **Billing Address only** | Only the billing address form is collected. Use this when you only need billing data for AVS / verification (e.g., digital goods). | A single **Billing address** form is rendered at the bottom of the checkout. |
| **Billing & Shipping Address** | Both billing and shipping address forms are available. | The SDK renders a **Shipping address** form, followed by a **"Billing address is the same as shipping address"** checkbox. The **Billing address** form only appears when the checkbox is unchecked. |
The "Billing address is the same as shipping address" checkbox is purely a Web SDK UX element. It is **not** configurable from the Checkout Builder. It appears automatically whenever both billing and shipping are enabled.
#### Important notes
* **Backward compatibility:** Existing checkouts that only had `billing_address` enabled continue to work exactly as before: the previous address fields are mapped to the billing address. No action is required for merchants who don't want shipping collection.
* **Standalone Postal Code:** The postal code field can be used standalone (without other address fields) for all providers and all SDK flows. When postal code is enabled and other address fields are disabled, the backend allows null values for all address fields except postal code. If both postal code and address fields are enabled in the Checkout Builder, the backend prioritizes address fields over postal code.
* **Configure during low-traffic periods:** Publishing changes to required fields affects all subsequent checkout sessions immediately. Customers in the middle of an in-flight session may see inconsistent forms during the propagation window. We recommend configuring and publishing this setting during low-traffic periods to minimize impact.
In the Required fields, you can also configure the behavior for enrolled cards. You can configure whether to request the CVV for every transaction or only during the customer's first payment.
### Edit name and logo
The name and logo settings control how a payment methods appear during checkout. This option is unavailable for enrolled payment methods. To adjust these settings:
1. Within **Payment method settings**, click the three dots icon next to any non-enrolled payment method and select **Edit name and logo**.
2. Select **Use custom settings** to make changes.
3. Enter your preferred name for the payment method.
4. Optionally, you can add a description and provide a new logo URL. The URL must start with "https\://". Use a square image (JPG or PNG), 100x100 pixels in size, and up tp 10 KB.
5. Click **Save changes**, followed by **Publish settings** to apply all changes.
## Checkout styling
Match your brand's unique look and feel using the Checkout Styling module. Changes made in this module are reflected in the end-user checkout immediately after publishing.
### General Styling Options
The General Styling section allows you to adjust key visual elements, creating a consistent and professional look throughout the checkout experience. In this section, you can customize the following elements:
| Customizable Element | Description |
| :---------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Background Color** | Set the background color applied across all checkout forms, establishing a base that reflects your brand's aesthetic. This background color serves as the foundation of the entire checkout interface. |
| **Accent Color** | Select an accent color to highlight interactive elements, enhancing the user experience and adding brand-specific touches. The accent color applies to:
The background color of the primary button
The border color of the secondary button
Checkbox colors
|
| **Primary Text Color** | Define the main text color for high-visibility elements. This color will apply to:
Titles and subtitle
User input fields
Dropdown values
Text on secondary buttons
Checkbox text
|
| **Secondary Text Color** | Choose a secondary text color for supporting text elements. This color applies to:
Field descriptions
Placeholder text
Help text for additional form guidance
|
| **Primary Button Text Color** | Set the text color for the primary button to ensure the call-to-action is noticeable and accessible. |
| **Typography** | Select your preferred font. |
## Real-time checkout preview
The Checkout Builder includes a live preview panel on the right side of the screen. The preview reflects your current configuration as you make changes, without requiring you to publish first.
The preview is available in both the **Payment method settings** and **Styling settings** tabs.
### What the preview shows
* The payment methods currently enabled and their display order
* Express payment buttons (PayPal, Apple Pay, Google Pay) when active
* The card form with all configured required fields
* Color, typography, and styling changes as you adjust them
### Interactive fields
You can interact with the form fields directly in the preview panel. This lets you test field validation and error messages: for example, entering an invalid CVV triggers the error copy in real time.
The preview supports interactive field testing up to the **Pay** button. It does not simulate a complete end-to-end payment flow. To test a full transaction, use the SDK in a [test environment](https://docs.y.uno/docs/yuno-testing-gateway).
### Simulating conditions
Use the **Country**, **Currency**, and **Amount** filters above the preview panel to simulate different order contexts. This lets you verify that your display conditions are working as expected before publishing: for example, confirming that a payment method only appears for specific countries or amounts.
### Styling settings preview
When you switch to the **Styling settings** tab, the preview updates in real time as you adjust colors, typography, and layout options. Changes are visible immediately in the preview, including background color, accent color, and text colors, before you save or publish.
# Connections
Source: https://docs.y.uno/docs/using-yuno/dashboard-overview/connections
Add, edit, and manage provider connections for payment methods, processors, and anti-fraud solutions
The Connections section within the dashboard enables you to integrate and manage various providers, including payment methods, payment processors, and anti-fraud solutions. The ability to connect with providers from around the world using Yuno greatly reduces integration times and brings additional functionalities to your customers, increasing conveniency and revenue.
Let's walk through the process of adding, creating, and managing connections to enhance your payment processing and routing capabilities.
## Adding a connection
1. The **Explore** tab will display by default when opening Connections in the dashboard. From here, browse through the list of available providers or use the **Search** box to find your desired connection. Providers may include payment methods, processors, and anti-fraud solutions. Click **Connect** to proceed.
2. After selecting a provider, you will start the quick three-step process to configure the connection. First, you will be asked for provider credentials, necessary to establish a secure connection. Enter a memorable name for the connection and then enter the details required. The specific information you must enter will vary by provider, though you'll most likely have this data beforehand. Feel free to reach out to the provider in case you're unsure about any of these fields or missing information. Optionally, you may check **3DS Credentials** and enter the required data to activate the feature. Click **Next**.
3. The next screen, **Set up costs**, will let you enter cost information to use in Smart Routing and Reconciliations (Fees). Select **Set up cost** to enter costs for successful and unsuccessful payments. This option is entirely optional, so you may click **Next** without entering data.
4. **Set up accounts** lets you select the accounts that will be affected by the changes. Check specific accounts or **Current account only** and click **Save** to finish. The system will confirm the connection has been created, establishing a bridge between your Yuno account and the chosen provider.
**Editing connections**
When you create connections, one connection is set up for each account you select. If you need to make changes later, you must edit each connection individually: bulk editing is not supported.
5. With your connections set, you can proceed to the [Routing](/docs/routing) section to configure payment processing routes using the provider and payment methods you have available within Yuno.
**Set up costs for new connections**
When you add a new connection, you can set up its costs. This optional step allows you to set different costs for successful and unsuccessful payments to help manage fees using the [Smart Routing feature](/docs/routing#smart-routing).
You can set default costs for all payments and add specific conditions for different situations, like setting a unique cost when a customer uses Visa.
Costs are applied in the order you create them, but you can rearrange them by dragging and dropping. This setup helps Yuno Payments automatically choose the most cost-effective route for each transaction when you activate the Smart Routing.
Costs are used both for Smart Routing and for Fees in Reconciliations.
## Managing connections
The **Your connections** tab within Connections allows you to manage existing connections to suit your evolving business needs. Available actions include:
* **Editing connections**: Easily update credentials or change a connection's settings by selecting the three dots next to the connection and selecting **Edit**.
* **Pausing and unpausing connections**: To temporarily halt the interaction with a specific provider, you can choose to **Pause** a connection. When ready to resume, **Unpause** it. This flexibility allows you to adapt to changing circumstances without having to redo your connections.
* **Deleting connections**: If a connection is no longer needed, you can delete it. Exercise caution when deleting connections, as this action is irreversible.
* **Managing multiple connections**: Check the box next to two or more connections to pause, unpause and delete connections in bulk.
## Dynamic metadata configuration
The Dynamic Metadata feature allows you to control which metadata fields are sent to each connected provider, configuring exactly which metadata keys are sent from your connection settings. This is especially useful when different providers require different metadata.
To use Dynamic Metadata:
1. Turn on the "Dynamic Metadata Configuration" flag in your connection settings.
2. Set up key mappings from your public API metadata to provider-specific metadata.
3. Only the configured metadata keys will be sent to the provider during transactions.
**Important for Stripe users**
The current metadata logic in Stripe will be removed on **August 29, 2025**. Make sure to update your connection to use dynamic mapping before this date to avoid any disruption to your payment processing.
# Insights
Source: https://docs.y.uno/docs/using-yuno/dashboard-overview/insights
Analyze payment performance, conversion rates, and fraud metrics with customizable charts and exports
The **Insights** section provides a unified view of your payment performance metrics and analytics, directly within the dashboard. It turns raw transaction data into charts covering volume, conversion, and fraud, with a customizable interface tailored to your business needs.
## Understand your payment landscape
Gain a complete understanding of your payment ecosystem through insightful analytics. Access all critical payment data from a centralized platform, including:
* Payment volumes
* Transaction types
* Payment methods
* Customer demographics
Using historical data, you can monitor payment performance trends over time, identify strengths, and pinpoint areas for optimization to continuously refine your payment strategies.
Yuno Insights organizes your data into four distinct tabs, each providing a unique perspective:
A high-level overview of your payment processing, including total payment volume, average ticket size, and conversion rate trends.
Details on payment volume, refunds and chargebacks by provider, payment method, and country.
Performance metrics including approval rates, retry attempts, and validation success.
Fraud detection and prevention metrics, including fraud rates and pattern insights.
## Informed decision-making
The data presented within Yuno Insights is strategically organized around two core facets:
* Volume: Data aligned with business metrics to understand the overall flow and value of your transactions.
* Performance: Operational efficiency data to gauge the effectiveness and success rate of your payment processes.
Analyzing the available data from these two angles will allow you to easily extract valuable data, including:
* Overall and segmented conversion rates (by payment method and provider) to identify top-performing options.
* Detailed information on declined transactions, helping you understand and address reasons for non-conversion.
* Clear visibility into transaction volume trends, allowing you to track growth and identify fluctuations.
## Tailor and export insights
The Insight section contains several options to filter, customize, and extract data based on your preferences:
* **Filters**: Use the **Add filters** button to segment the displayed information by card brand, currency, date range, and other criteria, including **country**, **issuer country**, and **network tokens**. This allows you to focus on specific data segments for targeted analysis. You can quickly apply or clear large selections using the **Select all** and inverse selection controls in each filter.
* **Personalization**: Click **Customize** to control the reports you see and their arrangement.
Drag and drop elements to reorder them according to your priorities, or click the trash bin icon to remove less relevant reports. Remember to click **Done** to save your personalized layout.
* **Set your charts**: Use the **Add chart** button to fine-tune visualizations displayed. After selecting this option, click the icon next to each report to toggle its visibility. Select **Apply** to confirm your chart selections.
* **Export as PDF**: The **Download** button allows you to export the current Insights page as a PDF file. This feature simplifies the process of sharing Yuno's valuable reports across your organization.
## Your custom charts
This section lets you build fully personalized dashboards using natural language prompts. Generate tailored data visualizations that adapt to your analysis needs, all without any manual setup required. You can create as many charts as needed, each born from your written input.
Each chart includes an information icon (ⓘ) where you can view the exact prompt used to generate it, providing full transparency and allowing you to easily reuse or refine prompts.
Display a key total or metric at a glance.
Visualize trends or compare performance over time.
Compare categories such as countries, payment methods, or providers.
Show the proportional distribution of categories within your data.
### Best practices for prompting
* **Be specific and detailed**: Clearly describe what you want to visualize, including relevant details such as transaction type, status, country, provider, or any filters you wish to apply.
"Show a bar chart of approved credit card transactions by country for the last 3 months."
* **Always include a time range and frequency**: When requesting line or bar charts, specify both the period and the aggregation level (e.g., daily, weekly, monthly) for accurate trend analysis.
"Line chart of total volume per week for the last quarter."
* **Use dynamic time references for reusable charts**: Instead of fixed dates, use relative time frames such as "last week" or "previous month" to ensure your charts remain automatically up to date.
"Show total transactions by day for the last 30 days."
## Merchant advisory codes (MAC) insights
Insights includes charts that highlight merchant advisory codes (MAC), helping you understand why issuers recommend actions such as trying again later or updating information.
Key MAC visualisations include:
* **Top merchant advisory codes**: A breakdown of the most frequent MAC codes returned in your transactions, along with their relative share.
* **Daily top merchant advisory codes**: A time-series chart that shows how the top MAC codes evolve over time, helping you spot trends and changes in issuer behaviour.
Use these views to identify common advisory patterns, refine your retry strategies, and work with issuers or providers to reduce avoidable declines.
## Fraud insights
The Fraud tab breaks down fraud screening, 3DS authentication, and chargeback activity into the charts below, organized into three main sections:
### Fraud screening
Monitor fraud screening activities and performance:
* **Total fraud screening volume**: Track the total number of fraud screenings performed
* **Successful fraud screening volume**: Monitor successful fraud screenings
* **Unsuccessful fraud screening volume**: Track unsuccessful fraud screenings
* **Daily fraud screening conversion rate**: View conversion rate trends over time through bar charts
### 3DS
Analyze 3D Secure authentication performance:
* **Total 3DS authentication volume**: Track total 3DS authentication attempts
* **Successful 3DS authentication volume**: Monitor successful 3DS authentications
* **Unsuccessful 3DS authentication volume**: Track unsuccessful 3DS authentications
* **Daily 3DS conversion rate**: View conversion rate trends over time
* **3DS decline reasons**: Analyze reasons for 3DS authentication declines
* **Daily fraudiness vs challenge**: Compare fraudiness scores (a score indicating the likelihood that a transaction is fraudulent) against challenge rates
### Chargebacks
Monitor chargeback activity and outcomes:
* **Total chargebacks volume**: Track total chargebacks received
* **Won chargebacks volume**: Monitor chargebacks that were successfully won
* **Lost chargebacks volume**: Track chargebacks that were lost
* **Disputed chargebacks volume**: Monitor chargebacks currently in dispute
* **Daily chargebacks rate**: View chargeback rate trends over time
* **Chargebacks rate by provider and card brand**: Analyze chargeback rates segmented by provider and card brand
* **Chargeback reason distribution**: Understand the distribution of chargeback reasons
* **Daily chargebacks win rate**: Track the rate at which chargebacks are won
* **Daily disputed chargebacks**: Monitor chargebacks in dispute status
* **Chargebacks status distribution**: View the distribution of chargeback statuses
* **Chargebacks by type**: Analyze chargebacks categorized by type
Use fraud insights to optimize your fraud prevention strategies, adjust fraud detection rules, and ensure you're protecting your business without unnecessarily declining legitimate transactions.
# Monitors
Source: https://docs.y.uno/docs/using-yuno/dashboard-overview/monitors
Detect approval rate drops and automatically redirect traffic to fallback providers to protect conversion
Yuno's monitors feature helps you detect and address payment processing issues in real-time. Accessible from the Monitors section of your Yuno dashboard, this tool automatically identifies anomalies in payment provider performance and takes immediate action to maintain optimal approval rates and high conversion rates across your payment routes.
## Monitoring process operation
The monitoring process consists of four key steps that help identify and restore payment routes:
The system continuously monitors approval rates. When rates drop below your defined threshold, it triggers alerts through your configured channels like email or **Opsgenie**.
If approval rates fall below the threshold, Yuno immediately notifies you through your chosen alert channels.
Upon detecting low approval rates, Yuno automatically redirects payments to your fallback providers. A small portion of transactions continues through the original provider to monitor for service recovery.
When the primary provider's approval rate rises above the threshold again, traffic automatically returns to the original route.
This automated process helps maintain optimal payment processing by quickly detecting issues and implementing solutions to keep approval rates high.
### Additional monitoring scenarios
The monitor feature handles various payment route scenarios to maintain optimal processing. Here's how it manages specific situations:
Provider interruptions:
* When a provider has interruptions, traffic automatically redirects to the configured fallback provider
* If the fallback provider experiences issues, traffic moves to a second fallback provider (if configured)
* When all providers are unavailable, traffic routes to the provider with the highest recent approval rate
* The system continuously monitors providers and dynamically adjusts traffic for optimal approval rates
* Provider status (down/recovered) is determined by your configuration settings
Traffic redirection sequence:
1. When a provider drops below the approval threshold, traffic redirects to the fallback provider
2. If the fallback provider also drops below threshold, traffic moves to the second fallback (if available)
3. If all providers are below threshold, traffic routes to whichever provider has the highest approval rate
The diagram below illustrates these traffic redirection scenarios:
## Configure a monitor
To configure a monitor for your payment routes:
1. Go to the **Routing** tab in your dashboard and open an existing route. You can set up different approval rate monitors for each condition.
2. Customize your payment route with your preferred settings.
3. Add the necessary conditions and payment providers for each set.
4. Click the Monitors icon (bell) and configure these settings:
* **Time frame**: Set how long to measure the approval rate
* **Approval rate limit**: Set the threshold that triggers alerts and actions
* **Number of payments**: Set minimum, maximum, or range of payments needed to trigger the condition. This prevents redirects from anomalies during low payment volumes
* **Alert channels**: Choose email or **Opsgenie** notifications
* **Automatic traffic redistribution**: Enable automatic redirection when alerts trigger. Requires a fallback provider for **Error** and **Pause** conditions
* **Percentage of traffic**: Set how much traffic stays with the original provider for monitoring
5. Save the monitor changes, or save it as a template for future usage.
**Monitor Restriction**
Monitors cannot be created for routes that are already published.
# Payment Links
Source: https://docs.y.uno/docs/using-yuno/dashboard-overview/payment-links
Create no-code payment links with custom amounts, expiration dates, and advanced checkout options
The dashboard's payment links section allows you to create URLs to collect payments without writing code. Yuno's payment links combine a simple setup with advanced checkout options.
## A no-code experience
* **Custom-built payment links**: You can create payment links tailored to your needs without coding
* **Simple setup**: Construct a payment link in a few intuitive steps. Specify a country, currency, amount, and at least one payment method for rapid link creation
* **Start and expiration dates**: Enhance payment link utility by setting start and expiration dates. Increase your control by defining the exact time and timezone
## Advantages of payment links
* An intuitive interface with no need for coding
* Highly customizable links aligning with business needs and enhancing customer engagement
* Enhanced control allowing for the cancellation of links on demand
* Transaction insights deliver deep visibility and valuable analytics into payment activity and transaction status
## Create a payment link
If you are using the dashboard, follow these steps to create a payment link:
1. Access the [Yuno dashboard](https://auth.y.uno/u/login?)
2. Navigate to the **Payment links** section
3. Click **Create payment link**
4. Fill in the **Basic info** (description, country, currency, and amount) for your payment. Then, configure **Advanced options**
5. (Optional) Use **Payment settings** to add more payment methods, which could increase conversion
6. Share the payment link with your customer
If you are using the API integration, follow these steps:
1. (Optional) Create a customer using the [Create customer](/reference/create-customer) endpoint.
2. Create the payment link using the [Create payment link](/reference/create-payment-link) endpoint.
3. Share the payment link with your customer.
## Advanced options
Payment links can be enhanced in multiple ways:
* **Connect the payment link to an existing order ID**: Simplify order tracking by matching the payment link to an order ID
* **Collect multiple payments**: Determine whether a link should accept multiple payments or a single transaction
* **Set start and expiration date**: Set a timeframe in which your link will be active, down to the minute and timezone. If you don't set a start date, your link will be active immediately
* **Add order details**: Include items, services, or causes to provide a comprehensive view of the order within the payment link checkout
* **Airline ticket information**: Beneficial for airlines and travel-related businesses, this feature allows the integration of airline ticket information within the payment link checkout
## Using payment links
When customers open payment links, they will be greeted with a clean interface informing them of the amount to be paid and the payment methods available, according to what you selected when generating the link. The look of the page will adapt dynamically to phones and tablets. After following the on-screen instructions, customers will be able to process their payment, which can be viewed on the dashboard when managing payment links.
Want customers to open the payment link under your own domain, with no Yuno branding? See [Payment Link White Label](/docs/sdks/customization/web/payment-link-white-label).
## Payment link management
**Payment links** will display all your links in a list. Click any link to see an overview and payments performed. You may also narrow your search by payment link ID or using filters. Additionally, selecting the three dots next to each link will display:
* **Share payment link**: Quickly retrieve the link to share with your customers
* **View details**: See payment methods and previous payments
* **Disable**: Deactivate the link once it's no longer needed
For detailed insights and inquiries, consult Yuno's documentation or contact the support team.
# Payments
Source: https://docs.y.uno/docs/using-yuno/dashboard-overview/payments
Review payments, transactions, fraud screenings, and payouts, plus batch refunds and scheduled exports
The Payments dashboard section shows all payments, transactions, fraud screening, and payout data. In addition, you can use filters to refine your searches and enjoy extensive configuration of exports and reports.
## Payments section breakdown
Default view showing all payments regardless of their status.
Process multiple refunds by uploading a CSV file.
Detailed view of all transactions related to your payments.
Verify potential fraudulent transactions in a dedicated view.
Access and filter all payouts to find specific transactions.
Export customized data and schedule recurring email reports.
The Payments section lets you view, filter, and export payment data, and process batch refunds, all from a single dashboard view.
## Batch refunds
The batch refund feature allows you to process refunds for several transactions simultaneously, saving time and effort. You can refund up to 1000 payments at once.
To execute batch refunds, access the **All payments** tab and select **Batch refunds → Upload**. From here, upload a CSV file with your refunds. You can download a sample file to help with the formatting. For each payment to refund, you should inform:
* Payment ID
* Transaction ID
* Amount to refund
* Currency
* Merchant reference
* Reason (`DUPLICATE`, `FRAUDULENT`, or `REQUESTED_BY_CUSTOMER`)
You can also download the [batch refunds sample file](https://dashboard-assets.y.uno/samples-files/Batch_refunds_sample_file.xlsx).
After uploading the file, you can track the refund status of each payment by accessing **All payments** and selecting **Batch refunds → Overview**.
## Exporting Data
Click the **Export** button to see three tabs, each giving you specialized control over your data exports:
**Quick export**: Select a specific date range and customize the columns visible in the export.\
**Scheduled reports**: Configure a report to send periodically to your email address. You may also set the columns to export.
**Downloads**: Previous reports are saved in this tab for easy download.
# Reconciliations
Source: https://docs.y.uno/docs/using-yuno/dashboard-overview/reconciliations
Compare transactions against provider settlements to resolve discrepancies and confirm accurate payouts
Reconciliation is a process that compares your transactions with settlement documents from payment providers to:
* Identify and resolve discrepancies
* Ensure all processed transactions are properly settled
* Maintain accurate financial records
The reconciliation process works by:
Gather settlement files from each payment provider.
Compare those files with transactions processed through Yuno.
Check account balances with your acquirers.
Verify all records are accurate, consistent and up-to-date.
## Why reconciliation matters
Reconciliation helps you identify and resolve discrepancies in your payment processing. While some discrepancies are harmless, factors like payment timing, deposits, and pending transactions can affect your bank account balances. Regular reconciliation allows you to:
* Detect and prevent balance errors
* Identify potential fraud
* Track failed payments
* Ensure accurate financial records
The key objectives of reconciliation are to:
* Verify that merchants receive all payments from successful Yuno transactions
* Ensure compliance with payment terms between merchants and acquirers
* Monitor acquisition processing costs and validate them against agreed terms
* Maintain data integrity and accurate transaction states in the Yuno dashboard
For best results, perform reconciliation daily. If daily reconciliation isn't feasible, aim to reconcile weekly or at minimum monthly.
## How Yuno facilitates reconciliation
Yuno provides a comprehensive transaction reconciliation process that helps you:
* Ensure proper payment accreditation
* Verify compliance with payment terms
* Track processing costs
Our system orchestrates and manages data from Yuno, partners, and merchants to execute accurate reconciliation.
### Reconciliation status
Each transaction can have one of the following reconciliation statuses:
| Status | Description |
| :--------------- | :------------------------------------------------------------------------------------------------------------------------ |
| Reconciled | The transaction was found in the provider's settlement and will be credited to your bank account |
| Non reconcilable | The transaction cannot be reconciled as it doesn't meet reconciliation criteria. No further action will be taken |
| Not reconciled | The transaction is pending identification in a settlement. Check the sub-status to see if it's still within payment terms |
| Conflict | A matching transaction was found in the settlement but has discrepancies with the processed record |
### State machine
### Reports
Yuno provides two reconciliation reports:
1. **Transaction reconciliation report**
* Shows reconciliation status and sub-status
* Includes reconciliation ID for each transaction
2. **Settlement report**
* Lists all transactions in bank transfers to your account
* Includes reconciliation details for each transaction
# Risk Conditions
Source: https://docs.y.uno/docs/using-yuno/dashboard-overview/risk-conditions
Create fraud prevention rules, blocklists, and allowlists to control which transactions get screened
Yuno's **Risk conditions** empower merchants with advanced fraud prevention tools. This feature allows you to create and manage user lists and custom rules tailored to your business model, offering the flexibility to adapt protection strategies to your specific needs. Using the Risk conditions section reduces unnecessary requests to fraud prevention providers, optimizing resources and enhancing operational efficiency.
**Go to the routing section to include your lists and rules in your routes**
Activate the Risk Conditions provider in the Connections section. Once the connection is established, add it to your routes, where you can then select one or more lists and/or rules you want to use for each condition set.
Currently, the Risk conditions section provides three main tabs:
* [Rules](#rules)
* [Blocklists](#blocklists)
* [Allowlists](#allowlists)
## Rules
Yuno offers customizable velocity rules to help detect and respond to suspicious behaviour patterns, such as sudden surges in transaction volume over a short period. This proactive approach helps mitigate risks associated with stolen cards or compromised accounts exploited by cybercriminals.
With Yuno, you can create protection rules tailored to your specific business needs. These rules monitor transaction frequency and volume per individual account, allowing you to detect unusual activity in real time. You can select from multiple rule types and combine them to target specific fraudulent behaviours with precision.
**Rule Example**
Block payments if the number of payments per user exceeds 5, with an amount greater than 50 USD per payment, within a 10-minute timeframe.
In addition to blocking fraudulent payments, Yuno's rules also help identify secure transactions.
You can automatically bypass Fraud Screening or 3DS for verified payments to streamline the user experience. However, it's important to configure these rules carefully, as incorrect settings may lead to security gaps or unintended transaction blocks.
**Remove Rules and Lists**
You can't delete allowlists, blocklists, or rules. Yuno uses this approach to ensure you'll have access to the history of affected payments. If you want to stop using a rule or a list, you only need to remove it from your routes.
Within the **Rules** tab, select **Create rule** to configure your own rules. Set the following parameters based on your needs:
* **Name**: Give your rule a memorable name and description.
* **Rule type**: Track the number of payments or cards used by a user within a specific timeframe. Add conditions to track shipping changes, IP addresses, card brands, metadata, and more.
* **Settings**: Define the parameter used to count users, the types of payments to include (succeded, declined, etc.), and whether to count payments across the organization or the only current account.
* **Outcome**: Choose to allow, block, review, or test payments when a rule is triggered.
* **Apply this list to other accounts**: Choose whether to apply the rule to other accounts.
## Blocklists
Blocklists help prevent fraudulent activity by automatically declining payments from users that match specific parameters. You can manually add users to the list or upload a CSV file to block multiple users at once. It's also possible to configure an automatic removal period for each entry.
A payment will be blocked if it matches any of the following:
* Email
* Phone number
* Card BIN
* IP address
* Merchant customer ID
* Card BIN + last 4 digits
* Document number
* Customer ID
* Card/bank account holder name
* Device ID
* Shipping address
* Metadata
From the **Blocklists** tab, click **Create blocklist** to configure these parameters:
1. **List name**: Enter a clear, descriptive name for the blocklist.
2. **List type**: Select the parameter you want to block by (email, phone number, card BIN, device ID, etc.).
3. **Add emails**: You can either:
* Enter individual values directly into the field (separated by commas or tabs), or
* Upload a CSV file containing a batch of entries.
* Optionally, enable the setting to **automatically remove entries** after a specified period of time.
4. **Apply this list to other accounts**: Select which accounts the blocklist should apply to. By default, it only applies to the current account, but you can include other accounts by checking them from the list.
## Allowlists
Allowlists let you automatically approve transactions from trusted users based on matching parameters. This reduces friction and improves the experience for known, verified customers. You can add users manually or in bulk via CSV, and also configure automatic expiration for each entry.
Users can be allowlisted based on:
* Email
* Phone number
* Card BIN
* IP address
* Merchant customer ID
* Card BIN + Last 4 digits
* Document number
* Customer ID
* Card/bank account holder name
* Device ID
* Shipping address
* Metadata
From the **Allowlists** tab, click **Create allowlist** to configure these parameters:
1. **List name**: Enter a descriptive name for the allowlist.
2. **List type**: Choose the parameter to match against, such as an email, card BIN, or device ID.
3. **List outcome**: Select what happens when a match is found:
* Skip fraud screening
* Skip 3DS
* Skip both fraud screening and 3DS
4. **Add emails**: Add addresses manually (separated by commas or tabs) or upload a CSV file.
5. **Auto-remove**: Optionally enable automatic removal after a defined period of time.
6. **Apply to accounts**: Choose which accounts the list should apply to. By default, it's limited to the current account, but you can apply it to others as needed.
You must configure the **Risk conditions** connection to enable rules and lists. Follow these steps:
Navigate to **Connections**, search for **Risk conditions**, and click **Connect**.
Follow the on-screen instructions to add the Risk condition connection.
Access **Routing**, select a route, and add **Risk conditions** to it. Select your desired rules and lists.
Publish your route to activate the changes.
**Remove Rules and Blocklists**
You can't delete blocklists or rules. Yuno uses this approach to ensure you'll have access to the history of affected payments. If you want to stop using a rule or blocklist, you only need to remove it from your routes.
# Routing
Source: https://docs.y.uno/docs/using-yuno/dashboard-overview/routing
Configure dynamic and Smart Routing rules to direct payments across providers and boost approval rates
## What is dynamic routing?
Dynamic routing is a payment orchestration technique that enhances users' payment experience while automating the process of increasing approval rates. It involves directing payment transactions to the most suitable payment service provider or acquiring bank based on various factors such as card type, transaction amount, currency, and payment origin. You can also use the [Smart Routing](#smart-routing) feature, which uses artificial intelligence to identify the optimal conversion rate and allocate transactions to the most suitable provider.
**Routing Configuration**
If you're using our Embedded or Semi-lite checkout integrations, you can configure the routing of your enabled payment methods after setting the conditions for when each method should be displayed. However, if you're using the Lite version, all available payment methods will be immediately accessible, allowing you to start configuring how each payment is processed.
**Editing Published Routes**
You can configure and edit any aspect of a published route, including monitors and other settings. Published routes remain fully editable.
## Why use dynamic routing?
Yuno's user-friendly [dashboard](https://dashboard.y.uno/auth/login) offers a graphical interface to configure business rules for payments. Yuno's dynamic routing feature allows you to create personalized payment flows by defining validation and processing services according to your specific requirements. As a result, you can prioritize services that align with your needs, such as those with lower fees or higher approval rates.
By leveraging dynamic routing, you will enjoy several advantages:
Optimize your payment processing strategy in response to market changes or regulatory demands by quickly adjusting routing rules.
Significantly reduce payment processing fees by routing transactions through the most cost-effective PSP or service.
Direct high-risk transactions to specialized fraud prevention providers, minimizing your exposure to fraudulent activities.
Ensure efficient transaction processing by directing volume to the most suitable PSP based on capacity and response times.
## Configuring the dynamic routing
1. First, access your [Yuno dashboard](https://dashboard.y.uno/auth/login) and go to **Routing**. The Routing section separates the payment methods by **published** and **Not published**. In the **Not published** tab, you will find the payment methods connected to your account that don’t have a published route.
2. Choose a payment method and click **Set up**. A panel will then appear, click **Create new route** to start configuring routes.
3. Name the route you will build and hit **Save**.
4. Use the **Add new condition** button to define the condition that will trigger the payment processing route.
5. Select and define one or more condition types to narrow the route usage. The conditions available vary depending on the selected payment method. Check a condition to see intuitive options for configuring each.
6. Add connections to the condition created. Click the arrow next to your condition and then **Add step**. You will see a list of available connections including fraud solutions, processors, and acquirers, select one and click **Select**. If you select more than one connection, you will have to click **Next** and either determine the percentage of payments going through each, or select Smart Routing to handle the allocation automatically based on your preference.
7. For each new connection, you can define paths for each possible case (**Succeeded**, **Pending**, **Declined**, and **Error**). New steps can be connected to each scenario to build a complete routing that meets your demands.
8. After adding all steps of the payment process route, you can publish it using the **Publish** button, making it available for the respective payment method.
## Smart routing
Smart Routing is a solution designed to intelligently optimize payment performance according to the variable you choose to optimize as a merchant. To activate Smart Routing, select two or more connections when setting conditions, click **Next**, and turn on the Smart Routing toggle.
Smart Routing can optimize your payments in two ways:
* **Conversion rate and latency**: Make intelligent decisions to optimize processing time while also achieving the highest conversion rate.
* **Conversion rate and costs**: Make smart decisions to optimize costs while also achieving the highest conversion rate. Input the costs associated with each provider through the [Connections](/docs/connections) section. Smart Routing uses the costs you set up on the connection page to optimize your costs.
You only need to specify which providers you want to work with and which variable you want to optimize, and Smart Routing will route each payment through the optimal path.
Smart routing can be applied automatically, optimizing payment distribution for you. Alternatively, manual control lets you define the exact percentage of transactions to route through each connection.
## Post-authorization after Smart Routing
You can add a post-authorization provider after a Smart Routing step. This lets you run additional actions, such as risk reviews or settlements/captures, after approval. Add a new step and choose your desired provider (for example, Cybersource).
## Antifraud & Authentication
You can configure antifraud and authentication flows as part of your routing configuration. These flows help enhance security and compliance for your payment processing.
### How to configure antifraud and authentication flows
When building or editing a route in the Routing section:
1. After adding a connection or step to your route, click the step to configure it.
2. In the step configuration panel, you'll find options for **Antifraud & Authentication** flows.
3. Select the flow type you want to configure:
* **3DS**: Enable 3D Secure authentication to add an extra layer of security for card payments. This requires cardholders to complete additional authentication during the payment process.
* **Preauth**: Set up pre-authorization flows to validate payment methods before completing the transaction. This allows you to verify that funds are available and the payment method is valid before finalizing the transaction.
* **Postauth**: Configure post-authorization flows to perform additional checks after a payment has been authorized. If a post-authorization check is declined, you can set up a cancel transaction action to automatically reverse the authorization.
4. Configure any additional settings specific to the selected flow type.
5. Save your changes to apply the configuration to your route.
### Available flows
* **3DS**: Configure 3D Secure authentication to add an extra layer of security for card payments. This flow requires cardholders to complete additional authentication steps during the payment process, helping reduce fraud and comply with Strong Customer Authentication (SCA) requirements.
* **Preauth**: Set up pre-authorization flows to validate payment methods before completing the transaction. This allows you to verify that funds are available and the payment method is valid before finalizing the transaction, reducing the risk of declined payments later in the process.
* **Postauth**: Configure post-authorization flows to perform additional security checks after a payment has been authorized. If a post-authorization check is declined, you can set up a cancel transaction action to automatically reverse the authorization, protecting your business from fraudulent transactions that pass initial authorization.
### Automatic capture
You can configure automatic capture with a defined delay. This allows you to automatically capture authorized payments after a specified time period, streamlining your payment processing workflow.
**Automatic Capture Configuration**
Automatic capture with delay is configured via the [Create Payment API](/reference/create-payment) using `delayed_capture_settings` when creating a payment. This feature is not currently available in the Routing dashboard interface. For detailed information on configuring delayed capture, including delay format and settings, see the [Cancel and Capture Flow](/docs/payment-features/Cancel-and-capture-flow) documentation.
When using automatic capture:
* Set `capture: false` in your payment request
* Configure `delayed_capture_settings` with a `delay` field following ISO 8601 format (e.g., "P7D" for 7 days, "PT3H" for 3 hours)
* Optionally set `simplified_mode: true` to enable automatic retry if capture fails
The automatic capture will process authorized payments after the specified delay period, reducing manual intervention and ensuring timely settlement of transactions.
## Risk Profiles in routing conditions
A routing condition can be gated by a risk profile: a non-payment connection (Fraud, 3DS, or Authentication) placed at the start of the condition, ahead of its payment providers. This enables block lists, allow lists, and velocity rules on a route.
This feature allows you to add and remove risk profiles in place, leaving the existing payment chain untouched. Previously, you had to delete the routing condition and rebuild it from scratch.
**Availability**
This feature is available for Payins only (it is hidden for Payouts), and can be accessed from three entry points:
* The per-condition menu (⋮) in tree view.
* The per-row menu (⋮) in list view.
* The bulk action bar in list view, to apply the change to several conditions at once.
### Adding a risk profile
When adding a risk profile:
1. Select a Fraud, 3DS, or Authentication connection.
2. The connection is inserted at the start of the condition: its **Succeeded** output inherits whatever the condition previously started with.
3. The existing payment routing, including percentage splits, is preserved unchanged, and the risk profile becomes the new entry point.
**Stacking Risk Profiles**
Risk profiles stack: adding a second risk profile places it in front of the existing one (e.g., 3DS → Risk Screening → Payments).
When the chosen connection is Yuno Risk Screening, an optional second step lets you configure its block list, allow list, or velocity rules in the same flow, applied to every selected condition. Skipping that step inserts the connection with no further configuration.
### Removing a risk profile
Removing a risk profile takes it off the start of the condition and promotes its Succeeded branch back to the start: the payment routing it was gating becomes the entry point again, with traffic splits preserved.
Only the **Succeeded** branch survives. Any route left unreachable as a result, such as the removed profile's **Error**, **Declined**, or **Pending** fallback branches and anything downstream of them, is removed recursively.
A route still reachable through the **Succeeded** branch (for example, a provider targeted by both Succeeded and Declined) is kept. The result is always a clean routing graph with no orphaned nodes.
In bulk actions, removal targets the chosen connection across all selected conditions. Conditions that do not use the selected connection are left untouched.
## List view
When working with complex or lengthy routes, you can use the List view instead of the visual flow diagram. The List view provides a structured, table-based representation of your route configuration, making it easier to review and manage routes that have many condition sets or complex configurations.
To access List view, navigate to a route in the Routing section and click the **List view** button in the top navigation bar. The List view displays your route configuration in a table format with columns for Condition set ID, Condition set name, Conditions, and Primary providers.
You can filter condition sets by ID, search for specific configurations, and click the eye icon on any row to view detailed information. This view is particularly useful when your route has many condition sets or when the visual diagram becomes difficult to navigate.
# Home
Source: https://docs.y.uno/docs/using-yuno/dashboard-overview/your-payment-operative-system
Overview of the Yuno Dashboard's layout and core capabilities for managing payment operations
The Yuno dashboard provides a centralized interface for managing and configuring your Yuno accounts, with key functionalities organized for quick access. Some of the dashboard's functionalities include:
* Connect to an ever-growing list of providers
* Design custom checkout experiences
* Visualize comprehensive payment data
* Configure Smart Routing
* And much more
Yuno's unified checkout and payments integration streamlines your payment stack and integrates APIs and tools from across the web, creating dynamic end-to-end payment flows. Our documentation will guide you through the dashboard's architecture, key components, and functionalities, empowering you to effectively leverage Yuno's payment orchestration capabilities.
# Environments
Source: https://docs.y.uno/docs/using-yuno/environments
Understand Test Mode and Live Mode in the Dashboard and how to switch between them
This guide explains how **Test Mode** and **Live Mode** work in the Yuno dashboard and how to switch between them. For API base URLs and credentials per environment, see the [API Environments](/reference/api-environments) reference.
Yuno uses a single account for both environments. You can switch between Test Mode and Live Mode with one toggle, using the same username and password. This Test Mode/Live Mode toggle is separate from the US/EMEA regional dashboards described below — it does not change which region your account operates in.
## Regional dashboards (US and EMEA)
Yuno operates two regional dashboards: `https://dashboard.y.uno` (US) and `https://dashboard.eu.y.uno` (EMEA). How organizations and users relate across the two:
* **Organizations replicate across regions:** every organization/merchant that exists in US also exists in EMEA, and vice versa.
* **Users replicate, but accounts don't:** every user that exists in US also exists in EMEA. However, **accounts are not synchronized** between the two regions — only users are.
* **New users need explicit EMEA access:** a user invited to US from now on automatically gets a corresponding user in EMEA, but with no account access or permissions there. An EMEA admin must explicitly grant that user access before they can use the EMEA dashboard.
* **Same behavior via the public API:** this replication is not limited to the dashboard UI — if a user is created through the public API, it is created in both US and EMEA regardless of which base URL (US or EMEA) was called.
Beyond account/user replication, other dashboard behavior may differ between the US and EMEA regions; check with your Yuno contact for specifics not covered here.
## Understanding the environments
Yuno has two distinct environments, each serving a specific purpose:
* **Test Mode (Sandbox):** When you register, your organization starts with an "Inactive" status and has access only to Test Mode. Use it to explore the dashboard, learn how features work, and run tests without affecting live operations. Test Mode is ideal for trying new configurations and integrations safely.
* **Live Mode (Production):** Live Mode is where real customer transactions occur. To access it, you must submit an activation request. Once your account is active, you can run production traffic while keeping the same security and controls. Use Live Mode when you are ready to go live with your integration.
## Transitioning to Live Mode
1. **Requesting activation:** From the dashboard home page, submit a request for activation. Your organization's status will change from "Inactive" to "Under Verification". Test Mode remains available during verification.
2. **Verification process:** Yuno typically completes verification within a few hours. If we need more information, we will contact you.
3. **Access granted:** When verification is complete, Live Mode is enabled for your account.
## Switching environments
Switching between Sandbox and Production in the dashboard is simple:
* **One-click switching:** Use the dashboard **Test mode** toggle to switch between environments.
* **Single login:** One set of credentials gives you access to both environments; no separate passwords or accounts.
## Related docs
* [API Environments](/reference/api-environments): Base URLs, timeouts, and API behaviour per environment.
* [Developers credentials](/docs/using-yuno/settings/developers-credentials): Where to find API keys for Test and Live.
# Account Management
Source: https://docs.y.uno/docs/using-yuno/settings/account-management
Create, edit, and review organizational accounts to manage access and segment your business
The dashboard's [Account management](https://dashboard.y.uno/accounts) section lets you create, edit, and review organizational accounts with ease. You can access it by clicking on your profile image and selecting **See all your accounts**. Creating multiple accounts is handy for managing access, upholding security, and streamlining business operations.
## Advantages of creating multiple accounts
* **Granular access management**: Multiple accounts allow fine-tuning of access permissions. Each account can represent countries, franchises, business units, or any segmentation you require. This enhances the security and management of your dashboard.
* **Diverse user roles**: Users can access and engage with multiple accounts, each with its own role and permissions. Refer to [Teams and Roles](/docs/using-yuno/settings/teams-and-roles) for an overview of role allocation and management.
## Streamlining your experience
* **Filtering across accounts**: The **Add filters** menu found inside many of the dashboard's sections allows you to filter and combine information from one or more accounts, so you can visualize data based on your organization's needs without managing multiple credentials.
* **Set preferred account**: The Account management section allows you to select a preferred account, which sets it as the default filter selection when using the dashboard. This ensures you see the most relevant information regardless of how many accounts exist on your system.
## Unique account IDs
Each account within the dashboard will have unique Account IDs for both Live mode and Test mode. The Account IDs can be found by clicking on the account name inside the Account management section, or through the Developers section.
# Audit logs
Source: https://docs.y.uno/docs/using-yuno/settings/audit-logs
Track team member and API activity across the Dashboard for security and compliance
The **Audit logs** section provides transparency, security, and regulatory compliance by logging and tracking all team members' activities within the dashboard. Using the audit logs, you can stay informed about the actions happening inside your organization.
Yuno audit logs streamline management tasks through several features:
* **Comprehensive activity logging**: Track every action carried out within the dashboard, when it occurred, and the changes made. This level of detail ensures transparency and accountability in all operations.
* **User tracking**: Audit logs ensure every action is traceable to a specific individual, enabling you to pinpoint the cause of any change and analyze user behavior for continuous improvement.
* **Detailed technical data**: Clicking the **Event** tag for each action (such as "Updated" or "Created") provides additional information for developers and technical users, including the IP address of the device used to make the change and the API endpoint's response body.
* **Advanced search capabilities**: Select **Add filters** to quickly narrow your search. Choose from a variety of filters, including accounts, dates, team members, and more to efficiently locate the data you need.
Audit logs are essential for Yuno's security and compliance, ensuring every action is recorded. This provides critical control, safeguards your operations, and facilitates root cause analysis after user changes.
## Navigating Audit Logs
The **Audit logs** section gives you full transparency into actions taken across your Yuno account. It's organized into two main tabs:
* **Dashboard**: Here, you'll find a record of actions performed by team members directly within the Yuno dashboard.
* **Monitors**: This tab allows you to track events created via API, offering insight into automated or programmatic activities.
On both tabs, you can easily adjust the timeframe to view events. Choose from predefined options like today, this month, or the last 30 days, or set a custom date range.
To efficiently pinpoint specific information, use the **Add filters** button. This offers several options to refine your search:
### Within the Dashboard tab
* **Accounts**: Sort events by the different accounts within your Yuno dashboard.
* **Date**: Select from various time filters or enter a custom date range.
* **Event**: Filter for specific actions like "created," "updated," or "deleted" events.
* **Source**: Filter by source (webhooks, payment links, connections, routing, refunds, and other sources) to narrow your search.
* **Team member**: View logs generated by actions from one or more specific team members.
### The Monitors tab offers a different set of filters
* **Actions**: Filter by events that redistribute traffic or not.
* **Created at**: Specify the timeframe for your search.
* **Payment methods**: Sort by the different payment methods you've configured, such as credit card.
* **Providers**: Filter out by specific payment providers.
* **Status**: View only solved or unresolved events.
# Developers (Credentials)
Source: https://docs.y.uno/docs/using-yuno/settings/developers-credentials
Manage organization and account keys, customized API keys, allowed IPs, and webhooks
The **Developers** section in the Yuno dashboard provides secure authentication credentials (also known as keys) for integrating Yuno's services. Yuno maintains separate keys for Test and Live environments, keeping credentials isolated between environments and reducing the risk of accidentally using live credentials in testing.
## Credential structure
Yuno implements a two-tier authentication hierarchy:
1. **Organization keys**
* Primary authentication layer providing a gateway to your overarching operations
* Grant access to all [accounts](/docs/using-yuno/settings/account-management) associated to your organization
* Assigned to your organization after registering with Yuno
2. **Account keys**
* Unique to each account within your organization
* Operate independently between Test and Live modes
* Provide granular access control
## Accessing credentials
You can access your authentication credentials in two ways:
* **Account management**: The Yuno dashboard's [**Account management**](https://dashboard.y.uno/accounts) section contains credentials for each account. Click each account name to gain instant access to its keys.
* **Developers section**: You can also access your authentication credentials from the **Developers** section. The **Authentication** tab, open by default, will showcase account, organization, and customized API keys. Your permissions will determine which keys are visible. This area is particularly valuable when integrating Yuno functionalities into your applications or systems.
## Customized API keys
Yuno lets you create customized API keys for increased security and control, ensuring only authorized members can access data and reports via the API.
Inside the Authentication tab of the Developers section, look for Customized API keys and click **Create key** next to it. From here, you can set various parameters:
* Key name and the member who can access it.
* One or more accounts associated with the new key.
* One or more products accessible by the key, such as subscriptions, payments, installment plans, and more.
The flexibility of customized API keys streamlines access and permission control, enabling easy and secure API integration management through the Yuno dashboard.
**Important: API Key Display**
When you create a customized API key, the key value is displayed only once during creation. Make sure to copy and securely store the key immediately, as you won't be able to view it again. If you lose the key or need to rotate it for security reasons, you can roll (regenerate) the key, which will invalidate the previous key and generate a new one.
## Safeguarding your credentials
Protecting your authentication credentials is paramount for maintaining secure operations. Follow these guidelines:
* Treat credentials as sensitive information
* Never share credentials with unauthorized parties
* Monitor credential usage
**Security Alert**
If you suspect credential exposure or unauthorized access, contact our support team immediately. Prompt action helps maintain the security of your operations.
## Allowed IPs
You can configure a list of allowed IP addresses to restrict API access to specific IP addresses or IP ranges. This adds an additional layer of security by ensuring that API requests can only originate from approved IP addresses.
**Important: IP Validation**
If no IP addresses are added, IPs will not be validated by default. Please be mindful when adding new IPs, as it is a sensitive change that may impact payment processing.
To configure allowed IPs:
1. Navigate to the **Developers** section in the Yuno dashboard.
2. Go to the **Authentication** tab.
3. Click the **List of allowed IPs** button (located in the top right area of the Authentication tab).
4. In the modal that opens, enter IP addresses or IP ranges in the **Enter IP address** field. You can:
* Enter individual IP addresses (e.g., `192.168.1.1`)
* Enter IP ranges using CIDR notation (e.g., `192.168.1.0/24`)
* Add multiple IPs by separating them with a comma, semicolon, space, or by pressing Enter
5. Review the list of allowed IPs in the table below.
6. Click **Save changes** to apply the configuration.
Once configured, API requests from IP addresses not in the allowed list will be rejected, enhancing the security of your API integrations.
**IP Address Management**
You can add multiple IP addresses or ranges, and update or remove them as needed. Changes to the allowed IP list take effect immediately.
## Webhooks
The **Webhooks** tab in the Developers section allows you to create and manage webhooks for receiving real-time notifications about events in your Yuno account.
### Creating a webhook
To create a new webhook:
1. Navigate to the **Developers** section in the Yuno dashboard.
2. Click on the **Webhooks** tab.
3. Click **Add webhook** to open the webhook creation form.
4. Fill in the required information in the **Details** section:
* **Name**: Provide a descriptive name for your webhook.
* **Endpoint URL**: Enter the URL where Yuno should send webhook notifications.
* **x-api-key** and **x-secret**: Set authentication credentials for webhook verification (optional but recommended).
* **Use OAuth2 Authentication**: Enable OAuth2 authentication for webhook verification (optional).
* **Use HMAC Authentication**: Enable HMAC authentication for webhook verification (optional).
5. Under **Trigger on** (required), select the events that should trigger the webhook. Available event categories include:
* **Enrollment**: Enroll, Unenroll
* **Payment**: Authorize, Cancel, Capture, Refund, Verify, Chargeback, Purchase
* **Report**: Create, Update
* **Subscription**: Create, Pause, Resume, Cancel, Complete
Yuno recommends selecting all relevant events to ensure comprehensive coverage.
6. Under **Apply this webhook to other accounts** (required), select which accounts should receive webhook notifications. You can:
* Select specific accounts from the list
* Use "Select all" to apply to all accounts
* Use "Inverse" to invert your selection
* Choose "Current account only" to limit the webhook to the current account
7. Click **Add** to create the webhook.
### Managing webhooks
Once created, you can:
* **View webhook details**: See the webhook configuration, endpoint URL, and triggered events.
* **Edit webhook**: Update the webhook name, endpoint URL, authentication credentials, or triggered events.
* **Test webhook**: Send a test notification to verify the webhook is working correctly.
* **Delete webhook**: Remove a webhook that is no longer needed.
**Webhook Security**
Always use HTTPS for your webhook endpoint URLs to ensure secure transmission of webhook data. Additionally, verify webhook signatures using the provided public key and private secret key to ensure the webhooks are authentic and haven't been tampered with.
# Security
Source: https://docs.y.uno/docs/using-yuno/settings/security
Manage password policies, two-factor authentication, SSO, and login methods for your organization
The **Security** section of the dashboard lets you manage password policies, two-factor authentication, single sign-on, and login methods for your organization. To access this section, select **Security** after clicking your profile image.
## Security overview
The different tabs include several unique functionalities:
* **Password management**: Your first line of defense is strong password management. Easily update your password and view password requirements.
* **Two-factor authentication (2FA)**: Configure 2FA for your account or enforce it across all organization members. This feature is highly recommended to ensure your account remains fortified against unauthorized access.
* **Single Sign-On (SSO)**: Use a trusted identity provider to enable SSO via SAML 2.0. This improves security and simplifies access by reducing password usage across your organization. Easily enable or disable SSO based on your organization's needs.
* **Login methods**: Select the preferred login methods across your organization based on your current configuration.
## Unlocking future enhancements
Yuno is committed to enhancing your security measures beyond password management and 2FA by offering advanced security solutions:
* **Session management**: Soon, you'll monitor and control active login sessions. Easily log out of any open sessions to ensure utmost security and oversight.
* **Password expiration policies**: Designated team members can set password expiration policies, ensuring ongoing privacy and security.
* **SAML group mappings**: Integrate Single Sign-On (SSO) with SAML group mappings to assign user permissions automatically based on identity provider group data.
* **Login method customization**: Define user access methods like passwords, social sign-ins (Google, Microsoft), and SSO (SAML). Align user entry with your organization's preferences.
## Security best practices
Ensuring the highest level of security for your Yuno account involves following a set of recommended best practices. These actions help strengthen your defenses against potential threats.
* **Regular audits**: Periodically review and update your password to reduce exposure to security risks.
* **Multi-factor authentication (MFA)**: Enable two-factor authentication (also known as multi-factor authentication) to add an extra layer of protection, preventing unauthorized access even if your password is compromised.
# Single Sign-On (SSO)
Source: https://docs.y.uno/docs/using-yuno/settings/single-sign-on-sso/index
Set up SAML 2.0 SSO through domain verification and a hosted configuration portal
**Single Sign-On (SSO)** lets your team log in to the Yuno dashboard using your company's existing identity provider (IdP), instead of creating separate credentials for Yuno.
Yuno supports SSO through the **SAML 2.0** standard and is compatible with a wide range of identity providers, including Google Workspace, Microsoft Entra ID (Azure AD), Okta, OneLogin, JumpCloud, ADFS, Ping Identity, Auth0, Keycloak, and any SAML 2.0–compliant provider. Configuration is handled through a dedicated hosted portal: you do not need to paste SAML metadata, entity IDs, or certificates inside the Yuno dashboard.
This page describes the current SSO setup flow, which uses a hosted portal for both domain verification and SSO configuration. If your organization set up SSO using the previous in-dashboard approach, reconfigure it using the steps below.
## Prerequisites
**Before you begin**
* **Admin role** in every account that belongs to your organization.
* **DNS access** to add a TXT record during domain verification.
* **IdP admin access** to complete the SAML configuration in your identity provider's console.
## Setting up SSO
The **Security → Single sign-on** tab contains two cards: **Domain Verification** and **Single Sign-On**. Complete them in order. SSO configuration is locked until your domain is verified.
Domain verification proves that your organization owns the email domain its users will sign in with (for example, `acme.com`).
1. In the Yuno dashboard, go to your profile menu → **Security** → **Single sign-on**.
2. In the **Domain Verification** card, click **Configure Domain**.
3. A new browser tab opens with Yuno's domain verification portal.
4. Enter the email domain you want to verify and click **Continue**.
5. Copy the TXT record the portal provides, then add it to your DNS provider exactly as shown, with no extra quotes or whitespace.
6. Return to the portal and click **Verify**.
7. Return to the Yuno dashboard. Once the record propagates and the portal validates it, the Domain Verification card displays a green **Domain verified · your-domain.com** pill.
DNS propagation can take a few minutes to a few hours. The verification status updates automatically when you reopen the page.
Once your domain is verified, the **Configure SSO** button on the Single Sign-On card becomes active. If your domain is not yet verified, the button is disabled and the card shows the message *"You must verify a domain before configuring SSO."*
1. Click **Configure SSO**. A new browser tab opens with the hosted SSO setup portal.
2. Choose your identity provider from the catalog (Google, Microsoft Entra ID, Okta, OneLogin, JumpCloud, Generic SAML, and others).
3. The portal walks you through the connection setup with provider-specific instructions. The typical fields are:
| Field | Direction |
| -------------------------------------------- | ------------------------------------------- |
| **ACS URL** (Assertion Consumer Service URL) | Provided by the portal, paste into your IdP |
| **SP Entity ID** | Provided by the portal, paste into your IdP |
| **IdP Sign-In URL** | Provided by your IdP, paste into the portal |
| **IdP X.509 Certificate** | Provided by your IdP, paste into the portal |
4. Save the connection in the portal. The portal validates the connection end-to-end before it goes live.
5. Return to the Yuno dashboard. The **Single Sign-On** card displays one of the following statuses:
| Status | Meaning |
| -------------------------------------------------------------- | --------------------------------------------------------------------------------------------- |
| **SSO is ready to use** · `Google SAML` / `Okta SAML` / `SAML` | Connection is active and users can sign in with SSO. The pill includes the connection type. |
| **SSO connection active** | Connection exists and is functional but not yet marked ready for general use |
| **SSO connection not configured** | No connection exists or the connection is inactive. Click **Configure SSO** to complete setup |
You do not need to upload XML metadata, paste an entity ID, or upload a certificate inside the Yuno dashboard. All SAML configuration lives in the hosted portal.
## Signing in with SSO
Once the connection is active, users can sign in with SSO from the Yuno login page:
1. Open `dashboard.y.uno`. You are briefly redirected through `id.y.uno`, Yuno's authentication domain.
2. Enter your corporate email address and click **Continue with SSO**.
3. You are redirected to your identity provider to authenticate.
4. After your IdP authenticates you, you land back in the Yuno dashboard.
## Managing SSO
* **Disable or re-enable SSO**: Go to **Security** → **Login methods** and toggle SSO on or off.
* **Edit an existing connection**: Go to **Security** → **Single sign-on** and click **Configure SSO** to reopen the hosted portal and update the configuration.
## Troubleshooting
**Users bounce back to the login screen**
Yuno enforces that both the SAML response and assertion are signed using SHA-256. If sign-in fails, confirm in your IdP that both the response and the assertion are signed with SHA-256, and that the certificate registered in the hosted portal matches the one your IdP is currently using.
**Certificate rotation**
When you rotate certificates in your IdP, reopen the hosted SSO portal and update the certificate there. Until the portal reflects the new certificate, SSO sign-ins will fail.
**SSO sign-in logs**
Dashboard users cannot view audit logs for SSO attempts directly. To investigate an authentication issue, contact Yuno Support with the user's email address and the approximate timestamp so the support team can retrieve the relevant logs.
# Microsoft Entra ID SSO Guide
Source: https://docs.y.uno/docs/using-yuno/settings/single-sign-on-sso/microsoft-entra-id-sso-guide
Connect the Dashboard to Microsoft Entra ID for SSO using SAML 2.0 configuration
This guide explains how to connect Yuno to Microsoft Entra ID (formerly Azure Active Directory) using SAML 2.0.
## Prerequisites
* A Microsoft Entra ID tenant
* An application for use with Yuno
* Entra ID admin privileges to manage SSO settings
* Access to the [Yuno dashboard](https://dashboard.y.uno/)
First, go to the dashboard and click your profile image, then open **Security**. Navigate to the Single Sign-On (SSO) tab, click **Set up** and gather this info:
* Identifier (Entity ID)
* Assertion Consumer Service URL
In Microsoft Entra ID, go to:
**Enterprise applications → All applications → Your application → Single sign-on**
Under **Basic SAML configuration**, enter the values from the Yuno dashboard.
In Microsoft Entra ID, navigate to the **SAML certificates** section and download the **Federation Metadata XML** file.
Then, in the Yuno dashboard:
1. Upload the XML file under **Yuno configuration → Option A: Upload metadata XML**
2. Wait for the **Upload completed** confirmation
3. Click **Save**
Alternatively, you can take the information listed in **Option B** and enter it manually.
In Microsoft Entra ID, open **SAML certificates** and make sure:
* The signing option is **Sign SAML response and assertion**
* The signing algorithm is **SHA-256**
Click **Save** to apply the changes.
## Troubleshooting
If you cannot set up the SSO connection or run into issues after initial configuration:
* Remember Yuno requires **signed SAML responses**, check:
* Both the SAML response and the assertion are signed
* The signing algorithm is **SHA-256**
* The signing certificate matches the one uploaded to Yuno
* Review SSO logs in the Yuno dashboard under **Security → Single sign-on (SSO)**
# Okta SSO Guide
Source: https://docs.y.uno/docs/using-yuno/settings/single-sign-on-sso/okta-sso-guide
Connect the Dashboard to Okta for SSO using SAML 2.0 application configuration
This guide explains how to connect Yuno to Okta using SAML 2.0.
## Prerequisites
* An Okta account
* Admin privileges in Okta to manage SSO settings and create applications (you'll create the SAML application for Yuno in Step 1 below; no application needs to exist beforehand)
* Access to the [Yuno dashboard](https://dashboard.y.uno/)
In Okta, go to:
**Applications → Create App Integration → SAML 2.0 → Next**
Select a name for your application and, optionally, upload a logo. You will then see the SAML configuration form.
Open the Yuno dashboard, click your profile image, then open **Security**. Navigate to the **Single Sign-On (SSO)** tab, click **Set up**, and gather this info:
* Identifier (Entity ID)
* Assertion Consumer Service URL
Copy these values into the Okta SAML form:
* **Audience URI (SP Entity ID)** → Identifier (Entity ID)
* **Single sign-on URL** → Assertion Consumer Service URL
Click **Next**, then check the option **This is an internal app…**, and finish the setup.
In Okta, locate the **Metadata URL** under the application’s settings and open it. Save the file as `metadata.xml`.
Then, in the Yuno dashboard:
1. Upload the `metadata.xml` file under **Yuno configuration → Option A: Upload metadata XML**
2. Wait for the **Upload completed** confirmation
3. Click **Save**
Alternatively, you can take the information listed in **Option B** and enter it manually.
Once configuration is complete, you can assign Okta users or groups to the application so they can log in using SSO.
## Troubleshooting
If you cannot set up the SSO connection or run into issues after initial configuration:
* Yuno requires **signed SAML responses**, check:
* Both the SAML response and the assertion are signed
* The signing algorithm configured in Okta is **SHA-256**
* The certificate used for signing matches the one included in the metadata
* Review SSO logs in the Yuno dashboard under **Security → Single sign-on (SSO)**
# Teams and Roles
Source: https://docs.y.uno/docs/using-yuno/settings/teams-and-roles
Create teams, assign default or custom roles, and manage member permissions across accounts
The **Team and roles** section allows you to create teams, define roles, and assign permissions with precision. This setup supports structured collaboration and enforces access controls to maintain a secure and organized environment. To access this section within the Yuno dashboard, click your profile image and select **Team and roles**.
## Harnessing the power of teams
* **Building dynamic teams**: Yuno allows you to create flexible teams composed of users from different accounts. A single user can be part of multiple teams, each with unique roles tailored to their responsibilities.
* **Cross-account participation**: Yuno supports cross-account collaboration, enabling users to contribute to teams across different accounts. This promotes a unified, efficient workflow across your organization.
* **Customizable roles**: Roles define each member's level of access and responsibilities. Yuno offers a set of predefined roles with specific permissions, ensuring that every user has the appropriate tools and access to perform their tasks.
## Working with teams
The **Team members** tab allows you to invite new members and manage existing ones. The actions available to you will depend on your assigned permissions.
* **Invite members**: Send one or more invitations via email and assign roles to new members.
* **Member management**: Click the three-dot icon next to a member's name to edit their role or delete them from the team.
Use **Add filters** to sort between your [accounts](/docs/account-management).
**Team for each account**
Please, take into consideration that you will have to create a team for each account you have created.
## The dynamics of roles
Defining clear roles and permissions strengthens the security of your operations. Each team member works within a specific scope, reducing the risk of accidental errors or unauthorized access. Roles give individuals the access they need to do their jobs efficiently, while keeping workflows organized and secure.
There are two types of roles in Yuno:
* **Default roles**: Yuno offers a set of predefined roles, each encapsulating a distinct array of permissions. These default roles serve as a foundation for streamlined team functioning.
* **Custom role creation**: Yuno's flexibility extends to crafting custom roles. Tailor permissions to suit your precise requirements, allowing your teams to function optimally while adhering to the principle of least privilege.
There are 6 types of default roles:
| Roles | Description |
| :-------- | :--------------------------------------------------------------------------------- |
| Admin | An Admin user has access to all features in the dashboard. |
| Agent | An Agent user can view and take actions on payments. |
| Developer | A Developer user can view and take actions on integrations and webhooks. |
| Read only | A Read-only user can view all features in the dashboard. |
| Custodian | Assign this role when you invite Yuno team experts to join your team. |
| IAM Admin | Users with this role manage access and security settings like SSO, MFA, and roles. |
The **Roles management** tab shows the permissions assigned to each role. Select **Create role** to define custom roles tailored to your team's specific needs.
## Creating custom roles
To create a custom role, navigate to the **Roles management** tab and select **Create role**. You can then define the role name, description, and assign specific permissions for each environment according to your team's needs, giving you precise access controls that promote better security and operational control.
### Environment-specific configuration
For each permission, you can independently configure access for:
* **Sandbox environment**: Perfect for testing and development activities
* **Production environment**: For live operations and sensitive data
This granular control allows you to create roles where users might have full access in sandbox for testing purposes, but restricted access in production for security reasons.
### Available permissions
The custom role creation interface includes these permissions:
* **Insights** - Access to actionable payment insights
* **Payments** - View and operate payments, manage payment links
* **Payouts** - View payouts and transaction details
* **Reconciliation** - View settlement reports
* **Connections** - View and manage payment connections
* **Routing** - View and manage processing routes
* **Checkout builder** - View and build checkout configurations
* **Developers** - View and manage account keys
* **Webhooks** - View and manage webhooks
* **Accounts** - Manage account settings
* **Team and roles** - View and manage team members and roles
* **Risk conditions** - View and manage rules and lists
* **Audit logs** - View dashboard, API, and monitor logs
* **Security** - Manage 2FA and SSO configurations
# Direct Integration
Source: https://docs.y.uno/docs/wallets/apple-pay/apple-pay-direct-integration
Integrate Apple Pay directly with Yuno's API for one-time and recurring CIT/MIT payments.
This guide describes how to integrate Apple Pay directly with Yuno's API. Direct integration offers full control over the payment flow and is ideal for merchants who need custom implementations or have existing payment systems.
Yuno's Apple Pay Direct integration supports one-time and recurring payments (useful for subscriptions and other regular transactions).
Before implementing Apple Pay payments, ensure you have completed the [Apple Pay prerequisites](/docs/prerequisites-apple-pay).
## Apple Pay overview
1. Customer initiates payment on their iOS device
2. Receive `payment_token` via Apple SDK
3. [Create a payment](/reference/create-payment) with Yuno including the stringified token
4. Yuno processes with your configured provider or providers and returns a response
5. Monitor response status via [webhooks](/docs/webhooks)
## One-time payments
To integrate a single transaction, such as an online purchase, use Yuno's API to [create a payment](/reference/create-payment). This requires you to obtain certain information from the Apple SDK's response, which is generated when the customer authorizes the payment.
### Example Apple Pay response
The Apple Pay SDK returns an object like the example below, we call this response the `payment_token`.
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"paymentMethod": {
"type": "credit",
"displayName": "Visa 3748",
"network": "Visa"
},
"paymentData": {
"data": "B5NSQI0TdXuLwqadBCL0yOwtik/rJx7v41xxE8rNSlFBTHR2W88iRck7a6bH9Kx/bBFsk2ZyinIEl2aXusHp22a0pSmuCUoPgbkFc1/D3PRAoWITfZkalBeuzMhHJGhhCe2wqOgMmjS2w97nN9vifb1cMrS3kOqpPPMihHVvhLYbwtNhh8lfeTOyL+RBXbdFScVTFCB1eFQ4znUFV79SHVK/SRjLxLawO1HGIO0VIUTj8uVgG4MmBrfQhDBD/P9a4lWypiNoyURHm7ubgcOEelbVDGlKSNDmYFD10i554b+7z8GXBtWdQc1zhWKcGOn8RsOYtxxdqzHEtJzcFsf92/rEhfpEThXjsLLMTmovGyQS30qM/qO2YgqduEID7IS+xOH/FXpplT5Yqur7/+FgEwcv2lGsa0K6kNMEUn1xSWc=",
"signature": "MIAGCSqGSIb3DQEHAqCAMIACAQExDTALBglghkgBZQMEAgEwgAYJKoZIhvcNAQcBAACggDCCA+MwggOIoAMCAQICCBZjTIsOMFcXMAoGCCqGSM49BAMCMHoxLjAsBgNVBAMMJUFwcGxlIEFwcGxpY2F0aW9uIEludGVncmF0aW9uIENBIC0gRzMxJjAkBgNVBAsMHUFwcGxlIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRMwEQYDVQQKDApBcHBsZSBJbmMuMQswCQYDVQQGEwJVUzAeFw0yNDA0MjkxNzQ3MjdaFw0yOTA0MjgxNzQ3MjZaMF8xJTAjBgNVBAMMHGVjYy1zbXAtYnJva2VyLXNpZ25fVUM0LVBST0QxFDASBgNVBAsMC2lPUyBTeXN0ZW1zMRMwEQYDVQQKDApBcHBsZSBJbmMuMQswCQYDVQQGEwJVUzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABMIVd+3r1seyIY9o3XCQoSGNx7C9bywoPYRgldlK9KVBG4NCDtgR80B+gzMfHFTD9+syINa61dTv9JKJiT58DxOjggIRMIICDTAMBgNVHRMBAf8EAjAAMB8GA1UdIwQYMBaAFCPyScRPk+TvJ+bE9ihsP6K7/S5LMEUGCCsGAQUFBwEBBDkwNzA1BggrBgEFBQcwAYYpaHR0cDovL29jc3AuYXBwbGUuY29tL29jc3AwNC1hcHBsZWFpY2EzMDIwggEdBgNVHSAEggEUMIIBEDCCAQwGCSqGSIb3Y2QFATCB/jCBwwYIKwYBBQUHAgIwgbYMgbNSZWxpYW5jZSBvbiB0aGlzIGNlcnRpZmljYXRlIGJ5IGFueSBwYXJ0eSBhc3N1bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJsZSBzdGFuZGFyZCB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRlIHBvbGljeSBhbmQgY2VydGlmaWNhdGlvbiBwcmFjdGljZSBzdGF0ZW1lbnRzLjA2BggrBgEFBQcCARYqaHR0cDovL3d3dy5hcHBsZS5jb20vY2VydGlmaWNhdGVhdXRob3JpdHkvMDQGA1UdHwQtMCswKaAnoCWGI2h0dHA6Ly9jcmwuYXBwbGUuY29tL2FwcGxlYWljYTMuY3JsMB0GA1UdDgQWBBSUV9tv1XSBhomJdi9+V4UH55tYJDAOBgNVHQ8BAf8EBAMCB4AwDwYJKoZIhvdjZAYdBAIFADAKBggqhkjOPQQDAgNJADBGAiEAxvAjyyYUuzA4iKFimD4ak/EFb1D6eM25ukyiQcwU4l4CIQC+PNDf0WJH9klEdTgOnUTCKKEIkKOh3HJLi0y4iJgYvDCCAu4wggJ1oAMCAQICCEltL786mNqXMAoGCCqGSM49BAMCMGcxGzAZBgNVBAMMEkFwcGxlIFJvb3QgQ0EgLSBHMzEmMCQGA1UECwwdQXBwbGUgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxEzARBgNVBAoMCkFwcGxlIEluYy4xCzAJBgNVBAYTAlVTMB4XDTE0MDUwNjIzNDYzMFoXDTI5MDUwNjIzNDYzMFowejEuMCwGA1UEAwwlQXBwbGUgQXBwbGljYXRpb24gSW50ZWdyYXRpb24gQ0EgLSBHMzEmMCQGA1UECwwdQXBwbGUgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxEzARBgNVBAoMCkFwcGxlIEluYy4xCzAJBgNVBAYTAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE8BcRhBnXZIXVGl4lgQd26ICi7957rk3gjfxLk+EzVtVmWzWuItCXdg0iTnu6CP12F86Iy3a7ZnC+yOgphP9URaOB9zCB9DBGBggrBgEFBQcBAQQ6MDgwNgYIKwYBBQUHMAGGKmh0dHA6Ly9vY3NwLmFwcGxlLmNvbS9vY3NwMDQtYXBwbGVyb290Y2FnMzAdBgNVHQ4EFgQUI/JJxE+T5O8n5sT2KGw/orv9LkswDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBS7sN6hWDOImqSKmd6+veuv2sskqzA3BgNVHR8EMDAuMCygKqAohiZodHRwOi8vY3JsLmFwcGxlLmNvbS9hcHBsZXJvb3RjYWczLmNybDAOBgNVHQ8BAf8EBAMCAQYwEAYKKoZIhvdjZAYCDgQCBQAwCgYIKoZIzj0EAwIDZwAwZAIwOs9yg1EWmbGG+zXDVspiv/QX7dkPdU2ijr7xnIFeQreJ+Jj3m1mfmNVBDY+d6cL+AjAyLdVEIbCjBXdsXfM4O5Bn/Rd8LCFtlk/GcmmCEm9U+Hp9G5nLmwmJIWEGmQ8Jkh0AADGCAYgwggGEAgEBMIGGMHoxLjAsBgNVBAMMJUFwcGxlIEFwcGxpY2F0aW9uIEludGVncmF0aW9uIENBIC0gRzMxJjAkBgNVBAsMHUFwcGxlIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRMwEQYDVQQKDApBcHBsZSBJbmMuMQswCQYDVQQGEwJVUwIIFmNMiw4wVxcwCwYJYIZIAWUDBAIBoIGTMBgGCSqGSIb3DQEJAzELBgkqhkiG9w0BBwEwHAYJKoZIhvcNAQkFMQ8XDTI1MTAwMjE5MjYyNFowKAYJKoZIhvcNAQk0MRswGTALBglghkgBZQMEAgGhCgYIKoZIzj0EAwIwLwYJKoZIhvcNAQkEMSIEIIglNywQdAxKnixbc4TJLaopplLPs5m84zjbAlsJuvnOMAoGCCqGSM49BAMCBEcwRQIhANjW5bxOlsS4oBDrxUn6OtIHWxpHshyj0ozI518Ty/rbAiAW+dbxN9OQJ9a2B3VMps89dm0ZB6MdQCG7iHM2g2Tn1gAAAAAAAA==",
"header": {
"publicKeyHash": "YK8kdoBXLGqBQKBtCZOl0DQTUHOWidRCxgOgf/1gBMM=",
"ephemeralPublicKey": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEEVv32VVJYlg+E0zMsthvBaldJcH45NUWhVckme/CQYFtHf60FEdFtzwabOEMY3u1De+6e+IuBv53OxmWx+1w2w==",
"transactionId": "87a03c4cc1b242a25d74257d4bc990a6473b9866392850e584a9f680dcdf3d0f"
},
"version": "EC_v1"
}
}
```
### Example one-time payment request
Here is an example of a one-time Apple Pay payment request using Yuno's Direct API. The request includes the **stringified** Apple Pay response inside `payment_token`, as received from the Apple Pay SDK, along with required fields such as amount, currency, and account information. Adjust the values as needed for your integration.
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
curl --location 'https://api-sandbox.y.uno/v1/payments' \
--header 'X-idempotency-key: 20cc2a07-9170-47d7-88ff-c4d3ee48274e' \
--header 'public-api-key: '\
--header 'private-secret-key: ' \
--header 'Keep-Alive: timeout=5, max=1000' \
--header 'Content-Type: application/json' \
--data-raw '{
"country": "US",
"amount": {
"currency": "USD",
"value": 2000
},
"customer_payer": {
"id": "24e25748-6ab3-4d43-bb8b-eb0204bb0954",
"email": "customer@example.com",
"first_name": "John",
"last_name": "Doe"
},
"workflow": "DIRECT",
"payment_method": {
"vault_on_success": true,
"type": "APPLE_PAY",
"detail": {
"wallet": {
"payment_token": "{\r\n \"paymentMethod\":{\r\n \"type\":\"credit\",\r\n \"displayName\":\"Visa 3748\",\r\n \"network\":\"Visa\"\r\n },\r\n \"paymentData\":{\r\n \"data\":\"B5NSQI0TdXuLwqadBCL0yOwtik\/rJx7v41xxE8rNSlFBTHR2W88iRck7a6bH9Kx\/bBFsk2ZyinIEl2aXusHp22a0pSmuCUoPgbkFc1\/D3PRAoWITfZkalBeuzMhHJGhhCe2wqOgMmjS2w97nN9vifb1cMrS3kOqpPPMihHVvhLYbwtNhh8lfeTOyL+RBXbdFScVTFCB1eFQ4znUFV79SHVK\/SRjLxLawO1HGIO0VIUTj8uVgG4MmBrfQhDBD\/P9a4lWypiNoyURHm7ubgcOEelbVDGlKSNDmYFD10i554b+7z8GXBtWdQc1zhWKcGOn8RsOYtxxdqzHEtJzcFsf92\/rEhfpEThXjsLLMTmovGyQS30qM\/qO2YgqduEID7IS+xOH\/FXpplT5Yqur7\/+FgEwcv2lGsa0K6kNMEUn1xSWc=\",\r\n \"signature\":\"MIAGCSqGSIb3DQEHAqCAMIACAQExDTALBglghkgBZQMEAgEwgAYJKoZIhvcNAQcBAACggDCCA+MwggOIoAMCAQICCBZjTIsOMFcXMAoGCCqGSM49BAMCMHoxLjAsBgNVBAMMJUFwcGxlIEFwcGxpY2F0aW9uIEludGVncmF0aW9uIENBIC0gRzMxJjAkBgNVBAsMHUFwcGxlIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRMwEQYDVQQKDApBcHBsZSBJbmMuMQswCQYDVQQGEwJVUzAeFw0yNDA0MjkxNzQ3MjdaFw0yOTA0MjgxNzQ3MjZaMF8xJTAjBgNVBAMMHGVjYy1zbXAtYnJva2VyLXNpZ25fVUM0LVBST0QxFDASBgNVBAsMC2lPUyBTeXN0ZW1zMRMwEQYDVQQKDApBcHBsZSBJbmMuMQswCQYDVQQGEwJVUzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABMIVd+3r1seyIY9o3XCQoSGNx7C9bywoPYRgldlK9KVBG4NCDtgR80B+gzMfHFTD9+syINa61dTv9JKJiT58DxOjggIRMIICDTAMBgNVHRMBAf8EAjAAMB8GA1UdIwQYMBaAFCPyScRPk+TvJ+bE9ihsP6K7\/S5LMEUGCCsGAQUFBwEBBDkwNzA1BggrBgEFBQcwAYYpaHR0cDovL29jc3AuYXBwbGUuY29tL29jc3AwNC1hcHBsZWFpY2EzMDIwggEdBgNVHSAEggEUMIIBEDCCAQwGCSqGSIb3Y2QFATCB\/jCBwwYIKwYBBQUHAgIwgbYMgbNSZWxpYW5jZSBvbiB0aGlzIGNlcnRpZmljYXRlIGJ5IGFueSBwYXJ0eSBhc3N1bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJsZSBzdGFuZGFyZCB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRlIHBvbGljeSBhbmQgY2VydGlmaWNhdGlvbiBwcmFjdGljZSBzdGF0ZW1lbnRzLjA2BggrBgEFBQcCARYqaHR0cDovL3d3dy5hcHBsZS5jb20vY2VydGlmaWNhdGVhdXRob3JpdHkvMDQGA1UdHwQtMCswKaAnoCWGI2h0dHA6Ly9jcmwuYXBwbGUuY29tL2FwcGxlYWljYTMuY3JsMB0GA1UdDgQWBBSUV9tv1XSBhomJdi9+V4UH55tYJDAOBgNVHQ8BAf8EBAMCB4AwDwYJKoZIhvdjZAYdBAIFADAKBggqhkjOPQQDAgNJADBGAiEAxvAjyyYUuzA4iKFimD4ak\/EFb1D6eM25ukyiQcwU4l4CIQC+PNDf0WJH9klEdTgOnUTCKKEIkKOh3HJLi0y4iJgYvDCCAu4wggJ1oAMCAQICCEltL786mNqXMAoGCCqGSM49BAMCMGcxGzAZBgNVBAMMEkFwcGxlIFJvb3QgQ0EgLSBHMzEmMCQGA1UECwwdQXBwbGUgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxEzARBgNVBAoMCkFwcGxlIEluYy4xCzAJBgNVBAYTAlVTMB4XDTE0MDUwNjIzNDYzMFoXDTI5MDUwNjIzNDYzMFowejEuMCwGA1UEAwwlQXBwbGUgQXBwbGljYXRpb24gSW50ZWdyYXRpb24gQ0EgLSBHMzEmMCQGA1UECwwdQXBwbGUgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxEzARBgNVBAoMCkFwcGxlIEluYy4xCzAJBgNVBAYTAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE8BcRhBnXZIXVGl4lgQd26ICi7957rk3gjfxLk+EzVtVmWzWuItCXdg0iTnu6CP12F86Iy3a7ZnC+yOgphP9URaOB9zCB9DBGBggrBgEFBQcBAQQ6MDgwNgYIKwYBBQUHMAGGKmh0dHA6Ly9vY3NwLmFwcGxlLmNvbS9vY3NwMDQtYXBwbGVyb290Y2FnMzAdBgNVHQ4EFgQUI\/JJxE+T5O8n5sT2KGw\/orv9LkswDwYDVR0TAQH\/BAUwAwEB\/zAfBgNVHSMEGDAWgBS7sN6hWDOImqSKmd6+veuv2sskqzA3BgNVHR8EMDAuMCygKqAohiZodHRwOi8vY3JsLmFwcGxlLmNvbS9hcHBsZXJvb3RjYWczLmNybDAOBgNVHQ8BAf8EBAMCAQYwEAYKKoZIhvdjZAYCDgQCBQAwCgYIKoZIzj0EAwIDZwAwZAIwOs9yg1EWmbGG+zXDVspiv\/QX7dkPdU2ijr7xnIFeQreJ+Jj3m1mfmNVBDY+d6cL+AjAyLdVEIbCjBXdsXfM4O5Bn\/Rd8LCFtlk\/GcmmCEm9U+Hp9G5nLmwmJIWEGmQ8Jkh0AADGCAYgwggGEAgEBMIGGMHoxLjAsBgNVBAMMJUFwcGxlIEFwcGxpY2F0aW9uIEludGVncmF0aW9uIENBIC0gRzMxJjAkBgNVBAsMHUFwcGxlIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRMwEQYDVQQKDApBcHBsZSBJbmMuMQswCQYDVQQGEwJVUwIIFmNMiw4wVxcwCwYJYIZIAWUDBAIBoIGTMBgGCSqGSIb3DQEJAzELBgkqhkiG9w0BBwEwHAYJKoZIhvcNAQkFMQ8XDTI1MTAwMjE5MjYyNFowKAYJKoZIhvcNAQk0MRswGTALBglghkgBZQMEAgGhCgYIKoZIzj0EAwIwLwYJKoZIhvcNAQkEMSIEIIglNywQdAxKnixbc4TJLaopplLPs5m84zjbAlsJuvnOMAoGCCqGSM49BAMCBEcwRQIhANjW5bxOlsS4oBDrxUn6OtIHWxpHshyj0ozI518Ty\/rbAiAW+dbxN9OQJ9a2B3VMps89dm0ZB6MdQCG7iHM2g2Tn1gAAAAAAAA==\",\r\n \"header\":{\r\n \"publicKeyHash\":\"YK8kdoBXLGqBQKBtCZOl0DQTUHOWidRCxgOgf\/1gBMM=\",\r\n \"ephemeralPublicKey\":\"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEEVv32VVJYlg+E0zMsthvBaldJcH45NUWhVckme\/CQYFtHf60FEdFtzwabOEMY3u1De+6e+IuBv53OxmWx+1w2w==\",\r\n \"transactionId\":\"87a03c4cc1b242a25d74257d4bc990a6473b9866392850e584a9f680dcdf3d0f\"\r\n },\r\n \"version\":\"EC_v1\"\r\n }\r\n}",
"soft_descriptor": "TEST"
}
}
}
},
"account_id": "fe14c7c6-c75e-43b7-bdbe-4c87ad52c482",
"description": "Apple Pay recurring setup",
"merchant_order_id": "recurring-setup-123"
}'
```
## Recurring payments with Direct API
Recurring Apple Pay payments with Direct integration require implementation of Customer Initiated Transactions (CIT) and Merchant Initiated Transactions (MIT).
* **Customer Initiated Transaction (CIT):** The first transaction where the customer authorizes recurring payments. This generates a `vaulted_token` for future use.
* **Merchant Initiated Transaction (MIT):** Subsequent automated transactions using the `vaulted_token` without customer interaction.
### Customer Initiated Transaction (CIT)
When a customer authorizes the subscription and you have a response from the Apple SDK, use the stringified `payment_token` in Yuno's [create payment API](/reference/create-payment) to create the CIT.
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
curl --location 'https://api-sandbox.y.uno/v1/payments' \
--header 'X-idempotency-key: 30cc2a07-9170-47d7-88ff-c4d3ee48274e' \
--header 'public-api-key: ' \
--header 'private-secret-key: ' \
--header 'Keep-Alive: timeout=5, max=1000' \
--header 'Content-Type: application/json' \
--data-raw '{
"country": "US",
"amount": {
"currency": "USD",
"value": 2000
},
"customer_payer": {
"id": "24e25748-6ab3-4d43-bb8b-eb0204bb0951",
"email": "customer@example.com",
"first_name": "John",
"last_name": "Doe"
},
"workflow": "DIRECT",
"payment_method": {
"vault_on_success": true,
"type": "APPLE_PAY",
"detail": {
"wallet": {
"payment_token": "{\r\n \"paymentMethod\":{\r\n \"type\":\"credit\",\r\n \"displayName\":\"Visa 3748\",\r\n \"network\":\"Visa\"\r\n },\r\n \"paymentData\":{\r\n \"data\":\"B5NSQI0TdXuLwqadBCL0yOwtik\/rJx7v41xxE8rNSlFBTHR2W88iRck7a6bH9Kx\/bBFsk2ZyinIEl2aXusHp22a0pSmuCUoPgbkFc1\/D3PRAoWITfZkalBeuzMhHJGhhCe2wqOgMmjS2w97nN9vifb1cMrS3kOqpPPMihHVvhLYbwtNhh8lfeTOyL+RBXbdFScVTFCB1eFQ4znUFV79SHVK\/SRjLxLawO1HGIO0VIUTj8uVgG4MmBrfQhDBD\/P9a4lWypiNoyURHm7ubgcOEelbVDGlKSNDmYFD10i554b+7z8GXBtWdQc1zhWKcGOn8RsOYtxxdqzHEtJzcFsf92\/rEhfpEThXjsLLMTmovGyQS30qM\/qO2YgqduEID7IS+xOH\/FXpplT5Yqur7\/+FgEwcv2lGsa0K6kNMEUn1xSWc=\",\r\n \"signature\":\"MIAGCSqGSIb3DQEHAqCAMIACAQExDTALBglghkgBZQMEAgEwgAYJKoZIhvcNAQcBAACggDCCA+MwggOIoAMCAQICCBZjTIsOMFcXMAoGCCqGSM49BAMCMHoxLjAsBgNVBAMMJUFwcGxlIEFwcGxpY2F0aW9uIEludGVncmF0aW9uIENBIC0gRzMxJjAkBgNVBAsMHUFwcGxlIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRMwEQYDVQQKDApBcHBsZSBJbmMuMQswCQYDVQQGEwJVUzAeFw0yNDA0MjkxNzQ3MjdaFw0yOTA0MjgxNzQ3MjZaMF8xJTAjBgNVBAMMHGVjYy1zbXAtYnJva2VyLXNpZ25fVUM0LVBST0QxFDASBgNVBAsMC2lPUyBTeXN0ZW1zMRMwEQYDVQQKDApBcHBsZSBJbmMuMQswCQYDVQQGEwJVUzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABMIVd+3r1seyIY9o3XCQoSGNx7C9bywoPYRgldlK9KVBG4NCDtgR80B+gzMfHFTD9+syINa61dTv9JKJiT58DxOjggIRMIICDTAMBgNVHRMBAf8EAjAAMB8GA1UdIwQYMBaAFCPyScRPk+TvJ+bE9ihsP6K7\/S5LMEUGCCsGAQUFBwEBBDkwNzA1BggrBgEFBQcwAYYpaHR0cDovL29jc3AuYXBwbGUuY29tL29jc3AwNC1hcHBsZWFpY2EzMDIwggEdBgNVHSAEggEUMIIBEDCCAQwGCSqGSIb3Y2QFATCB\/jCBwwYIKwYBBQUHAgIwgbYMgbNSZWxpYW5jZSBvbiB0aGlzIGNlcnRpZmljYXRlIGJ5IGFueSBwYXJ0eSBhc3N1bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJsZSBzdGFuZGFyZCB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRlIHBvbGljeSBhbmQgY2VydGlmaWNhdGlvbiBwcmFjdGljZSBzdGF0ZW1lbnRzLjA2BggrBgEFBQcCARYqaHR0cDovL3d3dy5hcHBsZS5jb20vY2VydGlmaWNhdGVhdXRob3JpdHkvMDQGA1UdHwQtMCswKaAnoCWGI2h0dHA6Ly9jcmwuYXBwbGUuY29tL2FwcGxlYWljYTMuY3JsMB0GA1UdDgQWBBSUV9tv1XSBhomJdi9+V4UH55tYJDAOBgNVHQ8BAf8EBAMCB4AwDwYJKoZIhvdjZAYdBAIFADAKBggqhkjOPQQDAgNJADBGAiEAxvAjyyYUuzA4iKFimD4ak\/EFb1D6eM25ukyiQcwU4l4CIQC+PNDf0WJH9klEdTgOnUTCKKEIkKOh3HJLi0y4iJgYvDCCAu4wggJ1oAMCAQICCEltL786mNqXMAoGCCqGSM49BAMCMGcxGzAZBgNVBAMMEkFwcGxlIFJvb3QgQ0EgLSBHMzEmMCQGA1UECwwdQXBwbGUgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxEzARBgNVBAoMCkFwcGxlIEluYy4xCzAJBgNVBAYTAlVTMB4XDTE0MDUwNjIzNDYzMFoXDTI5MDUwNjIzNDYzMFowejEuMCwGA1UEAwwlQXBwbGUgQXBwbGljYXRpb24gSW50ZWdyYXRpb24gQ0EgLSBHMzEmMCQGA1UECwwdQXBwbGUgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxEzARBgNVBAoMCkFwcGxlIEluYy4xCzAJBgNVBAYTAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE8BcRhBnXZIXVGl4lgQd26ICi7957rk3gjfxLk+EzVtVmWzWuItCXdg0iTnu6CP12F86Iy3a7ZnC+yOgphP9URaOB9zCB9DBGBggrBgEFBQcBAQQ6MDgwNgYIKwYBBQUHMAGGKmh0dHA6Ly9vY3NwLmFwcGxlLmNvbS9vY3NwMDQtYXBwbGVyb290Y2FnMzAdBgNVHQ4EFgQUI\/JJxE+T5O8n5sT2KGw\/orv9LkswDwYDVR0TAQH\/BAUwAwEB\/zAfBgNVHSMEGDAWgBS7sN6hWDOImqSKmd6+veuv2sskqzA3BgNVHR8EMDAuMCygKqAohiZodHRwOi8vY3JsLmFwcGxlLmNvbS9hcHBsZXJvb3RjYWczLmNybDAOBgNVHQ8BAf8EBAMCAQYwEAYKKoZIhvdjZAYCDgQCBQAwCgYIKoZIzj0EAwIDZwAwZAIwOs9yg1EWmbGG+zXDVspiv\/QX7dkPdU2ijr7xnIFeQreJ+Jj3m1mfmNVBDY+d6cL+AjAyLdVEIbCjBXdsXfM4O5Bn\/Rd8LCFtlk\/GcmmCEm9U+Hp9G5nLmwmJIWEGmQ8Jkh0AADGCAYgwggGEAgEBMIGGMHoxLjAsBgNVBAMMJUFwcGxlIEFwcGxpY2F0aW9uIEludGVncmF0aW9uIENBIC0gRzMxJjAkBgNVBAsMHUFwcGxlIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRMwEQYDVQQKDApBcHBsZSBJbmMuMQswCQYDVQQGEwJVUwIIFmNMiw4wVxcwCwYJYIZIAWUDBAIBoIGTMBgGCSqGSIb3DQEJAzELBgkqhkiG9w0BBwEwHAYJKoZIhvcNAQkFMQ8XDTI1MTAwMjE5MjYyNFowKAYJKoZIhvcNAQk0MRswGTALBglghkgBZQMEAgGhCgYIKoZIzj0EAwIwLwYJKoZIhvcNAQkEMSIEIIglNywQdAxKnixbc4TJLaopplLPs5m84zjbAlsJuvnOMAoGCCqGSM49BAMCBEcwRQIhANjW5bxOlsS4oBDrxUn6OtIHWxpHshyj0ozI518Ty\/rbAiAW+dbxN9OQJ9a2B3VMps89dm0ZB6MdQCG7iHM2g2Tn1gAAAAAAAA==\",\r\n \"header\":{\r\n \"publicKeyHash\":\"YK8kdoBXLGqBQKBtCZOl0DQTUHOWidRCxgOgf\/1gBMM=\",\r\n \"ephemeralPublicKey\":\"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEEVv32VVJYlg+E0zMsthvBaldJcH45NUWhVckme\/CQYFtHf60FEdFtzwabOEMY3u1De+6e+IuBv53OxmWx+1w2w==\",\r\n \"transactionId\":\"87a03c4cc1b242a25d74257d4bc990a6473b9866392850e584a9f680dcdf3d0f\"\r\n },\r\n \"version\":\"EC_v1\"\r\n }\r\n}",
"soft_descriptor": "TEST",
"stored_credentials": {
"reason": "SUBSCRIPTION",
"usage": "FIRST"
}
}
}
},
"account_id": "fe14c7c6-c75e-43b7-bdbe-4c87ad52c482",
"description": "Apple Pay recurring setup",
"merchant_order_id": "recurring-setup-123"
}'
```
#### Key parameters for CIT
* **`vault_on_success: true`**: Indicates this is a recurring payment setup and generates the vaulted token for future MIT transactions
* **`detail.wallet.stored_credentials.usage: FIRST`**: Indicates this is the initial transaction in a recurring series
* **`detail.wallet.payment_token`**: Must be the stringified Apple SDK response, the `payment_token`
### CIT response handling
When the CIT is successful, you'll receive a response containing the `vaulted_token`. It can be used for subsequent transactions. Store it encrypted at rest, and restrict access to only the systems that need it to create MIT charges.
The payment response is the only place the `vaulted_token` is returned. Wallet-vaulted instruments are intentionally not included in [Retrieve Enrolled Payment Methods](/reference/retrieve-enrolled-payment-methods-api), so don't rely on the customer's payment-methods list to rediscover the token — persist it (with any display metadata you need) when the CIT succeeds. A stored token can still be resolved individually with [Retrieve Enrolled Payment Method by ID](/reference/retrieve-enrolled-payment-method-by-id-api). See [Stored Credentials](/docs/payment-features/stored-credentials#wallet-originated-tokens-apple-pay-and-google-pay) for the tagging rules on stored wallet tokens.
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"id": "61533a3b-f971-422f-a839-9af61f8ec9ab",
"status": "SUCCEEDED",
"payment_method": {
"id": "7a2f1c44-3d57-4a9c-9ef0-3c0b5a8d2e1f",
"vaulted_token": "98c16e23-ebdd-4d0f-85bd-e0ba7d2fedf6"
}
}
```
### Merchant Initiated Transaction (MIT)
MIT transactions are processed automatically for recurring billing using the `vaulted_token` from the CIT.
#### Example MIT request
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
curl --location 'https://api-sandbox.y.uno/v1/payments' \
--header 'X-idempotency-key: 4793b6aa-b2b3-4296-8477-37316f27c287' \
--header 'public-api-key: ' \
--header 'private-secret-key: ' \
--header 'Keep-Alive: timeout=5, max=1000' \
--header 'Content-Type: application/json' \
--data-raw '{
"country": "US",
"amount": {
"currency": "USD",
"value": 2000
},
"customer_payer": {
"id": "24e25748-6ab3-4d43-bb8b-eb0204bb0951",
"email": "customer@example.com",
"first_name": "John",
"last_name": "Doe"
},
"workflow": "DIRECT",
"payment_method": {
"vault_on_success": true,
"vaulted_token": "98c16e23-ebdd-4d0f-85bd-e0ba7d2fedf6",
"type": "APPLE_PAY",
"detail": {
"card": {
"soft_descriptor": "TEST",
"stored_credentials": {
"reason": "SUBSCRIPTION",
"usage": "USED"
}
}
}
},
"account_id": "fe14c7c6-c75e-43b7-bdbe-4c87ad52c482",
"description": "Apple Pay recurring setup",
"merchant_order_id": "recurring-setup-123"
}'
```
#### Key parameters for MIT
* **`vaulted_token`**: The vaulted token generated during the CIT
* **`detail.card.stored_credentials.usage: "USED"`**: Indicates this is a subsequent transaction in a recurring series
* **No `payment_token` required**: Uses the stored `vaulted_token` instead
## Troubleshooting
* **Merchant validation failed**: verify Apple Pay certificates and merchant ID configuration
* **Invalid or expired Apple token**: obtain a fresh token from Apple SDK and ensure it is stringified
* **Unsupported network or country**: confirm your provider supports Apple Pay for the requested currency/country
* **Duplicate charges**: always send an `Idempotency-Key` with create payment calls
## Related documentation
* [Prerequisites for Apple Pay](/docs/prerequisites-apple-pay)
* [Apple Pay SDK integration](/docs/apple-pay-sdk-integration)
* [Create payment API](/reference/create-payment)
* [Subscription management](/docs/subscriptions)
* [Webhooks](/docs/webhooks)
# SDK Integration
Source: https://docs.y.uno/docs/wallets/apple-pay/apple-pay-sdk-integration
Integrate Apple Pay one-time and recurring payments using Yuno's SDK and checkout sessions.
This guide provides a comprehensive process to integrate Apple Pay with Yuno SDK for both one-time and recurring payments. The SDK simplifies Apple Pay integration by handling payment token management and providing built-in security.
**Setup Required**
Before implementing Apple Pay payments, ensure you have completed the [prerequisites](/docs/wallets/apple-pay/prerequisites-apple-pay).
**Testing Environment**
Apple Pay is not supported in the iOS Simulator. To test Apple Pay functionality, you must use a physical iOS device.
Apple Pay on the web is not limited to Safari or Apple devices. It also works in third-party browsers on iPhone, iPad, and macOS, and in any browser on Windows through Apple's cross-device payment flow. See [Supported devices and browsers](/docs/apple-pay#supported-devices-and-browsers) for the full matrix.
## Apple Pay overview
1. Customer initiates payment on their iOS device
2. Receive `payment_token` via Apple SDK
3. Create a checkout session with Yuno
4. Yuno processes with your configured provider(s) and returns a response
5. Monitor response status via webhooks
## Add Apple Pay capability
To add Apple Pay capability to your iOS app:
1. In Xcode, select your project in the navigator
2. Select your app target
3. Go to the **Signing & Capabilities** tab
4. Click **+ Capability** and search for "Apple Pay"
5. Add the **Apple Pay** capability
6. Configure your Merchant IDs in the Apple Pay section
Ensure your Apple Pay Merchant ID matches the one configured in your Yuno Dashboard provider connections.
## One-time payments with SDK
### Create checkout session
Use the [create checkout session](/reference/create-checkout-session) endpoint to create a payment session for one-time Apple Pay transactions:
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"country": "US",
"customer_id": "070a34cb-4649-4a4e-b231-065a53060379",
"merchant_order_id": "order-123",
"payment_description": "Apple Pay one-time payment",
"amount": {
"currency": "USD",
"value": 100
}
}
```
### Process the payment
The SDK handles the Apple Pay flow automatically. When the customer completes the Apple Pay authorization, the payment is processed immediately.
### Requesting Contact Information
You can configure which contact fields Apple Pay requests from the customer directly from the [Checkout Builder](/docs/using-yuno/dashboard-overview/checkout-builder#required-fields). The available fields are:
* Email
* Phone
* Holder name
* Billing address
* Shipping address
When any of these fields are enabled as required in the Checkout Builder, the Apple Pay payment sheet will prompt the customer to provide or confirm that information before completing the payment. The collected data is then included in the OTT response.
Each additional required field adds an extra step to the Apple Pay payment sheet, increasing friction for the customer. This can negatively impact conversion rates. Yuno recommends enabling only the fields that are strictly necessary for your business or regulatory requirements.
| Platform | Minimum version |
| -------- | --------------- |
| Web | 1.8.0 |
| iOS | 2.15.0 |
## Recurring payments with SDK
Recurring payments use both Customer‑Initiated (CIT) and Merchant‑Initiated (MIT) transactions. The overall flow is:
1. Create a checkout session with the `recurring_payment` object.
2. Perform a CIT to authorize and vault the customer's payment method.
3. Then use the returned `vaulted_token` for subsequent MIT charges.
### Create checkout session for recurring payments
Before creating the transaction, you need to create the checkout session with the `recurring_payment` object populated in your checkout session request:
**Free trial:** When offering a free trial period, set the root `amount.value` to `0` and include the `trial_billing` object as shown in the example below. The actual recurring charge is defined in `regular_billing`, which informs the customer of the amount they will be billed once the trial ends.
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"account_id": "123444",
"merchant_order_id": "12333",
"country": "US",
"callback_url": "https://your-callback-url.com",
"customer_id": "12333",
"amount": {
"currency": "EUR",
"value": 2000
},
"checkout_session": {
"payment_description": "Basic Plan — 3-day free trial",
"workflow": "SDK_CHECKOUT"
},
"recurring_payment": {
"description": "Basic Plan",
"management_url": "https://yourURL.com/subscriptions",
"billing_agreement": "After your 3-day free trial ends, you will be charged EUR 11.99/month until you cancel. Cancel anytime via account settings or by contacting support@test.com.",
"regular_billing": {
"label": "Monthly Plan",
"amount": 11.99,
"interval_unit": "month",
"interval_count": 1
},
"trial_billing": {
"label": "3-Day Free Trial",
"amount": 0,
"interval_unit": "day",
"interval_count": 3
},
"availability": {
"start_at": "2026-09-13T20:00:00Z",
"finish_at": "2026-09-30T16:10:00Z"
}
}
}
```
### Customer Initiated Transaction (CIT)
The CIT is the initial transaction where the customer authorizes recurring payments, such as when they subscribe to a monthly service. This transaction requires customer interaction and generates a token for future MIT transactions.
The following example shows a complete CIT request:
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"account_id": "62fa3145-1408-4044-a599-caa0c2159782",
"amount": {
"currency": "USD",
"value": 2000
},
"checkout": {
"session": "0793c7a5-79c6-40d6-aa5f-13e4e9bdf169"
},
"payment_method": {
"vault_on_success": true,
"type": "APPLE_PAY",
"token": "684f1f66-5322-4c84-a0b63d",
"detail": {
"wallet": {
"stored_credentials": {
"reason": "SUBSCRIPTION",
"usage": "FIRST"
},
"verify": true
}
}
},
"customer_payer": {
"id": "070a34cb-4649-4a4e-b231-065a53060379",
"nationality": "CO",
"browser_info": {
"user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15",
"accept_header": "application/json",
"accept_content": "*/*",
"accept_browser": "*/*",
"color_depth": "5",
"screen_height": "8",
"screen_width": "8",
"javascript_enabled": true,
"java_enabled": false,
"browser_time_difference": "300",
"language": "en",
"platform": "WEB"
}
},
"merchant_order_id": "merchant-order-123",
"country": "US",
"description": "Apple Pay recurring setup",
"workflow": "SDK_CHECKOUT"
}
```
The key parameters for a CIT are:
* **`vault_on_success: true`**: This parameter indicates this is a recurring payment setup and generates the token for future MIT transactions
* **`stored_credentials.usage: "FIRST"`**: Indicates this is the initial transaction in a recurring series
* **`verify`**: When `true`, enables a card verification flow through the wallet (for example, a zero-dollar authorization) instead of a regular payment charge.
Set `verify: true` for free trial flows where `amount` is `0`. Omit the field for standard paid CITs.
The `vaulted_token` is returned only in the CIT payment response. Wallet-vaulted instruments are intentionally not included in [Retrieve Enrolled Payment Methods](/reference/retrieve-enrolled-payment-methods-api), so don't rely on the customer's payment-methods list to rediscover the token — store it (with any display metadata you need) when the CIT succeeds. A stored token can still be resolved individually with [Retrieve Enrolled Payment Method by ID](/reference/retrieve-enrolled-payment-method-by-id-api). See [Stored Credentials](/docs/payment-features/stored-credentials#wallet-originated-tokens-apple-pay-and-google-pay).
### Merchant Initiated Transaction (MIT)
MIT transactions are processed automatically for subsequent billing cycles using the token generated during the CIT.
The following example shows a complete MIT request:
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"account_id": "account-id",
"amount": {
"currency": "USD",
"value": 100
},
"payment_method": {
"vaulted_token": "98c16e23-ebdd-4d0f-85bd-e0ba7d2fedf6",
"detail": {
"card": {
"stored_credentials": {
"reason": "SUBSCRIPTION",
"usage": "USED"
}
}
},
"type": "APPLE_PAY"
},
"customer_payer": {
"id": "customer-id"
},
"merchant_order_id": "recurring-order-456",
"country": "US",
"description": "Apple Pay recurring payment",
"workflow": "SDK_CHECKOUT"
}
```
The key parameters for an MIT are:
* **`vaulted_token`**: The token returned in the CIT response; used to charge the customer in subsequent billing cycles without requiring re-authorization
* **`stored_credentials.usage: "USED"`**: Indicates this is a subsequent transaction in a recurring series
* **No `payment_token` required**: Uses the stored token instead
Monitor payment status through [webhooks](/docs/webhooks) to handle edge cases and provide customer notifications.
## Obtain DPAN BIN in OTT response
When a payment is completed with Apple Pay, the iOS SDK returns the full OTT (One-Time Token) service response. Within this response, the `card_data` object contains card-related information associated with the Apple Pay payment, including the DPAN BIN (the first digits of the Device Primary Account Number used in the transaction).
Merchants can use this object to retrieve card details such as brand, type, issuer, and the `iin` field, which represents the DPAN BIN.
### Example OTT response (iOS SDK)
The following example shows the SDK response containing the `card_data` object with the `iin` field:
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"vault_on_success": false,
"country": "US",
"card_data": {
"category": "CLASSIC",
"lfd": "8880",
"fingerprint": null,
"issuer_name": "BANK",
"security_code_length": 0,
"brand": "VISA",
"issuer_code": null,
"type": "CREDIT",
"holder_name": "",
"country_code": "US",
"iin": "49411598",
"number_length": 0
},
"vaulted_token": null,
"installment": null,
"token": "0ac7f1c8-aba4-4600-b080-f88e9f328c1f",
"type": "CARD"
}
```
## Apple Pay Cancel Flow
When a user cancels the Apple Pay flow, the SDK reports the status `CANCELED_BY_USER`.
### Metadata and paymentCreated
The `oldClosePaymentFlow` method (and related cancel events) now includes an optional `metadata` parameter with the `paymentCreated` field. This allows merchants to know if a payment was already created on the backend before the user canceled the flow.
* **`paymentCreated: true`**: A payment was created (for example, during OTT creation phase). Merchants should check the payment status and potentially trigger an `abandonPayment` call.
* **`paymentCreated: false`**: No payment was created before cancellation.
The SDK automatically sets `paymentCreated = true` during the `onvalidatemerchant` phase to ensure correct tracking and abandonment of pending payments.
### Subscription management URL
For SDK recurring payments, you must provide a subscription management URL where customers can manage and cancel their subscription. Include it in your customer communications.
## Related documentation
* [Prerequisites for Apple Pay](/docs/wallets/apple-pay/prerequisites-apple-pay)
* [Apple Pay Direct integration](/docs/apple-pay-direct-integration)
* [Subscription management](/docs/subscriptions)
* [Webhooks](/docs/webhooks)
# Prerequisites (Apple Pay)
Source: https://docs.y.uno/docs/wallets/apple-pay/prerequisites-apple-pay
Walks through Apple Pay certificate setup, domain registration, and Yuno dashboard connection configuration.
Use this guide to prepare and configure Apple Pay with Yuno.
* [**Apple Developer prerequisites**](#apple-pay-certificate-options): Depending on your certificate path, you may need to create a merchant ID and generate certificates/keys (Own), or register your merchant domains (Yuno).
* [**Yuno Dashboard setup**](#finish-in-the-dashboard): Add the Apple Pay connection, set up routing, and enable Apple Pay in Checkout Builder.
When finished, you'll be ready to [choose your integration path](#next-steps) (SDK or Direct) for one-time and recurring payments.
## Apple Pay certificate options
In the Yuno Dashboard, you will find three options for Apple Pay certificates:
* **Yuno**: This option is for merchants who do not have an Apple Developer account or a mobile app (that is, they are web-only). In these cases, you must register your merchant domains in order to use Yuno's certificates. [→ Yuno certificates: register your merchant domains](#yuno-certificates-register-your-merchant-domains)
* **Own (manual)**: This option is for merchants who have an Apple Developer account and prefer to manage their own private keys. You generate and convert the certificates manually using Keychain Access and OpenSSL (Steps 2–9), then paste the PEM values into the Yuno Dashboard. [→ Own certificates (manual)](#own-certificates-manual)
* **Own — Yuno generates the CSRs**: This option is for merchants who have an Apple Developer account but don't want to generate private keys or run OpenSSL commands. Yuno generates the Certificate Signing Requests for you, then you upload them to Apple and return the signed certificates. [→ Own certificates with Yuno-generated CSRs](#own-certificates-with-yuno-generated-csrs)
## Own certificates (manual)
This path is for merchants who have an Apple Developer account and want to generate and manage their certificates manually using Keychain Access and OpenSSL.
### Step 1: Register a merchant identifier
If you're using VTEX as your e-commerce platform, you'll need to configure your Apple Pay Merchant ID. For detailed instructions, check out the [official VTEX documentation](https://developers.vtex.com/docs/guides/setting-up-merchant-id-in-apple-pay).
In the Apple Developer dashboard:
1. Log in to [Apple Developer](https://idmsa.apple.com/IDMSWebAuth/signin?appIdKey=891bd3417a7776362562d2197f89480a8547b108fd934911bcbea0110d07f757\&path=%2Faccount%2F\&rv=1), go to **Certificates, Identifiers & Profiles**, then select **Register a new identifier**.
2. Choose **Merchant IDs**.
3. Enter a **Description** (for example, `Apple Pay Integration`) and an **Identifier** in the format `merchant.com.y.uno.YourBusinessName`.
### Step 2: Generate a payment processing certificate
1. Create a new directory (for example, `Downloads/ApplePayFiles`) to store the certificate files.
2. Open **Keychain Access** on your Mac.
3. Go to **Keychain Access > Certificate Assistant > Request a Certificate From a Certificate Authority**.
4. Fill out the form:
* **Email Address**: your email address
* **Common Name**: a name for the certificate (for example, `John Doe ProcessingCertificate`)
* **CA Email Address**: leave blank
* Select **Saved to disk**
* Check **Let me specify key pair information**
5. Click **Continue**, then save the file as `CertificateSigningRequestPaymentProcessingCertificate.certSigningRequest` in your working directory.
6. When prompted for key pair settings, use:
* **Key Type**: Elliptic Curve (EC)
* **Key Size**: 256-bit
* **Algorithm**: ECDSA
### Step 3: Retrieve and convert the payment processing certificate
1. Go to the [Apple Developer Merchant ID list](https://developer.apple.com/account/resources/identifiers/list/merchant).
2. Select your Merchant ID and click **Create Certificate** under **Apple Pay Payment Processing Certificate**.
3. When prompted, answer **No** to "Will payments... be processed exclusively in China mainland?"
4. Upload the file `CertificateSigningRequestPaymentProcessingCertificate.certSigningRequest`.
5. Download the signed certificate as `apple_pay.cer` and save it to your directory.
6. Convert the certificate to PEM format:
```bash theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
openssl x509 -inform DER -in apple_pay.cer -out apple_pay.pem
```
### Step 4: Export the private key
1. In **Keychain Access**, find the key you created (for example, `John Doe ProcessingCertificate`).
2. Right-click and choose **Export**.
3. Export the key as a `.p12` file (for example, `JohnDoeProcessingCertificate.p12`) and save it to your working directory.
4. Set a strong password (you’ll use it in the next step).
5. Convert the `.p12` to a PEM-format private key:
```bash theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
openssl pkcs12 -in JohnDoeProcessingCertificate.p12 -nocerts -nodes | sed -ne '/-BEGIN PRIVATE KEY-/,/-END PRIVATE KEY-/p' > ProcessingCertificatePrivateKey.pem
```
The private key will be stored in `ProcessingCertificatePrivateKey.pem`.
### Step 5: Upload the certificate and key to Yuno
1. Open the [Yuno Dashboard](https://dashboard.y.uno/auth/login) **> Connections > Apple Pay > Connect**
2. Enter the contents of `ProcessingCertificatePrivateKey.pem` to the **Payment processing key** field.
3. Enter the contents of `apple_pay.pem` into the **Payment processing certificate** field.
### Step 6: Generate a merchant identity certificate
1. Open **Keychain Access**, navigate to **Certificate Assistant > Request a Certificate From a Certificate Authority**, and enter:
* **Email Address**: your email
* **Common Name**: for example, `John Doe MerchantIdentityCertificate`
* Leave **CA Email Address** blank
* Select **Saved to disk**
2. Save as `CertificateSigningRequestMerchantIdentityCertificate.certSigningRequest`.
### Step 7: Retrieve and convert the merchant identity certificate
1. Go to the [Apple Developer Merchant ID list](https://developer.apple.com/account/resources/identifiers/list/merchant).
2. Select your Merchant ID and click **Create Certificate** under **Apple Pay Merchant Identity Certificate**.
3. Upload the `CertificateSigningRequestMerchantIdentityCertificate.certSigningRequest` file.
4. Download the signed certificate as `merchant_id.cer` and save it.
5. Convert it to PEM:
```bash theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
openssl x509 -inform DER -in merchant_id.cer -out merchant_id.pem
```
### Step 8: Export the merchant identity private key
1. In **Keychain Access**, find the certificate created in step 6, for example, `John Doe MerchantIdentityCertificate`.
2. Right-click and export as `JohnDoeMerchantIdentityCertificate.p12`.
3. Set a strong password.
4. Convert the private key to PEM:
```bash theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
openssl pkcs12 -in JohnDoeMerchantIdentityCertificate.p12 -nocerts -nodes | sed -ne '/-BEGIN PRIVATE KEY-/,/-END PRIVATE KEY-/p' > MerchantIdentityCertificatePrivateKey.pem
```
The private key will be available as `MerchantIdentityCertificatePrivateKey.pem`.
### Step 9: Upload the merchant identity certificate and key
1. Return to your Apple Pay connection in the [Yuno Dashboard](https://dashboard.y.uno/auth/login).
2. Copy the contents of `MerchantIdentityCertificatePrivateKey.pem` and paste them into the **Merchant Identity key** field.
3. Paste the contents of `merchant_id.pem` into the **Merchant Identity certificate** field.
## Own certificates with Yuno-generated CSRs
This option is for merchants who have an Apple Developer account but don't want to generate private keys, run OpenSSL commands, or paste PEM values into the Dashboard. Yuno generates both Certificate Signing Requests (Payment Processing and Merchant Identity) for you. You upload them to Apple, download the signed .cer files Apple returns, and upload those .cer files back to Yuno from the Apple Pay connection form.
**Where to find it:** In the Yuno Dashboard, open **Connections** → **Certificates & Domains** → **Apple Pay** → **Certificate Signing Request**.
### Step 1: Enter your Apple Merchant ID
In the **Your Apple Merchant ID** field, enter the Merchant ID you registered in the Apple Developer Portal (for example, `merchant.com.example.app`).
Find your Apple Merchant ID in your Apple Developer Portal → Certificates, Identifiers & Profiles → Merchant IDs.
### Step 2: Generate the Payment Processing CSR
Apple Pay requires two separate certificates. The Payment Processing Certificate is an ECC P-256 certificate used by Apple to encrypt the payment token your store receives.
Apple allows only one active Payment Processing certificate per Merchant ID.
Click **Generate Payment Processing CSR**. Yuno generates the signing request. Click **Download .csr file** to save it locally.
### Step 3: Generate the Merchant Identity CSR
The Merchant Identity Certificate is an RSA 2048 certificate used to authenticate your server to Apple via mTLS when starting an Apple Pay session on the Web.
Multiple active Merchant Identity certificates per Merchant ID are allowed.
Click **Generate Merchant Identity CSR**. Click **Download .csr file** to save the second .csr locally.
### Step 4: Upload each .csr to Apple
Repeat these steps twice: once for the Payment Processing CSR, and once for the Merchant Identity CSR.
1. Go to [developer.apple.com](https://developer.apple.com) → **Certificates, Identifiers & Profiles**.
2. Select your Merchant ID.
3. Under **Apple Pay Payment Processing Certificate** (first pass) or **Apple Pay Merchant Identity Certificate** (second pass), click **Create Certificate**.
4. When prompted, answer **No** to "Will payments… be processed exclusively in China mainland?"
5. Upload the .csr file when prompted.
6. Download the .cer file Apple gives you.
You will end up with two .cer files: one for Payment Processing and one for Merchant Identity.
### Step 5: Set up the Apple Pay connection
1. In **Use certificates**, select **Own — Yuno generates the CSRs**.
2. Pick your **Merchant Identifier** from the dropdown, pre-populated with the CSRs you generated.
3. Fill in **Display Name** and **Domain Name**.
4. Under **Payment Processing Certificate** → **Apple-issued .cer file**, click **Choose file** and select the .cer Apple issued for Payment Processing.
5. Under **Merchant Identity Certificate** → **Apple-issued .cer file**, click **Choose file** and select the .cer Apple issued for Merchant Identity.
## Yuno certificates: register your merchant domains
Before the Apple Pay button can appear on your website, every domain that displays it must be registered. You have two options:
### Dashboard (recommended)
Register your domains directly in the Yuno Dashboard: Yuno registers each domain with Apple on your behalf.
1. In the Dashboard, go to **Connections › Certificates & Domains › Apple Pay** and open the **Domains** tab.
2. Click **Add domain**.
3. Enter the domains where the Apple Pay button will appear, **one per line** (up to 10 at a time).
Before adding the domain, you must host a verification file on each registered domain as plain text (do not leave it as a downloadable file), using the following hosting path:
`/.well-known/apple-developer-merchantid-domain-association`
You can find this file in the Dashboard section for domain registration (Connections › Certificates & Domains › Apple Pay › Domains).
4. Click **Add**. Each domain appears in the table with a status of **Verifying** while Yuno completes registration with Apple.
5. When registration succeeds, the status changes to **Active**: the domain is ready to show Apple Pay.
### API
Use the following endpoints to manage your domain registration:
* [Register domain](/reference/domains/register-domain)
* [Get domain](/reference/domains/get-domain)
* [Delete domain](/reference/domains/delete-domain)
* [Domain webhooks](/reference/domains/webhooks-domains)
## Finish in the Dashboard
All three certificate paths, Yuno, Own, and Own (Yuno-generated CSRs), converge here to complete the setup in the Yuno Dashboard.
### Step 1: Connect Apple Pay
1. Log in to your [Yuno Dashboard](https://dashboard.y.uno/connections).
2. Navigate to **Connections › Certificates & Domains › Apple Pay** and click **Connect**.
3. Provide a **Name** for the connection, select **Apple Pay** as **Payment method**, and in the **Use certificates** dropdown, select the option that matches your setup:
* **Yuno**: Yuno manages the certificates on your behalf automatically. No additional certificate configuration is required.
* **Own** (manual): paste the PEM values you generated in the previous steps.
* **Own — Yuno generates the CSRs**: select this option and upload the `.cer` files issued by Apple as described in the [Own certificates with Yuno-generated CSRs](#own-certificates-with-yuno-generated-csrs) section.
4. Click **Next**, then complete the two screens that follow: setup costs (optional) and accounts.
5. Click **Save**. Apple Pay will be added to your connections.
### Step 2: Configure routing
Set up a new route to control how payments are processed through Apple Pay.
Visit the [Routing](/docs/routing) page for additional information on this step.
1. In the [Yuno Dashboard](https://dashboard.y.uno/), navigate to the **Routing** section.
2. Find the **Apple Pay** connection. If you have not created a route for Apple Pay yet, it will be on the **Not published** tab.
3. Set up a new route by pressing **Setup** on your **Apple Pay** module (or **View** if the route is published) and then clicking on **Create new route**. Give the connection a name and click **Save**.
4. Add conditions to specify how payments should be routed through Apple Pay.
5. Add Apple Pay as the payment processor for this route to ensure that payments meeting the defined conditions are processed through Apple Pay.
6. **Publish** the route once all configurations are defined.
Here's a simple route processing all payments through Apple Pay.
### Step 3: Enable Apple Pay in Checkout Builder
Visit the [Checkout Builder](/docs/checkout-builder) page for additional information on this step.
To make Apple Pay available to your end users, you have to enable it on the Checkout Builder:
1. In the [Yuno Dashboard](https://dashboard.y.uno/), navigate to the **Checkout Builder** section.
2. Locate the available **Payment methods** and enable **Apple Pay**. Click the three dots next to each method for additional options.
3. Click **Publish settings** to make Apple Pay available as a payment option for all transactions that meet the defined routing criteria.
If you plan to implement recurring payments, you will need to configure an additional URL in your Apple Pay connection where customers can manage their subscriptions (cancel, modify, etc.). This URL must be created and hosted by your merchant platform.
## Next steps
After completing the Dashboard setup, choose your path to integrate via SDK or Direct:
* **SDK Integration**: [one-time](/docs/apple-pay-sdk-integration#one-time-payments-with-sdk) and [recurring](/docs/apple-pay-sdk-integration#recurring-payments-with-sdk)
* **Direct integration**: [one-time](/docs/apple-pay-direct-integration#one-time-payments) and [recurring](/docs/apple-pay-direct-integration#recurring-payments-with-direct-api)
# Click to Pay
Source: https://docs.y.uno/docs/wallets/click-to-pay
Integrate Click to Pay as a standalone method or embedded in the card flow.
Click to Pay is an online payment solution designed to streamline and secure online transactions. It's based on the EMVCo secure payment standard, a global consortium comprising major card companies like Visa, MasterCard, American Express, and Discover.
*Networks available in Yuno*: [MasterCard](https://www.mastercard.us/en-us/personal/ways-to-pay/click-to-pay.html)
## Key features and benefits
* **Ease of Use**: It enables consumers to make online purchases with a single click, eliminating the need to enter credit card details for each purchase manually.
* **Enhanced Security**: Utilizes modern authentication standards to minimize fraud risk. This may include methods such as two-factor authentication or payment tokens.
* **Consistent Across Various Sites**: Offers a similar payment experience across all websites that support this technology, meaning consumers don’t have to learn different processes for each online store.
* **Integration with Card Brands**: Being backed by major card brands, Click to Pay is widely accepted and trusted.
* **Mobile and Desktop Compatibility**: Designed to work across various devices, it facilitates online shopping on both desktops and mobile devices.
This feature enhances the customer experience and aligns with modern digital payment trends, potentially increasing conversion rates and customer loyalty. By incorporating Click to Pay, you can reduce checkout friction and address security concerns in online transactions.
**Network Tokens Requirement**
Network tokens support is required for Click to Pay in all flows (Golden Flow and APM, both with and without passkeys). Merchants must configure network tokens in their **Routing** rules to ensure successful processing.
## Integration
To integrate and start offering Click to Pay to your customers, follow these 4 simple steps:
1. Create a [connection](https://dashboard.y.uno/connections) in the Yuno dashboard using your Click to Pay credentials.
2. Define the payment method route in the [Routing](https://dashboard.y.uno/routing) section to enable it in the Checkout Builder.
3. Enable Click to Pay in the [Checkout builder](https://dashboard.y.uno/checkout-builder).
4. Define the Card route: Taking in consideration that Click to Pay is a wallet that stores credit card information, the **route** where you will need to define the providers for each scenario is the same as the **Card** payment method.
## Checkout Flows
Merchants can choose how Click to Pay appears at checkout. Both experiences support passkeys across web and mobile platforms.
### 1. Standalone Payment Method (APM Flow)
Click to Pay appears as a separate payment button alongside cards and other methods.
* **Mandatory Enrollment**: Account creation is mandatory for all users.
* **Payload Requirement**: Requires a C2P-specific payload.
* **Visibility**: Best for merchants who want Click to Pay prominently featured.
### 2. Embedded in Card (Golden Flow)
Click to Pay is embedded within the card payment method and is invisible until the user selects "Card."
* **Optional Enrollment**: Enrollment is via a checkbox. If declined, the user proceeds with manual card entry (the transaction still shows `CLICK_TO_PAY` in the one-time token (OTT)).
* **Visibility**: Best for low-friction UX where enrollment feels optional.
**Certification Note**
The golden flow with passkeys in Mobile is currently in certification.
## Activation Guide
Follow the steps below based on your desired configuration:
### Option 1: Click to Pay Only (APM)
1. Request the **DPA ID** from the card network (for example, Mastercard).
2. Add the **Click to Pay connection** in the Yuno dashboard using the DPA ID.
3. Add the **card connection** that will process these cards.
4. Define the payment method route in **Routing** and enable Click to Pay in the **Checkout Builder**.
### Option 2: Click to Pay + Passkey
*Supported on web browsers only (not supported in WebView).*
1. Request the **DPA ID** from the card network (for example, Mastercard).
2. Add the **Click to Pay connection** using the DPA ID.
3. Add the **card connection** and configure the **Acquirer BIN**.
4. Request the Yuno backend team to enable the **Passkey** and **Dual Payload** flags.
5. Create checkout sessions with a `price` for Passkey to work correctly.
### Option 3: Click to Pay + Golden Flow
1. Request the **DPA ID** from the card network (for example, Mastercard).
2. Add the **Click to Pay connection** using the DPA ID.
3. Add the **card connection** that will process these cards.
4. Request the Yuno backend team to enable the **Golden Flow** flag.
### Option 4: Click to Pay + Golden Flow + Passkey
*Supported on web browsers only (not supported in WebView).*
1. Request the **DPA ID** from the card network (for example, Mastercard).
2. Add the **Click to Pay connection**.
3. Add the **card connection** and configure the **Acquirer BIN**.
4. Request the Yuno backend team to enable **Passkey**, **Dual Payload**, and **Golden Flow** flags.
5. Create checkout sessions with a `price` for Passkey to work correctly.
## SDK integration (Click to Pay Passkey)
**Important**
Standard Click to Pay card flows use the existing SDK callbacks, but Passkey users must include a `callback_url` that matches the app’s deeplink scheme so the shopper returns to the app after authentication (on Android this must match the scheme configured in `AndroidManifest.xml`). For example:
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"callback_url": "myapp://pay/ctp"
}
```
For Passkey transactions, the one-time token (OTT) never reaches the usual SDK callbacks (including `callbackOTT` on Android). Always read it from the deeplink parameters before continuing the flow.
### Mobile: handling the response (OTT and deeplink)
The integration flow for Click to Pay Passkey has a specific response handling that differs from the standard payment flow.
When a shopper completes a payment using CTP Passkey, the one-time token (OTT) is **not** delivered through the usual delegate/listener methods. Instead, the transaction result — both success and failure — is communicated to your app through the **deeplink URL**.
This is the same on **iOS, Android, and Flutter**: the merchant reads the result from the deeplink URL and acts on it. Only *where* the deeplink arrives changes per platform.
**Read two parameters from the deeplink URL**
* `has_error` — an error occurred or the shopper canceled. Read the `message` parameter and show the error.
* `one_time_token` — the transaction succeeded and the OTT is contained in the URL.
**Once you have the `one_time_token`**
1. Send it to your backend to create the payment via the [Create payment](/reference/payments/create-payment) endpoint.
2. Continue the flow in the SDK with `continuePayment` to finalize the transaction.
**Where the deeplink arrives on each platform**
* **iOS** — in `application(_:open:options:)`. Call `Yuno.receiveDeeplink(url)` to close the Passkey browser, then read the parameters from `url`.
* **Flutter** — in your deeplink handler. `await Yuno.receiveDeeplink(url: uri)` to close the Passkey browser, then read the parameters from `uri`.
* **Android** — the deeplink relaunches your `Activity` (there is no SDK close call). Read the parameters from `intent.data` in `onCreate`/`onNewIntent`. The receiving activity must declare an `intent-filter` in `AndroidManifest.xml` matching the scheme/host/path of your `callback_url`.
```swift iOS theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
guard url.scheme == "myapp" else { return false }
Yuno.receiveDeeplink(url) // closes the Passkey browser
let items = URLComponents(url: url, resolvingAgainstBaseURL: false)?.queryItems
if items?.contains(where: { $0.name == "has_error" }) == true {
// handle error (read the `message` parameter)
} else if let ott = items?.first(where: { $0.name == "one_time_token" })?.value {
// send `ott` to your backend, then continue the flow in the SDK
}
return true
}
```
```dart Flutter theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
Future _handleDeepLink(Uri uri) async {
await Yuno.receiveDeeplink(url: uri); // closes the Passkey browser
if (uri.queryParameters.containsKey('has_error')) {
// handle error (read the `message` parameter)
} else {
final ott = uri.queryParameters['one_time_token'];
if (ott != null) {
// send `ott` to your backend, then continue the flow in the SDK
}
}
}
```
```kotlin Android theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
val uri = intent.data ?: return
when {
uri.getBooleanQueryParameter("has_error", false) ->
showError(uri.getQueryParameter("message") ?: "Operation canceled")
uri.getQueryParameter("one_time_token") != null -> {
val ott = uri.getQueryParameter("one_time_token")
// send `ott` to your backend, then continue the flow in the SDK
}
}
}
```
# Direct Integration
Source: https://docs.y.uno/docs/wallets/google-pay/google-pay-direct-integration
Integrate Google Pay directly with Yuno's API by passing the encrypted payment token.
With Direct integration, you integrate with the Google Pay™ API on your frontend, obtain the encrypted payment token from Google, and pass it to Yuno's API for processing. This gives you full control over the Google Pay user experience.
**Workflow:** `DIRECT`
Not sure which integration to use? See the [Google Pay overview](/docs/google-pay#integration-options) to compare all three options.
## Requirements
Before starting, ensure you meet the [general Google Pay requirements](/docs/google-pay#requirements). Additionally, you need to register with the [Google Pay Business Console](https://pay.google.com/business/console) to obtain a Google merchant ID. Complete the console configuration by following these steps:
1. Complete the **Business Profile**
2. Review the information required in **Google Pay API** > **Integrate with your website**:
* Your website – This must exactly match the domain of your hosted checkout page (with or without "www")
* Integration type – **GATEWAY**
3. Screenshots:
* Payment method screen – Your hosted checkout page
* Google Pay API payment screen – The Google Pay payment sheet (shown after clicking the GPay button)
* Post-purchase screen – Transaction confirmation page
* Submit the screenshots, indicate that you have submitted the request, and share the merchantId (BCR)
Use the assigned Merchant ID to configure the Google Pay connection in the Yuno dashboard.
## Integration
To integrate Google Pay with Yuno, follow these steps:
1. In the [Yuno dashboard](https://dashboard.y.uno/), go to the Connections tab. Find Google Pay and click Connect. Enter your credentials in the side panel. Choose a name for the connection and use the merchant ID obtained from the [Google Pay Business Console](https://pay.google.com/business/console) in the Merchant ID field.
2. Create a route in Yuno's dashboard using the processor you want for Google Pay payments. See the [Configure dynamic routing](/docs/routing#configuring-the-dynamic-routing) guide for more information.
Yuno processes the payment token received from Google Pay through your configured payment processor. Google Pay transactions appear in your Yuno dashboard alongside your other payment methods.
## Enable and test Google Pay with Yuno
After integrating, you can enable and test Google Pay with Yuno as follows:
1. Create a Google Wallet Test Account:
* Visit the [Google Wallet Test Account Sign-In](https://accounts.google.com/InteractiveLogin/signinchooser?continue=https%3A%2F%2Fpay.google.com%2Fbusiness%2Fconsole%2F\&followup=https%3A%2F%2Fpay.google.com%2Fbusiness%2Fconsole%2F\&osid=1\&passive=1209600\&ifkv=AeDOFXjl_LLJZyuykU06uleha4p7uSXJNnLCv_n2jshX6QVJYCy9AKq3K28mIfpgyfS2NDHfimnAFg\&flowName=GlifWebSignIn\&flowEntry=ServiceLogin) page.
* If you do not have a Google account, create one to proceed.
* Once signed in, you will be redirected to the Google Wallet business console.
2. Access the Google Wallet API Section:
* In the Google Wallet business console, navigate to the API management or integration section (usually under developer or integration settings).
3. Select **Create a Pass** to enable **Demo Mode**:
* In the Google Wallet API section, find the option labeled **Create a Pass**.
* Click this option to enable **Demo mode**. This allows you to simulate and test pass creation and interactions without real transactions.
4. Download the [Google Wallet App](https://play.google.com/store/apps/details?id=com.google.android.apps.walletnfcrel\&hl=en\&gl=US) from the Play Store.
5. Go through the payment flow to test the integration.
By following these steps, you can ensure Google Pay is integrated and working as expected before making it available to your customers.
## Go live
After completing all integration steps in the testing environment, request [Google Production Access](https://developers.google.com/pay/api/web/guides/test-and-deploy/request-prod-access) and contact your Technical Account Manager. The Yuno team will help verify your configuration and confirm you are ready to go live.
## Implementation details
Key details for your Google Pay integration with Yuno:
### Google Pay API authorization methods
Yuno supports both Google Pay API authorization methods:
* **`PAN_ONLY`**: Card credentials stored in the user's Google account. When used, Yuno automatically handles 3D Secure authentication if enabled.
* **`CRYPTOGRAM_3DS`**: Device-based card credentials with built-in authentication. These credentials include cryptographic authentication and don't require additional 3DS processing. These credentials decrypt to a device-specific number (DPAN), so see [Card last four digits for device tokens](#card-last-four-digits-for-device-tokens) if you display the card's last four digits to the cardholder.
Both methods are supported globally across all countries where Yuno operates. On the frontend, include both `PAN_ONLY` and `CRYPTOGRAM_3DS` in your `allowedAuthMethods` array for maximum payment success rates.
* **3D Secure (3DS) for`PAN_ONLY` credentials**: If Google Pay returns a `PAN_ONLY` credential (a card stored in the user's Google account), Yuno will automatically handle the 3D Secure authentication flow if 3DS is enabled. On the frontend, make sure your Google Pay API request includes `PAN_ONLY` in the `allowedAuthMethods` array.
* **Gateway and GatewayMerchantID configuration**: When registering with the [Google Pay Business Console](https://pay.google.com/business/console), ensure that under **Google Pay API** > **Integrate with your website**, the **Integration type** is set to **GATEWAY**. The `Merchant ID` from the Google Pay Business Console is used in the "Merchant ID" field when setting up the Google Pay connection in the Yuno dashboard. Set `gateway` to `yuno` and use your assigned Merchant ID as the `gatewayMerchantId` in your Google Pay API configuration.
* **Authorization methods**: Yuno supports standard authorization methods (purchase, authorization, capture). Availability depends on the payment processor and acquiring bank for each country and payment.
* **Billing address requirements**: If your payment processing requires the customer's billing address (for example, for AVS checks), configure this in your Google Pay API request. Google provides `BillingAddressParameters` to specify the required detail (for example, MIN or FULL). See [Google's documentation](https://developers.google.com/pay/api/web/reference/request-objects#BillingAddressParameters). Only request billing address details if necessary, as this can increase checkout friction.
* **Transaction data and payment cryptography**: Merchants integrate Yuno's SDKs (Android, iOS, Web) into their applications. When a customer chooses Google Pay, Yuno's SDK interacts with the Google Pay API and securely receives the encrypted payment data (payment token) from Google. This token is passed from your app to your backend server, which then uses Yuno's server-side APIs to submit the token for payment processing. Yuno handles decryption and processing with the payment processor.
## Pass Google Pay payment token in request
**Important: ECv2 Protocol Version Required (Android SDK v2.8.0+)**
Starting from Yuno Android SDK version 2.8.0, only Google Pay's ECv2 (Encrypted Card Version 2) protocol is supported. If your Google Pay integration is configured to use ECv1, payments will not be processed correctly.
Please ensure your Google Pay API configuration includes `"protocolVersion": "ECv2"` in the tokenization specification. ECv1 has been deprecated by Google and is no longer supported by Yuno's SDK.
If you are upgrading from a version prior to 2.8.0 or migrating from a custom SDK build, verify that your Google Pay merchant configuration uses ECv2 before processing payments. For guidance on updating your Google Pay configuration, refer to [Google's documentation](https://developers.google.com/pay/api/android/guides/resources/payment-data-cryptography#encrypted-card-version).
When you initiate a transaction with Google Pay, a payment token containing encrypted payment data is returned. Pass the complete token received from Google Pay in the `payment_method.detail.wallet.payment_token` field as a JSON string in your payment request.
### Google Pay wallet response object
The Google Pay SDK returns the following object structure, which must be passed as the complete `payment_token` value:
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"signature": "MEQCIBvkZdkroLuBAj0K0yhqF4RfvkcWM8hW4nInpGnbSbqHAiA4emX0LkHkdnYqIiGgAQ+gF2Md5ac1DIsHItwJfwj9DQ==",
"intermediateSigningKey": {
"signedKey": "{\"keyValue\":\"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEZ8tVNZqE1G6292tV11Ff1Pc1xZDZU9Mj5QSqDaU9hMjaH+CYI7+XL+Cor0X+4r0jICgcZgQkS/q+WzY8Eku1Fg==\",\"keyExpiration\":\"1766083480615\"}",
"signatures": [
"MEYCIQC75wFVZ3JkWTZenVvU9WVdWzeKUvTiB2FAGtUjIP6qFgIhAP3nB97NF+2lXsqpflH/livwpy24IPSfWMF7i1pHqrw1"
]
},
"protocolVersion": "ECv2",
"signedMessage": "{\n \"encryptedMessage\": \"Fvw/m1KNUIAXRRd6gbbuH2eWEhARKpQL/WZBJF5GCWE9QTuJf15pJUASEIjooQa36AwbGuSUs5qtm36x/yWe8pGi4w2vNyN+bUcnw4HuxrhrPMD+VoioLwmJenHU7/ypW5wzGfOmaCWn3FQ8GjE59mfFtC+8+LPmt3Z9xcvr/wT4Qm09TNRp3k/4/6JaV2+OTYqeOER6pAvqb7WEEjRLjIapvAYKPE6VXrhIo5zdwGh2VWvxY000nkzEIbn3OKShJ/mT7ITLQF9b5J4caGGRVFBn2oobaO72I8CCpiTAWgsw3GnyQACk9ggqnXOugVWinFDDazcs0q2YF3x6fBjz8sJpODx1dTUPrOacvFzEJ9XPovYooYK3wDiRfrtwqoadG/SYlESoguIuuAx+XOdc1jP+NWy0WDVKIqAJOwsg5qkSvNS2qi3m7SKapX3EVLiw/619l9JpTIRHdiIIeOu5BtFYL86o4yb0plrE8/ivvQ2/7U4ISGxzaJ4o6PFk7RZ96nWafdT0m30JlxMmTOI6iUOtsw02SVtinwS+83xcN3s6XRAPWRjJ0d1kaUd/4kHbPy8S/UKNBjanytDwDzn6wEccluisI4E=\",\n \"ephemeralPublicKey\": \"BPUzeogQZAp0N4D3vLYrvQ7Hc+fc261ZW17LIoMnIAgcWaANAhM39Z8mDCYxpiNIO/F0WtOkJhcvVZFSnI/yq/w=\",\n \"tag\": \"owzrWByO1bNLbw9m/G2kzGmWDnBCs7QoMN+N0zovZAo=\"\n}"
}
```
### Request example
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"account_id": "d34257e7-55d4-44cf-8b90-3a5152bbe020",
"description": "Google Pay test",
"merchant_order_id": "MER01",
"country": "US",
"amount": {
"currency": "USD",
"value": 1
},
"customer_payer": {
"email": "testing@y.uno"
},
"workflow": "DIRECT",
"payment_method": {
"detail": {
"wallet": {
"payment_token": "{\"signature\":\"MEQCIBvkZdkroLuBAj0K0yhqF4RfvkcWM8hW4nInpGnbSbqHAiA4emX0LkHkdnYqIiGgAQ+gF2Md5ac1DIsHItwJfwj9DQ\\u003d\\u003d\",\"intermediateSigningKey\":{\"signedKey\":\"{\\\"keyValue\\\":\\\"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEZ8tVNZqE1G6292tV11Ff1Pc1xZDZU9Mj5QSqDaU9hMjaH+CYI7+XL+Cor0X+4r0jICgcZgQkS/q+WzY8Eku1Fg\\\\u003d\\\\u003d\\\",\\\"keyExpiration\\\":\\\"1766083480615\\\"}\",\"signatures\":[\"MEYCIQC75wFVZ3JkWTZenVvU9WVdWzeKUvTiB2FAGtUjIP6qFgIhAP3nB97NF+2lXsqpflH/livwpy24IPSfWMF7i1pHqrw1\"]},\"protocolVersion\":\"ECv2\",\"signedMessage\":\"{\\\"encryptedMessage\\\":\\\"Fvw/m1KNUIAXRRd6gbbuH2eWEhARKpQL/WZBJF5GCWE9QTuJf15pJUASEIjooQa36AwbGuSUs5qtm36x/yWe8pGi4w2vNyN+bUcnw4HuxrhrPMD+VoioLwmJenHU7/ypW5wzGfOmaCWn3FQ8GjE59mfFtC+8+LPmt3Z9xcvr/wT4Qm09TNRp3k/4/6JaV2+OTYqeOER6pAvqb7WEEjRLjIapvAYKPE6VXrhIo5zdwGh2VWvxY000nkzEIbn3OKShJ/mT7ITLQF9b5J4caGGRVFBn2oobaO72I8CCpiTAWgsw3GnyQACk9ggqnXOugVWinFDDazcs0q2YF3x6fBjz8sJpODx1dTUPrOacvFzEJ9XPovYooYK3wDiRfrtwqoadG/SYlESoguIuuAx+XOdc1jP+NWy0WDVKIqAJOwsg5qkSvNS2qi3m7SKapX3EVLiw/619l9JpTIRHdiIIeOu5BtFYL86o4yb0plrE8/ivvQ2/7U4ISGxzaJ4o6PFk7RZ96nWafdT0m30JlxMmTOI6iUOtsw02SVtinwS+83xcN3s6XRAPWRjJ0d1kaUd/4kHbPy8S/UKNBjanytDwDzn6wEccluisI4E\\\\u003d\\\",\\\"ephemeralPublicKey\\\":\\\"BPUzeogQZAp0N4D3vLYrvQ7Hc+fc261ZW17LIoMnIAgcWaANAhM39Z8mDCYxpiNIO/F0WtOkJhcvVZFSnI/yq/w\\\\u003d\\\",\\\"tag\\\":\\\"owzrWByO1bNLbw9m/G2kzGmWDnBCs7QoMN+N0zovZAo\\\\u003d\\\"}\"}"
}
},
"type": "GOOGLE_PAY"
}
}
```
## Card last four digits for device tokens
When Google Pay returns a `CRYPTOGRAM_3DS` credential, the encrypted token decrypts to the **DPAN** — a device-specific number, not the card stored by the cardholder. Its last four digits are not the ones the cardholder recognizes, so `card_data.lfd` in the payment response is empty or shows the DPAN's last four.
The real card's last four digits are available to you in Google's response, outside the encrypted token:
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"paymentMethodData": {
"info": {
"cardDetails": "1515",
"cardNetwork": "VISA"
},
"tokenizationData": {
"token": "..."
}
}
}
```
Send `paymentMethodData.info.cardDetails` as `payment_method.detail.wallet.card_data.lfd` and Yuno uses it in place of the DPAN-derived value.
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"payment_method": {
"type": "GOOGLE_PAY",
"detail": {
"wallet": {
"payment_token": "{\"protocolVersion\":\"ECv2\", ...}",
"card_data": {
"lfd": "1515"
}
}
}
}
}
```
| Field | Type | Required | Description |
| :---- | :----- | :------- | :--------------------------------------------------------------------------------------------------------------------------------- |
| `lfd` | string | No | Last four digits of the cardholder's real card, taken from `paymentMethodData.info.cardDetails`. Must be exactly 4 numeric digits. |
The field is optional and backward compatible. If you do not send it, behavior is unchanged.
* Yuno applies the value only when the token is a device token — `auth_method` is `CRYPTOGRAM_3DS`, or `pan_type` is `DPAN` when `auth_method` is absent.
* `PAN_ONLY` credentials ignore the value. Those decrypt to the real card, so Yuno keeps the decrypted last four.
* Only `lfd` is accepted. `brand` and the remaining card fields keep their decrypted values, because the DPAN's BIN already identifies the card network correctly.
* The value is ignored for other wallets, such as Apple Pay.
Once applied, the value appears in the create payment response, in the Get payment by ID response, and in payment webhooks, under `payment_method.detail.card.card_data.lfd`. Webhook payloads nest it under `payment_method_detail` instead of `detail`.
If `lfd` is present but is not exactly 4 numeric digits, the request is rejected:
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"code": "INVALID_REQUEST",
"messages": [
"Invalid Request. payment_method.detail.wallet.card_data.lfd must be exactly 4 numeric digits."
]
}
```
## Related documentation
* [Google Pay overview](/docs/google-pay)
* [Google Pay SDK integration](/docs/google-pay-sdk-integration)
* [Google Pay via provider](/docs/integration-via-provider-google-pay)
* [Google Pay with PIX](/docs/google-pay-with-pix)
# SDK Integration
Source: https://docs.y.uno/docs/wallets/google-pay/google-pay-sdk-integration
Integrate Google Pay one-time and recurring payments using Yuno's SDK and checkout sessions.
This guide covers how to integrate Google Pay™ with Yuno using the SDK. With this approach, Yuno's SDK manages the complete Google Pay experience: displaying the Google Pay button, presenting the payment sheet, and handling the payment token. You don't need to integrate directly with the Google Pay API.
Before implementing, review the [Google Pay requirements](/docs/google-pay#requirements) and ensure Google Pay is available in your operating countries.
## Integration flow
1. Create a checkout session with Yuno.
2. Initialize Yuno's SDK in your app (Web, Android, or iOS).
3. The SDK displays the Google Pay button and handles the payment sheet.
4. The customer authorizes the payment through Google Pay.
5. Yuno receives the payment token and processes the transaction with your configured provider.
6. Monitor the payment status via [webhooks](/docs/webhooks).
## Requirements
* A Yuno account with API credentials ([Dashboard](https://dashboard.y.uno/))
* A payment provider connection configured in the Yuno dashboard that supports Google Pay
* A routing rule that includes the Google Pay payment method
* Yuno SDK integrated in your app ([Web](/docs/sdks/resources/references/web), [Android](/docs/sdks/resources/references/android), or [iOS](/docs/sdks/resources/references/ios))
## Integration steps
### Step 1: Create a checkout session
Use the [create checkout session](/reference/create-checkout-session) endpoint to start a payment session:
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"country": "US",
"customer_id": "customer-uuid",
"merchant_order_id": "order-123",
"payment_description": "Google Pay payment",
"amount": {
"currency": "USD",
"value": 5000
}
}
```
The response returns a `checkout_session` ID to initialize the SDK.
### Step 2: Initialize the SDK
Initialize Yuno's SDK with the checkout session. The SDK automatically detects available payment methods, including Google Pay, based on your dashboard configuration.
Refer to the SDK documentation for your platform:
* [Web SDK integration](/docs/sdks/full-checkout/web-payments)
* [Android SDK integration](/docs/sdks/full-checkout/android-payments)
* [iOS SDK integration](/docs/sdks/full-checkout/ios-payments)
### Step 3: Customer completes payment
The SDK handles the rest. When the customer selects Google Pay:
1. The Google Pay payment sheet appears with the customer's saved cards.
2. The customer selects a card and authorizes the payment.
3. The SDK sends the encrypted payment token to Yuno.
4. Yuno processes the payment through your configured provider.
### Step 4: Handle the response
The SDK returns the payment result. You can also monitor payment status through [webhooks](/docs/webhooks) for asynchronous confirmation.
## Create a payment with the SDK workflow
If you need to call the payment API directly while using the SDK checkout flow, set the `workflow` to `SDK_CHECKOUT` and include the checkout session:
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"account_id": "your-account-id",
"description": "Google Pay via SDK",
"merchant_order_id": "order-123",
"country": "US",
"amount": {
"currency": "USD",
"value": 5000
},
"checkout": {
"session": "checkout-session-id"
},
"customer_payer": {
"id": "customer-uuid",
"email": "customer@example.com"
},
"payment_method": {
"type": "GOOGLE_PAY"
},
"workflow": "SDK_CHECKOUT"
}
```
When integrating wallets like Google Pay, the `payment_method.type` field is required even when using the SDK workflow. Set it to `GOOGLE_PAY`.
## Enable and test Google Pay
To test Google Pay in sandbox:
1. Integrate [Yuno's SDK](/docs/sdks/full-checkout/android-payments) into your app.
2. Create a Google test account and sign in to the [Google Pay Business Console](https://pay.google.com/business/console).
3. In the Google Pay Business Console, navigate to the API section and select **Create a Pass** to enable **Demo mode**.
4. Download the [Google Wallet App](https://play.google.com/store/apps/details?id=com.google.android.apps.walletnfcrel\&hl=en\&gl=US) on your test device.
5. Run through the payment flow to verify the integration works.
## Go live
After testing, request [Google Production Access](https://developers.google.com/pay/api/web/guides/test-and-deploy/request-prod-access) and contact your Technical Account Manager. The Yuno team will verify your configuration before going live.
## Related documentation
* [Google Pay overview](/docs/google-pay)
* [Google Pay Direct integration](/docs/google-pay-direct-integration)
* [Google Pay via provider](/docs/integration-via-provider-google-pay)
* [Google Pay with PIX](/docs/google-pay-with-pix)
# Google Pay with PIX
Source: https://docs.y.uno/docs/wallets/google-pay/google-pay-with-pix
Explains how Google Pay presents PIX as an asynchronous payment option in Brazil.
In Brazil, Yuno supports Google Pay™ as an interface for PIX payments. Customers select Google Pay at checkout, and the payment is processed through PIX, Brazil's instant payment system. This combines the convenience of Google Pay's stored payment methods with PIX's real-time settlement.
Google Pay with PIX is available only in Brazil, with transactions in BRL (Brazilian Real).
## What is Google Pay PIX
Google Pay PIX uses **Open Finance** to enable PIX payments through the Google Pay wallet. Instead of opening their banking app to complete a PIX transfer, customers can pay directly from their Google Wallet, making the checkout experience faster and more convenient.
To pay with Google Pay PIX, the end customer must first configure a bank account for PIX payments inside their Google Wallet. Google provides setup instructions at [Set up PIX in Google Wallet](https://support.google.com/wallet/answer/14600929?hl=pt-BR).
## How it works
From the merchant's perspective, a Google Pay + PIX payment behaves like a standard asynchronous PIX payment, even though the customer starts in Google Pay.
1. The customer selects Google Pay at checkout.
2. Google Pay presents PIX as a payment option within the Google Pay payment sheet.
3. The customer selects a bank or credential that can initiate a PIX transfer and authorizes the payment.
4. Yuno creates the payment in `PENDING` status and returns the standard PIX artifacts (QR code, copy-and-paste code, or deeplink) depending on the provider and configuration.
5. The customer completes the PIX transfer through their bank.
6. The bank confirms the transfer to the provider, which notifies Yuno.
7. Yuno updates the payment status to `SUCCEEDED` and fires a webhook.
```mermaid theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
sequenceDiagram
participant Customer
participant GooglePay as Google Pay
participant Merchant
participant Yuno
participant Provider
participant Bank
Customer->>GooglePay: Selects Google Pay
GooglePay->>Customer: Shows PIX option
Customer->>GooglePay: Authorizes PIX payment
GooglePay->>Merchant: Returns payment data
Merchant->>Yuno: Creates payment
Yuno->>Provider: Routes PIX payment
Provider-->>Yuno: Returns PIX artifacts
Yuno-->>Merchant: Payment PENDING + PIX artifacts
Merchant-->>Customer: Displays QR code / instructions
Customer->>Bank: Completes PIX transfer
Bank->>Provider: Confirms transfer
Provider->>Yuno: Payment confirmed
Yuno->>Merchant: Webhook: SUCCEEDED
```
## Supported providers
Google Pay PIX is currently available through the following providers:
* **Adyen**
* **Santander**
* **Itau**
For other providers, contact your Yuno account manager to discuss availability and prioritize integration.
## Requirements
* A Yuno account with a connection to a [supported provider](#supported-providers)
* Transactions must be in **BRL** (Brazilian Real)
* The customer must have a bank account configured for PIX in their [Google Wallet](https://support.google.com/wallet/answer/14600929?hl=pt-BR)
## Integration
Google Pay with PIX follows the same integration patterns as Google Pay with card payments. Choose the integration method that fits your architecture:
* **[SDK integration](/docs/google-pay-sdk-integration)**: Yuno's SDK handles the full flow, including presenting PIX as an option within Google Pay.
* **[Direct integration](/docs/google-pay-direct-integration)**: You manage the Google Pay frontend and pass the PIX payment token to Yuno.
* **[Provider integration](/docs/integration-via-provider-google-pay)**: Your payment provider handles the Google Pay + PIX flow.
When creating the payment, set the `payment_method.type` to `GOOGLE_PAY_PIX`. This tells Yuno the payment is a PIX transaction initiated through Google Pay.
## Payment request
Create a payment using the `GOOGLE_PAY_PIX` payment method type. Set the country to `BR` and the currency to `BRL`:
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"account_id": "your-account-id",
"description": "Google Pay PIX payment",
"merchant_order_id": "order-456",
"country": "BR",
"amount": {
"currency": "BRL",
"value": 5000
},
"customer_payer": {
"email": "customer@example.com"
},
"payment_method": {
"type": "GOOGLE_PAY_PIX"
}
}
```
For Google Pay PIX, use `payment_method.type = GOOGLE_PAY_PIX` instead of `GOOGLE_PAY`. This is different from Google Pay card payments, which use `GOOGLE_PAY`.
## Payment statuses
Google Pay with PIX is **asynchronous**. Unlike card payments through Google Pay, which typically resolve immediately, PIX payments go through a pending state while waiting for the bank transfer to complete.
| Status | Description |
| ----------- | ----------------------------------------------------------------- |
| `PENDING` | Payment created. The PIX transfer has not been completed yet. |
| `SUCCEEDED` | The bank confirmed the PIX transfer. Funds have settled. |
| `EXPIRED` | The PIX payment was not completed before the expiration deadline. |
| `DECLINED` | The payment was declined by the provider or bank. |
### Status lifecycle
```mermaid theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
stateDiagram-v2
[*] --> PENDING: Payment created
PENDING --> SUCCEEDED: Bank confirms PIX transfer
PENDING --> EXPIRED: PIX expiration deadline reached
PENDING --> DECLINED: Provider/bank declines
SUCCEEDED --> [*]
EXPIRED --> [*]
DECLINED --> [*]
```
## Handling user cancellation
If the customer closes the Google Pay sheet or the PIX instructions screen before completing the bank transfer:
* The **frontend/SDK** reports that the user left the flow (for example, the SDK returns a user-cancelled status).
* The **payment in the API remains `PENDING`**. The PIX reference is still valid and the customer can still complete the transfer from their bank app.
* The PIX payment only moves to `EXPIRED` when the expiration deadline is reached, not when the user closes the UI.
Your checkout should handle this by:
1. **Re-displaying the PIX instructions** if the customer returns to the same session, since the PIX reference is still valid.
2. **Letting the customer pay later** if your UX supports it. The PIX code remains active until it expires.
3. **Polling the payment status** via `GET /v1/payments/{id}` or listening for webhooks to detect when the transfer completes.
## Webhooks
Standard payment webhooks fire for all status transitions. The webhook payload follows the same structure as any other Yuno payment notification.
Monitor these events:
* **Payment succeeded**: The PIX transfer was completed. Update your order status and confirm to the customer.
* **Payment expired**: The PIX deadline passed without a transfer. Stop displaying the QR code or PIX instructions and prompt the customer to start a new payment.
See [Webhooks](/docs/webhooks) for configuration details.
## Differences from card payments
| Aspect | Google Pay with cards | Google Pay with PIX |
| ------------------------------ | -------------------------------- | --------------------------------------------- |
| Processing | Usually synchronous | Asynchronous (PENDING until bank confirms) |
| Settlement | Depends on provider and acquirer | Instant (PIX network) |
| Currency | Multiple currencies supported | BRL only |
| Country | Global availability | Brazil only |
| Refunds | Standard refund flow | PIX refund flow |
| Recurring payments | Supported via vaulted tokens | Not supported |
| Customer action after checkout | None required | Must complete PIX transfer via bank |
| Expiration | N/A | PIX reference expires per provider/Yuno rules |
## Related documentation
* [Google Pay overview](/docs/google-pay)
* [Google Pay SDK integration](/docs/google-pay-sdk-integration)
* [Google Pay Direct integration](/docs/google-pay-direct-integration)
* [Google Pay via provider](/docs/integration-via-provider-google-pay)
# Integration Via Provider
Source: https://docs.y.uno/docs/wallets/google-pay/integration-via-provider-google-pay
Integrate Google Pay through a payment provider that manages token decryption and processing.
With provider integration, Google Pay™ is handled entirely by your payment provider (for example, Adyen, Cielo). Yuno routes the transaction to the provider, which manages the Google Pay token decryption and processing. Card data does not pass through Yuno in this flow.
This is ideal if you are already using a provider's Google Pay solution or if the provider manages the Google Pay certification process on your behalf.
Not sure which integration to use? See the [Google Pay overview](/docs/google-pay#integration-options) to compare all three options.
## Requirements
Ensure you meet the [general Google Pay requirements](/docs/google-pay#requirements).
## Providers
To incorporate Google Pay into your system using Yuno, select one provider supporting this payment method first.
You must have credentials to connect to the selected provider using [Yuno dashboard](https://dashboard.y.uno/) before integrating Google Pay.
## Integration
You need to cover some steps to integrate Google Pay into your system using Yuno.
1. First, you will review Google’s approval process for [Android devices](https://developers.google.com/pay/api/android/overview) or [Google Pay on the Web](https://developers.google.com/pay/api/web/overview).
1. Start by checking the Terms of Service and Acceptable Use Policy.
2. Complete the tutorials and integration checklist.
3. Complete the integration checklist for [Android](https://developers.google.com/pay/api/android/guides/test-and-deploy/integration-checklist) or [Web](https://developers.google.com/pay/api/web/guides/test-and-deploy/integration-checklist) before requesting production credentials from Google.
4. Finally, you will request your production access.
2. Get the developer credentials from the provider you choose to start using with Yuno.
**Adyen Connection**
For Adyen, merchants need to create a [testing account](https://www.adyen.com/signup) and get a **Merchant Account** and a **x-api-key**.
1. Within the [Yuno dashboard](https://dashboard.y.uno/), select the **Connections** tab. Find the provider you choose and click **Connect**. Fulfill the side panel fields with your credentials. Below, you will find examples of connecting panels for Adyen and Cielo.
4. Create a route in Yuno's dashboard using the gateway you have connected. Access the [Configure dynamic routing](/docs/routing#configuring-the-dynamic-routing) guide page for further information on creating routes.
## Enable and test Google Pay with Yuno
After performing the integration on Yuno, you can enable Google Pay with Yuno and perform integration tests using the following steps:
1. First, integrate [Yuno's SDK](/docs/sdks/full-checkout/android-payments) into your app.
2. Create a Google Wallet Test Account:
1. Visit the [Google Wallet Test Account Sign-In](https://accounts.google.com/InteractiveLogin/signinchooser?continue=https%3A%2F%2Fpay.google.com%2Fbusiness%2Fconsole%2F\&followup=https%3A%2F%2Fpay.google.com%2Fbusiness%2Fconsole%2F\&osid=1\&passive=1209600\&ifkv=AeDOFXjl_LLJZyuykU06uleha4p7uSXJNnLCv_n2jshX6QVJYCy9AKq3K28mIfpgyfS2NDHfimnAFg\&flowName=GlifWebSignIn\&flowEntry=ServiceLogin) page.
2. If you don't have a Google account, you'll need to create one to proceed.
3. Once signed in, you'll be redirected to the Google Wallet business console.
3. Access the Google Wallet API Section:
1. In the Google Wallet business console, navigate to the section related to API management or integration. It is found in the developer or integration settings.
4. Select **Create a Pass** to Enable **Demo Mode**:
1. Within the Google Wallet API section, locate the option labeled **Create a Pass**.
2. Click on this option to enable **Demo mode**. This mode allows you to simulate and test pass creation and interactions without making real transactions.
5. Download the Google Wallet App from the Play Store.
6. Navigate through the payment flow to test the integration.
Following these steps, you can ensure that Google Pay is integrated into your app and works as expected before making it available for your customers.
## Implementation details
Yuno supports both Google Pay API authorization methods:
* **`PAN_ONLY`**: Card credentials stored in the user's Google account. When used, the selected provider handles authentication as configured.
* **`CRYPTOGRAM_3DS`**: Device-based card credentials with built-in authentication. These credentials include cryptographic authentication.
Both methods are supported globally across all countries where Yuno operates. On the frontend, include both `PAN_ONLY` and `CRYPTOGRAM_3DS` in your `allowedAuthMethods` array for maximum payment success rates.
* **Provider-specific configuration**: The handling of Google Pay authorization methods may vary depending on your selected provider. Consult your provider's documentation for specific requirements and capabilities regarding `PAN_ONLY` and `CRYPTOGRAM_3DS` processing.
## Related documentation
* [Google Pay overview](/docs/google-pay)
* [Google Pay SDK integration](/docs/google-pay-sdk-integration)
* [Google Pay Direct integration](/docs/google-pay-direct-integration)
* [Google Pay with PIX](/docs/google-pay-with-pix)
# Wallets Overview
Source: https://docs.y.uno/docs/wallets/index
Lists the wallet connections available on Yuno, including Apple Pay, Google Pay, Click to Pay, and NuPay.
Here you find the complete list of Wallets' connections available on Yuno. Wallets let your customers use the stored cards they have with different providers. Select the desired wallet to access more information.
# NuPay
Source: https://docs.y.uno/docs/wallets/nupay
Accept payments with NuPay, the digital payment method from NuBank, using either Yuno's SDK or Direct API workflows for one-time payments, enrollment, and 2FA mode.
This guide explores how to integrate NuPay, the digital payment method from NuBank, into your checkout. Yuno supports both the **Yuno SDK** (recommended) and **Direct API** workflows. You'll learn how to:
* Enroll NuPay as a customer payment method
* Make payments without enrollment (2FA mode)
* Make payments with installments (payment conditions)
* Set up subscriptions
## Requirements
Before starting, you need:
* A Yuno account with Dashboard access
* API keys and an `account_id` (found in the dashboard)
* A customer created in Yuno (or create one in Step 1)
## Create and manage customers
Create the customer once using your external `merchant_customer_id`, then retrieve by Yuno `id` or by `merchant_customer_id` as needed.
1. Use the [Create Customer](/reference/create-customer) endpoint and provide your own `merchant_customer_id` (the unique id of the customer in your system). The response returns `id` which is the Yuno customer id.
2. Use [Retrieve Customer](/reference/retrieve-customer) with the Yuno `id`.
3. Use [Retrieve Customer by External Id](/reference/retrieve-customer-by-external-id) with query parameter `merchant_customer_id`.
## Enroll NuPay payment method
Follow the steps below to enroll the `NU_PAY_ENROLLMENT` payment method to a customer.
With the SDK integration, Yuno handles displaying the NuPay payment method, redirecting the customer to NuBank for authentication, and managing the return flow.
### Step 1: Create a customer
Create a customer and obtain their Yuno customer `id` using the [Create Customer](/reference/create-customer) endpoint.
### Step 2: Create a customer session
Use the customer `id` and the [Create Customer Session](/reference/create-customer-session) endpoint to receive a `customer_session`.
### Step 3: Initialize the SDK and enroll
Initialize Yuno's SDK (Web, Android, or iOS) with the `customer_session`.
If using the SDK checkout or headless integration, call [Enroll Payment Method (Checkout)](/reference/enroll-payment-method-checkout) (`POST /customers/sessions/{customer_session}/payment-methods`) with `payment_method_type`: `NU_PAY_ENROLLMENT`.
The SDK automatically displays the NuPay payment method, manages the customer redirection to NuBank, and handles the authentication flow.
### Step 4: Confirm enrollment
Listen to [webhooks](/docs/webhooks) or retrieve enrolled payment methods to verify the status is `ENROLLED`.
Follow these steps to enroll `NU_PAY_ENROLLMENT` to a customer using the Direct workflow.
### Step 1: Create a customer
If you don't have a customer yet, create one as shown above. You'll use the returned customer `id`.
### Step 2: Enroll the payment method
Use [Enroll Payment Method](/reference/enroll-payment-method-api) with the following request parameters:
* **type**: `NU_PAY_ENROLLMENT`
* **account\_id**: UUID of your account (from the Yuno Dashboard)
* **workflow**: `DIRECT`
Expected response fields:
* **vaulted\_token**: UUID for the enrolled payment method
* **status**: `READY_TO_ENROLL`
* **sub\_status**: `WAITING_ADDITIONAL_STEP`
* **action**: `REDIRECT_URL`
* **redirect\_url**: URL to redirect the customer to Nu for authentication
### Step 3: Redirect the customer
Redirect the customer to the `redirect_url`. The customer completes the Nu flow. Nu notifies Yuno of the final state.
### Step 4: Confirm enrollment
Use [Retrieve Enrolled Payment Method by id](/reference/retrieve-enrolled-payment-method-by-id-api) with the `vaulted_token`. A successful enrollment returns:
* **status**: `ENROLLED`
* **sub\_status**: `ENROLLED`
The enrollment is only complete after Yuno receives Nu’s confirmation.
## Payments without enrollment (2FA mode)
You can accept one-time payments with NuPay without requiring the customer to enroll their payment method. This is often referred to as **2FA mode**, as the customer authenticates each transaction individually.
Accept payments without enrollment using Yuno's SDK. The SDK handles displaying NuPay and redirecting the customer to complete the authentication.
### Step 1: Create a checkout session
Start by creating a checkout session using the [Create Checkout Session](/reference/create-checkout-session) endpoint.
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"country": "BR",
"customer_id": "{{customer_id}}",
"merchant_order_id": "order-0000024",
"amount": {
"currency": "BRL",
"value": 15000
}
}
```
The response returns a `checkout_session` ID.
### Step 2: Initialize the SDK
Initialize Yuno's SDK (Web, Android, or iOS) with the `checkout_session` ID. NuPay will automatically render as an available payment option in the SDK interface.
### Step 3: Customer completes payment
When the customer selects NuPay:
1. The SDK prompts the customer for authentication.
2. The customer is redirected to Nu for 2FA authentication.
3. The SDK receives the result and processes the payment through Yuno.
### Step 4: Handle SDK workflow payments (Optional)
If you are calling the Yuno payments API directly while using the SDK checkout, set the `workflow` to `SDK_CHECKOUT` and pass the `checkout.session` token:
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"description": "One-time NuPay Payment via SDK",
"account_id": "{{account_id}}",
"merchant_order_id": "0000024",
"country": "BR",
"amount": {
"currency": "BRL",
"value": 150
},
"customer_payer": {
"id": "{{customer_id}}"
},
"workflow": "SDK_CHECKOUT",
"checkout": {
"session": "{{checkout_session_id}}"
},
"payment_method": {
"type": "NU_PAY"
}
}
```
### Step 1: Create a payment
Use [Create payment](/reference/create-payment) with the Direct workflow and the `NU_PAY` payment method type. In this mode, you don't need a `vaulted_token`.
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"description": "One-time NuPay Payment",
"account_id": "{{account_id}}",
"merchant_order_id": "0000024",
"country": "BR",
"amount": {
"currency": "BRL",
"value": 150
},
"customer_payer": {
"id": "{{customer_id}}"
},
"workflow": "DIRECT",
"callback_url": "https://your-callback.com",
"payment_method": {
"type": "NU_PAY"
}
}
```
### Step 2: Handle the response
Since this mode requires customer authentication, the response will return an action to redirect the user.
* **status**: `READY_TO_PAY`
* **sub\_status**: `WAITING_ADDITIONAL_STEP`
* **action**: `REDIRECT_URL`
* **redirect\_url**: URL to redirect the customer to Nu for 2FA authentication.
### Step 3: Confirm payment
After the customer completes the authentication, use [Retrieve payment by id](/reference/retrieve-payment-by-id) to confirm the final status.
## Payments with payment conditions (installments)
NuPay supports installments for both enrolled payment methods and one-time payments (2FA mode).
NuPay supports installments for enrolled payment methods and one-time payments (2FA mode) within the SDK.
### Step 1: Get payment conditions
Request available installment options using the [APM installments](/reference/installments/apm-installments) endpoint, depending on the flow:
```bash theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
curl -X POST --location 'https://api-sandbox.y.uno/v1/apm-installments' \
--header 'public-api-key: {{your_public_api_key}}' \
--header 'private-secret-key: {{your_secret_api_key}}' \
--header 'X-account-code: {{your_account_code}}' \
--header 'Content-Type: application/json' \
--data '{
"country": "BR",
"amount": {
"currency": "BRL",
"value": "250"
},
"customer": {
"id": "{{customer_id}}"
},
"payment_method": "NU_PAY_ENROLLMENT",
"vaulted_token": "{{vaulted_token}}"
}'
```
```bash theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
curl -X POST --location 'https://api-sandbox.y.uno/v1/apm-installments' \
--header 'public-api-key: {{your_public_api_key}}' \
--header 'private-secret-key: {{your_secret_api_key}}' \
--header 'X-account-code: {{your_account_code}}' \
--header 'Content-Type: application/json' \
--data '{
"country": "BR",
"payment_method": "NU_PAY",
"amount": {
"currency": "BRL",
"value": "250"
},
"customer": {
"document": {
"document_type": "CPF",
"document_number": "12345678900"
},
"email": "customer@email.com"
}
}'
```
Select the plan `id` and installments number from the response.
### Step 2: Create payment using SDK workflow
Create the payment using the SDK workflow by setting `workflow: "SDK_CHECKOUT"` and passing the `checkout.session` along with the plan details:
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"description": "NuPay Installment Payment via SDK",
"account_id": "{{account_id}}",
"merchant_order_id": "0000023",
"country": "BR",
"amount": {
"currency": "BRL",
"value": 250
},
"customer_payer": {
"id": "{{customer_id}}"
},
"workflow": "SDK_CHECKOUT",
"checkout": {
"session": "{{checkout_session_id}}"
},
"payment_method": {
"type": "NU_PAY_ENROLLMENT",
"vaulted_token": "{{vaulted_token}}",
"detail": {
"wallet": {
"card_data": {
"installments_plan_id": "{{plan_id}}",
"installments": 2
}
}
}
}
}
```
### Step 1: Ensure prerequisites
Depending on the flow, you'll need:
* **Enrollment Flow**: A Yuno customer `id` and an enrolled NuPay `vaulted_token`.
* **2FA Mode**: Customer details, specifically their tax ID (CPF) and email.
### Step 2: Get payment conditions
Request available installment options for NuPay using the [APM installments](/reference/installments/apm-installments) endpoint. The request parameters vary based on the integration flow.
```bash theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
curl -X POST --location 'https://api-sandbox.y.uno/v1/apm-installments' \
--header 'public-api-key: {{your_public_api_key}}' \
--header 'private-secret-key: {{your_secret_api_key}}' \
--header 'X-account-code: {{your_account_code}}' \
--header 'Content-Type: application/json' \
--data '{
"country": "BR",
"amount": {
"currency": "BRL",
"value": "250"
},
"customer": {
"id": "{{customer_id}}"
},
"payment_method": "NU_PAY_ENROLLMENT",
"vaulted_token": "{{vaulted_token}}"
}'
```
```bash theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
curl -X POST --location 'https://api-sandbox.y.uno/v1/apm-installments' \
--header 'public-api-key: {{your_public_api_key}}' \
--header 'private-secret-key: {{your_secret_api_key}}' \
--header 'X-account-code: {{your_account_code}}' \
--header 'Content-Type: application/json' \
--data '{
"country": "BR",
"payment_method": "NU_PAY",
"amount": {
"currency": "BRL",
"value": "250"
},
"customer": {
"document": {
"document_type": "CPF",
"document_number": "12345678900"
},
"email": "customer@email.com"
}
}'
```
The response returns an array of installment plans, including `id`, available `installments`, and amounts. Select a plan `id` and an allowed installments number.
### Step 3: Create payment
Use [Create payment](/reference/create-payment) with the Direct workflow and NuPay type. Include the selected plan id and installments in the wallet `card_data`.
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"description": "test",
"account_id": "{{account_id}}",
"merchant_order_id": "0000023",
"country": "BR",
"merchant_reference": "ref-merchant-AA01",
"amount": {
"currency": "BRL",
"value": 250
},
"customer_payer": {
"id": "{{customer_id}}"
},
"workflow": "DIRECT",
"callback_url": "https://your-callback.com",
"payment_method": {
"type": "NU_PAY_ENROLLMENT",
"vaulted_token": "{{vaulted_token}}",
"detail": {
"wallet": {
"card_data": {
"installments_plan_id": "{{plan_id}}",
"installments": 2
}
}
}
}
}
```
### Step 4: Retrieve payment
Use [Retrieve payment by id](/reference/retrieve-payment-by-id) to confirm final status.
## Subscription flow
You can use NuPay for recurring charges.
Recurring payments/subscriptions with NuPay can be easily set up using the SDK enrollment token:
1. Create a customer.
2. Enroll NuPay via Yuno SDK (Checkout workflow) to obtain a `vaulted_token`.
3. Create a subscription with the enrolled `vaulted_token` using the [Create subscription](/reference/create-subscription) endpoint.
4. Retrieve and manage subscription state as needed.
1. Create a customer
2. Enroll NuPay as a payment method (see above)
3. Create a subscription with the enrolled `vaulted_token` using [Create subscription](/reference/create-subscription)
4. Retrieve the subscription using [Retrieve subscription](/reference/retrieve-subscription)
**Limitations**
* Subscriptions with NuPay do not support payment conditions (installments)
* Creating subscriptions directly within a payment request is not supported
## Endpoints
* [Create customer](/reference/create-customer)
* [Retrieve customer](/reference/retrieve-customer)
* [Retrieve customer by external id](/reference/retrieve-customer-by-external-id)
* [Enroll payment method (Direct)](/reference/enroll-payment-method-api)
* [Enroll payment method (Checkout)](/reference/enroll-payment-method-checkout)
* [Retrieve enrolled payment method by id](/reference/retrieve-enrolled-payment-method-by-id-api)
* [Create payment](/reference/create-payment)
* [Retrieve payment by id](/reference/retrieve-payment-by-id)
* [APM installments](/reference/installments/apm-installments)
* [Create subscription](/reference/create-subscription)
* [Retrieve subscription](/reference/retrieve-subscription)
# Configure Webhooks
Source: https://docs.y.uno/docs/webhooks/configure-webhooks
Sets up webhook endpoints, authentication, and trigger events from the Yuno Dashboard Developers tab
## Setup
You can also manage webhooks programmatically with the [Webhooks API](/reference/webhooks), which exposes the same configuration you set up here.
You can configure webhooks using the [Yuno dashboard](https://dashboard.y.uno/):
1. Navigate to the **Developers** tab
2. Click **Webhooks**
3. Click **Add webhook**
A sidebar will open where you'll configure:
* **Name**: Identify your webhook
* **Endpoint URL**: Your server URL to receive notifications
* **x-api-key**: Your API key (sent in notification headers)
* **x-secret**: Your secret (sent in notification headers)
* **Use OAuth2 Authentication**: Optional checkbox for OAuth2
* **Use HMAC Authentication**: Optional checkbox for HMAC signature verification
**Trigger on**: Select which events will trigger this webhook (enrollment, payment, subscription, etc.)
Once configured, the webhook will send notifications whenever the selected events occur. The image below shows the side panel to add a webhook.
In the [Yuno dashboard](https://dashboard.y.uno/) Developers tab, you can activate and deactivate webhooks using the **Status** toggle button.
Access the [Webhooks Examples](/docs/object-and-examples) page to check examples for payment, enrollment, and many other notification events.
### HMAC authentication
When you enable **Use HMAC Authentication** in the dashboard, you'll provide a client secret key. Yuno will use this key to generate an HMAC signature and send it in the `x-hmac-signature` HTTP header with each webhook request, allowing you to verify that webhooks genuinely come from Yuno and haven't been tampered with.
See the [Verify Webhook Signatures (HMAC)](/docs/verify-webhook-signatures-hmac) guide for implementation details.
### OAuth2
When you enable **Use OAuth2 Authentication** in the dashboard, you can configure the following parameters so Yuno can obtain the authorization token that will be sent in the webhook headers:
* `Authentication_url`: url to use for authentication
* `Credentials`: Necessary credentials to communicate with the authentication\_url.
* Client Secret\_key
* Client\_ID
* `Grant type`: Type of grant for the authentication.
## Receipt confirmation process
Yuno webhooks expect to receive an HTTP 200 OK status as a response to indicate that the webhook was received. The merchant system response does not need to provide any information on the body request, only the HTTP 200 status. In case of not receiving a response at the specified time, Yuno webhooks will send the event notification up to seven times to avoid information loss. The table below presents the webhooks notification schedule and the confirmation waiting time.
| Event | Deadline after the first try |
| :---------- | :--------------------------- |
| First try | - |
| Second try | 5 minutes |
| Third try | 50 minutes |
| Fourth try | 6 hours |
| Fifth try | 24 hours |
| Sixth try | 48 hours |
| Seventh try | 96 hours |
## Webhooks event types
Depending on the type of event, you will receive a different type of webhook and event. The next table presents the possible event types currently available.
| type | type\_event |
| :------------------------ | :--------------------------------- |
| enrollment | enroll |
| enrollment | unenroll |
| enrollment | expiration |
| enrollment | update |
| payment | purchase |
| payment | authorize |
| payment | capture |
| payment | refund |
| payment | cancel |
| payment | verify |
| payment | chargeback |
| payment | fraud\_screening |
| payout | payout |
| subscription | create |
| subscription | active |
| subscription | pause |
| subscription | resume |
| subscription | cancel |
| subscription | complete |
| subscription | close\_to\_renewal |
| subscription | plan\_change\_scheduled |
| subscription | plan\_change\_canceled |
| subscription | plan\_changed |
| onboarding | create |
| onboarding | pending |
| onboarding | pending\_additional\_documentation |
| onboarding | pending\_recipient\_action |
| onboarding | succeeded |
| onboarding | canceled |
| onboarding | declined |
| onboarding | rejected |
| onboarding | blocked |
| onboarding | unblocked |
| onboarding | error |
| onboarding | expired |
| onboarding | failed |
| split\_transfer | succeeded |
| split\_transfer | failed |
| split\_transfer\_reverse | succeeded |
| split\_transfer\_reverse | failed |
| banking.entity | created |
| banking.entity | updated |
| banking.entity | deleted |
| banking.onboarding | created |
| banking.onboarding | pending |
| banking.onboarding | pending\_additional\_documentation |
| banking.onboarding | succeeded |
| banking.onboarding | failed |
| banking.onboarding | declined |
| banking.onboarding | cancelled |
| banking.onboarding | expired |
| banking.account | created |
| banking.account | updated |
| banking.account | activated |
| banking.account | closed |
| banking.transfer | pending |
| banking.transfer | processing |
| banking.transfer | completed |
| banking.transfer | failed |
| banking.transfer | cancelled |
| banking.transfer | reversed |
| banking.transfer.incoming | pending |
| banking.transfer.incoming | completed |
> `subscription.active` is sent once, when the subscription first becomes active (at `billing_cycles.current` = 2); it is not re-sent on subsequent renewal cycles. Each renewal charge is delivered as a `payment.purchase` webhook (outcome in `status`/`sub_status`); `$0`/trial cycles emit none.
### Fraud Screening Webhook Behavior
When a transaction is declined by the fraud screening and doesn't move forward to processing with any provider, no transactions are created: the `transactions` array comes back empty. In this case, the only elements that get created are within the `fraud_screening` object, and the webhook that's triggered is `payment.fraud_screening`.
If due to the routing configuration the fraud screening declines but the transaction still proceeds to processing, the event sent to the client is `payment.purchase`.
# Webhooks Overview
Source: https://docs.y.uno/docs/webhooks/index
Summarizes webhook delivery, retry schedule, and event types across payments, subscriptions, payouts, and banking connectivity
## What is a webhook
Webhooks let your system receive real-time event notifications from Yuno through an HTTP POST, instead of polling for updates. After you configure your webhook endpoint, Yuno sends a notification every time a relevant event happens in the payment flow.
## Requirements
To use Yuno's webhooks, build a public REST API endpoint to receive event notifications (POST requests). This endpoint should not require authentication or access restrictions through a header. Despite being public, the endpoint stays secure: Yuno's event notifications aren't discoverable by the public and are sent to a unique URL known only to your system.
## Webhooks delivery and response requirements
Yuno webhooks expects to receive an **HTTP 200 OK** status as a response to confirm the webhook was successfully received. The merchant system does not need to include any information in the response's body. Only the HTTP 200 status is required.
If no response is received within the specified time, Yuno will retry sending the event notification up to seven times. Refer to the [Receipt Confirmation Process](/docs/webhooks/configure-webhooks#receipt-confirmation-process) section for details on the notification schedule and confirmation waiting times for each retry.
## De-duplication
Because Yuno retries delivery when it doesn't receive a confirmation, your endpoint can receive the same event more than once. This is expected behavior, not a bug: your integration should be able to identify and skip duplicates.
### The identifier
Every event payload includes `data.idempotency_key`. It stays stable across every retry of the same event, so you can use it to tell a duplicate delivery apart from a genuinely new event.
### Coverage
`data.idempotency_key` is currently included in:
* `payment` events
* `refund` events
* `chargeback` events
* `subscription` events
For `subscription.*` events the key identifies the **subscription**, not the event: it is the `X-Idempotency-Key` sent when the subscription was created, and it is repeated identically on every lifecycle event for that subscription. De-duplicate `subscription.*` events on `type_event` **plus** `data.idempotency_key` — matching on the key alone collapses every event for a subscription into one and silently drops `subscription.active`, `subscription.cancel` and the rest.
Support for `enrollment` events is planned but not yet available. Until then, enrollment payloads do not include `data.idempotency_key`.
### Why you might see the same event twice
Each payload also includes a top-level `retry` field with the number of delivery attempts made for that event (`0` on the first attempt). If your endpoint doesn't return an HTTP 200 OK in time, Yuno resends the same event (same `data.idempotency_key`, incremented `retry`) following the schedule described in [Webhooks delivery and response requirements](#webhooks-delivery-and-response-requirements) above. Treat any event whose `type_event` and idempotency key you've already processed as a duplicate, regardless of its `retry` value.
### Recommended handling
Store every `data.idempotency_key` you've successfully processed together with the event's `type_event`, and check incoming events against that store before acting on them:
```js theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
async function handleWebhookEvent(event) {
// Scope the key by event type: a subscription's key is the same on every
// one of its lifecycle events.
const key = `${event.type_event}:${event.data.idempotency_key}`;
if (await store.has(key)) {
// Already processed, acknowledge and skip.
return;
}
await processEvent(event);
await store.add(key);
}
```
Keep in mind that not every event type carries `data.idempotency_key` yet (see Coverage above). For event types without it, fall back to your own de-duplication key, such as the combination of resource ID and event type.
## Common Webhook Events
Yuno sends event notifications for various activities within the payment ecosystem. Below are the available event categories and their corresponding events.
### Payment events
| Event | Description |
| -------------------- | ------------------------------------------------------------------------------ |
| `payment.purchase` | Occurs when a payment is created or its status changes during a purchase flow. |
| `payment.chargeback` | Occurs when a chargeback or inquiry is received for a payment. |
### Refund events
| Event | Description |
| ---------------- | ------------------------------------------------ |
| `payment.refund` | Occurs when a refund is processed for a payment. |
### Subscription events
| Event | Description |
| ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `subscription.create` | Sent when a subscription is first created. |
| `subscription.active` | Sent once, when the subscription first becomes active (at `billing_cycles.current` = 2). Not re-sent on subsequent renewal cycles. |
| `subscription.pause` | Sent when a subscription is paused. |
| `subscription.resume` | Sent when a paused subscription is resumed. |
| `subscription.cancel` | Sent when a subscription is canceled. Once canceled it is terminated and cannot be reactivated. |
| `subscription.complete` | Sent when a subscription reaches its end date or total billing cycles and transitions to `COMPLETED`. |
| `subscription.close_to_renewal` | Sent ahead of an upcoming renewal. Timing is controlled by `renewal_notification_days`. |
| `subscription.plan_change_scheduled` | Sent when a plan change is scheduled for the next billing cycle via `PATCH /v1/subscriptions/{id}`. |
| `subscription.plan_change_canceled` | Sent when a pending plan change is undone by the merchant (`MERCHANT_UNDO`) or aborted because the target plan was canceled (`TARGET_PLAN_CANCELED`). Not sent when the subscription itself is canceled — only `subscription.cancel` fires then. |
| `subscription.plan_changed` | Sent when a plan change takes effect. A scheduled change is applied at the renewal that first bills the new plan and keeps the same subscription `code`. `POST /v1/subscriptions/{id}/plan` instead replaces the subscription: the payload carries a new `code` with `previous_subscription_id` set, and a separate `subscription.cancel` (`cancellation_source: PLAN_CHANGE`) fires for the original. |
Each renewal charge is delivered as a `payment.purchase` webhook tied to the subscription, with the outcome (success or decline) carried in the `status`/`sub_status` fields. `$0`/trial cycles emit no payment webhook, and there is currently no `subscription.error` event.
Treat the plan-change events as notifications, not as the source of truth. Reconcile against `GET /v1/subscriptions/{id}` — `pending_plan_change` for a scheduled change and `plan_id` for an applied one — rather than relying on webhook delivery alone.
### Enrollment events
| Event | Description |
| ------------------- | ----------------------------------------------------------------------------- |
| `enrollment.enroll` | Sent when a payment method is successfully enrolled. |
| `enrollment.update` | Sent when enrolled card details are updated (e.g., via Card Account Updater). |
### Payout events
| Event | Description |
| --------------- | -------------------------------- |
| `payout.payout` | Sent when a payout event occurs. |
### Marketplace Split Transfer events
| Event | Description |
| -------------------------------------------- | ---------------------------------------------- |
| `succeeded` (Type: `split_transfer`) | Split transfer completed successfully |
| `succeeded` (Type: `split_transfer_reverse`) | Split transfer reversal completed successfully |
## Banking Connectivity webhook events
Banking Connectivity (Banking as a Service) webhook notifications follow the same delivery and retry behavior described above. Yuno sends these events to your configured webhook endpoint when the status of a Banking Connectivity resource changes.
For incoming transfer payload structure, see [Webhook Notifications (Banking Connectivity)](/reference/banking-connectivity/webhooks/webhook-notifications-banking). Incoming transfer notifications are sent to your endpoint at `{merchant_base_URL}/v1/banking/transfers`.
### Entity events
| Event | Description |
| ------------------------ | -------------- |
| `banking.entity.created` | Entity created |
| `banking.entity.updated` | Entity updated |
| `banking.entity.deleted` | Entity deleted |
### Onboarding events
| Event | Description |
| ----------------------------------------------------- | -------------------------- |
| `banking.onboarding.created` | Onboarding created |
| `banking.onboarding.pending` | Submitted, awaiting review |
| `banking.onboarding.pending_additional_documentation` | More documents required |
| `banking.onboarding.succeeded` | Onboarding approved |
| `banking.onboarding.failed` | Onboarding failed |
| `banking.onboarding.declined` | Provider declined |
| `banking.onboarding.cancelled` | Merchant cancelled |
| `banking.onboarding.expired` | Onboarding expired |
### Account events
| Event | Description |
| --------------------------- | ----------------- |
| `banking.account.created` | Account created |
| `banking.account.updated` | Account updated |
| `banking.account.activated` | Account activated |
| `banking.account.closed` | Account closed |
### Transfer events (outgoing)
| Event | Description |
| ----------------------------- | ------------------- |
| `banking.transfer.pending` | Transfer pending |
| `banking.transfer.processing` | Transfer processing |
| `banking.transfer.completed` | Transfer completed |
| `banking.transfer.failed` | Transfer failed |
| `banking.transfer.cancelled` | Transfer cancelled |
| `banking.transfer.reversed` | Transfer reversed |
### Transfer events (incoming)
| Event | Description |
| ------------------------------------- | ------------------------------------ |
| `banking.transfer.incoming.pending` | Incoming transfer pending settlement |
| `banking.transfer.incoming.completed` | Incoming transfer settled |
# Object and Examples
Source: https://docs.y.uno/docs/webhooks/object-and-examples
Documents webhook payload attributes with example JSON for payments, chargebacks, enrollments, payouts, and subscriptions
## Webhook attributes
The JSON attributes for Yuno webhooks are listed below:
The unique identifier of the account in Yuno (MAX 64; MIN 36).
Specifies the notification type.
Specifies the event notification type.
Specifies the version of the webhook sent. Currently 2.
Specifies the number of retries for that notification.
Specifies the [payment](/reference/the-payment-object) (for payment type) or [payment method object](/reference/the-payment-method-object-api) (for enrollment and other objects).
Identifier used to skip duplicate deliveries. It stays stable across every retry of the same event. On `subscription.*` events it identifies the subscription rather than the event, so de-duplicate those on `type_event` plus this key. See [De-duplication](/docs/webhooks#de-duplication) for coverage details.
Optional. The HMAC-SHA256 signature sent in the HTTP header for webhook verification when HMAC authentication is enabled.
## Examples
Yuno provides several webhooks related to enrollment and payment notifications. Here you will find some examples of data structures related to each event.
## Payment
### Payment Webhook V2
Example payload:
Webhook payloads for events corresponding to a bank transfer payment method include `payment.payment_method.payment_method_detail.bank_transfer.bank_id`. The field mirrors the `bank_id` sent in the original payment request and is omitted when no bank was selected.
Each transaction includes `connection_data`, which identifies the provider connection that processed it. Use `connection_data.id` as the stable identifier to attribute transactions to a specific connection when you operate multiple connections for the same provider. `connection_data.name` is the display name configured in the Yuno dashboard and can be `null` on some events, such as follow-up transactions.
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"type": "payment",
"type_event": "payment.purchase",
"account_id": "2c05976d-1234-1234-1234-6421883de48d",
"retry": 0,
"version": 2,
"data": {
"payment": {
"id": "a546c566-1703-4fba-b334-c46e89bc97f7",
"account_id": "2c05976d-1234-1234-1234-6421883de48d",
"description": "Testing Yuno",
"country": "UY",
"status": "SUCCEEDED",
"sub_status": "APPROVED",
"order_id": "Order1234",
"merchant_order_id": "Test1234",
"created_at": "2024-07-19T16:31:59.528561Z",
"updated_at": "2024-07-19T16:32:02.203776Z",
"idempotency_key": "9e2aba6a-1234-1234-1234-03a0a67ee15f",
"amount": {
"currency": "UYU",
"value": 1458,
"refunded": 0,
"captured": 0
},
"checkout": {
"session": "2f3423dd-1234-1234-1234-2c7da5ad1caf",
"sdk_action_required": false
},
"customer_payer": {
"id": "96bf8513-1234-1234-1234-0087b2a60535",
"merchant_customer_id": "user1234",
"first_name": "harry ",
"last_name": "potter ",
"gender": "",
"date_of_birth": null,
"email": "testing6@y.uno",
"nationality": null,
"ip_address": "123.123.123.27",
"device_fingerprint": null,
"third_party_session_id": "third_party_session_id",
"merchant_customer_created_at": "2019-01-08T18:38:55.617Z",
"browser_info": {
"user_agent": "Yuno's/20979 CFNetwork/1496.0.7 Darwin/23.5.0",
"accept_header": "*/*",
"color_depth": null,
"screen_height": "844.0",
"screen_width": "390.0",
"javascript_enabled": null,
"language": "es-UY",
"accept_content": null,
"accept_browser": null,
"java_enabled": null,
"browser_time_difference": null
},
"document": {
"document_number": "99999999",
"document_type": "CI"
},
"billing_address": {
"address_line_1": "GEANT - Av. A la Playa y calle de 17",
"address_line_2": "",
"city": "Canelones",
"country": "UY",
"state": "Canelones",
"zip_code": "-",
"neighborhood": null
},
"shipping_address": {
"address_line_1": "GEANT - Av. A la Playa y calle de 17",
"address_line_2": "",
"city": "Canelones",
"country": "UY",
"state": "Canelones",
"zip_code": "-",
"neighborhood": null
},
"phone": {
"country_code": "598",
"number": "12345678"
}
},
"additional_data": {
"order": {
"shipping_amount": 0,
"fee_amount": null,
"tip_amount": null,
"items": [
{
"id": "item123",
"name": "Yuno Testing",
"quantity": 1,
"unit_amount": 1458,
"category": "services",
"brand": null,
"sku_code": null,
"manufacture_part_number": null,
"image_url": null
}
],
"taxes": []
},
"airline": null,
"seller_details": null
},
"transactions": {
"id": "3a35add9-89d6-4b11-9f17-24a76f4d046e",
"type": "PURCHASE",
"status": "SUCCEEDED",
"category": "CARD",
"amount": 1458,
"provider_id": "YUNO TEST GATEWAY",
"response_code": "SUCCEEDED",
"merchant_reference": "Test1234",
"response_message": "Transaction successful",
"reason": null,
"description": "Testing Yuno",
"created_at": "2024-07-19T16:31:59.617130Z",
"updated_at": "2024-07-19T16:32:02.138835Z",
"payment_method": {
"token": "902f17f9-1234-1234-1234-3322f5ebdbb5",
"type": "CARD",
"vaulted_token": "795b4f2e-1234-1234-1234-fcc1930d5d4c",
"vault_on_success": false,
"payment_method_detail": {
"card": {
"verify": null,
"capture": true,
"installments": 1,
"installments_plan_id": null,
"first_installment_deferral": null,
"installments_amount": null,
"installments_type": null,
"soft_descriptor": "",
"authorization_code": "123456",
"retrieval_reference_number": "",
"acquirer_reference_number": "",
"voucher": null,
"card_data": {
"holder_name": "HARRY POTTER",
"iin": "51584511",
"lfd": "1234",
"number_length": 16,
"security_code_length": 3,
"brand": "MASTERCARD",
"issuer_name": "ECONSTAR SA",
"issuer_code": null,
"category": "MRG - Prepaid MasterCard Card",
"type": "CREDIT",
"three_d_secure": {
"version": null,
"electronic_commerce_indicator": null,
"cryptogram": null,
"transaction_id": null,
"directory_server_transaction_id": null,
"pares_status": null,
"acs_id": null
},
"network_token": null,
"fingerprint": null
},
"stored_credentials": {
"reason": null,
"usage": null
}
},
"wallet": null,
"bnpl": null,
"bank_transfer": null,
"ticket": null,
"payment_link": null
}
},
"provider": {
"provider_transaction_id": "YUNO-51056-b673b951-aaa-aaa-aaa-123489aee2e0"
},
"provider_data": {
"raw_response": {
"value": "provider raw response"
},
"id": "DLOCAL",
"transaction_id": "YUNO-51056-b673b951-aaa-aaa-aaa-123489aee2e0",
"account_id": "699ec8d444",
"status": "PAID",
"status_detail": null,
"response_message": "The payment was paid.",
"response_code": "200",
"third_party_transaction_id": "",
"third_party_account_id": ""
},
"connection_data": {
"id": "88292fd3-bf5b-4b23-bb95-7186ba4e7f88",
"name": "dLocal US"
},
"simplified_mode": false,
"third_party_session_id": "third_party_session_id"
},
"transactions_history": [
{
"id": "3a35add9-89d6-4b11-9f17-24a76f4d046e",
"type": "PURCHASE",
"status": "SUCCEEDED",
"category": "CARD",
"amount": 1458,
"provider_id": "YUNO TEST GATEWAY",
"response_code": "SUCCEEDED",
"merchant_reference": "Test1234",
"response_message": "Transaction successful",
"reason": null,
"description": "Testing Yuno",
"created_at": "2024-07-19T16:31:59.617130Z",
"updated_at": "2024-07-19T16:32:02.138835Z",
"payment_method": {
"token": "902f17f9-1234-1234-1234-3322f5ebdbb5",
"type": "CARD",
"vaulted_token": "795b4f2e-1234-1234-1234-fcc1930d5d4c",
"vault_on_success": false,
"payment_method_detail": {
"card": {
"verify": null,
"capture": true,
"installments": 1,
"installments_plan_id": null,
"first_installment_deferral": null,
"installments_amount": null,
"installments_type": null,
"soft_descriptor": "",
"authorization_code": "123456",
"retrieval_reference_number": "",
"acquirer_reference_number": "",
"voucher": null,
"card_data": {
"holder_name": "HARRY POTTER",
"iin": "51584511",
"lfd": "1234",
"number_length": 16,
"security_code_length": 3,
"brand": "MASTERCARD",
"issuer_name": "ECONSTAR SA",
"issuer_code": null,
"category": "MRG - Prepaid MasterCard Card",
"type": "CREDIT",
"three_d_secure": {
"version": null,
"electronic_commerce_indicator": null,
"cryptogram": null,
"transaction_id": null,
"directory_server_transaction_id": null,
"pares_status": null,
"acs_id": null
},
"network_token": null,
"fingerprint": null
},
"stored_credentials": {
"reason": null,
"usage": null
}
},
"wallet": null,
"bnpl": null,
"bank_transfer": null,
"ticket": null,
"payment_link": null
}
},
"provider": {
"provider_transaction_id": "YUNO-51056-b673b951-aaa-aaa-aaa-123489aee2e0"
},
"provider_data": {
"raw_response": {
"value": "raw_response"
},
"id": "DLOCAL",
"transaction_id": "YUNO-51056-b673b951-aaa-aaa-aaa-123489aee2e0",
"account_id": "699ec8d444",
"status": "PAID",
"status_detail": null,
"response_message": "The payment was paid.",
"response_code": "200",
"third_party_transaction_id": "",
"third_party_account_id": ""
},
"connection_data": {
"id": "88292fd3-bf5b-4b23-bb95-7186ba4e7f88",
"name": "dLocal US"
},
"simplified_mode": false,
"third_party_session_id": "json object"
}
],
"callback_url": null,
"workflow": "SDK_CHECKOUT",
"split": [],
"payment_link_code": "",
"subscription_id": null,
"fraud_screening": null,
"metadata": [],
"routing_rules": {
"condition": {
"id": 222770,
"name": null,
"description": null
}
}
}
}
}
```
### Payment Webhook V1
Example payload:
```json JSON theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"payment":{
"code":"b3da6717-7949-454e-8699-e449bfaccb69",
"id":"b3da6717-7949-454e-8699-e449bfaccb69",
"idempotency_key":"28f14927-421b-4424-b4d2-5de4d83ca138",
"organization_code":"9c99108c-7681-4d48-acca-bce037685e99",
"account_code":"c004cfd7-0c65-4add-b9b3-3d7e3949c9f1",
"account_id":"c004cfd7-0c65-4add-b9b3-3d7e3949c9f1",
"description":"test description",
"country":"CO",
"status":"SUCCEEDED",
"sub_status":"APPROVED",
"order_id":"1679531154456",
"merchant_order_id":"1679531154456",
"created_at":"2023-03-23T00:26:38.093810Z",
"updated_at":"2023-03-23T00:26:51.285333Z",
"amount":{
"currency":"COP",
"value":2000.0,
"refunded":0.0,
"captured":0.0
},
"checkout":{
"session":"fb98b19d-39c0-42d2-bed6-438605458964",
"sdk_action_required":false
},
"customer_payer":{
"code":"8122d1f5-c07d-4d88-9dfe-a09ccdaeda0b",
"id":"8122d1f5-c07d-4d88-9dfe-a09ccdaeda0b",
"organization_customer_external_id":"1679531154456",
"merchant_customer_id":"1679531154456",
"first_name":"Aaron",
"last_name":"Hegmann",
"gender":"F",
"date_of_birth":"1990-02-28",
"email":"andrea@y.uno",
"nationality":"CO",
"ip_address":"192.168.123.167",
"device_fingerprint":"278994bb-9ece-5c63-8c44-c03481851625",
"browser_info":null,
"document":{
"document_number":"1032765432",
"document_type":"CC"
},
"billing_address":{
"address_line_1":"Calle 34 # 56 - 78",
"address_line_2":"Apartamento 502, Torre I",
"city":"Bogotá",
"country":"CO",
"state":"Cundinamarca",
"zip_code":"111111"
},
"shipping_address":{
"address_line_1":"Calle 34 # 56 - 78",
"address_line_2":"Apartamento 502, Torre I",
"city":"Bogotá",
"country":"CO",
"state":"Cundinamarca",
"zip_code":"111111"
},
"phone":{
"country_code":"57",
"number":"3991111111"
}
},
"additional_data":{
"order":{
"shipping_amount":0.0,
"fee_amount":0.0,
"items":[
{
"id":"123AD",
"name":"Skirt",
"quantity":1,
"unit_amount":2000.0,
"category":"Clothes",
"brand":"XYZ",
"sku_code":"8765432109",
"manufacture_part_number":"XYZ123456",
"image_url":null
}
]
},
"airline":null
},
"transactions":{
"code":"98c80022-fe05-4b9b-b478-2e102fc72cc3",
"id":"98c80022-fe05-4b9b-b478-2e102fc72cc3",
"type":"PURCHASE",
"status":"SUCCEEDED",
"category":"CARD",
"amount":2000.0,
"provider_id":"KUSHKI",
"response_code":"SUCCEEDED",
"merchant_reference":null,
"response_message":"Transaction successful",
"reason":null,
"description":"test description",
"created_at":"2023-03-23T00:26:38.290239Z",
"updated_at":"2023-03-23T00:26:51.258039Z",
"payment_method":{
"token":"e12440ca-920c-4aab-b656-6ed63f9ed5ac",
"type":"CARD",
"vaulted_token":null,
"vault_on_success":false,
"payment_method_detail":{
"card":{
"verify":null,
"capture":false,
"installments":1,
"first_installment_deferral":null,
"installments_amount":null,
"installments_type":null,
"soft_descriptor":"",
"authorization_code":"",
"retrieval_reference_number":"",
"acquirer_reference_number":"",
"voucher":null,
"card_data":{
"holder_name":"APROBADO",
"iin":"54519515",
"lfd":"5480",
"number_length":16,
"security_code_length":3,
"brand":"MASTERCARD",
"issuer_name":"BANCO DE LA PRODUCCION S.A. (PRODUBANCO)",
"issuer_code":null,
"category":"BLACK",
"type":"CREDIT"
}
},
"wallet":null,
"bnpl":null,
"bank_transfer":null,
"payment_link":null
}
},
"provider":{
"provider_transaction_id":"488990863216107201"
},
"provider_data":{
"raw_response":{
"details":{
"amount":{
"currency":"COP",
"ice":0,
"iva":0,
"subtotalIva":0,
"subtotalIva0":2000
},
"approvalCode":"000000",
"approvedTransactionAmount":2000,
"binInfo":{
"bank":"Banco de la Produccion S.A. (PRODUBANCO)",
"bindCard":"545195",
"cardCountry":"Ecuador",
"lastFourDigits":"5480",
"type":"credit"
},
"cardHolderName":"APROBADO",
"created":1679531210000,
"merchantId":"20000000107058310000",
"merchantName":"kushkiCOSBX Colombia",
"paymentBrand":"Mastercard",
"processorBankName":"0032~BANCO INTERNACIONAL",
"requestAmount":2000,
"responseCode":"000",
"responseText":"Transacción aprobada",
"transactionId":"091607275430589119",
"transactionReference":"eb6eb9e1-68d3-46be-8a0b-41ec8ff3ad73",
"transactionStatus":"APPROVAL",
"transactionType":"SALE"
},
"ticketNumber":"488990863216107201",
"transactionReference":"eb6eb9e1-68d3-46be-8a0b-41ec8ff3ad73"
},
"id":"KUSHKI",
"transaction_id":"488990863216107201",
"account_id":null,
"status":"APPROVAL",
"status_detail":"Transacción aprobada",
"response_message":"Transacción aprobada"
},
"connection_data":{
"id":"88292fd3-bf5b-4b23-bb95-7186ba4e7f88",
"name":"Kushki Colombia"
}
},
"callback_url":null,
"workflow":"CHECKOUT",
"split":[
],
"subscription_id":null,
"payment_link_id":null
}
}
```
### Chargeback Webhook V2
Example payload:
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"type":"payment",
"type_event":"payment.chargeback",
"account_id":"a4441009-df56-4a59-a515-ca9b949c4ce3",
"retry":0,
"version":2,
"data":{
"payment":{
"id":"ae70d7f9-e0a2-4e37-a12f-765e8af87924",
"account_id":"a4441009-df56-4a59-a515-ca9b949c4ce3",
"description":"test Ecommerce",
"country":"MX",
"status":"IN_DISPUTE",
"sub_status":"RECEIVED",
"order_id":"584-67f854a2eb05a22320e86071",
"merchant_order_id":"584-67f854a2eb05a22320e86071",
"created_at":"2025-04-10T23:30:53.210656Z",
"updated_at":"2025-04-17T04:46:49.640765Z",
"idempotency_key":"485d3965-6deb-4fc5-81de-4a7211c835bc",
"amount":{
"currency":"MXN",
"value":418.0,
"refunded":0.0,
"captured":0.0,
"currency_conversion": {
"code": "ccv_01HVK3Z9M2...",
"cardholder_currency": "QAR",
"cardholder_amount": 3640.00,
"cardholder_accepted": true,
"rate": 3.6400,
"rate_margin_percentage": 3.75,
"rate_source": "ECB",
"provider": "FEXCO",
"description": "You have chosen to pay in QAR. Amount: 3640.00 QAR. Rate: 3.6400.",
"created_at": "2026-04-24T14:30:00Z",
"expires_at": "2026-04-24T15:30:00Z",
"status": "APPLIED",
"error_reason": null,
"provider_data": {
"acquirer_id": "MPGS_01"
}
}
},
"checkout":{
"session":"4f335b32-79de-41a7-b30b-f478620bc7a8",
"sdk_action_required":false
},
"customer_payer":{
"id":"4476c479-9a32-4910-83d8-b74b7b8eb86f",
"merchant_customer_id":"67f854536e2a02461a1a8f5f",
"first_name":"merit",
"last_name":"amador",
"gender":"",
"date_of_birth":null,
"email":"bolitas.nuca9b@icloud.com",
"nationality":null,
"ip_address":"200.68.159.190",
"device_fingerprint":null,
"third_party_session_id":null,
"device_fingerprints":[
],
"merchant_customer_created_at":"2025-04-10T23:23:46.357Z",
"browser_info":{
"user_agent":"Mozilla/5.0 (iPhone; CPU iPhone OS 18_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1",
"accept_header":"*/*",
"color_depth":"24",
"screen_height":"852",
"screen_width":"393",
"javascript_enabled":true,
"language":"es",
"accept_content":"*/*",
"accept_browser":"*/*",
"java_enabled":false,
"browser_time_difference":"360"
},
"document":null,
"billing_address":{
"address_line_1":"Av. test test No. 193 Local C-1-2-3 Plaza Galerias Col. test test C.P11300 test D.F",
"address_line_2":"",
"city":"test",
"country":"MX",
"state":"-",
"zip_code":"-",
"neighborhood":null
},
"shipping_address":{
"address_line_1":"Av. test test No. 193 Local C-1-2-3 test test Col. test test C.P11300 test D.F",
"address_line_2":"",
"city":"CDMX",
"country":"MX",
"state":"-",
"zip_code":"-",
"neighborhood":null
},
"phone":{
"country_code":"52",
"number":"5659708369"
}
},
"additional_data":{
"order":{
"shipping_amount":0.0,
"fee_amount":0.0,
"tip_amount":null,
"items":[
{
"id":"26609",
"name":"McTrío Grande Signature BBQ Crispy Onion",
"quantity":2,
"unit_amount":193.0,
"category":"others",
"brand":null,
"sku_code":"26609",
"manufacture_part_number":null,
"image_url":null
}
],
"taxes":[
],
"shipping":null,
"account_funding":null,
"tickets":[
],
"fulfillment":null,
"discounts":[
]
},
"airline":null,
"seller_details":null
},
"transactions":{
"id":"5f354190-ffe8-4b25-a73d-55fe25821067",
"type":"CHARGEBACK",
"status":"CREATED",
"category":"CARD",
"amount":418.0,
"provider_id":"ADYEN",
"response_code":"ACTION_REQUIRED",
"merchant_reference":"YU00000058467f854a2eb05a22320e86071",
"response_message":"Chargeback or Inquiry received. Decision or documentation must be provided",
"reason":"REQUESTED_BY_CUSTOMER",
"description":"webhook transaction",
"created_at":"2025-04-17T04:46:49.591869Z",
"updated_at":"2025-04-17T04:46:49.616143Z",
"payment_method":{
"token":"592c7a1c-e34c-4dc1-851f-5bd41bc32c68",
"type":"CARD",
"vaulted_token":"2146a9c4-56c9-43a5-a35b-916bf15f7772",
"vault_on_success":false,
"parent_payment_method_type":null,
"payment_method_detail":{
"card":{
"verify":false,
"capture":false,
"installments":1,
"installments_plan_id":null,
"first_installment_deferral":null,
"installments_amount":null,
"installments_type":null,
"soft_descriptor":"",
"authorization_code":"373761",
"retrieval_reference_number":"",
"acquirer_reference_number":"",
"voucher":null,
"card_data":{
"holder_name":"YOANA CALAM",
"iin":"55123824",
"lfd":"2451",
"number_length":16,
"security_code_length":3,
"brand":"MASTERCARD",
"issuer_name":"BANCO AZTECA INSTITUCION BANCA MULTIPLE",
"issuer_code":null,
"country_code":"MX",
"category":"DEBIT MASTERCARD",
"type":"DEBIT",
"three_d_secure":{
"version":null,
"electronic_commerce_indicator":null,
"cryptogram":null,
"transaction_id":null,
"directory_server_transaction_id":null,
"pares_status":null,
"acs_id":null
},
"network_token":null,
"fingerprint":"355e7384-7e75-4a32-94b9-26031a4faab5",
"expiration_month":12,
"expiration_year":26
},
"stored_credentials":{
"reason":null,
"usage":null,
"subscription_agreement_id":null,
"network_transaction_id":null
}
},
"wallet":null,
"bnpl":null,
"bank_transfer":null,
"ticket":null,
"payment_link":null
}
},
"provider":{
"provider_transaction_id":"L2JC9B5K995BJDF6"
},
"provider_data":{
"raw_response":null,
"id":"ADYEN",
"transaction_id":"L2JC9B5K995BJDF6",
"account_id":null,
"status":"NOTIFICATION_OF_CHARGEBACK",
"status_detail":null,
"response_message":null,
"response_code":null,
"third_party_transaction_id":null,
"third_party_account_id":null,
"iso8583_response_code":null,
"iso8583_response_message":null
},
"connection_data":{
"id":null,
"name":null
},
"device_fingerprint":null,
"simplified_mode":false,
"third_party_session_id":null
},
"transactions_history":[
{
"id":"5f354190-ffe8-4b25-a73d-55fe25821067",
"type":"CHARGEBACK",
"status":"CREATED",
"category":"CARD",
"amount":418.0,
"provider_id":"ADYEN",
"response_code":"ACTION_REQUIRED",
"merchant_reference":"YU00000058467f854a2eb05a22320e86071",
"response_message":"Chargeback or Inquiry received. Decision or documentation must be provided",
"reason":"REQUESTED_BY_CUSTOMER",
"description":"webhook transaction",
"created_at":"2025-04-17T04:46:49.591869Z",
"updated_at":"2025-04-17T04:46:49.616143Z",
"payment_method":{
"token":"592c7a1c-e34c-4dc1-851f-5bd41bc32c68",
"type":"CARD",
"vaulted_token":"2146a9c4-56c9-43a5-a35b-916bf15f7772",
"vault_on_success":false,
"parent_payment_method_type":null,
"payment_method_detail":{
"card":{
"verify":false,
"capture":false,
"installments":1,
"installments_plan_id":null,
"first_installment_deferral":null,
"installments_amount":null,
"installments_type":null,
"soft_descriptor":"",
"authorization_code":"373761",
"retrieval_reference_number":"",
"acquirer_reference_number":"",
"voucher":null,
"card_data":{
"holder_name":"YOANA CALAM",
"iin":"55123824",
"lfd":"2451",
"number_length":16,
"security_code_length":3,
"brand":"MASTERCARD",
"issuer_name":"BANCO AZTECA INSTITUCION BANCA MULTIPLE",
"issuer_code":null,
"country_code":"MX",
"category":"DEBIT MASTERCARD",
"type":"DEBIT",
"three_d_secure":{
"version":null,
"electronic_commerce_indicator":null,
"cryptogram":null,
"transaction_id":null,
"directory_server_transaction_id":null,
"pares_status":null,
"acs_id":null
},
"network_token":null,
"fingerprint":"355e7384-7e75-4a32-94b9-26031a4faab5",
"expiration_month":12,
"expiration_year":26
},
"stored_credentials":{
"reason":null,
"usage":null,
"subscription_agreement_id":null,
"network_transaction_id":null
}
},
"wallet":null,
"bnpl":null,
"bank_transfer":null,
"ticket":null,
"payment_link":null
}
},
"provider":{
"provider_transaction_id":"L2JC9B5K995BJDF6"
},
"provider_data":{
"raw_response":null,
"id":"ADYEN",
"transaction_id":"L2JC9B5K995BJDF6",
"account_id":null,
"status":"NOTIFICATION_OF_CHARGEBACK",
"status_detail":null,
"response_message":null,
"response_code":null,
"third_party_transaction_id":null,
"third_party_account_id":null,
"iso8583_response_code":null,
"iso8583_response_message":null
},
"connection_data":{
"id":null,
"name":null
},
"device_fingerprint":null,
"simplified_mode":false,
"third_party_session_id":null
},
{
"id":"4d508842-5ffc-438a-a864-deeceb9935ca",
"type":"PURCHASE",
"status":"SUCCEEDED",
"category":"CARD",
"amount":418.0,
"provider_id":"ADYEN",
"response_code":"SUCCEEDED",
"merchant_reference":"YU00000058467f854a2eb05a22320e86071",
"response_message":"Transaction successful",
"reason":null,
"description":"McDonalds Ecommerce",
"created_at":"2025-04-10T23:30:53.319251Z",
"updated_at":"2025-04-10T23:30:54.496131Z",
"payment_method":{
"token":"592c7a1c-e34c-4dc1-851f-5bd41bc32c68",
"type":"CARD",
"vaulted_token":"2146a9c4-56c9-43a5-a35b-916bf15f7772",
"vault_on_success":false,
"parent_payment_method_type":null,
"payment_method_detail":{
"card":{
"verify":false,
"capture":true,
"installments":1,
"installments_plan_id":null,
"first_installment_deferral":null,
"installments_amount":null,
"installments_type":null,
"soft_descriptor":"",
"authorization_code":"373761",
"retrieval_reference_number":"",
"acquirer_reference_number":"",
"voucher":null,
"card_data":{
"holder_name":"YOANA CALAM",
"iin":"55123824",
"lfd":"2451",
"number_length":16,
"security_code_length":3,
"brand":"MASTERCARD",
"issuer_name":"BANCO AZTECA INSTITUCION BANCA MULTIPLE",
"issuer_code":null,
"country_code":"MX",
"category":"DEBIT MASTERCARD",
"type":"DEBIT",
"three_d_secure":{
"version":null,
"electronic_commerce_indicator":null,
"cryptogram":null,
"transaction_id":null,
"directory_server_transaction_id":null,
"pares_status":null,
"acs_id":null
},
"network_token":null,
"fingerprint":"355e7384-7e75-4a32-94b9-26031a4faab5",
"expiration_month":12,
"expiration_year":26
},
"stored_credentials":{
"reason":null,
"usage":null,
"subscription_agreement_id":null,
"network_transaction_id":null
}
},
"wallet":null,
"bnpl":null,
"bank_transfer":null,
"ticket":null,
"payment_link":null
}
},
"provider":{
"provider_transaction_id":"L2JC9B5K995BJDF6"
},
"provider_data":{
"raw_response":{
"additionalData":{
"acquirerAccountCode":"AdyenProsa_ArcosDouradosPlataforma-MX_Cvv",
"acquirerCode":"AdyenProsa",
"acquirerReference":"373761",
"authCode":"373761",
"authorisationMid":"9024452",
"avsResult":"0 Unknown",
"cardFunction":"Consumer",
"cavv":"N/A",
"cavvAlgorithm":"N/A",
"cvcResult":"1 Matches",
"cvcResultRaw":"1 Matches",
"eci":"N/A",
"liabilityShift":"false",
"paymentMethod":"mc",
"paymentMethodVariant":"mcstandarddebit",
"refusalReasonRaw":"00 : Approved or completed successfully",
"threeDAuthenticated":"false",
"threeDAuthenticatedResponse":"N/A",
"threeDOffered":"false",
"threeDOfferedResponse":"N/A",
"threeds2.cardEnrolled":"true",
"xid":"N/A"
},
"amount":{
"currency":"MXN",
"value":41800
},
"merchantReference":"584-67f854a2eb05a22320e86071",
"paymentMethod":{
"brand":"mc",
"type":"scheme"
},
"pspReference":"L2JC9B5K995BJDF6",
"resultCode":"Authorised"
},
"id":"ADYEN",
"transaction_id":"L2JC9B5K995BJDF6",
"account_id":"test-account",
"status":"Authorised",
"status_detail":"Authorised",
"response_message":null,
"response_code":null,
"third_party_transaction_id":"L2JC9B5K995BJDF6",
"third_party_account_id":"",
"iso8583_response_code":"00 ",
"iso8583_response_message":null
},
"connection_data":{
"id":"72f2adb3-ed95-4bca-be01-20bbe4d5a1cb",
"name":null
},
"device_fingerprint":null,
"simplified_mode":false,
"third_party_session_id":null
}
],
"callback_url":"https://test.com.mx/api/callback/my-orders?path=%2Fmi-cuenta%2Fmis-pedidos%2F67f854a2eb05a22320e86071&checkoutSession=5f446b32-79de-41a7-b30b-f478620bc7a8",
"workflow":"SDK_CHECKOUT",
"split_marketplace":[
],
"payment_link_code":"",
"subscription_id":null,
"fraud_screening":null,
"metadata":[
{
"key":"riskdata.deliveryMethod",
"value":"MOP"
},
{
"key":"riskdata.storeId",
"value":"584"
},
{
"key":"riskdata.basket.item1.amountPerItem",
"value":"41800"
},
{
"key":"riskdata.basket.item1.itemID",
"value":"26609"
},
{
"key":"riskdata.basket.item1.category",
"value":"test value"
},
{
"key":"riskdata.basket.item1.currency",
"value":"MXN"
},
{
"key":"riskdata.basket.item1.quantity",
"value":"2"
},
{
"key":"riskdata.basket.item1.productTitle",
"value":"test value"
}
],
"routing_rules":{
"smart_routing":false,
"monitors":false,
"condition":{
"id":537769,
"name":null,
"description":null
}
}
}
}
}
```
### Chargeback Webhook V1
Example payload:
```json JSON theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"payment":{
"code":"b3da6717-7949-454e-8699-e449bfaccb69",
"id":"b3da6717-7949-454e-8699-e449bfaccb69",
"idempotency_key":"28f14927-421b-4424-b4d2-5de4d83ca138",
"organization_code":"9c99108c-7681-4d48-acca-bce037685e99",
"account_code":"c004cfd7-0c65-4add-b9b3-3d7e3949c9f1",
"account_id":"c004cfd7-0c65-4add-b9b3-3d7e3949c9f1",
"description":"test description",
"country":"CO",
"status":"CHARGEBACK",
"sub_status":"LOST",
"order_id":"1679531154456",
"merchant_order_id":"1679531154456",
"created_at":"2023-03-23T00:26:38.093810Z",
"updated_at":"2023-03-23T00:26:51.285333Z",
"amount":{
"currency":"COP",
"value":2000.0,
"refunded":0.0,
"captured":0.0
},
"checkout":{
"session":"fb98b19d-39c0-42d2-bed6-438605458964",
"sdk_action_required":false
},
"customer_payer":{
"code":"8122d1f5-c07d-4d88-9dfe-a09ccdaeda0b",
"id":"8122d1f5-c07d-4d88-9dfe-a09ccdaeda0b",
"organization_customer_external_id":"1679531154456",
"merchant_customer_id":"1679531154456",
"first_name":"Aaron",
"last_name":"Hegmann",
"gender":"F",
"date_of_birth":"1990-02-28",
"email":"andrea@y.uno",
"nationality":"CO",
"ip_address":"192.168.123.167",
"device_fingerprint":"278994bb-9ece-5c63-8c44-c03481851625",
"browser_info":null,
"document":{
"document_number":"1032765432",
"document_type":"CC"
},
"billing_address":{
"address_line_1":"Calle 34 # 56 - 78",
"address_line_2":"Apartamento 502, Torre I",
"city":"Bogotá",
"country":"CO",
"state":"Cundinamarca",
"zip_code":"111111"
},
"shipping_address":{
"address_line_1":"Calle 34 # 56 - 78",
"address_line_2":"Apartamento 502, Torre I",
"city":"Bogotá",
"country":"CO",
"state":"Cundinamarca",
"zip_code":"111111"
},
"phone":{
"country_code":"57",
"number":"3991111111"
}
},
"additional_data":{
"order":{
"shipping_amount":0.0,
"fee_amount":0.0,
"items":[
{
"id":"123AD",
"name":"Skirt",
"quantity":1,
"unit_amount":2000.0,
"category":"Clothes",
"brand":"XYZ",
"sku_code":"8765432109",
"manufacture_part_number":"XYZ123456",
"image_url":null
}
]
},
"airline":null
},
"transactions":{
"code":"98c80022-fe05-4b9b-b478-2e102fc72cc3",
"id":"98c80022-fe05-4b9b-b478-2e102fc72cc3",
"type":"CHARGEBACK",
"status":"LOST",
"category":"CARD",
"amount":2000.0,
"provider_id":"KUSHKI",
"response_code":"CHARGEBACK",
"merchant_reference":null,
"response_message":"Transaction successful",
"reason":null,
"description":"test description",
"created_at":"2023-03-23T00:26:38.290239Z",
"updated_at":"2023-03-23T00:26:51.258039Z",
"payment_method":{
"token":"e12440ca-920c-4aab-b656-6ed63f9ed5ac",
"type":"CARD",
"vaulted_token":null,
"vault_on_success":false,
"payment_method_detail":{
"card":{
"verify":null,
"capture":false,
"installments":1,
"first_installment_deferral":null,
"installments_amount":null,
"installments_type":null,
"soft_descriptor":"",
"authorization_code":"",
"retrieval_reference_number":"",
"acquirer_reference_number":"",
"voucher":null,
"card_data":{
"holder_name":"APROBADO",
"iin":"54519515",
"lfd":"5480",
"number_length":16,
"security_code_length":3,
"brand":"MASTERCARD",
"issuer_name":"BANCO DE LA PRODUCCION S.A. (PRODUBANCO)",
"issuer_code":null,
"category":"BLACK",
"type":"CREDIT"
}
},
"wallet":null,
"bnpl":null,
"bank_transfer":null,
"payment_link":null
}
},
"provider":{
"provider_transaction_id":"488990863216107201"
},
"provider_data":{
"raw_response":{
},
"id":"KUSHKI",
"transaction_id":"488990863216107201",
"account_id":null,
"status":"CHARGEBACK",
"status_detail":"",
"response_message":""
}
},
"callback_url":null,
"workflow":"SDK_CHECKOUT",
"split":[
]
}
}
```
## Enrollment
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"type": "enrollment",
"type_event": "enrollment.enroll",
"account_id": "493e9374-510a-4201-9e09-de669d75f256",
"retry": 0,
"version": 2,
"data": {
"payment_method": {
"id": "03c3aae1-ed42-4be6-bc24-de5487f58491",
"account_id": "493e9374-510a-4201-9e09-de669d75f256",
"name": "VISA ****1111",
"description": "VISA ****1111",
"type": "CARD",
"category": "CARD",
"country": "CO",
"status": "ENROLLED",
"customer_id": "2f38972e-2427-43b7-95be-ee4cf21cef1b",
"created_at": "2024-09-10T15:04:10.453741Z",
"updated_at": "2024-09-10T15:04:10.453745Z",
"enrollment": {
"session": null,
"sdk_action_required": false
},
"verify": {
"vault_on_success": false,
"currency": null,
"payment": null
},
"detail": {
"card": {
"holder_name": "Pepito Perez",
"expiration_month": 3,
"expiration_year": 26,
"iin": "41111111",
"lfd": "1111",
"security_code_length": 3,
"number_length": 16,
"brand": "VISA",
"issuer_name": "JPMORGAN CHASE BANK N A",
"issuer_code": null,
"type": "CREDIT",
"category": "CREDIT",
"country_code": "US",
"country_name": "United States of America",
"fingerprint_code": "d244e20d-43a1-43f7-9b48-0a76423be35e",
"created_at": "2024-09-10T15:04:10.453799Z",
"updated_at": "2024-09-10T15:04:10.453800Z"
}
}
}
}
}
```
## Payouts
```json JSON theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"type": "payout",
"type_event": "payout.payout",
"account_id": "f7c5fe77-721b-49c2-84d3-957748df3c2c",
"retry": 0,
"version": 2,
"data": {
"id": "0cbc7bd4-04f3-4897-b3c6-4d5f36a6b9a7",
"status": "SUCCEEDED",
"merchant_reference": "MR-12345",
"description": null,
"country": "BR",
"account_code": "f7c5fe77-721b-49c2-84d3-957748df3c2c",
"organization_code": "6c6a6b2c-c9c0-4104-9dd0-4237e6f00047",
"purpose": null,
"amount": {
"currency": "BRL",
"value": 100
},
"beneficiary": {
"merchant_beneficiary_id": "test_merchant_deposit_id",
"national_entity": null,
"first_name": null,
"last_name": null,
"legal_name": null,
"email": null,
"country": "BR",
"date_of_birth": null,
"document": null,
"phone": null,
"address": null
},
"transactions": [
{
"id": "2be03290-70a9-414a-a285-8c573d26de5a",
"status": "SUCCEEDED",
"type": "ASTROPAY_PAYOUT",
"response_code": "SUCCEEDED",
"purpose": null,
"description": null,
"amount": {
"currency": "BRL",
"value": 100
},
"withdrawal_method": {
"type": "ASTROPAY_PAYOUT",
"provider_id": null,
"detail": {
"bank_transfer": null,
"wallet": {
"code": "h15sg84U6rCl",
"email": null,
"country": null,
"document": null,
"phone": null
}
}
},
"provider_data": {
"id": "ASTROPAY",
"transaction_id": "32389",
"account_id": "",
"beneficiary_id": "test_merchant_deposit_id",
"raw_response": "\"{\\n \\\"cashout_id\\\" : 32389,\\n \\\"merchant_cashout_id\\\" : \\\"2be03290-70a9-414a-a285-8c573d26de5a\\\",\\n \\\"status\\\" : \\\"APPROVED\\\",\\n \\\"user_id\\\" : \\\"h15sg84U6rCl\\\"\\n}\"",
"status_detail": "APPROVED",
"provider_status": null
},
"created_at": "2024-05-27T19:10:32.723578Z",
"updated_at": "2024-05-27T19:10:33.757137Z"
}
],
"metadata": [],
"created_at": "2024-05-27T19:10:32.494514Z",
"updated_at": "2024-05-27T19:10:33.757143Z"
}
}
```
## Subscriptions
```json JSON theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"type": "subscription",
"type_event": "subscription.create",
"account_id": "c24d6c92-99a7-40bb-bc7b-efc40337f9f4",
"retry": 0,
"version": 2,
"data": {
"subscription": {
"code": "8fc8a985-bc18-4f9a-9403-d0cf6fc64e94",
"name": "Subscription",
"description": "retries activos",
"country": "CO",
"account_code": "c24d6c92-99a7-40bb-bc7b-efc40337f9f4",
"merchant_reference": "subscription-ref-merchant-002",
"status": "CREATED",
"amount": {
"currency": "COP",
"value": 36000
},
"frequency": null,
"billing_date": {
"type": "DAY",
"day": 30
},
"billing_cycles": {
"total": 5,
"current": 1,
"next_at": "2026-02-28T18:25:49.995376Z"
},
"customer_payer": {
"code": "a9f9140a-1216-481c-8356-1a125078f905"
},
"payment_method": {
"type": "CARD",
"vaulted_token": "7eeb8d32-d5c3-45a8-955b-30accc625d1f"
},
"availability": {
"start_at": "2026-02-01T18:25:49.995376Z",
"finish_at": null
},
"retries": {
"retry_on_decline": false,
"amount": 6
},
"metadata": [
{
"key": "Canal 1",
"value": "Soccer"
}
],
"additional_data": null,
"payments": [],
"trial_period": {
"billing_cycles": 1,
"amount": {
"currency": null,
"value": null
}
},
"initial_payment_validation": true,
"subscription_agreement_id": null,
"created_at": "2025-05-21T15:33:16.662026Z",
"updated_at": "2025-05-21T15:33:16.662026Z"
}
}
}
```
### subscription.active
Sent when a subscription transitions from any other valid status into `ACTIVE`. Use this event to trigger post-activation processes without polling.
```json JSON theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"type": "subscription",
"type_event": "subscription.active",
"account_id": "c24d6c92-99a7-40bb-bc7b-efc40337f9f4",
"retry": 0,
"version": 2,
"data": {
"subscription": {
"code": "e98ef674-9baa-4f7a-8da4-4c812c4749a4",
"name": "Subscription",
"description": "retries activos",
"country": "CO",
"account_code": "c24d6c92-99a7-40bb-bc7b-efc40337f9f4",
"merchant_reference": "subscription-ref-merchant-002",
"status": "ACTIVE",
"amount": {
"currency": "COP",
"type": "FIXED",
"value": 36000
},
"frequency": {
"type": "MINUTES",
"value": 3,
"monthly_billing_day": null,
"execution": "YUNO"
},
"billing_date": null,
"billing_cycles": {
"total": 5,
"current": 2,
"next_at": "2025-12-04T00:32:25.485281Z"
},
"customer_payer": {
"code": "a9f9140a-1216-481c-8356-1a125078f905"
},
"payment_method": {
"type": "CARD",
"vaulted_token": "7eeb8d32-d5c3-45a8-955b-30accc625d1f",
"card": {
"installments": null,
"network_transaction_id": "651161211088410"
}
},
"availability": {
"start_at": "2025-12-04T00:29:25.485281Z",
"finish_at": null
},
"retries": {
"retry_on_decline": true,
"amount": 6
},
"metadata": [
{
"key": "Canal 1",
"value": "Soccer"
}
],
"additional_data": null,
"payments": [],
"trial_period": {
"billing_cycles": 1,
"amount": {
"currency": null,
"value": null
}
},
"initial_payment_validation": true,
"provider_subscription_id": null,
"subscription_agreement_id": null,
"created_at": "2025-12-04T00:29:25.485281Z",
"updated_at": "2025-12-04T00:29:59.216998Z"
}
}
}
```
### subscription.pause
Sent when a subscription is paused. Use this event to update the status in your system and pause related services.
```json JSON theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"type": "subscription",
"type_event": "subscription.pause",
"account_id": "c24d6c92-99a7-40bb-bc7b-efc40337f9f4",
"retry": 0,
"version": 2,
"data": {
"subscription": {
"code": "e98ef674-9baa-4f7a-8da4-4c812c4749a4",
"name": "Subscription",
"status": "PAUSED",
"amount": {
"currency": "COP",
"type": "FIXED",
"value": 36000
},
"customer_payer": {
"code": "a9f9140a-1216-481c-8356-1a125078f905"
}
}
}
}
```
### subscription.resume
Sent when a paused subscription is resumed and transitions back to the `ACTIVE` status.
```json JSON theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"type": "subscription",
"type_event": "subscription.resume",
"account_id": "c24d6c92-99a7-40bb-bc7b-efc40337f9f4",
"retry": 0,
"version": 2,
"data": {
"subscription": {
"code": "e98ef674-9baa-4f7a-8da4-4c812c4749a4",
"name": "Monthly Plan",
"description": "Monthly subscription",
"country": "US",
"account_code": "c24d6c92-99a7-40bb-bc7b-efc40337f9f4",
"merchant_reference": "subscription-ref-merchant-002",
"status": "ACTIVE",
"amount": {
"currency": "USD",
"type": "FIXED",
"value": 42.46
},
"frequency": {
"type": "MONTH",
"value": 1,
"monthly_billing_day": null,
"execution": "YUNO"
},
"billing_date": null,
"billing_cycles": {
"total": null,
"current": 2,
"next_at": "2026-07-14T19:19:31.914Z"
},
"customer_payer": {
"code": "a9f9140a-1216-481c-8356-1a125078f905"
},
"payment_method": {
"type": "CARD",
"vaulted_token": "4ba74a56-14d4-4161-a0ba-8036e9b8abf6",
"card": {
"installments": null,
"network_transaction_id": "000000000000000",
"usage": "USED"
}
},
"availability": {
"start_at": "2026-06-14T19:19:31.914Z",
"finish_at": null
},
"retries": {
"retry_on_decline": true,
"amount": 4,
"strategy": "DEFAULT",
"schedule": null,
"stop_on_hard_decline": null,
"cancel_on_exhausted_retries": null
},
"metadata": [
{
"key": "plan_id",
"value": "monthly_plan"
}
],
"additional_data": null,
"payments": [],
"trial_period": {
"billing_cycles": 1,
"amount": {
"currency": null,
"value": null
}
},
"initial_payment_validation": false,
"provider_subscription_id": null,
"reason": null,
"subscription_agreement_id": null,
"soft_descriptor": null,
"renewal_notification_days": null,
"cancellation_time": null,
"cancellation_source": null,
"ending_time": null,
"created_at": "2026-05-14T19:19:32.117629Z",
"updated_at": "2026-06-15T07:11:52.504031Z",
"history": null
}
}
}
```
### subscription.cancel
Sent when a subscription is canceled. Once canceled, the subscription is terminated and cannot be reactivated.
The subscription object carries a `cancellation_source` field describing what triggered the cancellation — `MERCHANT`, `SYSTEM`, `PLAN_CHANGE`, or `RETRIES_EXHAUSTED`. See [the subscription object](/reference/subscriptions/the-subscription-object) for what each value means.
Treat `cancellation_source` as open-ended. New values can be added as Yuno introduces new cancellation behaviors, so handle an unrecognized value gracefully rather than switching exhaustively over the current list. `RETRIES_EXHAUSTED` is the most recent addition — it is sent when retries for a billing cycle end without a successful payment on a subscription created with `retries.cancel_on_exhausted_retries` set to `true`.
```json JSON theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"type": "subscription",
"type_event": "subscription.cancel",
"account_id": "c24d6c92-99a7-40bb-bc7b-efc40337f9f4",
"retry": 0,
"version": 2,
"data": {
"subscription": {
"code": "e98ef674-9baa-4f7a-8da4-4c812c4749a4",
"name": "Subscription",
"status": "CANCELED",
"amount": {
"currency": "COP",
"type": "FIXED",
"value": 36000
},
"customer_payer": {
"code": "a9f9140a-1216-481c-8356-1a125078f905"
}
}
}
}
```
### subscription.complete
Sent when a subscription reaches its end date or total billing cycles and transitions to the `COMPLETED` status.
```json JSON theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"type": "subscription",
"type_event": "subscription.complete",
"account_id": "c24d6c92-99a7-40bb-bc7b-efc40337f9f4",
"retry": 0,
"version": 2,
"data": {
"subscription": {
"code": "e98ef674-9baa-4f7a-8da4-4c812c4749a4",
"name": "Subscription",
"status": "COMPLETED",
"amount": {
"currency": "COP",
"type": "FIXED",
"value": 36000
},
"customer_payer": {
"code": "a9f9140a-1216-481c-8356-1a125078f905"
}
}
}
}
```
### subscription.close\_to\_renewal
Sent ahead of an upcoming renewal. Timing is controlled by `renewal_notification_days` on the subscription.
```json JSON theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"type": "subscription",
"type_event": "subscription.close_to_renewal",
"account_id": "c24d6c92-99a7-40bb-bc7b-efc40337f9f4",
"retry": 0,
"version": 2,
"data": {
"subscription": {
"code": "e98ef674-9baa-4f7a-8da4-4c812c4749a4",
"name": "Monthly Plan",
"description": "Monthly subscription",
"country": "US",
"account_code": "c24d6c92-99a7-40bb-bc7b-efc40337f9f4",
"merchant_reference": "subscription-ref-merchant-002",
"status": "ACTIVE",
"amount": {
"currency": "USD",
"type": "FIXED",
"value": 42.46
},
"frequency": {
"type": "MONTH",
"value": 1,
"monthly_billing_day": null,
"execution": "YUNO"
},
"billing_date": null,
"billing_cycles": {
"total": null,
"current": 2,
"next_at": "2026-07-14T19:19:31.914Z"
},
"customer_payer": {
"code": "a9f9140a-1216-481c-8356-1a125078f905"
},
"payment_method": {
"type": "CARD",
"vaulted_token": "4ba74a56-14d4-4161-a0ba-8036e9b8abf6",
"card": {
"installments": null,
"network_transaction_id": "000000000000000",
"usage": "USED"
}
},
"availability": {
"start_at": "2026-06-14T19:19:31.914Z",
"finish_at": null
},
"retries": {
"retry_on_decline": true,
"amount": 4,
"strategy": "DEFAULT",
"schedule": null,
"stop_on_hard_decline": null,
"cancel_on_exhausted_retries": null
},
"metadata": [
{
"key": "plan_id",
"value": "monthly_plan"
}
],
"additional_data": null,
"payments": [],
"trial_period": {
"billing_cycles": 1,
"amount": {
"currency": null,
"value": null
}
},
"initial_payment_validation": false,
"provider_subscription_id": null,
"reason": null,
"subscription_agreement_id": null,
"soft_descriptor": null,
"renewal_notification_days": 3,
"cancellation_time": null,
"cancellation_source": null,
"ending_time": null,
"created_at": "2026-05-14T19:19:32.117629Z",
"updated_at": "2026-06-15T07:11:52.504031Z",
"history": null
}
}
}
```
### subscription.plan\_change\_scheduled
Sent when a plan change is scheduled for the next billing cycle. The `plan_change` block describes the pending change; `applies_at` is the next billing date the change will take effect on.
```json JSON theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"type": "subscription",
"type_event": "subscription.plan_change_scheduled",
"account_id": "c24d6c92-99a7-40bb-bc7b-efc40337f9f4",
"retry": 0,
"version": 2,
"data": {
"subscription": {
"code": "e98ef674-9baa-4f7a-8da4-4c812c4749a4",
"name": "Subscription",
"status": "ACTIVE",
"amount": {
"currency": "USD",
"type": "FIXED",
"value": 9.99
},
"customer_payer": {
"code": "a9f9140a-1216-481c-8356-1a125078f905"
}
},
"plan_change": {
"plan_id": "1904911d-5df9-429e-8488-ad41abea1a4d",
"plan_name": "Pro",
"direction": "UPGRADE",
"effective": "NEXT_BILLING_CYCLE",
"phases_behavior": "START_FROM_REGULAR",
"applies_at": "2026-08-15T00:00:00Z",
"requested_at": "2026-07-28T14:02:11Z"
}
}
}
```
### subscription.plan\_change\_canceled
Sent when a pending plan change is undone or aborted. The `reason` inside `plan_change` is `MERCHANT_UNDO` when the merchant sent `"plan_change": null`, or `TARGET_PLAN_CANCELED` when the target plan was canceled before the change applied — the subscription stays on its current plan in both cases. If the subscription itself is canceled, the pending change is silently discarded and only `subscription.cancel` is sent.
```json JSON theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"type": "subscription",
"type_event": "subscription.plan_change_canceled",
"account_id": "c24d6c92-99a7-40bb-bc7b-efc40337f9f4",
"retry": 0,
"version": 2,
"data": {
"subscription": {
"code": "e98ef674-9baa-4f7a-8da4-4c812c4749a4",
"name": "Subscription",
"status": "ACTIVE",
"amount": {
"currency": "USD",
"type": "FIXED",
"value": 9.99
},
"customer_payer": {
"code": "a9f9140a-1216-481c-8356-1a125078f905"
}
},
"plan_change": {
"plan_id": "1904911d-5df9-429e-8488-ad41abea1a4d",
"plan_name": "Pro",
"reason": "MERCHANT_UNDO"
}
}
}
```
### subscription.plan\_changed
Sent when a plan change takes effect. `previous_plan_id` identifies the plan the subscription moved away from; the embedded subscription already reflects the new plan.
A scheduled change is applied at the renewal that first bills the new plan, in place — the embedded subscription keeps the same `code`. `POST /v1/subscriptions/{id}/plan` instead replaces the subscription: the payload carries a new `code` with `previous_subscription_id` set, and a separate `subscription.cancel` (`cancellation_source: PLAN_CHANGE`) fires for the original.
```json JSON theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"type": "subscription",
"type_event": "subscription.plan_changed",
"account_id": "c24d6c92-99a7-40bb-bc7b-efc40337f9f4",
"retry": 0,
"version": 2,
"data": {
"subscription": {
"code": "e98ef674-9baa-4f7a-8da4-4c812c4749a4",
"name": "Subscription",
"status": "ACTIVE",
"plan_id": "1904911d-5df9-429e-8488-ad41abea1a4d",
"amount": {
"currency": "USD",
"type": "FIXED",
"value": 29.99
},
"customer_payer": {
"code": "a9f9140a-1216-481c-8356-1a125078f905"
}
},
"previous_plan_id": "0804911d-5df9-429e-8488-ad41abea1a4c"
}
}
```
### Renewal charges and failures (no `subscription.error`)
There is **no `subscription.error` webhook**. Yuno does not emit a subscription event when a renewal charge fails. Renewal-charge outcomes — successful rebills and failed/declined attempts — are delivered as `payment.purchase` webhooks tied to the subscription, with the result carried in the `status`/`sub_status` fields. Subscribe to `payment.purchase` to track renewal results. `$0`/trial cycles emit no payment webhook.
The renewal **charge** itself is always signaled by a `payment.purchase` webhook, never by a subscription webhook. The `payments` array inside the subscription object is currently always empty in webhook payloads. `subscription.active` is sent once (at `billing_cycles.current` = 2), not on every renewal.
There is one case where a failed renewal does produce a subscription webhook. If the subscription has `retries.cancel_on_exhausted_retries` set to `true`, then once retries for that cycle end without a successful payment the subscription is canceled and a single [`subscription.cancel`](#subscriptioncancel) is emitted with `cancellation_source` set to `RETRIES_EXHAUSTED`. This is still not a `subscription.error` — the individual failed attempts remain `payment.purchase` webhooks. Only the final cancellation is signaled on the subscription.
## Onboardings
```json Example theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"type": "onboarding",
"type_event": "onboarding.error",
"account_id": "c2721496-89c3-497a-8e24-0872c2e1386c",
"retry": 0,
"version": 2,
"data": {
"id": "d1fbb1d7-321d-4855-b603-135cd4f4ab82",
"type": "TWO_STEP_ONBOARDING",
"workflow": "DIRECT",
"description": null,
"status": "ERROR",
"response_message": null,
"callback_url": "https://merchant.example.com/webhook/onboarding",
"provider": {
"id": "STRIPE",
"connection_id": "caaeba00-05c8-4295-815f-1736c2b0b622",
"redirect_url": null,
"recipient_id": "",
"onboarding_url": "",
"legal_entity": null
},
"documentation": [],
"legal_representatives": [],
"withdrawal_methods": {
"bank": {
"code": "002",
"branch": "002",
"branch_digit": null,
"account": "9876543210",
"account_digit": null,
"account_type": "CHECKINGS",
"routing": "021000022",
"country": "US",
"currency": "USD",
"payout_schedule": null
}
},
"requirements": [
{
"field": "withdrawal_methods.bank.routing",
"message": "Invalid routing number",
"status": "REJECTED"
}
],
"terms_of_service": null,
"metadata": [],
"recipient": {
"id": "c5e0d5d5-5346-4fea-9b3e-97e825b11b07",
"national_entity": "INDIVIDUAL",
"merchant_recipient_id": "12b2b154-3ac9-4255-848a-46c8e3a70476",
"entity_type": "PRIVATE",
"first_name": "Juan",
"last_name": "Pérez",
"legal_name": null,
"email": "juan.perez@example.com",
"date_of_birth": "1990-01-15",
"country": "CO",
"website": "https://juanperez.com",
"industry": "Technology",
"merchant_category_code": "5734",
"document": {
"document_number": "1234567890",
"document_type": "CC"
},
"phone": {
"country_code": "57",
"number": "3001234567"
},
"address": {
"address_line_1": "Carrera 7 # 32-16",
"address_line_2": "Oficina 201",
"city": "Bogotá",
"country": "CO",
"state": "Cundinamarca",
"zip_code": "110311",
"neighborhood": "Centro"
},
"withdrawal_methods": {
"bank": {
"code": "001",
"branch": "004",
"branch_digit": "123",
"account": "1234567890",
"account_digit": "123",
"account_type": "SAVINGS",
"routing": "021000021",
"country": "CO",
"currency": "COP",
"payout_schedule": null
}
},
"documentation": [],
"legal_representatives": [
{
"merchant_reference": "REP_001",
"first_name": "María",
"last_name": "González",
"email": "maria.gonzalez@example.com",
"date_of_birth": "1985-05-20",
"country": "CO",
"nationality": "CO",
"title": "CEO",
"publicly_exposed_person": false,
"ultimate_beneficial_owner": true,
"document": {
"document_number": "0987654321",
"document_type": "CC"
},
"phone": {
"country_code": "+57",
"number": "3109876543"
},
"address": {
"address_line_1": "Calle 26 # 13-19",
"address_line_2": null,
"city": "Bogotá",
"country": "CO",
"state": "Cundinamarca",
"zip_code": "110311",
"neighborhood": null
}
}
],
"created_at": "2025-10-21T16:29:36.997492Z",
"updated_at": "2025-10-21T16:29:36.997505Z"
},
"created_at": "2025-10-21T16:29:41.88055Z",
"updated_at": "2025-10-21T16:29:42.571531Z",
"expires_at": null
}
}
```
## Marketplace Split Transfers
### split\_transfer.succeeded
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"type": "split_transfer",
"type_event": "succeeded",
"trace_id": "abc123",
"transfer_id": "TRF_7kB2mQ9xPnL4vR",
"account_id": "2c05976d-1234-1234-1234-6421883de48d",
"retry": 0,
"version": 1,
"data": {
"id": "TRF_7kB2mQ9xPnL4vR",
"recipient_id": "550e8400-e29b-41d4-a716-446655440000",
"amount": {
"currency": "USD",
"value": 150.00
},
"status": "SUCCEEDED",
"description": "Weekly marketplace earnings",
"merchant_reference": "TRANSFER-2026-02-15-001",
"metadata": [],
"provider": "adyen",
"transactions": [
{
"code": "7ac2c5f3-7c79-4e99-b45e-aa5952620188",
"type": "SPLIT_TRANSFER",
"status": "SUCCEEDED",
"provider_transfer_id": "tr_1T9eKVIiMnPsFcbbRTb8ObsZ",
"created_at": "2026-03-11T04:25:06.229027Z",
"updated_at": "2026-03-11T04:25:07.917364Z"
}
],
"created_at": "2026-03-11T04:25:06.208761Z",
"updated_at": "2026-03-11T04:25:07.928000342Z",
"completed_at": "2026-03-11T04:25:07.927971142Z"
}
}
```
### split\_transfer\_reverse.succeeded
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"type": "split_transfer_reverse",
"type_event": "succeeded",
"trace_id": "xyz789",
"transfer_id": "TRF_7kB2mQ9xPnL4vR",
"account_id": "2c05976d-1234-1234-1234-6421883de48d",
"retry": 0,
"version": 1,
"data": {
"id": "TRF_REV_9xPnL4vR7kB2mQ",
"recipient_id": "550e8400-e29b-41d4-a716-446655440000",
"amount": {
"currency": "USD",
"value": 50.00
},
"status": "SUCCEEDED",
"description": "Reversal of partial earnings",
"merchant_reference": "REVERSE-2026-02-16-001",
"metadata": [],
"provider": "adyen",
"transactions": [
{
"code": "8bd3d6f4-8d80-5f00-c56f-bb6063731299",
"type": "SPLIT_TRANSFER_REVERSE",
"status": "SUCCEEDED",
"provider_transfer_id": "tr_2U0fLWIjNoQtGdccSUc9PbtA",
"created_at": "2026-03-12T05:26:07.229027Z",
"updated_at": "2026-03-12T05:26:08.917364Z"
}
],
"created_at": "2026-03-12T05:26:07.208761Z",
"updated_at": "2026-03-12T05:26:08.928000342Z",
"completed_at": "2026-03-12T05:26:08.927971142Z"
}
}
```
## Refunds
```json Example theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"type": "payment",
"type_event": "payment.refund",
"account_id": "2e7bc710-32db-43b2-a7aa-21c3bd031f8f",
"retry": 0,
"version": 2,
"data": {
"payment": {
"code": "f7bcf40d-7255-4e13-9dba-df6fa09be6b2",
"id": "f7bcf40d-7255-4e13-9dba-df6fa09be6b2",
"idempotency_key": "49eda7f2-bb05-437f-9676-7c8bb6df94a9",
"organization_code": "c60f4657-6ec5-487c-b9d5-a5fdbc887a1f",
"account_code": "2e7bc710-32db-43b2-a7aa-21c3bd031f8f",
"account_id": "2e7bc710-32db-43b2-a7aa-21c3bd031f8f",
"description": "Test goold",
"country": "CO",
"status": "REFUNDED",
"sub_status": "REFUNDED",
"order_id": "0000023",
"merchant_order_id": "0000023",
"created_at": "2025-09-03T21:51:08.633533Z",
"updated_at": "2025-09-03T21:53:40.368707Z",
"amount": {
"currency": "COP",
"value": 30000,
"refunded": 30000,
"captured": 0,
"currency_conversion": {
"code": "ccv_01HVK3Z9M2...",
"cardholder_currency": "USD",
"cardholder_amount": 7.50,
"cardholder_accepted": true,
"rate": 4000.00,
"rate_margin_percentage": 3.0,
"rate_source": "BLOOMBERG",
"provider": "PLANET",
"description": "DCC quote for retail shopping.",
"created_at": "2026-04-24T14:30:00Z",
"expires_at": "2026-04-24T15:30:00Z",
"status": "APPLIED",
"error_reason": null,
"provider_data": {
"terminal_id": "TERM_99"
}
}
},
"checkout": {
"session": null,
"sdk_action_required": false
},
"customer_payer": {
"code": "1ca7351f-8855-4765-bbe5-bd5110809cf2",
"id": "1ca7351f-8855-4765-bbe5-bd5110809cf2",
"organization_customer_external_id": "1756936266",
"merchant_customer_id": "1756936266",
"first_name": "Willintong",
"last_name": "Ramirez",
"gender": "M",
"date_of_birth": "1990-02-28",
"email": "willintong.ramirez@y.uno",
"nationality": "AR",
"ip_address": null,
"device_fingerprint": null,
"third_party_session_id": null,
"device_fingerprints": [],
"browser_info": null,
"document": {
"document_number": "123554332",
"document_type": "PASS"
},
"billing_address": {
"address_line_1": "Calle 34 # 56 - 78",
"address_line_2": "Apartamento 502, Torre I",
"city": "Bogotá",
"country": "CO",
"state": "Cundinamarca",
"zip_code": "111111",
"neighborhood": null
},
"shipping_address": {
"address_line_1": "Calle 34 # 56 - 78",
"address_line_2": "Apartamento 502, Torre I",
"city": "Bogotá",
"country": "CO",
"state": "Cundinamarca",
"zip_code": "111111",
"neighborhood": null
},
"phone": {
"country_code": "57",
"number": "3132450765"
},
"merchant_customer_created_at": null,
"geo_location": {
"latitude": null,
"longitude": null
},
"merchant_customer_validations": {
"account_is_verified": true,
"email_is_verified": true,
"phone_is_verified": true
}
},
"additional_data": {
"order": {
"shipping_amount": 10.35,
"fee_amount": 40.5,
"tip_amount": null,
"items": [
{
"id": "123AD",
"name": "Skirt",
"quantity": 3,
"unit_amount": 20,
"category": "Clothes",
"brand": "XYZ",
"sku_code": "8765432109",
"manufacture_part_number": "XYZ123456",
"image_url": null
}
],
"taxes": [],
"shipping": null,
"account_funding": null,
"tickets": [],
"fulfillment": null,
"discounts": [],
"sales_channel": null
},
"airline": null,
"transportations": null,
"seller_details": null
},
"transactions": {
"code": "14a2ca8a-07bd-47b2-9070-4868ab176ac8",
"id": "14a2ca8a-07bd-47b2-9070-4868ab176ac8",
"type": "REFUND",
"status": "SUCCEEDED",
"category": "CARD",
"amount": 30000,
"provider_id": "YUNO_TEST_PAYMENT_GW",
"response_code": "SUCCEEDED",
"merchant_reference": "REFUND_001",
"response_message": "Transaction successful",
"reason": "REQUESTED_BY_CUSTOMER",
"description": "Test refund",
"created_at": "2025-09-03T21:53:40.230290Z",
"updated_at": "2025-09-03T21:53:40.346884Z",
"payment_method": {
"token": null,
"type": "CARD",
"vaulted_token": null,
"vault_on_success": false,
"parent_payment_method_type": null,
"payment_method_detail": {
"card": {
"verify": false,
"capture": false,
"installments": 1,
"installments_plan_id": null,
"first_installment_deferral": null,
"installments_amount": null,
"installments_type": null,
"soft_descriptor": "",
"authorization_code": "658571",
"retrieval_reference_number": "",
"acquirer_reference_number": "",
"voucher": null,
"card_data": {
"holder_name": "Pepito Perez",
"iin": "41111111",
"lfd": "1111",
"number_length": 16,
"security_code_length": 3,
"brand": "VISA",
"issuer_name": "CONOTOXIA SP Z O O",
"issuer_code": null,
"country_code": "PL",
"category": "CLASSIC",
"type": "DEBIT",
"three_d_secure": {
"version": null,
"electronic_commerce_indicator": null,
"cryptogram": null,
"transaction_id": null,
"directory_server_transaction_id": null,
"pares_status": null,
"acs_id": null,
"strong_customer_authentication_exemptions": null
},
"network_token": null,
"fingerprint": "3d49ec9d-e941-4eaf-80eb-251469d66108",
"expiration_month": 3,
"expiration_year": 26
},
"stored_credentials": {
"reason": null,
"usage": null,
"subscription_agreement_id": null,
"network_transaction_id": null
}
},
"wallet": null,
"bnpl": null,
"bank_transfer": null,
"ticket": null,
"payment_link": null
}
},
"provider": {
"provider_transaction_id": "a9908f18-71ca-458b-9f94-f63e55bdc94a"
},
"provider_data": {
"raw_response": {
"message": "provider response"
},
"id": "YUNO_TEST_PAYMENT_GW",
"transaction_id": "a9908f18-71ca-458b-9f94-f63e55bdc94a",
"account_id": null,
"status": null,
"status_detail": null,
"response_message": null,
"response_code": "SUCCEEDED",
"third_party_transaction_id": null,
"third_party_account_id": null,
"iso8583_response_code": null,
"iso8583_response_message": null
},
"connection_data": {
"id": null,
"name": null
},
"simplified_mode": false,
"third_party_session_id": null,
"receipt": false,
"receipt_language": null,
"receipt_url": null,
"device_fingerprint": null
},
"transactions_history": [],
"callback_url": null,
"workflow": "DIRECT",
"split_marketplace": [],
"payment_link_code": "",
"subscription_id": null,
"subscription": null,
"fraud_screening": null,
"metadata": [],
"routing_rules": {
"smart_routing": false,
"monitors": false,
"condition": {
"id": 148781,
"name": null,
"description": null
}
}
}
}
}
```
## HMAC - Authorization
```http theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
POST /your-webhook-endpoint HTTP/1.1
Host: your-server.com
Content-Type: application/json
x-api-key: your-api-key
x-secret: your-secret
x-hmac-signature: YwPQ1b2RcBkDGo32XvDS7R+/nMDuDIRjvQlsak72EMBY=
{
"live": "false",
"notificationItems": [
{
"NotificationRequestItem": {
"additionalData": {
"expiryDate": "12/2012",
"authCode": "1234",
"cardSummary": "7777",
"totalFraudScore": "10"
},
"amount": {
"currency": "EUR",
"value": 10100
},
"eventCode": "AUTHORISATION",
"eventDate": "2022-11-15T20:04:11+01:00",
"merchantAccountCode": "AcmeCorp",
"merchantReference": "2931874530016873",
"paymentMethod": "visa",
"pspReference": "CU4KVBAYAPFG0ZZKR",
"success": "true"
}
}
]
}
```
# Verify Webhook Signatures (HMAC)
Source: https://docs.y.uno/docs/webhooks/verify-webhook-signatures-hmac
Verifies webhook authenticity by validating the HMAC SHA256 signature sent in the request header
Webhook signature verification using HMAC (Hash-based Message Authentication Code) ensures that webhooks sent to your server actually originate from Yuno and haven't been intercepted or modified during transmission. This adds an extra layer of security beyond authentication methods like OAuth.
While OAuth provides authentication (verifying who is sending the request), HMAC signatures provide:
* **Data integrity**: Confirms the webhook payload hasn't been tampered with
* **Authenticity**: Verifies the webhook genuinely comes from Yuno
* **Protection**: Guards against man-in-the-middle attacks and replay attacks
* **Compliance**: Helps meet PCI DSS requirements for handling sensitive payment data
## How HMAC signatures work
When Yuno sends a webhook to your server:
1. **Signature generation**: Yuno creates an HMAC signature by hashing the webhook payload with your client secret key using the SHA-256 algorithm
2. **Header inclusion**: The signature is included in the `x-hmac-signature` HTTP header
3. **Verification**: Your server extracts the signature from the header, recreates it using the same payload and secret key, then compares
4. **Validation**: If the signatures match, the webhook is authentic and unaltered
## Configuration
To enable HMAC signature verification, check **Use HMAC Authentication** when creating or editing a webhook in the [Yuno dashboard](https://dashboard.y.uno/).
See [Configure Webhooks](/docs/webhooks/configure-webhooks) for step-by-step instructions on accessing the webhook configuration panel.
## What changes with HMAC
When HMAC signature verification is enabled, Yuno webhooks include an additional `x-hmac-signature` HTTP header. The webhook JSON payload remains unchanged.
### Example webhook request with HMAC
```http theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
POST /your-webhook-endpoint HTTP/1.1
Host: your-server.com
Content-Type: application/json
x-api-key: your-api-key
x-secret: your-secret
x-hmac-signature: K7gNU3sdo+OL0wNhqoVWhr3g6s1xYv72ol/pe/Unols=
{
"type": "payment",
"type_event": "payment.purchase",
"account_id": "2c05976d-1234-1234-1234-6421883de48d",
"retry": 0,
"version": 2,
"data": {
"payment": {
"id": "a546c566-1703-4fba-b334-c46e89bc97f7",
"status": "SUCCEEDED"
}
}
}
```
## Verification code example
Verify the `x-hmac-signature` header using the **raw request body** (before parsing JSON) and the same secret configured for the webhook in the Yuno dashboard.
**Node.js (Express):** use a body parser that keeps the raw body for the webhook route (for example, `express.raw()` for that path), then:
```javascript theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
const crypto = require('crypto');
function verifyWebhookSignature(rawBody, signatureHeader, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(rawBody)
.digest('base64');
return crypto.timingSafeEqual(
Buffer.from(signatureHeader, 'base64'),
Buffer.from(expected, 'base64')
);
}
// Example: const isValid = verifyWebhookSignature(req.body, req.headers['x-hmac-signature'], process.env.WEBHOOK_SECRET);
```
**Python:** use the raw request body bytes and the `x-hmac-signature` header:
```python theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
import hmac
import hashlib
import base64
def verify_webhook_signature(raw_body: bytes, signature_header: str, secret: str) -> bool:
expected = base64.b64encode(
hmac.new(secret.encode(), raw_body, hashlib.sha256).digest()
).decode()
return hmac.compare_digest(signature_header, expected)
```
If the computed signature does not match the header, reject the webhook (for example, return 401).
## Related documentation
* [Configure Webhooks](/docs/webhooks/configure-webhooks)
* [Webhook Examples](/reference/payments/payment-examples/index)
* [Webhooks Overview](/docs/webhooks)
# Declined Payment Calls
Source: https://docs.y.uno/reference/ai-caller/declined-payment-calls
openapi/ai-caller/declined-payment-calls.json POST /smart-support/external/payments/recover
Initiates bulk AI calls and WhatsApp messages to recover customers with declined payments
This endpoint allows you to initiate large-scale processing of calls and WhatsApp messages related to declined payments. To use the endpoint, you have to provide an object containing detailed information about the declined payment.
# Initiate Recovery Outreach for Abandoned User Flows
Source: https://docs.y.uno/reference/ai-caller/initiate-recovery-outreach-for-abandoned-user-flows
openapi/ai-caller/initiate-recovery-outreach-for-abandoned-user-flows.json POST /smart-support/external/payments
Notifies Yuno's recovery agent to contact a customer who abandoned checkout before completing payment
This endpoint allows merchants to notify Yuno's Recovery Agent when a user abandons their purchase flow, such as during product selection or after initiating checkout, before completing a payment. The submitted data enables Yuno to follow up with the user via call or WhatsApp to encourage completion of the transaction.
## Security and compliance
* **Authentication**: API access requires a valid API key provided in the request headers.
* **Data Protection**: All data must be transmitted over HTTPS. Yuno adheres to relevant data protection regulations, including **GDPR** and **LGPD**.
* **Data Usage**: Submitted data will be used solely for the purpose of customer engagement and will not be stored beyond the necessary duration.
**Use Case Example**
A user named Jane Doe adds a pair of wireless headphones to her cart on a merchant's website but abandons the checkout process. The merchant's system detects this and sends the relevant payload to Yuno’s Recovery Agent API. Yuno then initiates a WhatsApp message to Jane, reminding her of the items left in her cart and offering assistance to complete the purchase.
# Airline Information
Source: https://docs.y.uno/reference/airline-information
Lists standard passenger type, fare class, and loyalty tier values for airline related payment fields
On this page, you will find airline information you may need when using Yuno API endpoints. It covers passenger types, fare class codes, and loyalty tiers. Use this page to understand and have access to standard values for each information category.
## Passenger type
| `passenger_type` | Description |
| ---------------- | -------------- |
| `A` | Adult |
| `C` | Child |
| `I` | Infant or Baby |
## Fare class code
The values can be a letter (A-Z) but may vary depending on the airline's definition. Type: String (MAX:1; MIN:1).
## Loyalty tier
| `loyalty_tier` | Description |
| -------------- | --------------------------- |
| `1` | High classification level |
| `2` | Second classification level |
| `3` | Third classification level |
# API Enums & Identifiers
Source: https://docs.y.uno/reference/api-enums
Master reference for core routing enums and parameters used in the Yuno API.
This page serves as the **Single Source of Truth (SSOT)** for all key enums and identifiers across the Yuno platform. Consolidating these values here ensures consistency, streamlines API development, and provides a centralized location for developers to lookup valid parameters for all endpoints.
## Core API Identifiers
These are the primary standard identifiers used for transaction routing, payment method processing, and integration strategy selection across Yuno.
For an exhaustive, category-by-category mapping of which **Payment Method Types** are supported by which **Providers**, please refer directly to our comprehensive [Payment Catalog](/reference/payment-type-list). The tables below serve as flat lookup references for individual enum parameter values.
### Provider ID (`provider_id`)
Identifies the payment service provider (PSP) or gateway. This value is used in routing rules and API requests to target a specific provider.
### Payment Method Type (`payment_method_type`)
Specifies the payment instrument or channel used (e.g., credit card, bank transfer, digital wallet, BNPL).
### Enrollment Flow (`type_of_enrollment_flow`)
Defines the integration strategy used when enrolling new payment methods for customers.
| Value | Description |
| :------------- | :-------------------------------------------------- |
| `SDK_FULL` | Full enrollment flow managed by Yuno SDK. |
| `SDK_LITE` | Lite enrollment flow with partial UI control. |
| `SDK_HEADLESS` | Headless enrollment flow for full UI customization. |
| `DIRECT_API` | Enrollment via direct API calls (Server-to-Server). |
## Related References
To explore other specific classifications, please visit their dedicated references:
Passenger types and loyalty classifications.
3DS authentication outcomes.
All supported payment methods.
# Close Account
Source: https://docs.y.uno/reference/banking-connectivity/accounts/close-account-banking
openapi/banking-connectivity/accounts/close-account-banking.json DELETE /banking/accounts/{account_id}
Close a bank account for an onboarded entity through Banking Connectivity
Close a Banking Connectivity account. The account must have a zero balance before it can be closed.
# Create Account
Source: https://docs.y.uno/reference/banking-connectivity/accounts/create-account-banking
openapi/banking-connectivity/accounts/create-account-banking.json POST /banking/accounts
Create a bank account for an entity whose onboarding status has succeeded
Create a bank account for an onboarded entity. The onboarding referenced by `onboarding_id` must have `status: SUCCEEDED`.
The response includes region-specific banking identifiers. See [Account identifiers by region](/reference/banking-connectivity#account-identifiers-by-region) for which fields are returned per region.
# Get Account Details
Source: https://docs.y.uno/reference/banking-connectivity/accounts/get-account-details-banking
openapi/banking-connectivity/accounts/get-account-details-banking.json GET /banking/accounts/{account_id}
Retrieve the details and region-specific identifiers of a bank account
Retrieve the details of an existing Banking Connectivity account, including balance information, banking identifiers, and supported payment rails.
# Update Account
Source: https://docs.y.uno/reference/banking-connectivity/accounts/update-account-banking
openapi/banking-connectivity/accounts/update-account-banking.json PATCH /banking/accounts/{account_id}
Update the details of an existing bank account under Banking Connectivity
Update an existing Banking Connectivity account. Only include the fields you want to change.
# Create Entity (Banking Connectivity)
Source: https://docs.y.uno/reference/banking-connectivity/entities-banking-connectivity/create-entity
openapi/banking-connectivity/entities-banking-connectivity/create-entity.json POST /banking/entities
Create an individual or business entity for banking connectivity onboarding
Create a Yuno entity representing an individual or organization. Set `national_entity` to `INDIVIDUAL` or `ENTITY` and provide the corresponding `entity_detail` sub-object. See [Entity types](/reference/banking-connectivity#entity-types) for details.
Sensitive fields like `tax_id` and `document_number` are masked in responses (only last 4 digits returned).
# Get Entity Details (Banking Connectivity)
Source: https://docs.y.uno/reference/banking-connectivity/entities-banking-connectivity/get-entity-details
openapi/banking-connectivity/entities-banking-connectivity/get-entity-details.json GET /banking/entities/{entity_id}
Retrieve the details of an existing individual or business entity
Retrieve the details of an existing entity. Sensitive fields are masked in the response.
# Update Entity (Banking Connectivity)
Source: https://docs.y.uno/reference/banking-connectivity/entities-banking-connectivity/update-entity
openapi/banking-connectivity/entities-banking-connectivity/update-entity.json PATCH /banking/entities/{entity_id}
Update the details of an existing individual or business entity
Update an existing entity's information. Only include the fields you want to change. The `national_entity` type cannot be changed after creation.
# Cancel Entity Onboarding (Banking Connectivity)
Source: https://docs.y.uno/reference/banking-connectivity/entity-onboarding-banking-connectivity/cancel-entity-onboarding
openapi/banking-connectivity/entity-onboarding-banking-connectivity/cancel-entity-onboarding.json POST /banking/entities/{entity_id}/onboardings/{onboarding_id}/cancel
Cancel an in-progress entity onboarding with a banking connectivity provider
Cancel a pending onboarding. Only onboardings that have not reached a terminal status can be cancelled. See [Onboarding statuses](/reference/banking-connectivity#onboarding-statuses) for which statuses are terminal.
# Create Entity Onboarding (Banking Connectivity)
Source: https://docs.y.uno/reference/banking-connectivity/entity-onboarding-banking-connectivity/create-entity-onboarding
openapi/banking-connectivity/entity-onboarding-banking-connectivity/create-entity-onboarding.json POST /banking/entities/{entity_id}/onboardings
Onboard an existing entity with a banking connectivity provider using KYC or KYB documentation
Onboard an existing [Entity](/reference/create-entity) with a Banking Connectivity provider.
## Onboarding types
* **`ONE_STEP`**: Submit all information, compliance declarations, risk assessment, and documents at once. The provider processes immediately.
* **`PREVIOUSLY_ONBOARDED`**: Generate an internal Yuno onboarding ID without contacting the provider. Use when the entity was already onboarded externally.
For `ONE_STEP`, include `compliance_declaration`, `risk_assessment`, `source_of_funds`, and `documentation`. See [Documentation types](/reference/banking-connectivity#documentation-types) for the full list of supported document types.
Monitor progress via [Get Entity Onboarding Status](/reference/get-entity-onboarding-status) or webhook events. See [Onboarding statuses](/reference/banking-connectivity#onboarding-statuses) for the full status lifecycle.
# Get Entity Onboarding Status (Banking Connectivity)
Source: https://docs.y.uno/reference/banking-connectivity/entity-onboarding-banking-connectivity/get-entity-onboarding-status
openapi/banking-connectivity/entity-onboarding-banking-connectivity/get-entity-onboarding-status.json GET /banking/entities/{entity_id}/onboardings/{onboarding_id}
Retrieve the current status of an entity's onboarding with the provider
Retrieve the current status of an entity onboarding. See [Onboarding statuses](/reference/banking-connectivity#onboarding-statuses) for the full status lifecycle.
# Update Entity Onboarding
Source: https://docs.y.uno/reference/banking-connectivity/entity-onboarding-banking-connectivity/update-entity-onboarding
openapi/banking-connectivity/entity-transfers-banking-connectivity/update-entity-onboarding.json PATCH /banking/entities/{entity_id}/onboardings/{onboarding_id}
Update the documentation or details of an existing entity onboarding
Update an existing onboarding with new compliance declarations, risk assessment results, or additional documentation. Typically used when the onboarding is in `PENDING_ADDITIONAL_DOCUMENTATION` status.
# Cancel Entity Transfer (Banking Connectivity)
Source: https://docs.y.uno/reference/banking-connectivity/entity-transfers-banking-connectivity/cancel-entity-transfer
openapi/banking-connectivity/entity-transfers-banking-connectivity/cancel-entity-transfer.json POST /banking/accounts/{account_id}/transfers/{transfer_id}/cancel
Cancel a pending outgoing transfer before it reaches the payment network
Cancel a pending transfer. Only transfers in `PENDING` status can be cancelled. Transfers that have moved to `PROCESSING` or later statuses cannot be cancelled.
# Get Entity Transfer Status (Banking Connectivity)
Source: https://docs.y.uno/reference/banking-connectivity/entity-transfers-banking-connectivity/get-entity-transfer-status
openapi/banking-connectivity/entity-transfers-banking-connectivity/get-entity-transfer-status.json GET /banking/accounts/{account_id}/transfers/{transfer_id}
Retrieve the current status of a bank transfer initiated through an account
Retrieve the current status and details of a transfer. See [Transfer statuses](/reference/banking-connectivity#transfer-statuses) for the full status lifecycle.
# Initiate Entity Transfer (Banking Connectivity)
Source: https://docs.y.uno/reference/banking-connectivity/entity-transfers-banking-connectivity/initiate-entity-transfer
openapi/banking-connectivity/entity-transfers-banking-connectivity/initiate-entity-transfer.json POST /banking/transfers
Initiate an outgoing or internal book transfer from a banking connectivity account
Initiate an outgoing transfer from a Banking Connectivity account. For external transfers, provide the `destination_account` details. For internal (book) transfers between accounts on the same provider, set `destination_account_id` to the target account.
The required fields in `destination_account` depend on the region. See [Payment rails](/reference/banking-connectivity#payment-rails) and [Account identifiers by region](/reference/banking-connectivity#account-identifiers-by-region) for details.
The response returns `202 Accepted` with a `PENDING` status. Monitor progress via [Get Entity Transfer Status](/reference/get-entity-transfer-status) or webhook events. See [Transfer statuses](/reference/banking-connectivity#transfer-statuses) for the full status lifecycle.
# Banking Connectivity
Source: https://docs.y.uno/reference/banking-connectivity/index
Unified API to create bank accounts, run transfers, and onboard entities across multiple banking providers
Yuno Banking Connectivity provides a unified API to create bank accounts, process transfers, and manage entity onboarding across multiple banking providers. A single integration gives you access to providers across the US, UK, Australia, and EU.
## Integration flow
Follow these steps to go from entity creation to fund transfers:
1. **Create an entity**: Register an individual or business using [Create Entity](/reference/create-entity).
2. **Onboard the entity**: Submit KYC/KYB documentation through [Create Entity Onboarding](/reference/create-entity-onboarding).
3. **Wait for onboarding approval**: Monitor the onboarding status via [Get Entity Onboarding Status](/reference/get-entity-onboarding-status) or listen for webhook events.
4. **Create a bank account**: Once onboarding succeeds, open an account with [Create Account](/reference/create-account-banking).
5. **Initiate transfers**: Send funds using [Initiate Entity Transfer](/reference/initiate-entity-transfer).
## Entity types
The `national_entity` field determines the entity structure:
| Value | Description | Required detail |
| ------------ | -------------------------- | -------------------------------------------------------------------------------- |
| `INDIVIDUAL` | A natural person | `entity_detail.individual` with name, DOB, tax info, and identity document |
| `ENTITY` | A business or organization | `entity_detail.entity` with business name, type, tax info, and beneficial owners |
## Onboarding types
| Type | Behavior |
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| `ONE_STEP` | Submits all information, compliance declarations, risk assessment, and documents at once. The provider processes immediately. |
| `PREVIOUSLY_ONBOARDED` | Generates an internal Yuno onboarding ID without contacting the provider. Use when the entity has already been onboarded externally. |
## Onboarding statuses
| Status | Description | Terminal |
| ---------------------------------- | --------------------------------------------- | -------- |
| `CREATED` | Onboarding record created | No |
| `PENDING` | Submitted to provider, awaiting review | No |
| `PENDING_ADDITIONAL_DOCUMENTATION` | Provider requires more documents | No |
| `UNDER_REVIEW` | Provider is reviewing the submission | No |
| `SUCCEEDED` | Onboarding approved: entity can open accounts | Yes |
| `FAILED` | Onboarding failed due to errors | Yes |
| `DECLINED` | Provider declined the entity | Yes |
| `CANCELLED` | Onboarding cancelled by merchant | Yes |
| `EXPIRED` | Onboarding expired before completion | Yes |
## Transfer statuses
| Status | Description | Terminal |
| ------------ | -------------------------------------------------- | -------- |
| `PENDING` | Transfer created, awaiting processing | No |
| `PROCESSING` | Transfer submitted to the payment network | No |
| `COMPLETED` | Funds successfully delivered | Yes |
| `FAILED` | Transfer failed | Yes |
| `CANCELLED` | Transfer cancelled before processing | Yes |
| `REVERSED` | Completed transfer was reversed (e.g., ACH return) | Yes |
**Note:** Instant payment rails (RTP, FPS, NPP) skip the `PROCESSING` state and go directly from `PENDING` to `COMPLETED` or `FAILED`.
## Payment rails
Available payment rails depend on the provider's region:
| Region | Rail | Speed |
| ------------- | -------------- | --------------------- |
| **US** | `ACH_STANDARD` | 1–3 business days |
| **US** | `ACH_SAME_DAY` | Same day |
| **US** | `WIRE` | Same day |
| **US** | `RTP` | Instant |
| **UK** | `FPS` | Near-instant |
| **UK** | `CHAPS` | Same day (high value) |
| **UK** | `BACS` | 3 business days |
| **Australia** | `NPP` | Near-instant |
| **Australia** | `PAYTO` | Near-instant |
| **Australia** | `BPAY` | 1–2 business days |
## Account identifiers by region
Responses from [Create Account](/reference/create-account-banking) include region-specific banking identifiers:
| Region | Fields returned |
| --------- | ------------------------------------- |
| US | `account_number`, `routing_number` |
| UK | `account_number`, `sort_code`, `iban` |
| Australia | `account_number`, `bsb` |
| EU | `iban`, `swift` |
## Documentation types
When creating or updating an onboarding, the `documentation` array accepts items with a `type` discriminator. Populate the matching sub-object for each type:
| Type | Sub-object | Description |
| ------------------------ | ------------------------ | ------------------------------------------------------------------------------------------------------------------- |
| `IDENTITY_DOCUMENT` | `identity_document` | Passport, driver's license, national ID, or state ID with front/back images |
| `PROOF_OF_ADDRESS` | `proof_of_address` | Utility bill, bank statement, lease, mortgage, or tax document |
| `BANK_STATEMENT` | `bank_statement` | Bank statement with period and account details |
| `BUSINESS_DOCUMENT` | `business_document` | Articles of incorporation, business license, EIN confirmation, operating agreement, or certificate of good standing |
| `TAX_INFORMATION` | `tax_information` | W9, 1099, tax return, SSN card, ITIN letter, EIN confirmation, or VAT certificate |
| `FINANCIAL_DOCUMENT` | `financial_document` | Balance sheet, P\&L statement, cash flow statement, or financial audit |
| `BIOMETRIC_VERIFICATION` | `biometric_verification` | Facial recognition, fingerprint, voice, or iris scan with liveness check |
| `EMPLOYMENT_INFORMATION` | `employment_information` | Employment status, employer details, occupation, and income |
All file uploads use base64 encoding with `file_name`, `content_type`, and `content` fields.
## Webhook events
Yuno sends webhook notifications to your configured endpoint for the following events. For general webhook setup, delivery behavior, and retry logic, see [Webhooks Overview](/docs/webhooks#banking-connectivity-webhook-events).
### Entity events
* `banking.entity.created`: Entity created
* `banking.entity.updated`: Entity updated
* `banking.entity.deleted`: Entity deleted
### Onboarding events
* `banking.onboarding.created`: Onboarding created
* `banking.onboarding.pending`: Submitted, awaiting review
* `banking.onboarding.pending_additional_documentation`: More documents required
* `banking.onboarding.succeeded`: Onboarding approved
* `banking.onboarding.failed`: Onboarding failed
* `banking.onboarding.declined`: Provider declined
* `banking.onboarding.cancelled`: Merchant cancelled
* `banking.onboarding.expired`: Onboarding expired
### Account events
* `banking.account.created`: Account created
* `banking.account.updated`: Account updated
* `banking.account.activated`: Account activated
* `banking.account.closed`: Account closed
### Transfer events (outgoing)
* `banking.transfer.pending`: Transfer pending
* `banking.transfer.processing`: Transfer processing
* `banking.transfer.completed`: Transfer completed
* `banking.transfer.failed`: Transfer failed
* `banking.transfer.cancelled`: Transfer cancelled
* `banking.transfer.reversed`: Transfer reversed
### Transfer events (incoming)
* `banking.transfer.incoming.pending`: Incoming transfer pending settlement
* `banking.transfer.incoming.completed`: Incoming transfer settled
Incoming transfer notifications are sent to your endpoint at `{merchant_base_URL}/v1/banking/transfers`. See [Webhook Notifications](/reference/webhook-notifications-banking) for the payload structure.
## Error codes
| Code | HTTP Status | Description |
| ---------------------- | ----------- | ---------------------------------------------------- |
| `NOT_AUTHENTICATED` | 401 | Missing or invalid API keys |
| `AuthenticationFail` | 401 | Authentication failed |
| `BadRequest` | 400 | Malformed request |
| `VALIDATION_ERROR` | 400 | Request validation failed |
| `DUPLICATE_ENTITY` | 409 | Entity with this `merchant_entity_id` already exists |
| `ENTITY_NOT_FOUND` | 404 | Entity not found |
| `ONBOARDING_NOT_FOUND` | 404 | Onboarding not found |
| `ACCOUNT_NOT_FOUND` | 404 | Account not found |
| `INSUFFICIENT_BALANCE` | 422 | Insufficient funds for transfer |
| `CURRENCY_MISMATCH` | 422 | Transfer currency does not match account currency |
| `PROVIDER_ERROR` | 502 | Error from the banking provider |
| `PROVIDER_TIMEOUT` | 504 | Provider did not respond in time |
| `InternalError` | 500 | Internal server error |
| `TooManyRequests` | 429 | Rate limit exceeded |
Error responses follow this format:
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"code": "ERROR_CODE",
"messages": ["Human-readable error message"],
"http_code": 400
}
```
# Webhook Notifications
Source: https://docs.y.uno/reference/banking-connectivity/webhooks/webhook-notifications-banking
openapi/banking-connectivity/webhooks/webhook-notifications-banking.json POST /banking/transfers
Receive incoming transfer notifications with sender, amount, rail, and status details
Yuno sends incoming transfer notifications to your endpoint at `{merchant_base_URL}/v1/banking/transfers`. Your endpoint must return a `200 OK` response with `{"received": true}`.
Notifications include sender details, transfer amount, payment rail, and status. Yuno retries on `5xx` responses and timeouts with exponential backoff.
See [Webhook events](/reference/banking-connectivity#webhook-events) for the complete list of Banking Connectivity webhook event types.
# Create Checkout
Source: https://docs.y.uno/reference/checkout-builder/create-checkout
openapi/checkout-builder/create-checkout.json POST /checkouts
Creates a new custom checkout as a published clone of the account's default checkout
This API is in **Beta**. Endpoints and schemas may change without prior notice.
The new checkout is born **`PUBLISHED`** as a clone of the account's default: payment methods — including icon/name overrides and required-field condition sets — are copied; general settings and styling inherit the account baseline until the checkout's first [Publish](/reference/checkout-builder/publish-checkout-configuration). It is never created as the account's default.
The response's top-level `id` is the `checkout_code` used by the [Fetch](/reference/checkout-builder/fetch-checkout-configuration), [Publish](/reference/checkout-builder/publish-checkout-configuration), and [Manage Checkout Lifecycle](/reference/checkout-builder/manage-checkout-lifecycle) endpoints.
`name` is required, non-blank, and unique per account — a duplicate is rejected with `409`. If the account has no default checkout to clone from, the request is rejected with `404`.
# Fetch Checkout Configuration
Source: https://docs.y.uno/reference/checkout-builder/fetch-checkout-configuration
openapi/checkout-builder/fetch-checkout-configuration.json GET /checkouts/{checkout_code}
Retrieves the configuration of a checkout session by its checkout code
This API is in **Beta**. Endpoints and schemas may change without prior notice.
# List Checkouts
Source: https://docs.y.uno/reference/checkout-builder/list-checkouts
openapi/checkout-builder/list-checkouts.json GET /checkouts
Lists the account's custom checkouts (summaries only): ids, names, statuses, and which one is the default
This API is in **Beta**. Endpoints and schemas may change without prior notice.
Results are sorted default-first, then most recently updated, and include `ARCHIVED` checkouts. Each item's `id` is the `checkout_code` used by the [Fetch](/reference/checkout-builder/fetch-checkout-configuration) and [Publish](/reference/checkout-builder/publish-checkout-configuration) endpoints.
Pagination is opt-in: without `page` or `size` the response is a bare array with every matching checkout; sending either switches the response to a paginated envelope (`data` + `pagination`, where `total` is the full filtered count).
# Manage Checkout Lifecycle
Source: https://docs.y.uno/reference/checkout-builder/manage-checkout-lifecycle
openapi/checkout-builder/manage-checkout-lifecycle.json PATCH /checkouts/{checkout_code}
Renames, publishes, unpublishes, archives, restores, or promotes a checkout by its checkout code
This API is in **Beta**. Endpoints and schemas may change without prior notice.
The body carries any combination of `name`, `description`, `status`, and `is_default` — at least one field is required. Metadata (`name`/`description`) is editable in **any** status, including `ARCHIVED`; configuration and styling of an archived checkout stay frozen (the [Publish](/reference/checkout-builder/publish-checkout-configuration) endpoint rejects it).
## Lifecycle state machine
```mermaid theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
stateDiagram-v2
[*] --> PUBLISHED: Create Checkout
PUBLISHED --> NOT_PUBLISHED: unpublish
NOT_PUBLISHED --> PUBLISHED: publish
PUBLISHED --> ARCHIVED: archive
NOT_PUBLISHED --> ARCHIVED: archive
ARCHIVED --> NOT_PUBLISHED: restore (step 1 of 2)
```
* **Publish** (`status: PUBLISHED`) is only valid from `NOT_PUBLISHED`.
* **Restore is two-step**: an `ARCHIVED` checkout goes back to draft first (`status: NOT_PUBLISHED`), then can be published (`status: PUBLISHED`). A direct `ARCHIVED → PUBLISHED` patch is rejected with `400 INVALID_STATUS_TRANSITION`.
* Patching to the **current** status is also rejected with `400`.
* **Promote** (`is_default: true`) force-publishes the checkout from any state — including `ARCHIVED` — and atomically demotes the previous default. When sent together with `status`, the promotion wins and `status` is ignored. `is_default: false` is rejected with `400`; demote a default by promoting another checkout.
* The **default checkout is guarded**: archiving or unpublishing it is rejected with `409` so the account's storefront is never left without a live checkout.
# Overview
Source: https://docs.y.uno/reference/checkout-builder/overview
Programmatically configure a merchant's Yuno checkout — payment methods, conditions, required fields, and styling — via Yuno's public B2B API.
**BETA — access is granted per account.** This API is in closed beta and is enabled per account. Your account must be explicitly allowlisted; requests from a non-allowlisted account are rejected with `401`. Endpoints are stable in shape but subject to additive changes during the BETA window.
Configure a merchant's Yuno checkout **server-to-server** — the same configuration surface that powers the Yuno Dashboard's Checkout Builder — so a partner can manage its merchants' checkouts programmatically, without using the Yuno UI:
* **Payment methods** — which methods are shown and in what display order
* **Conditions** — per-method rules (currency, country, amount, metadata) that gate when a method appears
* **Required fields** — per-method form field configuration (CVV, installments, billing address, etc.) for both the enrolled (saved-card) and non-enrolled (first-time) flows
* **General settings** — accepted document types per country
* **Styling & SDK settings** — colors, fonts, button shapes, logos, and Payment Link branding
## Base URL
| Environment | Base URL |
| ----------- | --------------------------- |
| Production | `https://api.y.uno` |
| Sandbox | `https://api-sandbox.y.uno` |
All examples in this reference use the production base URL. The sandbox host accepts the same endpoints and payload shapes.
## Authentication
Every request is authenticated with your merchant API credentials and scoped to a single account.
| Header | Required | Description |
| -------------------- | -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `PUBLIC-API-KEY` | Yes | Merchant public API key. Found in your Yuno dashboard under **Settings → API Keys**. |
| `PRIVATE-SECRET-KEY` | Yes | Merchant private secret key, paired with the public key. Server-side only — never embed it in client-side code. |
| `X-Account-Code` | Yes | UUID of the merchant account. The account is resolved **only** from this header (never from the request body or path) and must be in the beta allowlist. |
| `X-Idempotency-Key` | No | Optional client key, up to 64 characters. Best-effort — see [Idempotency](#idempotency). |
| `Content-Type` | Yes (POST/PUT/PATCH) | `application/json` |
The organization is resolved by Yuno from your credentials — **do not send** an organization header. Missing/invalid credentials, or a non-allowlisted account, return `401`.
## Endpoints
A **custom checkout** is identified by a `checkout_code` (a UUID). It is created, listed, read, written, and lifecycle-managed through the same resource — five operations:
| Method | Path | Purpose |
| ------- | ------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
| `POST` | `/v1/checkouts` | Create a new custom checkout as a published clone of the account's default. |
| `GET` | `/v1/checkouts` | List the account's custom checkouts (summaries only): ids, names, statuses, default flag. Supports filters and opt-in pagination. |
| `GET` | `/v1/checkouts/{checkout_code}` | Fetch the full custom checkout — configuration **and** styling, together. |
| `PUT` | `/v1/checkouts/{checkout_code}` | Publish configuration and/or styling. |
| `PATCH` | `/v1/checkouts/{checkout_code}` | Manage the lifecycle — rename, publish, unpublish, archive, restore, or promote to default. |
`{checkout_code}` must be a valid UUID; other values are rejected with `400` before any processing.
You obtain a `checkout_code` by calling [Create Checkout](/reference/checkout-builder/create-checkout) (the response's top-level `id`), by calling [List Checkouts](/reference/checkout-builder/list-checkouts) (each item's `id` is the `checkout_code`), or when the custom checkout is created in the Yuno dashboard / embedded Checkout Builder.
## Key behaviors
**`PUT` is a sparse upsert for configuration, not a full replace.** Payment methods omitted from the `payment_methods` array retain their previous state — they are not removed or disabled. To disable a method, include it with `is_active: false`.
* **Configuration — sparse update.** Only the payment methods you include are updated; omitted methods keep their previous state. Publishing updates existing methods only — **new payment methods cannot be created** via the API (contact your Yuno TAM to add methods).
* **Styling — partial merge.** Fields you omit (or send as `null`) are preserved; only the fields you include change. Partial styling updates are safe — you do not need to resend the entire `styles` object. To reset styling to defaults, use `flags.force_default_styles`.
* **Order is driven by `order_to_show`**, not by array position. Lower values are shown first.
* **At most one condition set per required field.** Sending more than one condition set on a field is rejected with `400` (`conditions_to_override must contain at most one condition set`).
* **Enrolled and non-enrolled flows are independent.** For CARD, configure the non-enrolled flow via `fields` and the enrolled (saved-card) flow via `enrollment_fields`. To leave one flow untouched, pass an empty array for that side.
* **Lifecycle transitions follow a state machine.** Publish is only valid from `NOT_PUBLISHED`; an `ARCHIVED` checkout is restored in two steps (`NOT_PUBLISHED` first, then `PUBLISHED`); the default checkout cannot be archived or unpublished. See [Manage Checkout Lifecycle](/reference/checkout-builder/manage-checkout-lifecycle) for the full rules.
* **Changes take effect immediately.** Validate payloads against the sandbox base URL before applying to production.
* Each request body is validated independently; on any rule failure the whole request is rejected with a single aggregated `400` and nothing is applied. See the [Publish](/reference/checkout-builder/publish-checkout-configuration) endpoint for the full request shape, allowed values, and error catalog.
## Errors
Validation failures return HTTP `400` with a single aggregated body listing every problem found:
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"code": "INVALID_PARAMETERS",
"messages": [
"payment_methods[0].order_to_show must be >= 0",
"styles.global.accent_color must be a 6- or 8-digit hex color (#RRGGBB or #RRGGBBAA)"
]
}
```
Other statuses: `401` (authentication / account not allowlisted), `404` (checkout not found for the account, or no default checkout to clone on create), `409` (duplicate checkout name, or archiving/unpublishing the default checkout). The full per-rule error catalog is on the [Publish](/reference/checkout-builder/publish-checkout-configuration) page.
## Idempotency
`X-Idempotency-Key` is **best-effort**: the header is accepted and validated (up to 64 characters), but replays of the same key are not guaranteed to be de-duplicated. Design your integration for at-least-once delivery.
# Publish Checkout Configuration
Source: https://docs.y.uno/reference/checkout-builder/publish-checkout-configuration
openapi/checkout-builder/publish-checkout-configuration.json PUT /checkouts/{checkout_code}
Publishes configuration and/or styling for a checkout by its checkout code
This API is in **Beta**. Endpoints and schemas may change without prior notice.
# Create Checkout Session
Source: https://docs.y.uno/reference/checkout-sessions/create-checkout-session
openapi/checkout-sessions/create-checkout-session.json POST /checkout/sessions
Creates a checkout session tied to a customer, used to initialize a payment through the SDK
This request creates a checkout session using the unique identifier generated when the `customer` resource was created.
If your workflow requires sending the `additional_data` object, it can be sent as part of the checkout session.
# Retrieve Checkout Session
Source: https://docs.y.uno/reference/checkout-sessions/retrieve-checkout-session
openapi/checkout-sessions/retrieve-checkout-session.json GET /checkout/sessions/{id}
Retrieves the details of a checkout session using its unique identifier
This request retrieves a checkout session using its unique identifier.
# Retrieve Payment Methods for Checkout
Source: https://docs.y.uno/reference/checkout-sessions/retrieve-payment-methods-for-checkout
openapi/checkout-sessions/retrieve-payment-methods-for-checkout.json GET /checkout/sessions/{checkout_session}/payment-methods
Retrieves the available payment methods associated with an existing checkout session
This request retrieves a checkout session using the unique identifier that was generated when the session was first created.
# The Checkout Session Object
Source: https://docs.y.uno/reference/checkout-sessions/the-checkout-session-object
Describes the checkout session object and its attributes, including amount, country, and installments
This object represents a checkout session that can be created to make a payment. You can Create a Checkout Session using the id generated when the Customer resource was created.
Create a checkout session is only required for flow **SDK\_CHECKOUT**.\
Only one payment is supported per each checkout session.
The checkout session expires 5 hours after its creation.
## Attributes
The unique identifier of the checkout session (MAX 64; MIN 36).
Example: 9104911d-5df9-429e-8488-ad41abea1a4b
The unique identifier of the customer (MAX 64; MIN 36).
Example: 9104911d-5df9-429e-8488-ad41abea1a4b
The unique identifier of the customer's order (MAX 255; MIN 3).
Example: 1234
The description of the payment (MAX 255; MIN 3).
Example: Purchase in Pepito market
The URL where to redirect the customer after the payment (MAX 526; MIN 3).
Example: [https://www.company.com/customer\_1231324](https://www.company.com/customer_1231324)
Country where the transaction must be processed (MAX 2; MIN 2; ISO 3166-1 ).
Possible enum values: Check the Country reference.
Checkout Session creation date and time (MAX 27; MIN 27; ISO 8601 ).
Example: 2022-05-09T20:46:54.786342Z
Specifies the payment amount object, with the value and currency.
The currency used to make the payment (MAX 3; MIN 3; ISO 4217 ).
Possible enum values: Check the Country reference.
The payment amount (multiple of 0.0001).
Example: 23.5676
Specifies a list of metadata objects. You can add up to 50 metadata objects. To use metadata to drive routing logic, it must be set here at the Checkout Session level.
Specifies a metadata key and the respective value.
Specifies one metadata key.
Example: age
Specifies the value for the defined metadata key.
Example: 28
\[Optional] The object to send the installment plan created in Yuno to show your customers and let them choose from. This optional field is used in case a particular installments plan needs to be used in the session. if not sent, we will display the installment plan created for the account for each scenario, if any.
Specifies a plan id created in Yuno to show your customer in the checkout session. If not defined, we will use the ones created for the account, if applicable. (MAX 64 ; MIN 64).
Possible enum values: Check the Country reference.
Installments to show the customer in with the checkout\_session. This optional struct is used in case a particular installments plan needs to be used in the session and does not have an installments plan created for it. if not sent, we will display the installment plan created for the account for each scenario, if any.
Specifies an installment available for the checkout session.
The number of monthly installments shoppers can choose
Example: 3
The rate the end user sees at checkout.
Example: 1.5
# Update Checkout Session
Source: https://docs.y.uno/reference/checkout-sessions/update-checkout-session
openapi/checkout-sessions/update-checkout-session.json PATCH /checkout/sessions/{checkout_session}
Updates fields on an existing checkout session, modifying only the values you send
Update an existing checkout session with this endpoint. Only fields you send will be updated.
# Create Campaign
Source: https://docs.y.uno/reference/communications-campaigns/create-campaign
openapi/communications-campaigns/create-campaign.json POST /campaigns
Creates a new communications campaign for declined payment recovery, defaulting to INACTIVE status.
Creates a new campaign. If no `status` is provided, campaigns default to `INACTIVE`.
See the [campaign object reference](/reference/communications-campaigns#campaign-object) for more information.
# Create Rules
Source: https://docs.y.uno/reference/communications-campaigns/create-rules
openapi/communications-campaigns/create-rules.json POST /campaigns/{campaign_id}/rules
Creates one or more targeting rules that determine which declined payments trigger a campaign.
Creates one or more rules for a campaign. All active rules must pass for a payment to trigger the campaign (AND logic).
Visit the [conditional operators reference](/reference/communications-campaigns#conditional-operators-reference) for more information on how to use them.
# Get Campaign
Source: https://docs.y.uno/reference/communications-campaigns/get-campaign
openapi/communications-campaigns/get-campaign.json GET /campaigns/{campaign_id}
Retrieves a single communications campaign by ID, including its attached rules.
Retrieves a single campaign by ID, including its rules.
# Get Rule
Source: https://docs.y.uno/reference/communications-campaigns/get-rule
openapi/communications-campaigns/get-rule.json GET /campaigns/{campaign_id}/rules/{rule_id}
Retrieves a specific targeting rule attached to a communications campaign.
Retrieves a specific rule from a campaign.
# Communications Campaigns
Source: https://docs.y.uno/reference/communications-campaigns/index
Explains the Campaigns API for automating declined payment recovery communications via WhatsApp or phone.
Learn how to integrate with the Yuno Campaigns API to automate personalized communications for declined payment recovery.
## Endpoints
**Base URL**: `https://api-sandbox.y.uno/v1`
* [Create campaign](/reference/create-campaign)
* [Get campaign](/reference/get-campaign)
* [List campaigns](/reference/list-campaigns)
* [Update campaign status](/reference/update-campaign-status)
* [Create rules](/reference/create-rules)
* [Get rule](/reference/get-rule)
* [Update rule](/reference/update-rule)
* [Update rule status](/reference/update-rule-status)
## Overview
The Campaigns API allows you to create automated communication campaigns that are triggered when a customer's payment is declined. When a payment event matches your campaign's targeting rules, Yuno automatically sends a personalized message to the customer through the configured channel (WhatsApp or phone call), helping recover the failed transaction.
### Key concepts
* **Campaign**: Defines who to target, through which channel, and when to send communications.
* **Rules**: Conditions attached to a campaign that determine which declined payments qualify. All active rules must pass for a payment to trigger the campaign (AND logic).
* **Schedule**: Controls the daily time window and timezone for sending communications.
* **Duration**: The start and end dates during which the campaign is active.
## How it works
```mermaid theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
flowchart TD
1[Payment declined] --> 2[Evaluate against active campaigns]
2 --> 3[Check all rules using AND logic]
3 --> 4{Rules pass?}
4 -->|Yes| 5[Send communication via channel]
4 -->|No| 6[Skip]
5 --> 7[Customer receives message or call]
```
**Example**: You create a campaign targeting declined payments in Colombia with amounts over 50,000 COP. When a Colombian customer's 80,000 COP payment is declined, Yuno automatically sends them a WhatsApp message with a personalized recovery suggestion.
## Authentication
All API requests require the following headers:
| Header | Description | Required |
| ---------------------- | -------------------------------------------------- | -------- |
| `X-Public-Api-Key` | Your merchant public API key | Yes |
| `X-Private-Secret-Key` | Your merchant private secret key | Yes |
| `Content-Type` | Must be `application/json` for POST/PATCH requests | Yes |
```bash theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
curl -X GET https://api-sandbox.y.uno/v1/campaigns \
-H "X-Public-Api-Key: your-public-api-key" \
-H "X-Private-Secret-Key: your-private-secret-key"
```
## Data models
### Campaign object
| Field | Type | Description |
| ------------------- | ------ | ------------------------------------------------------ |
| `id` | UUID | Unique campaign identifier |
| `name` | string | Campaign name |
| `account_id` | UUID | Yuno account ID |
| `organization_code` | UUID | Organization identifier |
| `country` | string | ISO 3166-1 alpha-2 country code |
| `channel` | enum | `WHATSAPP_MESSAGE` or `PHONE_CALL` |
| `focus` | string | Optional campaign focus descriptor |
| `schedule` | object | Scheduling configuration |
| `duration` | object | Campaign active period |
| `status` | string | `ACTIVE`, `PAUSED`, `COMPLETED`, or `CANCELLED` |
| `rules` | array | Rules attached to the campaign (included in GET by ID) |
| `created_at` | string | ISO 8601 creation timestamp |
| `updated_at` | string | ISO 8601 last update timestamp |
### Rule object
| Field | Type | Description |
| -------------- | ------ | ----------------------------------------------- |
| `id` | UUID | Unique rule identifier |
| `campaign_id` | UUID | ID of the campaign this rule belongs to |
| `rule_type` | string | Type of rule (see reference below) |
| `values` | array | Array of string values for comparison |
| `conditional` | string | Comparison operator (see reference below) |
| `metadata_key` | string | Metadata field name (only for `METADATA` rules) |
| `status` | string | `ACTIVE` or `INACTIVE` |
| `created_at` | string | ISO 8601 creation timestamp |
| `updated_at` | string | ISO 8601 last update timestamp |
### Rule types reference
Rules define which declined payments qualify for a campaign. All active rules on a campaign must pass (AND logic) for a communication to be triggered.
#### Payment data rules
These rules evaluate data directly available from the payment event.
| Rule Type | Values Format | Example |
| ----------------------------------------------------------- | ------------------------ | ------------------ |
| `AMOUNT` Filter by payment amount | `["number"]` | `["50000"]` |
| `CURRENCY` Filter by currency code | `["code"]` | `["COP"]` |
| `AMOUNT_AND_CURRENCY` Combined amount + currency check | `["amount", "currency"]` | `["50000", "COP"]` |
| `PAYMENT_STATUS` Filter by payment status | `["status"]` | `["DECLINED"]` |
#### Enriched data rules
These rules evaluate enriched transaction data (payment method, provider, card details, etc.).
| Rule Type | Values Format | Example |
| --------------------------------------------------------- | ----------------- | ---------------------- |
| `PAYMENT_METHOD` Filter by payment method type | `["method"]` | `["CARD"]` |
| `PROVIDER` Filter by payment provider ID | `["provider_id"]` | `["stripe"]` |
| `CARD_BIN` Filter by card BIN/IIN prefix | `["bin_prefix"]` | `["411111", "552345"]` |
| `RESPONSE_CODE` Filter by provider response code | `["code"]` | `["05", "51"]` |
| `ISO_RESPONSE_CODE` Filter by ISO 8583 response code | `["code"]` | `["51", "05"]` |
| `CATEGORY` Filter by transaction category | `["category"]` | `["ecommerce"]` |
#### Metadata rules
Evaluate custom metadata fields attached to the payment.
| Rule Type | Values Format | Requires `metadata_key` |
| --------------------------------------------------- | ------------- | ----------------------- |
| `METADATA` Filter by custom metadata key-value | `["value"]` | Yes |
**Example**: Target payments from a specific business vertical:
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"rule_type": "METADATA",
"metadata_key": "vertical",
"values": ["restaurant", "grocery"],
"conditional": "ONE_OF"
}
```
#### Rate limiting rules
Control communication frequency to avoid sending too many messages to the same user.
| Rule Type | Values Format | Example |
| ------------------------------------------------------------- | -------------- | ------- |
| `USER_COMMS_PER_DAY` Max communications per user per day | `["limit"]` | `["3"]` |
| `UNIQUE_BY_USER` One communication per user per campaign | Not applicable | - |
**Important notes on rate limiting rules**:
* Both `USER_COMMS_PER_DAY` and `UNIQUE_BY_USER` require a `user_id` field to be present in the payment metadata.
* `USER_COMMS_PER_DAY` does **not** require a `conditional` field. Only provide `values` with the daily limit.
* `UNIQUE_BY_USER` requires **neither** `values` nor `conditional`. Simply include the `rule_type`.
### Conditional operators reference
| Conditional | Applicable Rule Types | Values Count |
| ------------------------------------------------------------ | ------------------------------------------- | ---------------------------------- |
| `EQUAL` Exact match | All | 1 |
| `NOT_EQUAL` Does not match | All | 1 |
| `ONE_OF` Matches any value in list | All | 1+ |
| `NOT_ONE_OF` Matches none of the values | All | 1+ |
| `IN` Same as `ONE_OF` | All | 1+ |
| `GREATER_THAN` Greater than (numeric) | `AMOUNT`, `AMOUNT_AND_CURRENCY`, `METADATA` | 1 |
| `GREATER_THAN_OR_EQUAL` Greater than or equal (numeric) | `AMOUNT`, `AMOUNT_AND_CURRENCY`, `METADATA` | 1 |
| `LESS_THAN` Less than (numeric) | `AMOUNT`, `AMOUNT_AND_CURRENCY`, `METADATA` | 1 |
| `LESS_THAN_OR_EQUAL` Less than or equal (numeric) | `AMOUNT`, `AMOUNT_AND_CURRENCY`, `METADATA` | 1 |
| `BETWEEN` Between two values, inclusive (numeric) | `AMOUNT`, `AMOUNT_AND_CURRENCY`, `METADATA` | 2 (or 3 for `AMOUNT_AND_CURRENCY`) |
| `CONTAINS` Contains substring (case-insensitive) | `METADATA` | 1+ |
| `STARTS_WITH` Starts with prefix | `CARD_BIN`, `METADATA` | 1+ |
> **Note on `BETWEEN` with `AMOUNT_AND_CURRENCY`**: When using `BETWEEN` with `AMOUNT_AND_CURRENCY`, provide 3 values: `["min", "max", "currency"]`. For other rule types, provide 2 values: `["min", "max"]`.
## Getting started
### Step 1: Create a campaign
Define who to target, which channel to use, and when communications should be sent.
```bash theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
curl -X POST https://api-sandbox.y.uno/v1/campaigns \
-H "X-Public-Api-Key: your-public-api-key" \
-H "X-Private-Secret-Key: your-private-secret-key" \
-H "Content-Type: application/json" \
-d '{
"name": "Declined Payment Recovery - Colombia",
"account_id": "YOUR_ACCOUNT_ID",
"organization_code": "YOUR_ORGANIZATION_CODE",
"country": "CO",
"channel": "WHATSAPP_MESSAGE",
"schedule": {
"daily_start_time": "08:00",
"daily_end_time": "21:00",
"time_zone": "America/Bogota"
},
"duration": {
"start_at": "2025-07-01T00:00:00Z",
"end_at": "2026-07-01T00:00:00Z"
}
}'
```
> **Note**: The campaign is created with `ACTIVE` status by default. Save the returned `id` for the next step.
### Step 2: Add targeting rules
Define which declined payments should trigger this campaign. Use the campaign `id` from Step 1.
```bash theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
curl -X POST https://api-sandbox.y.uno/v1/campaigns/{campaign_id}/rules \
-H "X-Public-Api-Key: your-public-api-key" \
-H "X-Private-Secret-Key: your-private-secret-key" \
-H "Content-Type: application/json" \
-d '{
"rules": [
{
"rule_type": "PAYMENT_STATUS",
"values": ["DECLINED"],
"conditional": "EQUAL"
},
{
"rule_type": "CURRENCY",
"values": ["COP"],
"conditional": "EQUAL"
},
{
"rule_type": "AMOUNT",
"values": ["50000"],
"conditional": "GREATER_THAN"
},
{
"rule_type": "USER_COMMS_PER_DAY",
"values": ["2"]
}
]
}'
```
This campaign will now trigger a WhatsApp message when:
* Payment status is `DECLINED` **AND**
* Currency is `COP` **AND**
* Amount is greater than 50,000 **AND**
* The user has received fewer than 2 communications today
### Step 3: Verify your campaign
Confirm the campaign is set up correctly with its rules.
```bash theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
curl -X GET https://api-sandbox.y.uno/v1/campaigns/{campaign_id} \
-H "X-Public-Api-Key: your-public-api-key" \
-H "X-Private-Secret-Key: your-private-secret-key"
```
### Step 4: Monitor and manage
* **Pause** a campaign temporarily: `PATCH` with `{"status": "PAUSED"}`
* **Resume** a paused campaign: `PATCH` with `{"status": "ACTIVE"}`
* **Disable a specific rule** without deleting it: `PATCH /rules/{rule_id}/status` with `{"status": "INACTIVE"}`
* **End** a campaign permanently: `PATCH` with `{"status": "COMPLETED"}`
## Use case examples
### 1. Basic declined payment recovery
Send a WhatsApp message to customers in Mexico whose card payments are declined.
**[Campaign](/reference/create-campaign)**:
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"name": "Mexico Card Recovery",
"account_id": "YOUR_ACCOUNT_ID",
"organization_code": "YOUR_ORGANIZATION_CODE",
"country": "MX",
"channel": "WHATSAPP_MESSAGE",
"focus": "payment_recovery",
"schedule": {
"daily_start_time": "09:00",
"daily_end_time": "20:00",
"time_zone": "America/Mexico_City"
},
"duration": {
"start_at": "2025-08-01T00:00:00Z",
"end_at": "2026-08-01T00:00:00Z"
}
}
```
**[Rules](/reference/create-rules)**:
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"rules": [
{
"rule_type": "PAYMENT_STATUS",
"values": ["DECLINED"],
"conditional": "EQUAL"
},
{
"rule_type": "PAYMENT_METHOD",
"values": ["CARD"],
"conditional": "EQUAL"
}
]
}
```
### 2. High-value transaction recovery via phone call
Call customers whose transactions above 500 USD were declined.
**[Campaign](/reference/create-campaign)**:
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"name": "High Value Recovery - Phone",
"account_id": "YOUR_ACCOUNT_ID",
"organization_code": "YOUR_ORGANIZATION_CODE",
"country": "CO",
"channel": "PHONE_CALL",
"focus": "payment_recovery",
"schedule": {
"daily_start_time": "09:00",
"daily_end_time": "18:00",
"time_zone": "America/Bogota"
},
"duration": {
"start_at": "2025-08-01T00:00:00Z",
"end_at": "2026-08-01T00:00:00Z"
}
}
```
**[Rules](/reference/create-rules)**:
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"rules": [
{
"rule_type": "PAYMENT_STATUS",
"values": ["DECLINED"],
"conditional": "EQUAL"
},
{
"rule_type": "AMOUNT_AND_CURRENCY",
"values": ["500", "USD"],
"conditional": "GREATER_THAN"
},
{
"rule_type": "USER_COMMS_PER_DAY",
"values": ["1"]
}
]
}
```
### 3. Provider-specific recovery with amount range
Target declined payments from a specific provider within an amount range.
**[Rules](/reference/create-rules)**:
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"rules": [
{
"rule_type": "PAYMENT_STATUS",
"values": ["DECLINED"],
"conditional": "EQUAL"
},
{
"rule_type": "PROVIDER",
"values": ["stripe", "adyen"],
"conditional": "ONE_OF"
},
{
"rule_type": "AMOUNT",
"values": ["10000", "500000"],
"conditional": "BETWEEN"
},
{
"rule_type": "CURRENCY",
"values": ["COP"],
"conditional": "EQUAL"
}
]
}
```
### 4. Metadata-based segmentation
Target specific customer segments using payment metadata (e.g., business vertical or customer tier).
**[Rules](/reference/create-rules)**:
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"rules": [
{
"rule_type": "PAYMENT_STATUS",
"values": ["DECLINED"],
"conditional": "EQUAL"
},
{
"rule_type": "METADATA",
"metadata_key": "vertical",
"values": ["restaurant", "grocery"],
"conditional": "ONE_OF"
},
{
"rule_type": "METADATA",
"metadata_key": "customer_tier",
"values": ["premium", "gold"],
"conditional": "ONE_OF"
},
{
"rule_type": "UNIQUE_BY_USER"
}
]
}
```
### 5. Exclude specific response codes
Send recovery messages for all declined payments except those with specific response codes that indicate fraud or permanent issues.
**[Rules](/reference/create-rules)**:
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"rules": [
{
"rule_type": "PAYMENT_STATUS",
"values": ["DECLINED"],
"conditional": "EQUAL"
},
{
"rule_type": "ISO_RESPONSE_CODE",
"values": ["14", "43", "59"],
"conditional": "NOT_ONE_OF"
}
]
}
```
> **Note**: ISO codes `14` (invalid card number), `43` (stolen card), and `59` (suspected fraud) are excluded since these should not receive recovery communications.
## Error handling
All error responses follow a consistent format:
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"code": 400,
"message": "Descriptive error message",
"details": "Additional context (optional)"
}
```
### HTTP status codes
| Code | Description | Common Causes |
| ----- | --------------------- | ---------------------------------------------------------------------------------------------------------- |
| `400` | Bad Request | Invalid UUID, missing required fields, invalid query parameters |
| `404` | Not Found | Campaign or rule does not exist |
| `422` | Unprocessable Entity | Validation failed (e.g., invalid rule type, invalid conditional for rule type, `end_at` before `start_at`) |
| `500` | Internal Server Error | Unexpected server error |
### Common validation errors
| Error | Cause | Solution |
| ------------------------- | ------------------------------------------- | --------------------------------------------------------------------------------------------------------- |
| Invalid campaign\_id | Non-UUID path parameter | Use the UUID returned from campaign creation |
| Invalid rule\_type | Unrecognized rule type value | See [Rule Types Reference](#rule-types-reference) |
| Invalid conditional | Conditional not valid for rule type | See [Conditional Operators Reference](#conditional-operators-reference) |
| BETWEEN requires 2 values | `values` array has wrong number of elements | Provide exactly 2 values: `["min", "max"]` (or 3 for `AMOUNT_AND_CURRENCY`: `["min", "max", "currency"]`) |
| metadata\_key required | `METADATA` rule without `metadata_key` | Add `metadata_key` field |
| Invalid status transition | Attempting to change from a terminal status | `COMPLETED` and `CANCELLED` are final states |
# List Campaigns
Source: https://docs.y.uno/reference/communications-campaigns/list-campaigns
openapi/communications-campaigns/list-campaigns.json GET /campaigns
Lists communications campaigns with optional filtering and pagination.
Lists campaigns with optional filtering and pagination.
# Update Campaign Status
Source: https://docs.y.uno/reference/communications-campaigns/update-campaign-status
openapi/communications-campaigns/update-campaign-status.json PATCH /campaigns/{campaign_id}
Updates a campaign's status to pause, resume, complete, or cancel it.
Updates the status of a campaign. Use this to pause, resume, complete, or cancel a campaign.
## Status Transitions
* `ACTIVE` --> `PAUSED`, `COMPLETED`, `CANCELLED`
* `PAUSED` --> `ACTIVE`, `COMPLETED`, `CANCELLED`
* `COMPLETED` --> (terminal - no further transitions)
* `CANCELLED` --> (terminal - no further transitions)
# Update Rule
Source: https://docs.y.uno/reference/communications-campaigns/update-rule
openapi/communications-campaigns/update-rule.json PATCH /campaigns/{campaign_id}/rules/{rule_id}
Updates a campaign rule's type, values, conditional operator, or metadata key.
Updates a rule's type, values, conditional, or metadata key.
Visit the [conditional operators reference](/reference/communications-campaigns#conditional-operators-reference) for more information on how to use them.
See the [create rules](/reference/create-rules) endpoint for more examples.
# Update Rule Status
Source: https://docs.y.uno/reference/communications-campaigns/update-rule-status
openapi/communications-campaigns/update-rule-status.json PATCH /campaigns/{campaign_id}/rules/{rule_id}/status
Updates a campaign rule's status to activate or deactivate it without deleting it.
Updates a rule's type, values, conditional, or metadata key.
# Currency Conversion
Source: https://docs.y.uno/reference/conversion-rate/currency-conversion
Explains how Yuno's currency conversion service settles payments across merchant and customer currencies
Yuno's currency conversion service allows you to settle payments in both your currency and your customer's. Currency conversion is the process of converting one currency into another. It involves using exchange rates to determine the equivalent amount in the target currency.
### Benefits
* **Global Reach**: Allows businesses to operate internationally by accepting and making payments in multiple currencies.
* **Customer Convenience**: Customers can pay in their preferred currency, enhancing their buying experiences.
* **Cost Efficiency**: Optimizing conversion rates can reduce transaction costs.
* **Revenue Optimization**: Businesses can leverage favorable exchange rates to maximize profits.
### Some use Cases
* **E-commerce Platforms**: Online stores that sell products internationally use currency conversion to display prices in local currencies and process payments accordingly.
* **Remittance Services**: Companies that facilitate money transfers across borders rely on currency conversion to ensure recipients receive funds in their local currency.
* **Travel and Hospitality**: Businesses in this sector use currency conversion to handle payments from international travelers.
* **Investment Platforms**: Fintech platforms that offer trading in foreign stocks, bonds, or cryptocurrencies use currency conversion to manage investments across different currencies.
## Implementation
In Yuno, we connect different currency conversion providers, so you dont have to worry about the differences between each integration. The implementation of the service is going to depend on the currency conversion provider you choose to work with.
### Key Concepts
* **Exchange Rate**: The rate at which one currency can be exchanged for another. This can be a fixed rate or a floating rate that fluctuates based on market conditions.
* **Base Currency**: The currency you are converting from.
* **Cardholder Currency**: The currency you are converting to.
* **Conversion Spread**: The difference between the buy and sell rates, representing the profit margin for the entity providing the conversion service.
* **Real-Time Conversion**: Using up-to-date exchange rates to perform conversions at the exact time of the transaction.
### API implementation
In order to be able to use the currency conversion service you have two API implementations available.
#### Provider's rate service
The merchant can use the currency conversion service of an external provider and send the corresponding information directly in the payment in Yuno.
Example:
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
"amount": {
"currency": "USD",
"value": 1000.00,
"currency_conversion": {
"cardholder_currency": "QAR",
"cardholder_amount": 3640.00,
"cardholder_accepted": true,
"rate": 3.6400,
"rate_margin_percentage": 3.75,
"rate_source": "ECB",
"provider": "FEXCO",
"description": "You have chosen to pay in QAR. Amount: 3640.00 QAR. Rate: 3.6400.",
"created_at": "2026-04-24T14:30:00Z",
"expires_at": "2026-04-24T15:30:00Z"
}
}
```
## Parameter Reference
The following table describes the parameters for the `amount.currency_conversion` object:
### Request Fields
| Field | Type | Required | Description |
| ------------------------ | --------- | ----------- | ----------------------------------------------------------------------------------- |
| `cardholder_currency` | `string` | ✅ | Currency the cardholder is charged in. ISO 4217 alpha-3 code. |
| `cardholder_amount` | `number` | ✅ | Total amount billed to the cardholder in `cardholder_currency`. |
| `cardholder_accepted` | `boolean` | ✅ | Cardholder's explicit consent to the DCC offer. |
| `rate` | `number` | ✅ | Applied FX rate (markup included). |
| `rate_margin_percentage` | `number` | ✅ | Markup added over the wholesale rate, expressed as a percentage. |
| `rate_source` | `string` | Conditional | Wholesale benchmark used for the quote. Required when `rate_margin_percentage > 0`. |
| `provider` | `string` | ✅ | DCC provider that issued the quote (e.g., `FEXCO`, `PLANET`). |
| `description` | `string` | Optional | Verbatim disclosure text shown to the cardholder. |
| `created_at` | `string` | ✅ | Timestamp when the DCC provider issued the quote (ISO 8601). |
| `expires_at` | `string` | Optional | Timestamp when the quote expires (ISO 8601). |
### Webhook / Response Additions
| Field | Type | Description |
| --------------- | -------- | --------------------------------------------------------------------- |
| `code` | `string` | Yuno's internal identifier for this DCC record. |
| `status` | `string` | Lifecycle state of the conversion (e.g., `APPLIED`, `DECLINED`). |
| `error_reason` | `string` | Populated only when DCC could not be applied. |
| `provider_data` | `object` | Acquirer round-trip data returned by the underlying provider adapter. |
## Lifecycle Status
| Value | Meaning |
| ---------- | ------------------------------------------------------------------ |
| `QUOTED` | Quote received and validated; not yet applied to an authorization. |
| `APPLIED` | Quote was applied to the authorization successfully. |
| `EXPIRED` | Quote expired before it could be applied. |
| `DECLINED` | Cardholder declined the DCC offer. |
| `REVERSED` | Conversion was reversed as part of a cancellation or refund. |
In order to use this, please **contact your technical account manager** to make sure that the information is set properly.
# Get Conversion Rate
Source: https://docs.y.uno/reference/conversion-rate/get-conversion-rate
openapi/conversion-rate/get-conversion-rate.json POST /currency-conversion
Retrieves the currency conversion rate for a given transaction using an external provider
This page will help you get started with Currency conversions.
For more information on how to use the currency conversion service, please refer to the [Currency conversion page](/reference/currency-conversion) in the guides section.
# Country Reference
Source: https://docs.y.uno/reference/country-reference
Lists ISO country, currency, document type, and phone codes used across Yuno API endpoints
On this page, you will find the country's information you need when using Yuno API endpoints. The below table provides standard codes for the country's identification, currencies, document types used in each country, and phone codes. Use this page to understand and have access to standard values for each piece of information. Use the buttons below to go directly to the desired country list region.
## Americas
**(1)** *The number of digits after the decimal separator*
Name
Country code (ISO 3166-1 Alpha 2)
Currency code (ISO 4217 Alpha 3)
Currency decimal digits
(1)
Document type
Normalized type
Phone country calling code
Anguilla
`AI`
`XCD`
2
* **PAS** (Passport)
`passport`
1
Antigua and Barbuda
`AG`
`XCD`
2
* **PAS** (Passport)
`passport`
1
Argentina
`AR`
`ARS`
2
* **DNI** (Documento Nacional de Identidad)
* **CUIL** (Código Único de Identificación Laboral)
* **CUIT** (Código Único de Identificación Tributaria)
* **PAS** (Pasaporte)
* **CI** (Cédula de Identidad)
* **NIT** (Número de Identificación Tributaria)
* **PAS** (Pasaporte)
`national_id`, `tax_id_entity`, `passport`
591
Bonaire, Sint Eustatius and Saba
`BQ`
`USD`
2
* **PAS** (Passport)
`passport`
599
Brazil
`BR`
`BRL`
2
* **RG** (Registro Geral (Carteira de Identidade))
* **CPF** (Cadastro de Pessoas Físicas)
* **CNPJ** (Cadastro Nacional da Pessoa Jurídica)
* **CNH** (Carteira Nacional de Habilitação)
* **PAS** (Passaporte)
* **CI** (Cédula de Identidad y Electoral)
* **RNC** (Registro Nacional de Contribuyentes)
* **PAS** (Pasaporte)
`national_id`, `tax_id_entity`, `passport`
809/829/849
Ecuador
`EC`
`USD`
2
* **CI** (Cédula de Identidad)
* **RUC** (Registro Único de Contribuyentes)
* **PAS** (Pasaporte)
`national_id`, `tax_id_entity`, `passport`
593
El Salvador
`SV`
`USD`
2
* **DUI** (Documento Único de Identidad)
* **NIT** (Número de Identificación Tributaria)
* **PAS** (Pasaporte)
`national_id`, `tax_id_person`, `passport`
503
Falkland Islands (Malvinas)
`FK`
`FKP`
2
* **PAS** (Passport)
`passport`
500
French Guiana
`GF`
`EUR`
2
* **PAS** (Passport)
`passport`
594
Grenada
`GD`
`XCD`
2
* **PAS** (Passport)
`passport`
1
Guadeloupe
`GP`
`EUR`
2
* **PAS** (Passport)
`passport`
590
Guatemala
`GT`
`GTQ`
2
* **DPI** (Documento Personal de Identificación)
* **NIT** (Número de Identificación Tributaria)
* **PAS** (Pasaporte)
`national_id`, `tax_id_person`, `passport`
502
Guyana
`GY`
`GYD`
2
* **PAS** (Passport)
`passport`
592
Haiti
`HT`
`HTG`
2
* **PAS** (Passport)
`passport`
509
Honduras
`HN`
`HNL`
2
* **DNI** (Documento Nacional de Identificación)
* **TRN** (Registro Tributario Nacional)
* **PAS** (Pasaporte)
`national_id`, `tax_id_person`, `passport`
504
Jamaica
`JM`
`JMD`
2
* **PAS** (Passport)
`passport`
1
Martinique
`MQ`
`EUR`
2
* **PAS** (Passport)
`passport`
596
Mexico
`MX`
`MXN`
2
* **CURP** (Clave Única de Registro de Población)
* **RFC** (Registro Federal de Contribuyentes)
* **INE** (Credencial para Votar (INE))
* **PAS** (Pasaporte)
* **DNI** (Documento Nacional de Identidad)
* **NIE** (Número de Identidad de Extranjero)
* **NIF** (Número de Identificación Fiscal)
* **PAS** (Pasaporte)
## Antarctica
**(1)** *The number of digits after the decimal separator*
Name
Country code (ISO 3166-1 Alpha 2)
Currency code (ISO 4217 Alpha 3)
Currency decimal digits
(1)
Document type
Normalized type
Phone country calling code
Antarctica
`AQ`
`N/A`
2
* **PAS** (Passport)
`passport`
N/A
Bouvet Island
`BV`
`NOK`
2
* **PAS** (Passport)
`passport`
N/A
French Southern Territories
`TF`
`EUR`
2
* **PAS** (Passport)
`passport`
N/A
Heard Island and McDonald Islands
`HM`
`AUD`
2
* **PAS** (Passport)
`passport`
N/A
South Georgia and the South Sandwich Islands
`GS`
`GBP`
2
* **PAS** (Passport)
`passport`
N/A
# Create Customer Session
Source: https://docs.y.uno/reference/customer-sessions-enrollment/create-customer-session
openapi/customer-sessions-enrollment/create-customer-session.json POST /customers/sessions
Creates a customer session for enrolling and managing saved payment methods for future use
Creates a customer session for enrolling and managing payment methods. Use this to save cards, wallets, and other payment methods for future use. Requires a `customer_id` from [Create Customer](/reference/create-customer) .
# Enrollment Status
Source: https://docs.y.uno/reference/customer-sessions-enrollment/enrollment-workflow
Lists the possible statuses a payment method can have during the enrollment process
Yuno gives customers the possibility to enroll a payment method to use it for future purchases and have a seamless payment experience. That payment method enrollment can be used either in our [Full](/docs/sdks/overview/understanding-flows) or [Lite](/docs/sdks/overview/quickstart) payment implementation and could have one of the following statuses.
## Workflow
## Payment method status
| Status | Transaction Type | Description |
| :-------------------- | :--------------- | :---------------------------------------------------------- |
| `CREATED` | Enrollment | Initial state at the time of creating a payment method. |
| `EXPIRED` | Enrollment | The payment method has been expired. |
| `REJECTED` | Enrollment | Yuno has rejected the payment method enrollment. |
| `READY_TO_ENROLL` | Enrollment | The payment method is available for enrollment. |
| `DECLINED` | Enrollment | The payment method has been declined. |
| `CANCELED` | Enrollment | The payment method has been canceled. |
| `ENROLL_IN_PROCESS` | Enrollment | The payment method enrollment is being processed. |
| `ENROLLED` | Enrollment | The payment method enrollment has been successful. |
| `UNENROLL_IN_PROCESS` | Enrollment | The payment method unenrollment is being processed. |
| `UNENROLLED` | Enrollment | The payment method has been unenrolled. |
| `ERROR` | Enrollment | There was an error in the enrollment of the payment method. |
# The Customer Session Object
Source: https://docs.y.uno/reference/customer-sessions-enrollment/the-customer-session-object
Describes the customer session object and its attributes used for payment method enrollment
## Attributes
This object represents a customer session that can be created in order to enroll a customer's payment methods.
The customer session that has been created for the enrollment (MAX 64; MIN 36).
Example: fe50d39a-5a1c-11ed-9b6a-0242ac120002
The unique identifier of the customer (MAX 64; MIN 36).
Example: 3956053c-5a1d-11ed-9b6a-0242ac120002
The customer's country (MAX 2; MIN 2; ISO 3166-1 ).
Possible enum values: Check the Country reference.
The URL to redirect your customer after the enrollment is made in the provider´s environment (MAX 526; MIN 3).
Example: [www.your-url.com](http://www.your-url.com)
Customer Session creation date and time (MAX 27; MIN 27; ISO 8601 ).
Example: 2022-05-09T20:46:54.786342Z
# Create Customer
Source: https://docs.y.uno/reference/customers/create-customer
openapi/customers/create-customer.json POST /customers
Creates a customer resource with personal, billing, and shipping details for checkout initialization
This request creates a customer resource. You need to provide several parameters of the customer in the request body, including the unique identifier of the customer in the external merchant, personal information, as well as billing and shipping addresses.
Creating a customer generates a customer `id` that can be used to initialize the checkout.
**Important**
There are certain objects that are not mandatory when creating a "Customer". However the more information you provide, the approval, conversion and fraud prevention rates will be positively impacted.
# Delete Customer
Source: https://docs.y.uno/reference/customers/delete-customer
openapi/customers/delete-customer.json DELETE /customers/{customer_id}
Deletes or anonymizes a customer and triggers deletion with the associated payment providers
You can delete a customer via this API request. In addition to deleting or anonymizing the customer within Yuno, this request will also trigger the deletion process with the payment providers the customer has interacted with.
# Retrieve Customer
Source: https://docs.y.uno/reference/customers/retrieve-customer
openapi/customers/retrieve-customer.json GET /customers/{customer_id}
Retrieves customer details using the customer's unique Yuno identifier
This request enables you to retrieve details of customers based on their `id`, which needs to be provided in the request path.
# Retrieve Customer by External ID
Source: https://docs.y.uno/reference/customers/retrieve-customer-by-external-id
openapi/customers/retrieve-customer-by-external-id.json GET /customers
Retrieves customer details using the merchant assigned external customer identifier
This request enables you to retrieve details of customers based on their `merchant_customer_id`, which needs to be provided in the request path.
# The Customer Object
Source: https://docs.y.uno/reference/customers/the-customer-object
Describes the customer object and its attributes, including contact, address, and document data
This object represents a customer who will make payments using your service.
## Attributes
The unique identifier of the customer (MAX 64; MIN 36).
Example: faa89e18-5a11-11ed-9b6a-0242ac120002
The unique identifier of the customer in the external merchant (MAX 255; MIN 1).
Example: 50ca6f06-5a12-11ed-9b6a-0242ac120002
Customer´s registration date on the merchants platform (MAX 27; MIN 27 ISO 3166-1 ).
Example: 2022-05-09T20:46:54.786342Z
The customer's first name (MAX 255; MIN 1).
Example: John
The customer's last name (MAX 255; MIN 1).
Example: Doe
The customer's gender (MAX 2; MIN 1).
Possible enum values: `M`, `F` or `NB`
The customer's date of birth in the YYYY-MM-DD format (MAX 10; MIN 10).
Example: 1990-02-28
The customer's e-mail (MAX 255; MIN 3).
Example: [john.doe@email.com](mailto:john.doe@email.com)
The customer's nationality (MAX 2; MIN 2; ISO 3166-1 ).
Possible enum values: Check the Country reference.
The customer's country (MAX 2; MIN 2; ISO 3166-1 ).
Possible enum values: Check the Country reference.
Specifies the customer's document object, including its number and type.
The customer's document number (MAX 40; MIN 3).
Example: 1093333333
The customer's document type (MAX 6; MIN 2).
Possible enum values: Check the Country reference.
Specifies the customer's phone number object.
The country calling code of the customer's phone (MAX 3; MIN 1). Possible values: Check the Country reference .
Example: 57
The customer's phone number, without the country code (MAX 32; MIN 1).
Example: 3132450765
Specifies the customer's billing address object.
The primary billing address line of the customer (MAX 255; MIN 3).
Example: Calle 34 # 56 - 78
The secondary billing address line of the customer (MAX 255; MIN 3).
Example: Apartamento 502, Torre I
The city considered for the billing address (MAX 255; MIN 3).
Example: Bogotá
The country considered for the billing address (MAX 2; MIN 2; ISO 3166-1 ).
Possible enum values: Check the Country reference.
The state considered for the billing address (MAX 255; MIN 3; ISO 3166-2 ).
Example: Cundinamarca
The zipcode considered for the billing address (MAX 11; MIN 4).
Example: 111111
The neighborhood of the address line of the customer(MAX 255; MIN 2)
Example: Barrio 11
Specifies the customer's shipping address object.
The primary shipping address line of the customer (MAX 255; MIN 3).
Example: Calle 34 # 56 - 78
The secondary shipping address line of the customer (MAX 255; MIN 3).
Example: Apartamento 502, Torre I
The city considered for the shipping address (MAX 255; MIN 3).
Example: Bogotá
The country considered for the shipping address (MAX 2; MIN 2; ISO 3166-1 ).
Possible enum values: Check the Country reference.
The state considered for the shipping address (MAX 255; MIN 3; ISO 3166-2 ).
Example: Cundinamarca
The zipcode considered for the shipping address (MAX 10; MIN 5).
Example: 111111
The neighborhood of the address line of the customer(MAX 255; MIN 2)
Example: Barrio 11
Specifies a list of custom key–value pairs associated with the customer (for internal references, segmentation, or workflow tags). You can add up to 50 metadata objects.
Specifies a metadata key and the respective value.
Use to attach merchant-defined context (for example: `crm_id`, `segment`). Avoid sending sensitive or personal data.
Specifies one metadata key.
Example: age
Specifies the value for the defined metadata key.
Example: 28
Customer creation date and time (MAX 27; MIN 27; ISO 8601 ).
Example: 2022-05-09T20:46:54.786342Z
Last customer update date and time (MAX 27; MIN 27; ISO 8601 ).
Example: 2022-05-09T20:46:54.786342Z
## Operations
* [Create a Customer](/reference/customers/create-customer)
* [Retrieve a Customer](/reference/customers/retrieve-customer)
* [Retrieve by External ID](/reference/customers/retrieve-customer-by-external-id)
* [Update a Customer](/reference/customers/update-customer)
* [Delete a Customer](/reference/customers/delete-customer)
# Update Customer
Source: https://docs.y.uno/reference/customers/update-customer
openapi/customers/update-customer.json PATCH /customers/{id}
Updates fields on an existing customer, modifying only the values included in the request
You can update a customer created earlier with the `POST/customers` API request. The only required field for the request is the customer `id`. Other supported request fields are equal to the ones on the customer creation process.
You need to specify only the fields you want to update. Every field is available for update.
# Register a Dry-Run Provider Event
Source: https://docs.y.uno/reference/dry-run/register-dry-run-provider-event
openapi/dry-run/register-dry-run-provider-event.json POST /dry-run/provider-events
Register provider request, response, or webhook payloads for pre-production validation.
Dry-run is a pre-production validation surface. It receives the API calls your integration sends to a payment provider — request, response, and webhook payloads — and correlates them with the equivalent Yuno public-API call you make **in parallel** with the `X-Dry-Run: true` header set.
Yuno then executes an automated validation pipeline that grades the quality of the public-API request against the provider payload: missing fields, shape mismatches, wrong enum values, unmapped metadata, and any other inconsistency that would cause the real payment to fail or behave differently once you go live.
### How the pair works
1. Your integration makes its normal call to the provider (e.g. Stripe, Adyen, dlocal).
2. Your integration also calls the relevant Yuno public-API endpoint (e.g. `POST /v1/payments`) with the header **`X-Dry-Run: true`**. Yuno accepts the request, does not route it to any provider, and stores it for comparison.
3. Your integration calls `POST /v1/dry-run/provider-events` with the raw provider exchange (request, response, webhook) it just performed, correlated to the same `merchant_reference`.
4. Yuno pairs the two records by `merchant_reference` + `account_id` and runs the validation pipeline. Results are available through the dashboard and via `GET /v1/dry-run/provider-events/{id}` (read API, separate reference).
The outcome tells you whether the public-API request you are building today would produce the same provider behavior once Yuno starts routing it — without touching production money or sending a live transaction to the provider through Yuno.
### When to use it
* **Pre-launch**: certify your public-API integration against the provider behavior you already have working.
* **Provider migrations**: verify a new provider accepts the fields Yuno forwards before switching traffic.
* **Regression checks**: re-run dry-runs in CI to catch drift when your integration or the provider's contract changes.
One call can carry up to **10** event entries (REQUEST, RESPONSE, and/or WEBHOOK), all tied to the same payment via `merchant_reference`. See the [correlation rules](#correlation).
This endpoint has a companion: `POST /v1/payments` accepts an `X-Dry-Run: true` request header that tells Yuno to validate instead of routing. Both legs must share the same `merchant_reference` so validation can pair them.
Use `X-Idempotency-Key` for safe retries. Same key + same payload returns the original response; same key + different payload returns `409`.
**PCI boundary**
`headers` and `body` are sent **base64-encoded**. Yuno base64-decodes on ingest, applies deterministic PAN/CVV/auth-token redaction, and persists only the redacted form. See [PCI Compliance](/docs/security-and-compliance/pci-compliance).
***
## Correlation
* `merchant_reference` is always required and uniquely identifies the order on your side. Yuno uses it to resolve the event to a payment asynchronously when `payment_id` is not supplied.
* `payment_id`, if supplied, is resolved immediately. If the id is unknown for your account the request returns `404 PAYMENT_NOT_FOUND`.
* `provider_id` + `payment_method_type` optionally identify which integration surface the dry-run exercises (e.g. `stripe` + `CREDIT_CARD`). If omitted, Yuno uses the information from the associated payment.
# ECI Indicators List
Source: https://docs.y.uno/reference/eci-indicators-list
Lists ECI response codes returned by card networks during 3D Secure authentication attempts
An Electronic Commerce Indicator (ECI) is a response code used in 3D Secure transactions, specifically in EMV 3D Secure. It helps merchants determine the next steps to take in a transaction — proceed, reject the purchase, or try again. Below you will find the possible responses and ECI values you can receive.
## Successful authentication
The card issuer has successfully verified the cardholder's identity and validated the EMV 3Ds protocol. Consequently, the transaction is authorized to proceed, and all parties can benefit from the security and safeguards provided by 3DS.
Card type
ECI indicator
Visa Secure
05
Mastercard IdentityCheck
02
JC J/Secure 2.0
05
American Express SafeKey 2.0
05
Discover ProtectBuy 2.0
05
Elo 3DS
05
eftpos\*
05
Carte Bancaires Fast'r
05 / 02
UnionPay International\*
05 / 02
ITMX (LSS) Local Switch Secure
05 / 02
## Attempted authentication
The issuer's authentication service is currently unavailable. A merchant will receive this message when the customer is not enrolled in 3DS. This response serves as evidence that the merchant attempted authentication and fulfilled their due diligence as required by 3DS regulations.
Card type
ECI indicator
Visa Secure
06
Mastercard IdentityCheck
01
JC J/Secure 2.0
06
American Express SafeKey 2.0
06
Discover ProtectBuy 2.0
06
Elo 3DS
06
eftpos\*
06
Carte Bancaires Fast'r
06 / 01
UnionPay International\*
06 / 01
ITMX (LSS) Local Switch Secure
06 / 01
## Failed authentication
The issuer encountered challenges and could not authenticate the cardholder due to various factors. These may include instances where incorrect information was provided during the authentication process or when the cardholder themselves chose to cancel the authentication page. Other unspecified reasons could also contribute to the issuer's inability to complete the authentication successfully.
Card type
ECI indicator
Visa Secure
07
Mastercard IdentityCheck
00
JC J/Secure 2.0
07
American Express SafeKey 2.0
07
Discover ProtectBuy 2.0
07
Elo 3DS
07
eftpos\*
07
Carte Bancaires Fast'r
07 / 00
UnionPay International\*
07 / 00
ITMX (LSS) Local Switch Secure
07 / 00
## Not permitted authentication
The authentication request encountered obstacles that prevented its completion for various reasons. These reasons may include the exclusion of the card type from authentication attempts, the inability of the ACS (Access Control Server) to process the authentication request message or other unspecified factors. As a result, the authentication process could not be allowed to proceed.
Card type
Supported Version(s)
Visa Secure
07
Mastercard IdentityCheck
00
JC J/Secure 2.0
07
American Express SafeKey 2.0
07
Discover ProtectBuy 2.0
07
Elo 3DS
07
eftpos\*
07
Carte Bancaires Fast'r
07 / 00
UnionPay International\*
07 / 00
ITMX (LSS) Local Switch Secure
07 / 00
***
Although cobranded, transactions made through eftpos will receive ECI codes of 05/06/07, indicating the possible outcomes of authentication attempts.
UnionPay International: Transactions falling within the BIN ranges overlapping with UnionPay International will receive both ECI values - 05/06/07 and 02/01/00. These values signify different authentication results.
# Environments
Source: https://docs.y.uno/reference/getting-started/api-environments
Explains the sandbox and production API base URLs and their credentials and timeout behavior
API base URLs and the two environments (Sandbox and Production) for calling the Yuno API.
This page explains the API base URLs and the two environments you can use when calling the Yuno API: **Sandbox** and **Production**.
For how to switch between Test Mode and Live Mode in the Yuno dashboard, see [Environments (Dashboard)](/docs/environments).
## Overview: Sandbox vs Production
| Environment | Purpose | Base URL |
| --------------------- | ------------------------------------------------------------------- | ------------ |
| **Sandbox** | Testing and development. No live data or real transactions. | |
| **Production (US)** | Live environment based in the US. Real transactions and accounting. | |
| **Production (EMEA)** | Live environment based in EMEA. Real transactions and accounting. | |
In the dashboard, Sandbox is referred to as **Test Mode** and Production as **Live Mode**. You use the same account for both; the dashboard toggle switches which environment you are using.
## Credentials
****Credentials****
Sandbox and Production use **different API keys**. The credentials you use in Test Mode (Sandbox) are not the same as those for Live Mode (Production). In the dashboard, the keys shown depend on which environment you have selected. See [Developers credentials](/docs/developers-credentials) for where to find them.
## Base URLs
### Sandbox
Use this base URL for all API requests when testing. Data is simulated and does not affect live accounting or metrics.
```
https://api-sandbox.y.uno
```
### Production (US)
Use this base URL when your integration is live and based in the US, processing real payments.
```
https://api.y.uno
```
### Production (EMEA)
Use this base URL when your integration is live and based in EMEA, processing real payments.
```
https://api.eu.y.uno
```
## Processing time and timeout
****Processing time****
The processing time for each request depends on the processor or acquirer. Total time is the sum of Yuno's processing time and the processor's.
****Timeout****
Yuno uses a **60-second timeout** for all endpoints. The full request–response cycle must complete within 60 seconds. Response times are usually much shorter; 60 seconds covers slower processor responses.
# API Overview
Source: https://docs.y.uno/reference/getting-started/api-reference-overview
Introduces the Yuno REST API structure and links to authentication, SDKs, webhooks, and reference sections
The Yuno API has been implemented around RESTful. Our API uses standard HTTP protocols where JSON payloads are returned in response to the HTTP requests. All operations can be performed via GET, POST and PATCH requests.
**Choose Your Integration**
Before you start the integration, [choose the type of integration](/docs/sdks/overview/choose-integration) you want to use.
## Setup and integration
The options below highlight essential information you will need to consider when building your integration with Yuno.
Learn about the authentication system Yuno APIs use.
Check the existing environments for testing and production.
Explore the complete list of Yuno SDKs.
Receive automatic notification from your operations.
Discover essential data Yuno API uses.
## API services
Yuno provides a wide range of functionalities you can use through its API. Below are links to every API service available in the documentation.
## Supporting material
To make the integration process easier, Yuno provides supporting material so you can test Yuno APIs directly on your machine or run a ready-to-use web application using the example project.
Explore a web implementation of Yuno SDK.
} title="Postman" href="/reference/postman-collections">
Try out the Yuno APIs.
# API Updates
Source: https://docs.y.uno/reference/getting-started/api-updates
Explains how Yuno versions and rolls out backward compatible API changes and updates
Stay up to date with Yuno API changes and updates.
At Yuno, we make sure that all updates we make to our APIs are compatible with both the current version and previous versions.
When a disruptive modification is implemented to the Yuno API, a new version is released. To avoid any issues with your code, we do not require a version change until you are ready to proceed with the upgrade.
### Backwards compatible changes
We consider the following modifications to maintain backward compatibility:
* Add new resources to the API.
* Add new optional request parameters to existing API methods.
* Add new properties to existing API responses.
* Modify the order of properties in existing API responses.
* Alter the length or format of opaque strings, such as object identifiers, error messages, and other human-readable strings. This includes adding or removing prefixes.
* Introduce new types of events. Make sure your webhook receiving service supports unknown event types.
# Authentication
Source: https://docs.y.uno/reference/getting-started/authentication
Explains API key headers and idempotency keys used to authenticate and secure Yuno API requests
The Yuno API uses the ApiKey security schema to authenticate HTTP requests. API keys are alphanumeric credentials that grant access to specific API features.
All requests require `public-api-key` and `private-secret-key` headers. Find them in your [Yuno Dashboard](https://dashboard.y.uno/developers).
Do not share your secret API keys in public places like GitHub or Bitbucket to avoid malicious API calls.
Occasionally, an `X-Idempotency-Key` may be required. This UUID must be unique for each request. See [Idempotency](/reference/authentication#idempotency) for details.
**Example request**:
```sh theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
curl --request \\
--url \\
--header 'X-Idempotency-Key: 7bf41af5-70ae-4e79-9b28-a8fa75c3ac53' \\
--header 'accept: application/json' \\
--header 'content-type: application/json' \\
--header 'private-secret-key: ' \\
--header 'public-api-key: '
```
## Idempotency
Idempotency is the ability to make multiple identical requests and always get the same response. This is useful when a request fails due to a connection issue and the outcome is unclear; you can retry using the same `X-Idempotency-Key` and the API will not duplicate the operation.
Some requests include a unique identifier sent as the `X-Idempotency-Key` header (e.g., `7bf41af5-70ae-4e79-9b28-a8fa75c3ac53`). This key also serves to identify a specific transaction.
Set the `x-idempotency-key` value to `{$randomUUID}` to generate keys automatically.
Yuno stores the `X-Idempotency-Key` and the transaction status for 24 hours, regardless of the outcome (captured, authorized, or failed). Any subsequent request with the same key within that window returns the original response instead of creating a new transaction.
If two requests are sent simultaneously, the API may receive the second before responding to the first. In that case, the second request returns a `400 Bad Request` with error code `REQUEST_IN_PROCESS`, indicating there is already an open call for that `X-Idempotency-Key`. Retry the request after a few seconds.
If two requests are sent with the same key but different body contents, the API processes only the first one.
An `X-Idempotency-Key` is consumed by the first request that uses it, whether or not that request succeeds. To retry a request that returned a `400` or `500` error, correct it and send it with a new key.
# Postman Collections
Source: https://docs.y.uno/reference/getting-started/postman-collections
Walks through importing and configuring the Yuno Postman collection to test sandbox endpoints
Postman is an API platform to help developers design and test APIs. Postman is an alternative to run Yuno API requests using Readme.io. You can download Postman [here](https://www.postman.com/downloads/) for Linux, Windows, or Mac or use it through your web browser.
Here, you find how to import the Yuno Collection and Environment. All endpoints on the [API Reference](/reference/getting-started/api-reference-overview) are available on the Postman collection provided so that you can test Yuno services on your machine.
**Postman Collection**
Access the Yuno APIs Postman collection [here](https://documenter.getpostman.com/view/25083296/2sBXikpXDZ?utm_source=slack\&utm_medium=link_preview\&utm_campaign=other\&utm_content=link\&utm_term=other#173ba2dd-1dbb-466c-934c-19a4308d9d80).
## Step 1: Fork the Yuno Postman collection
Before testing the endpoints, you need to fork the Yuno collection to your Postman account.
1. Access the [Yuno Postman collection](https://documenter.getpostman.com/view/25083296/2sBXikpXDZ?utm_source=slack\&utm_medium=link_preview\&utm_campaign=other\&utm_content=link\&utm_term=other#173ba2dd-1dbb-466c-934c-19a4308d9d80).
2. Select the following **Run in Postman** button.
3. Select if you want to run Postman on your Browser or using the Postman app.
4. Sign up or log in to a Postman account.
5. Select a workspace to import the collection into.
**Collection and environment are separate**
Forking the collection only brings the requests. The environment (the file with your API keys and account variables) is a separate `.json` file that needs to be imported on its own, it does not come bundled with the collection fork.
## Step 2: Configure the environment variables
Before start testing the endpoint, you need to import and configure the environment. Otherwise, the requests will fail.
1. Download [`Yuno_Sandbox.postman_environment.json`](/files/postman/Yuno_Sandbox.postman_environment.json), then import it. Access **Environments** on the left panel, then **Import**.
2. Select the **Yuno Sandbox** environment once imported.
3. Update the variable's values. To start testing, you need to update at least `public_api_key`, `private_secret_key`, and `account_id`.
**Sandbox keys require test mode**
In the Yuno Dashboard, toggle **Test mode** on before copying your API keys. With test mode off, the keys are scoped to production and won't authenticate against the sandbox environment.
4. Define **Yuno Sandbox** as the environment using the **No Environment** selector at the top right corner.
The **Yuno Sandbox** environment has an extensive list of variables used on all requests inside the collection. You can define their values as you try new endpoints.
## Step 3: Run in Postman
After selecting the environment and defining the variable values, you can start testing the endpoint.
1. Select the **Yuno Payments API Playground** collection on the Collections tab.
2. Choose an endpoint.
3. Provide the necessary values to the parameters available on the **Headers** and **Body** tabs.
4. Use the **Send** button to perform the request to Yuno's server.
**Postman Variables**
In the Yuno Collection, various parameters are considered as variables. These values can be defined in the environment or upon receiving a response from the server. Postman variables aid in testing different endpoints in a sequence as the values received fill in the body parameters for the subsequent request.
## Useful resources
* [Yuno Postman collection](https://documenter.getpostman.com/view/25083296/2sBXikpXDZ?utm_source=slack\&utm_medium=link_preview\&utm_campaign=other\&utm_content=link\&utm_term=other#173ba2dd-1dbb-466c-934c-19a4308d9d80)
* [`Yuno_Sandbox.postman_environment.json`](/files/postman/Yuno_Sandbox.postman_environment.json)
* [`Yuno_Production.postman_environment.json`](/files/postman/Yuno_Production.postman_environment.json)
# HTTP Response Codes
Source: https://docs.y.uno/reference/getting-started/response-codes
Lists HTTP status codes and error codes returned by the Yuno API with their meanings
This section outlines the common error codes and resolutions you may encounter while using the Yuno API.
Yuno uses standard HTTP response codes to indicate the success or failure of API requests.
Codes in the 2xx range usually indicate success. Codes in the 4xx range indicate an error that occurred based on the information provided (e.g., a missing parameter, etc.), and codes in the 5xx range indicate an internal error.
## Example
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"code": "INVALID_REQUEST",
"messages": [
"Invalid request."
]
}
```
## Response attributes for errors
See what codes are returned by Yuno's Rest API.
| HTTP Status Code | Code | Description |
| :------------------------ | :------------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 400 Bad Request | `INVALID_REQUEST` | Invalid request. |
| | `INVALID_PARAMETERS` | Invalid parameters: list - \[parameter\_name]. |
| | `MISSING_PARAMETERS` | Missing parameters: list - \[parameter\_name]. |
| | `INVALID_STATUS` | Invalid transaction status. |
| | `COUNTRY_NOT_SUPPORTED` | Country not supported. |
| | `CURRENCY_NOT_ALLOWED` | Currency is not allowed for this country. |
| | `CUSTOMER_ID_DUPLICATED` | The customer id for the merchant is duplicated. |
| | `INVALID_AMOUNT` | Invalid amount for the payment method. |
| | `INVALID_ACCOUNT_ID` | Invalid Yuno's account id |
| | `INVALID_TRANSACTION` | Invalid transaction id |
| | `INVALID_API_VERSION` | Invalid API Version. |
| | `INVALID_TRANSACTION_TYPE` | Invalid transaction type for the request. |
| | `CHARGEBACK_IN_PROCESS` | Chargeback in place for this transaction. |
| | `UNAVAILABLE_PAYMENT_METHOD` | Unavailable payment method. |
| | `NOT_FOUND` | Resource not found. |
| | `UNEXPECTED_RESPONSE` | Unexpected service response. |
| | `BAD_REQUEST` | There was a bad error executing the request. |
| | `INVALID_REPORT_ID` | Report id must be UUID. |
| | `INVALID_REPORT_TYPE` | Invalid report type. |
| | `INVALID_DATE_FORMAT` | Start/end date format must be yyyy-MM-dd'T'HH:mm:ss.SSS'Z'. |
| | `REPORT_MAX_RANGE_ERROR` | Max range date is two months. |
| | `REPORT_RANGE_ERROR` | Start date must be before end date. Start/end date must be after now. |
| | `REPORT_STATUS_ERROR` | Report is not ready yet, status is %s. |
| | `REPORT_EMPTY` | Report requested is empty. |
| | `PAYMENT_METHOD_NOT_FOUND` | \[For Subscriptions] - Payment method associated to the customer not found |
| | `PAYMENT_METHOD_STATUS_INVALID` | \[For Subscriptions] - The payment method is a state that does not allow payments to be made. |
| | `INCORRECT_PAYMENT_METHOD_TYPE` | \[For Subscriptions] - The type of payment method of the request does not correspond to the vaulted\_token. |
| | `SUBSCRIPTION_NOT_FOUND` | \[For Subscriptions] - Subscription not found. |
| | `INVALID_STATE` | \[For Subscriptions] - The subscription state does not support the action requested. |
| | `INVALID_DATE` | \[For Subscriptions] - The subscription can not be resume due to a conflict with the availability dates. Please update availability dates and try again if you want to keep using the subscription |
| | `INVALID_PARAMETERS` | \[For Subscriptions] - Invalid parameters: list - \[parameter\_name]. |
| | `INVALID_CUSTOMER_FOR_TOKEN` | The token used for this transaction is associated with another customer object. |
| | `PAYMENT_NOT_FOUND` | Payment not found. |
| | `TRANSACTION_NOT_FOUND` | Transaction of payment not found |
| | `CUSTOMER_NOT_FOUND` | Customer not found |
| | `CHECKOUT_SESSION_NOT_FOUND` | Checkout session not found or inactive |
| | `REPORT_NOT_FOUND` | Report id not found |
| | `IDEMPOTENCY_DUPLICATED` | Idempotency is duplicated. |
| 401 Unauthorized | `INVALID_CREDENTIALS` | Invalid Credentials. |
| | `EXPIRED_CREDENTIALS` | Expired Credentials. |
| | `UNKNOWN_IP_ADDRESS` | Unregistered IP address. |
| | `INVALID_TOKEN` | Invalid Token. |
| | `TOKEN_IN_USE` | The token provided is currently being used in another request. |
| 403 Forbidden | `AUTHORIZATION_REQUIRED` | The merchant has no authorization to use this API. |
| 405 Method not allowed | `UNSUPPORTED_METHOD` | Method not supported. |
| 500 Internal Server Error | `INTERNAL_ERROR` | Internal error. |
| 504 Gateway Timeout | `REQUEST_TIMEOUT` | Request Timeout. |
# Industry Category
Source: https://docs.y.uno/reference/industry-category-list
Lists industry category codes and descriptions used when configuring merchant accounts via the API
On this page, you will find the industry category information you need when using Yuno API endpoints. The table below provides codes for each industry category available on the Yuno API and their descriptions. Use this page to understand better when to use each category.
| industry\_category | Description |
| :------------------------ | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `ADVERTISING` | Advertising company and services. |
| `ART` | Collectibles & Art. |
| `AUTOMOTIVE` | Parts & Accessories. |
| `ANTIVIRUS` | Antivirus security services. |
| `BABY` | Toys for Baby, Stroller, Stroller Accessories, Car Safety Seats. |
| `BEAUTY_&_PERSONAL_CARE` | Makeup, Skin Care Products, Hair Care Products, Perfumes & Fragrances. |
| `BOOKS` | Books. |
| `CAMERAS` | Cameras & Photography. |
| `CAR_ELECTRONICS` | Car Audio, Car Alarm Systems & Security, Car DVRs, Car Video Players, Car PC. |
| `COMPUTING` | Computers & Tablets. |
| `COUPONS` | Coupons. |
| `DONATIONS` | Donations. |
| `DELIVERY` | Goods delivery. |
| `ELECTRONICS` | Audio & Surveillance, Video & GPS, Others. |
| `ENTERTAINMENT` | Music, Movies & Series, Magazines & Comics. |
| `EDUCATION` | Education services. |
| `FASHION` | Men’s, Women’s, Kids & baby, Handbags & Accessories, Health & Beauty, Shoes, Jewelry & Watches. |
| `GAMES` | Online Games & Credits. |
| `GARDEN_&_OUTDOOR` | Outdoor Décor, Patio Furniture & Accessories, Outdoor Lighting Products, Pest Control Products. |
| `GROCERY_&_GOURMET_FOOD` | Alcoholic Beverages, Baby Foods, Frozen Foods, Fresh Produce. |
| `HANDMADE` | Accessories, jewelry, decorations. |
| `HOME` | Home appliances. Home & Garden. |
| `INDUSTRIAL_&_SCIENTIFIC` | Scales & Balances, Industrial Magnets. |
| `INVESTING_AND_FINANCIAL` | Investing and financial services. |
| `LEARNINGS` | Trainings, Conferences, Workshops. |
| `MUSICAL` | Instruments & Gear. |
| `OTHERS` | Other categories. |
| `PET_SUPPLIES` | Dogs and cats food, toys, furniture. |
| `PHONES` | Cell Phones & Accessories. |
| `PAYROLL` | Payroll services. |
| `SERVICES` | General services. |
| `SAAS` | Software as a service. |
| `TELEVISION` | LCD, LED, Smart TV, Plasmas, TVs. |
| `STREAMING` | Streaming services. |
| `TICKETS` | Tickets for Concerts, Sports, Arts, Theater, Family, Excursions tickets, Events & more. |
| `TOYS_&_GAMES` | Board Games & Toys. |
| `TRAVELS` | Plane tickets, Hotel vouchers, Travel vouchers. |
| `VIDEO_GAMES` | Video Games & Consoles. |
| `VIRTUAL_GOODS` | E-books, Music Files, Software, Digital Images, PDF Files and any item which can be electronically stored in a file, Mobile Recharge, DTH Recharge and any Online Recharge. |
# Create Installments Plan
Source: https://docs.y.uno/reference/installments/create-installments-plan
openapi/installments/create-installments-plan.json POST /installments-plans
Creates an installment plan defining amount range, card BIN, currency, and availability rules
Yuno allows you to create installment plans to offer to your customers. These plans can be used based on factors such as the amount to pay, currency, and card used, as described below:
* **Filtered by Amount Range (mandatory):** The system checks if the installment plan is suitable for the specific amount of your transaction. Only plans that can handle that amount are considered.
* **Card BIN:** The system verifies if the BIN of your card matches those allowed for certain installment plans. If there's a match, that plan is considered.
* **Specific Currency:** Only plans that work with the currency you are using are considered.
* **Plan Availability:** The system checks if the installment plan is active. Only plans that have not expired and are available are considered.
**Defining the Plan ID**
The `plan_id` is only necessary when applying a fixed installment plan that doesn't change during the purchase. If the `installment.plan_id` is not provided, the SDK will automatically search through all available installment plans associated with that account and select the one it considers most suitable. You should include the `plan_id` to ensure that a specific plan is applied.
**Merchants Installments**
This endpoint is only required for [Merchant installments integration](/docs/installments). For Provider defined installments, we use the installment plan defined by your payment provider.
For merchant-created installments, you also have the possibility of specifying the plan for every checkout session by using the `plan_id` while [creating the session](/reference/create-checkout-session). If you do not send it, we will use the installment plan that matches the conditions set for the checkout session.
# Delete Installments Plan
Source: https://docs.y.uno/reference/installments/delete-installments-plan-by-id
openapi/installments/delete-installments-plan-by-id.json DELETE /installments-plans/{installment_code}
Permanently deletes a specific installment plan by its installment code
The **Delete Installments Plan by ID** endpoint allows you to delete a specific installment plan from the system. This operation permanently removes the plan and makes it unavailable for future transactions.
# Get Installments Plan by ID
Source: https://docs.y.uno/reference/installments/get-installments-plan
openapi/installments/get-installments-plan.json GET /installments-plans/{installment_code}
Retrieves the configuration details of a specific installment plan by its code
The **Get Installments Plan** API lets you retrieve detailed information about an existing installment plan. This includes the plan’s installment options, billing frequency, amount limits, and other relevant details.
Use this endpoint to fetch the current configuration of a specific installment plan.
# Get Installments Plans
Source: https://docs.y.uno/reference/installments/get-installments-plan-by-account
openapi/installments/get-installments-plan-by-account.json GET /installments-plans
Retrieves the list of installment plans configured for a specific account
The **Get Installments Plan** API lets you retrieve a list of installment plans associated with a specific account. This endpoint helps view all available plans linked to an account, including their installment options, limits, and availability periods.
Use this API to fetch all installment plans available under a particular account ID.
# Update Plan
Source: https://docs.y.uno/reference/installments/update-plan
openapi/installments/update-plan.json PATCH /installments-plans/{installment_code}
Updates an existing installment plan's status, installment details, or payment method
The **Update Plan** API allows you to modify an existing plan, enabling you to update attributes such as the plan's status, installment details, and the payment method associated with the plan.
Use this API to manage and adjust subscription plans after creation.
# Items Category
Source: https://docs.y.uno/reference/items-category-list
Lists item category codes and descriptions used to classify products in order payloads
On this page, you will find the items category information you need when using Yuno API endpoints. The table below provides codes for each item category available on the Yuno API and their descriptions. Use this page to understand better when to use each category.
| item\_category | Description |
| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `ART` | Collectibles & Art. |
| `BABY` | Toys for Baby, Stroller, Stroller Accessories, Car Safety Seats. |
| `COUPONS` | Coupons. |
| `BEAUTY&_PERSONAL_CARE` | Makeup, Skin Care Products, Hair Care Products, Perfumes & Fragrances. |
| `DONATIONS` | Donations. |
| `COMPUTING` | Computers & Tablets. |
| `BOOKS` | Books. |
| `GROCERY_&_GOURMET_FOOD` | Alcoholic Beverages, Baby Foods, Frozen Foods, Fresh Produce. |
| `CAMERAS` | Cameras & Photography. |
| `VIDEO_GAMES` | Video Games & Consoles. |
| `TELEVISION` | LCD, LED, Smart TV, Plasmas, TVs. |
| `CAR_ELECTRONICS` | Car Audio, Car Alarm Systems & Security, Car DVRs, Car Video Players, Car PC. |
| `ELECTRONICS` | Audio & Surveillance, Video & GPS, Others. |
| `AUTOMOTIVE` | Parts & Accessories. |
| `TOYS_&_GAMES` | Board Games & Toys. |
| `MUSICAL_INSTRUMENTS` | Guitars, Ukuleles, Drums & Percussion, Musical Instrument Keyboards. |
| `HANDMADE` | Accesories, jewerly, decorations. |
| `GARDEN_&_OUTDOOR` | Outdoor Décor, Patio Furniture & Accessories, Outdoor Lighting Products, Pest Control Products. |
| `ENTERTAINMENT` | Music, Movies & Series, Magazines & Comics. |
| `INDUSTRIAL&_SCIENTIFIC` | Scales & Balances, Industrial Magnets. |
| `FASHION` | Men's, Women's, Kids & baby, Handbags & Accessories, Health & Beauty, Shoes, Jewelry & Watches. |
| `GAMES` | Online Games & Credits. |
| `PET_SUPPLIES` | Dogs and cats food, toys, furniture. |
| `HOME` | Home appliances. Home & Garden. |
| `MUSICAL` | Instruments & Gear. |
| `PHONES` | Cell Phones & Accessories. |
| `SERVICES` | General services. |
| `LEARNINGS` | Trainings, Conferences, Workshops. |
| `TICKETS` | Tickets for Concerts, Sports, Arts, Theater, Family, Excursions tickets, Events & more. |
| `TRAVELS` | Plane tickets, Hotel vouchers, Travel vouchers. |
| `VIRTUAL_GOODS` | E-books, Music Files, Software, Digital Images, PDF Files and any item which can be electronically stored in a file, Mobile Recharge, DTH Recharge and any Online Recharge. |
| `OTHERS` | Other categories. |
# Generate Network Token Cryptogram
Source: https://docs.y.uno/reference/network-tokens/generate-network-token-cryptogram
openapi/network-tokens/generate-network-token-cryptogram.json POST /network-tokens/cryptograms
Generates a fresh, single-use network token cryptogram for a vaulted card so it can be authorized on an external PSP. PCI-certified merchants only.
This endpoint returns an on-demand **network token cryptogram** for a vaulted card, together with the card's current network token (DPAN). A card's network token alone cannot authorize a payment — card schemes require a single-use cryptogram per transaction, and only Yuno can request it because Yuno holds the Token Requestor ID. Use this endpoint when you want to take a Yuno network token and authorize the transaction on your own PSP.
You identify the card with its `vaulted_token` — the same identifier you use in [Create Payment](/reference/create-payment). Yuno resolves the card's current network token internally and absorbs token rotation, so you always receive a consistent, current `(DPAN, cryptogram, ECI)` set.
**PCI merchants only**
This endpoint is only available for PCI-certified merchants, because the response contains the full network token (DPAN). To enable it, contact your Key Account Manager (KAM).
**Always submit the returned pair.** A cryptogram is bound to a specific network token. Submit the `network_token.number` (DPAN) returned in the **same response** together with its `cryptogram` and `eci`. Never pair a returned cryptogram with a previously stored DPAN — after a token rotation, a stored DPAN will no longer match.
## How it works
1. Request a cryptogram right before you authorize. Every call generates a **fresh, single-use** cryptogram from the scheme — there is no idempotency, and duplicate calls simply return new cryptograms (no money moves).
2. Submit `network_token.number` (DPAN), `cryptogram`, and `eci` to your PSP as a network-token transaction.
3. If the authorization is declined and you retry, request a **new** cryptogram first — a used or stale cryptogram cannot be replayed.
## Requirements
To use this endpoint your organization must:
* Be a **PCI-certified merchant** (the response contains the DPAN).
* Have the **product enabled** for your organization.
* Be **onboarded for network tokens** for the card's brand and the requested `country`.
The card referenced by `vaulted_token` must be an **enrolled card** of your organization that already has an **active network token**.
Supported networks: **Visa** and **Mastercard**.
**When you don't need this endpoint.** Recurring merchant-initiated transactions (MIT) authorize with the network token and the stored `network_transaction_id` and do **not** require a cryptogram. This endpoint is for customer-initiated transactions that need a fresh cryptogram.
## Cryptogram lifetime
The cryptogram is single-use — request it immediately before you authorize, and do not cache it.
## Errors
Errors return a `code` and a `messages` array. The exact `messages` value per `code`:
| HTTP | `code` | `messages` |
| ---- | ----------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| 404 | `PAYMENT_METHOD_NOT_FOUND` | "Payment method not found." |
| 400 | `INSTRUMENT_NOT_TOKENIZABLE` | "Payment method is not a card." |
| 400 | `PAYMENT_METHOD_NOT_ENROLLED` | "Payment method is not enrolled." |
| 400 | `NETWORK_TOKEN_NOT_FOUND` | "Payment method has no network token." |
| 400 | `TOKEN_NOT_ACTIVE` | "Network token is not active." |
| 400 | `NETWORK_NOT_SUPPORTED` | "Network token brand is not supported." |
| 400 | `COUNTRY_NOT_SUPPORTED` | "Country is not supported for this organization." |
| 400 | `INVALID_REQUEST` | The specific invalid field, e.g. "The field 'vaulted\_token' must be a valid uuid v4." |
| 403 | `PCI_MERCHANT_REQUIRED` | "This endpoint is only available to PCI-certified merchants." |
| 403 | `PRODUCT_NOT_ENABLED` | "The Network Token Cryptogram API is enabled per organization. Contact your Key Account Manager (KAM) to activate it." |
| 502 | `PROVIDER_ERROR` | "The network token cryptogram service is temporarily unavailable, please retry." |
A `vaulted_token` that doesn't exist and one that belongs to another organization both return the same `PAYMENT_METHOD_NOT_FOUND` — no existence leak.
# Authenticate Whitelabel User
Source: https://docs.y.uno/reference/organizations/authenticate-whitelabel-user
openapi/organizations/authenticate-whitelabel-user.json POST /organizations/authenticate
Authenticates a whitelabel user and returns a JWT embed token for subsequent requests
Authenticates a whitelabel user and returns a JWT embed token. This token can be used for subsequent authenticated requests on behalf of the whitelabel user.
# Connections & Routing Overview
Source: https://docs.y.uno/reference/organizations/connections-routing-overview
Merchant-facing reference for the new public-API surface that lets you create payment-provider connections and configure how Yuno routes payments across them.
Connections are how you bring your existing payment-provider accounts (Stripe, Adyen, dLocal, PayU, …) into Yuno's orchestration. Once a connection exists, you can reference it from a routing rule to send payments through that provider.
A routing tells Yuno, for one `payment_method` on one account, which connection to use — and lets you branch by buyer attributes (country, currency, amount, card brand, custom metadata, …).
## Common contract
### Base URL
```
https://api.y.uno
```
### Authentication & headers
| Header | Required | Notes |
| -------------------------------- | --------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `public-api-key` | yes | Your merchant public API key. The account this key belongs to determines which account the request operates on. |
| `private-secret-key` | yes | Your merchant private secret key. |
| `X-Idempotency-Key` | on `POST` and `PATCH` | UUID, 24-hour scope. Re-sending the same key + body returns the cached response; same key with a different body returns a `409`. |
| `Content-Type: application/json` | yes | |
### Conventions
* Field names are `snake_case` everywhere — request, response, errors. The one exception is inside `params[]` on the **provider catalog** response, where individual `param_id` values are passed through with their native casing (`merchantAccount`, `HMAC_KEY`, `apple-merchant-id`, etc.) — you must echo these verbatim when creating a connection.
* Error envelope is the same across all endpoints:
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"type": "validation_error",
"code": "MISSING_REQUIRED_PARAM",
"message": "Required param 'merchantAccount' is missing for provider 'ADYEN'",
"details": { "provider_id": "ADYEN", "param_id": "merchantAccount" }
}
```
Stable `code` values are listed per endpoint.
### API-key scopes
| Scope | Required for |
| ------------------- | ---------------------------------------------------------------------------------- |
| `connections:read` | `GET /v1/connections/catalog/{provider_id}`, `GET /v1/connections/{connection_id}` |
| `connections:write` | `POST /v1/connections` |
| `routing:read` | `GET /v1/routing/{routing_id}` |
| `routing:write` | `POST /v1/routing`, `PATCH /v1/routing/{routing_id}` |
Missing scope → `403 INSUFFICIENT_SCOPE`.
# Create a Connection
Source: https://docs.y.uno/reference/organizations/connections/create-connection
openapi/organizations/connections/create-connection.json POST /connections
Creates a connection in ACTIVE status from credentials and configuration you fill in based on the provider's catalog.
Creates a connection in `ACTIVE` status from credentials and configuration you fill in based on the provider's catalog. The response includes the `connection_id` you'll use to reference this connection from routing rules.
### Headers
UUID, 24-hour scope. Re-sending the same key + body returns the cached response; same key with a different body returns a `409`.
### Body
UUID of the account under which this connection will be created.
Your label for this connection. Must be unique within the account. Free-form (e.g., `"adyen-us-prod-001"`, `"stripe-eu-test"`).
Yuno provider identifier (e.g., `"STRIPE"`, `"ADYEN"`). Must exist in the catalog.
Must be `"PAYIN"`.
Subset of the provider's `payment_method_type[]` (from the catalog).
One `{param_id, value}` pair per parameter you're supplying. **Flat array** — even nested catalog params are submitted at the top level; Yuno resolves the hierarchy from the catalog tree.
Required params (where the catalog has `optional: false`) must be present and non-empty. Activating a `boolean` parent (`"value": true`) makes its `optional: false` children required.
The exact `param_id` from the catalog. Casing matters.
Match the `field_type` from the catalog. Numerics are submitted as JSON numbers (or strings if the catalog says `field_type: "string"`). For `field_type: "array"`, submit a JSON array.
Per-connection cost configuration. `currency` must be one supported by the provider.
Order of priority for the cost entry.
Label for the cost entry.
ISO 4217 currency code.
Fixed fee amount.
Percentage fee.
### Response
Unique identifier for the connection. **Save this value** to reference it from routing rules.
Your internal label for this connection.
The provider this connection belongs to (e.g., `ADYEN`).
Current status (always `ACTIVE` on create).
Always `PAYIN`.
List of supported payment methods.
Echoed parameters. Sensitive values are masked as `***`.
Cost configuration for the connection.
ISO 8601 timestamp.
ISO 8601 timestamp.
```bash cURL theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
curl -X POST 'https://api.y.uno/v1/connections' \
-H 'public-api-key: ' \
-H 'private-secret-key: ' \
-H 'Content-Type: application/json' \
-H 'X-Idempotency-Key: ' \
-d '{
"account_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"merchant_connection_id": "stripe-us-prod-001",
"provider_id": "STRIPE",
"flow_type": "PAYIN",
"payment_methods": ["CARD", "GOOGLE_PAY", "APPLE_PAY"],
"params": [
{ "param_id": "API_KEY", "value": "sk_live_..." },
{ "param_id": "PUBLISHABLE_KEY", "value": "pk_live_..." },
{ "param_id": "INTEGRATION_TYPE", "value": "PAYMENT_INTENTS" },
{ "param_id": "3DS_ENABLED", "value": true },
{ "param_id": "ORIGIN_URL", "value": "https://checkout.acme.com" }
],
"costs": [
{
"sort_number": 1,
"cost_name": "Transaction Fee",
"currency": "USD",
"cost_values": {
"successful": { "fixed_fee": 0.30, "percentage": 2.9 },
"unsuccessful": { "fixed_fee": 0.0, "percentage": 0.0 }
}
}
]
}'
```
```json 201 Created — Stripe theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"connection_id": "f1a3c4d5-7b8e-4a2c-9d1e-3f4a5b6c7d8e",
"merchant_connection_id": "stripe-us-prod-001",
"provider_id": "STRIPE",
"status": "ACTIVE",
"flow_type": "PAYIN",
"payment_methods": ["CARD", "GOOGLE_PAY", "APPLE_PAY"],
"params": [
{ "param_id": "API_KEY", "value": "***" },
{ "param_id": "PUBLISHABLE_KEY", "value": "pk_live_..." },
{ "param_id": "INTEGRATION_TYPE", "value": "PAYMENT_INTENTS" },
{ "param_id": "3DS_ENABLED", "value": true },
{ "param_id": "ORIGIN_URL", "value": "https://checkout.acme.com" }
],
"costs": [
{
"sort_number": 1,
"cost_name": "Transaction Fee",
"currency": "USD",
"cost_values": {
"successful": { "fixed_fee": 0.30, "percentage": 2.9 },
"unsuccessful": { "fixed_fee": 0.0, "percentage": 0.0 }
}
}
],
"created_at": "2026-05-12T10:24:00Z",
"updated_at": "2026-05-12T10:24:00Z"
}
```
```json 201 Created — Adyen theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"connection_id": "b2c4d5e6-1a2b-3c4d-5e6f-7a8b9c0d1e2f",
"merchant_connection_id": "adyen-eu-prod-001",
"provider_id": "ADYEN",
"status": "ACTIVE",
"flow_type": "PAYIN",
"payment_methods": ["CARD", "GOOGLE_PAY", "IDEAL"],
"params": [
{ "param_id": "merchantAccount", "value": "ACME_LIVE" },
{ "param_id": "x-api-key", "value": "***" },
{ "param_id": "HMAC_KEY", "value": "***" },
{ "param_id": "url-prefix", "value": "acme-live" },
{ "param_id": "transaction-identifier", "value": "MERCHANT_REFERENCE" },
{ "param_id": "MERCHANT_NAME", "value": "ACME Inc." },
{ "param_id": "CAPTURE_DELAY_HOURS", "value": "24" },
{ "param_id": "recurring-model", "value": "CardOnFile" },
{ "param_id": "3DS_ENABLED", "value": true },
{ "param_id": "ORIGIN_URL", "value": "https://checkout.acme.com" }
],
"costs": [
{
"sort_number": 1,
"cost_name": "Transaction Fee",
"currency": "EUR",
"cost_values": {
"successful": { "fixed_fee": 0.12, "percentage": 1.2 },
"unsuccessful": { "fixed_fee": 0.0, "percentage": 0.0 }
}
}
],
"created_at": "2026-05-12T10:31:42Z",
"updated_at": "2026-05-12T10:31:42Z"
}
```
```json 400 — Missing Param theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"type": "validation_error",
"code": "MISSING_REQUIRED_PARAM",
"message": "Required param 'API_KEY' is missing for provider 'STRIPE'",
"details": { "provider_id": "STRIPE", "param_id": "API_KEY" }
}
```
```json 409 — Conflict theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"type": "conflict",
"code": "CONNECTION_MERCHANT_ID_CONFLICT",
"message": "A connection with merchant_connection_id 'stripe-us-prod-001' already exists in this account",
"details": { "merchant_connection_id": "stripe-us-prod-001" }
}
```
**Secret handling:** any param marked `secret: true` in the catalog is returned as `"value": "***"`. Your submitted secret is stored encrypted and never echoed back.
### Errors
| HTTP | `code` |
| ----- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `400` | `PROVIDER_NOT_FOUND` Unknown `provider_id`. |
| `400` | `MISSING_REQUIRED_PARAM` A required param is missing. `details.param_id` names which one. |
| `400` | `UNSUPPORTED_PAYMENT_METHOD` `payment_methods` contains a method the provider doesn't support. |
| `400` | `UNSUPPORTED_CURRENCY` A `costs[].currency` isn't in the provider's supported list. |
| `400` | `INVALID_PROVIDER_CREDENTIALS` The credentials failed Yuno's pre-flight check against the provider. `details.provider_message` echoes the provider's reason. |
| `409` | `CONNECTION_MERCHANT_ID_CONFLICT` `merchant_connection_id` already exists in this account. |
| `403` | `INSUFFICIENT_SCOPE` API key missing `connections:write`. |
# Get Provider Catalog
Source: https://docs.y.uno/reference/organizations/connections/get-provider-catalog
openapi/organizations/connections/get-provider-catalog.json GET /connections/catalog/{provider_id}
Returns the schema you need to fill in to create a connection for a given provider.
Returns the schema you need to fill in to create a connection for a given provider: which payment methods the provider supports, and the recursive list of parameters (credentials, toggles, choices) the provider requires.
This is the discovery endpoint — call it first to find out what a provider expects, then use its response as the input to [Create a Connection](/reference/organizations/connections/create-connection).
This endpoint is provider-scoped, not connection-scoped. It returns a schema, not your existing connections.
### Path Parameters
Yuno provider identifier (`STRIPE`, `ADYEN`, `CYBERSOURCE`, …). Case-sensitive, UPPER\_SNAKE\_CASE.
### Response
The Yuno payment-method enums this provider supports. Pass any of these values into `payment_methods[]` on [Create a Connection](/reference/organizations/connections/create-connection).
Recursive parameter schema.
Identifier to echo back in `POST /v1/connections.params[].param_id`. Pass casing **verbatim**.
One of `string`, `boolean`, `array`, `number`.
Display label. May be a plain string or a localization object `{ "EN": "...", "ES": "...", "PT": "..." }`.
Optional placeholder text. Same shape rules as `description`.
Optional helper text.
If `false`, value is fixed/read-only.
If `true`, the value is sensitive — stored encrypted and surfaced as `"***"` on subsequent reads.
Only meaningful when `options[]` is present. If `true`, you may submit a free-form value alongside the catalog options (combobox semantics).
If `false`, you must supply a value.
If `true`, the param exists but should not be rendered to end users.
If `true`, the value is also required when configuring the Yuno SDK on the client side.
Present when the field is a constrained enum. With `field_type = "string"` → single-select. With `field_type = "array"` → multi-select. Plain strings or `{value, params}` objects (the latter when an option carries its own nested params).
Nested children — activated when this node's value is `true` (boolean parent) or matches one of the `options` (string/array parent).
```bash cURL theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
curl -X GET 'https://api.y.uno/v1/connections/catalog/STRIPE' \
-H 'public-api-key: ' \
-H 'private-secret-key: '
```
```json 200 OK — Stripe theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"payment_method_type": [
"CARD",
"GOOGLE_PAY",
"APPLE_PAY",
"ACH",
"KLARNA_PAY_NOW",
"KLARNA_PAY_LATER",
"IDEAL",
"GIROPAY",
"BANCONTACT",
"SEPA_DEBIT"
],
"params": [
{
"param_id": "API_KEY",
"field_type": "string",
"secret": true,
"description": "Stripe Secret API Key",
"editable_field": true,
"optional": false
},
{
"param_id": "PUBLISHABLE_KEY",
"field_type": "string",
"description": "Stripe Publishable Key",
"editable_field": true,
"optional": false
},
{
"param_id": "INTEGRATION_TYPE",
"field_type": "string",
"description": "Stripe integration variant",
"editable_field": true,
"optional": false,
"options": [
"PAYMENT_INTENTS",
"CHARGES",
"CONNECT_DESTINATION"
]
},
{
"param_id": "3DS_ENABLED",
"field_type": "boolean",
"description": "Enable 3DS validation flow",
"editable_field": true,
"optional": true,
"params": [
{
"param_id": "ORIGIN_URL",
"field_type": "string",
"description": "Your checkout origin URL",
"editable_field": true,
"optional": true
}
]
}
]
}
```
```json 404 Not Found theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"type": "not_found",
"code": "PROVIDER_NOT_FOUND",
"message": "Provider 'NOT_A_PROVIDER' is not in the Yuno provider catalog",
"details": { "provider_id": "NOT_A_PROVIDER" }
}
```
```json 403 Forbidden theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"type": "auth_error",
"code": "INSUFFICIENT_SCOPE",
"message": "API key is missing required scope 'connections:read'",
"details": { "required_scope": "connections:read" }
}
```
### How to read a node
| What you see | What it means |
| ----------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
| `field_type: "string"`, no `options[]` | Free-form text input. |
| `field_type: "string"`, `secret: true` | Password / API key — write-only. Returned as `"***"` on `GET`. |
| `field_type: "string"`, `options[]` present | Single-choice enum. The value you submit must be one of `options[]`. |
| `field_type: "string"`, `options[]` present, `allow_custom: true` | Combobox. Submit one of `options[]` **or** a free-form value. |
| `field_type: "boolean"` | Toggle. Setting it to `true` activates nested `params[]` and makes their `optional: false` children required. |
| `field_type: "array"`, `options[]` present | Multi-select. Submit a JSON array whose elements are a subset of `options[]`. |
| `field_type: "array"`, no `options[]` | Free-form list of strings. |
### Errors
| HTTP | `code` | When |
| ----- | -------------------- | ----------------------------------------------------- |
| `404` | `PROVIDER_NOT_FOUND` | The `provider_id` is not in Yuno's provider catalog. |
| `403` | `INSUFFICIENT_SCOPE` | Your API key is missing the `connections:read` scope. |
# Retrieve a Connection
Source: https://docs.y.uno/reference/organizations/connections/retrieve-connection
openapi/organizations/connections/retrieve-connection.json GET /connections/{connection_id}
Returns a connection you previously created. Secrets are masked.
Returns a connection you previously created. Secrets are masked.
### Path Parameters
The id returned by [Create a Connection](/reference/organizations/connections/create-connection). Must belong to the account your API key is scoped to.
### Response
Unique identifier for the connection.
Your internal label for this connection.
The provider this connection belongs to.
Current status.
Always `PAYIN`.
List of supported payment methods.
Echoed parameters. Sensitive values are masked as `***`.
Cost configuration for the connection.
ISO 8601 timestamp.
ISO 8601 timestamp.
```bash cURL theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
curl -X GET 'https://api.y.uno/v1/connections/f1a3c4d5-7b8e-4a2c-9d1e-3f4a5b6c7d8e' \
-H 'public-api-key: ' \
-H 'private-secret-key: '
```
```json 200 OK — Stripe theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"connection_id": "f1a3c4d5-7b8e-4a2c-9d1e-3f4a5b6c7d8e",
"merchant_connection_id": "stripe-us-prod-001",
"provider_id": "STRIPE",
"status": "ACTIVE",
"flow_type": "PAYIN",
"payment_methods": ["CARD", "GOOGLE_PAY", "APPLE_PAY"],
"params": [
{ "param_id": "API_KEY", "value": "***" },
{ "param_id": "PUBLISHABLE_KEY", "value": "pk_live_..." }
],
"costs": [
{
"sort_number": 1,
"cost_name": "Transaction Fee",
"currency": "USD",
"cost_values": {
"successful": { "fixed_fee": 0.30, "percentage": 2.9 },
"unsuccessful": { "fixed_fee": 0.0, "percentage": 0.0 }
}
}
],
"created_at": "2026-05-12T10:24:00Z",
"updated_at": "2026-05-12T10:24:00Z"
}
```
```json 404 Not Found theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"type": "not_found",
"code": "CONNECTION_NOT_FOUND",
"message": "Connection '...' was not found",
"details": { "connection_id": "..." }
}
```
### Errors
| HTTP | `code` | When |
| ----- | ---------------------- | ------------------------------------------------------------------ |
| `404` | `CONNECTION_NOT_FOUND` | Unknown `connection_id`, or the id belongs to a different account. |
| `403` | `INSUFFICIENT_SCOPE` | API key missing `connections:read`. |
# Create Account
Source: https://docs.y.uno/reference/organizations/create-account
openapi/organizations/create-account.json POST /organizations/account-groups/{account_group_id}/accounts
Creates a new merchant account under a specific account group in the organization
Creates a new account under a specific account group. Each account represents a distinct merchant environment or business unit within the group.
# Create Account Group
Source: https://docs.y.uno/reference/organizations/create-account-group
openapi/organizations/create-account-group.json POST /organizations/account-groups
Creates a new account group to organize merchants or business units within an organization
Creates a new group (sub-organization) within your organization. Account groups can be used to organize different merchants or business units under a single parent entity.
# Create Role
Source: https://docs.y.uno/reference/organizations/create-role
openapi/organizations/create-role.json POST /organizations/roles
Creates a custom role with a defined set of permissions for the organization
Create a custom role for the organization.
# Create User
Source: https://docs.y.uno/reference/organizations/create-user
openapi/organizations/create-user.json POST /organizations/users
Creates a new user within the authenticated organization
# Delete Account
Source: https://docs.y.uno/reference/organizations/delete-account
openapi/organizations/delete-account.json DELETE /organizations/accounts/{account_id}
Disables a specific merchant account within the organization
Disables a specific account within your organization.
# Delete Account Group
Source: https://docs.y.uno/reference/organizations/delete-account-group
openapi/organizations/delete-account-group.json DELETE /organizations/account-groups/{account_group_id}
Deletes an account group and reassigns its accounts to a default organization group
Deletes an account group. All accounts previously belonging to the deleted group are automatically reassigned to a default organization group.
# Delete Role
Source: https://docs.y.uno/reference/organizations/delete-role
openapi/organizations/delete-role.json DELETE /organizations/roles/{role_id}
Deletes a custom role and reassigns its users to the ReadOnly role
Delete a custom role. Users assigned to the deleted role will be automatically reassigned to the ReadOnly role.
# Delete User
Source: https://docs.y.uno/reference/organizations/delete-user
openapi/organizations/delete-user.json DELETE /organizations/users/{user_id}
Deletes a user and all associated organization, account, and role records
Deletes a user and removes all their associated records, including organization links, account links, and role assignments.
# Delete User Account Group Permission
Source: https://docs.y.uno/reference/organizations/delete-user-account-group-permission
openapi/organizations/delete-user-account-group-permission.json DELETE /organizations/users/{user_id}/account-group-permissions/{account_group_id}
Removes a specific account group permission assigned to a user
Removes a specific account group permission from a user.
# Delete User Account Permission
Source: https://docs.y.uno/reference/organizations/delete-user-account-permission
openapi/organizations/delete-user-account-permission.json DELETE /organizations/users/{user_id}/account-permissions/{account_id}
Removes a specific account permission assigned to a user
Removes a specific account permission from a user.
# List Account Groups
Source: https://docs.y.uno/reference/organizations/list-account-groups
openapi/organizations/list-account-groups.json GET /organizations/account-groups
Lists all account groups belonging to the authenticated organization
Lists all account groups for the authenticated organization. Use this endpoint to retrieve a summary of all sub-organizations under your parent entity.
# List Accounts
Source: https://docs.y.uno/reference/organizations/list-accounts
openapi/organizations/list-accounts.json GET /organizations/accounts
Lists all merchant accounts belonging to the authenticated organization
Lists all accounts belonging to the authenticated organization. Use this endpoint to see all sub-entities across all your account groups.
# List Accounts of Group
Source: https://docs.y.uno/reference/organizations/list-accounts-of-group
openapi/organizations/list-accounts-of-group.json GET /organizations/account-groups/{account_group_id}/accounts
Retrieves all accounts associated with a specific account group
Retrieves all accounts associated with a specific account group.
# List Permissions Catalog
Source: https://docs.y.uno/reference/organizations/list-permissions-catalog
openapi/organizations/list-permissions-catalog.json GET /organizations/permissions-catalog
Retrieves the catalog of permission sections available for custom roles
Slim permissions catalog including sections and specific permissions.
# List Roles
Source: https://docs.y.uno/reference/organizations/list-roles
openapi/organizations/list-roles.json GET /organizations/roles
Lists Yuno default roles and organization custom roles
List Yuno default and organization custom roles.
# List Users
Source: https://docs.y.uno/reference/organizations/list-users
openapi/organizations/list-users.json GET /organizations/users
Lists organization users, optionally filtered by account group or account
Lists all users belonging to the authenticated organization. You can optionally filter the results by account group or account ID.
# Replace User Account Group Permissions
Source: https://docs.y.uno/reference/organizations/replace-user-account-group-permissions
openapi/organizations/replace-user-account-group-permissions.json PUT /organizations/users/{user_id}/account-group-permissions
Replaces all account group permission assignments for a user
Replaces all account group permission assignments for a user. Full replacement.
# Replace User Account Permissions
Source: https://docs.y.uno/reference/organizations/replace-user-account-permissions
openapi/organizations/replace-user-account-permissions.json PUT /organizations/users/{user_id}/account-permissions
Replaces all account permission assignments for a user with a new set
Replaces all account permission assignments for a user. This is a full replacement — any existing account permissions not included in the request will be removed.
# Retrieve Account
Source: https://docs.y.uno/reference/organizations/retrieve-account
openapi/organizations/retrieve-account.json GET /organizations/accounts/{account_id}
Retrieves the details of a specific merchant account by its unique identifier
Retrieves the details of a specific account using its unique identifier (UUID).
# Retrieve Account Group
Source: https://docs.y.uno/reference/organizations/retrieve-account-group
openapi/organizations/retrieve-account-group.json GET /organizations/account-groups/{account_group_id}
Retrieves a specific account group by its unique identifier
Gets a specific account group by its unique identifier (UUID).
# Retrieve User
Source: https://docs.y.uno/reference/organizations/retrieve-user
openapi/organizations/retrieve-user.json GET /organizations/users/{user_id}
Retrieves the details of a specific user by their unique identifier
Retrieves the details of a specific user using their unique identifier (UUID).
# Retrieve User Account Group Permissions
Source: https://docs.y.uno/reference/organizations/retrieve-user-account-group-permissions
openapi/organizations/retrieve-user-account-group-permissions.json GET /organizations/users/{user_id}/account-group-permissions
Returns all account group permission assignments for a specific user
Returns all account group permission assignments for a user.
# Retrieve User Account Permissions
Source: https://docs.y.uno/reference/organizations/retrieve-user-account-permissions
openapi/organizations/retrieve-user-account-permissions.json GET /organizations/users/{user_id}/account-permissions
Returns all account permission assignments for a user, including role details
Returns all account permission assignments for a user, including the account name and role details.
# Create a Routing
Source: https://docs.y.uno/reference/organizations/routing/create-routing
openapi/organizations/routing/create-routing.json POST /routing
Creates a routing for one (account_id, payment_method) pair. Always live on success.
Creates a routing for one `(account_id, payment_method)` pair. Each routing references **connections** by their `connection_id`. Make sure your connections are created and `ACTIVE` for the requested `payment_method` *before* you call routing.
### Body
The merchant account ID this routing rule applies to.
E.g., `CARD`, `PIX`, `WALLET`. Immutable per routing — to route a different method, create a new routing.
Free-form label.
The route used when no `condition_sets[]` matches.
Each step is one provider attempt. `index` values are contiguous starting at 1.
Step ordinal.
Must match the provider of the connection.
Must be `ACTIVE` and support the `payment_method`.
Defines how to handle each possible outcome of this step.
The outcome status that triggers this rule (e.g., `APPROVED`, `DECLINED`, `DECLINE_GROUP`, `TIMEOUT`, `INTERNAL_ERROR`).
Required when `status` is `DECLINE_GROUP`. Specifies which decline subtypes trigger this rule (e.g., `INSUFFICIENT_FUNDS`, `DECLINED_BY_BANK`).
The `index` of the next step to execute. Omit if no fallback is needed.
Optional. Ordered by `sort_number` — first matching set wins.
Priority of the condition set.
Label for the set.
List of [Conditions](/reference/organizations/routing/routing-conditions) that must match.
The steps to execute if this set matches.
### Response
Unique identifier for the routing.
Unique identifier for the account.
The payment method this routing applies to (e.g., `CARD`).
Label for the routing.
The default routing logic.
Optional conditional logic.
ISO 8601 timestamp.
ISO 8601 timestamp.
```bash cURL theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
curl -X POST 'https://api.y.uno/v1/routing' \
-H 'public-api-key: ' \
-H 'private-secret-key: ' \
-H 'Content-Type: application/json' \
-H 'X-Idempotency-Key: ' \
-d '{
"account_id": "7825fc5e-e50a-4248-9ae8-5d3786afb0be",
"payment_method": "CARD",
"name": "Card routing — Stripe primary, Adyen fallback",
"default_route": {
"steps": [
{
"index": 1,
"provider_id": "STRIPE",
"connection_id": "f1a3c4d5-7b8e-4a2c-9d1e-3f4a5b6c7d8e",
"output": [
{
"status": "DECLINE_GROUP",
"decline_types": ["DECLINED_BY_BANK", "DO_NOT_HONOR"],
"next": 2
},
{ "status": "TIMEOUT", "next": 2 },
{ "status": "INTERNAL_ERROR", "next": 2 }
]
},
{
"index": 2,
"provider_id": "ADYEN",
"connection_id": "b2c4d5e6-1a2b-3c4d-5e6f-7a8b9c0d1e2f"
}
]
},
"condition_sets": [
{
"sort_number": 1,
"name": "Brazil — 3 to 6 installments via Adyen",
"description": "BR card transactions with 3–6 installments go to Adyen directly",
"conditions": [
{ "condition_type": "COUNTRY", "conditional": "EQUAL", "values": ["BR"] },
{ "condition_type": "INSTALLMENTS", "conditional": "BETWEEN", "values": ["3", "6"] }
],
"route": {
"steps": [
{ "index": 1, "provider_id": "ADYEN", "connection_id": "b2c4d5e6-..." }
]
}
}
]
}'
```
```json 201 Created theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"id": "r_8f2c1d3e-4b5a-6c7d-8e9f-0a1b2c3d4e5f",
"account_id": "acc-uuid",
"payment_method": "CARD",
"name": "Card routing — Stripe primary, Adyen fallback",
"default_route": {
"steps": [
{
"index": 1,
"provider_id": "STRIPE",
"connection_id": "f1a3c4d5-7b8e-4a2c-9d1e-3f4a5b6c7d8e",
"output": [
{ "status": "DECLINE_GROUP", "next": 2 },
{ "status": "TIMEOUT", "next": 2 }
]
},
{ "index": 2, "provider_id": "ADYEN", "connection_id": "b2c4d5e6-..." }
]
},
"condition_sets": [
{
"sort_number": 1,
"name": "Brazil — 3 to 6 installments via Adyen",
"conditions": [
{ "condition_type": "COUNTRY", "conditional": "EQUAL", "values": ["BR"] }
],
"route": { "steps": ["..."] }
}
],
"created_at": "2026-05-12T14:30:00Z",
"updated_at": "2026-05-12T14:30:00Z"
}
```
```json 400 — Non-contiguous Index theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"type": "validation_error",
"code": "ROUTING_VALIDATION_FAILED",
"message": "default_route.steps[].index must be contiguous starting at 1",
"details": { "path": "default_route.steps[1].index", "expected": 2, "received": 3 }
}
```
```json 409 — Already Exists theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"type": "conflict",
"code": "ROUTING_ALREADY_EXISTS",
"message": "A routing already exists for account 'acc-uuid' and payment_method 'CARD'",
"details": { "payment_method": "CARD", "existing_routing_id": "r_..." }
}
```
### Errors
| HTTP | `code` |
| ----- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| `400` | `ROUTING_VALIDATION_FAILED` Schema or rule violation. `details` names the offending field/path. |
| `400` | `ROUTING_PROVIDER_NOT_AVAILABLE` A step references a `(provider_id, connection_id)` not active for the account on this `payment_method`. |
| `409` | `ROUTING_ALREADY_EXISTS` A routing already exists for this `(account, payment_method)`. Use `PATCH` to update it. |
| `403` | `INSUFFICIENT_SCOPE` API key missing `routing:write`. |
# List Routings
Source: https://docs.y.uno/reference/organizations/routing/list-routings
openapi/organizations/routing/list-routings.json GET /routing
Lists all routings of an account, optionally filtered by payment method.
Lists the routings configured on an account. Each item returns the routing's current live configuration, with the same shape as [Retrieve a Routing](/reference/organizations/routing/retrieve-routing).
Pass `payment_method` to list only the routings for that payment method, and omit it to list all of them.
### Query Parameters
The account to list routings for. Must belong to the organization your API credentials are scoped to.
Optional filter by payment method (e.g., `CARD`, `PIX`). Same values as the `payment_method` field in routing responses.
### Response
The routings configured on the account, or an empty array if it has none. Each routing contains:
Unique identifier for the routing.
Unique identifier for the account.
The payment method this routing applies to (e.g., `CARD`).
Label for the routing.
The default routing logic.
Optional conditional logic.
ISO 8601 timestamp.
ISO 8601 timestamp.
Optional list of non-blocking orchestration warnings (e.g., `MONITOR_REDISTRIBUTION_DEFERRED`).
```bash cURL theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
curl -X GET 'https://api.y.uno/v1/routing?account_id=7825fc5e-e50a-4248-9ae8-5d3786afb0be&payment_method=CARD' \
-H 'public-api-key: ' \
-H 'private-secret-key: '
```
```json 200 OK theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
[
{
"id": "r_8f2c1d3e-4b5a-6c7d-8e9f-0a1b2c3d4e5f",
"account_id": "acc-uuid",
"payment_method": "CARD",
"name": "Card routing — Stripe primary, Adyen fallback",
"default_route": {
"steps": [
{
"index": 1,
"provider_id": "STRIPE",
"connection_id": "f1a3c4d5-7b8e-4a2c-9d1e-3f4a5b6c7d8e",
"output": [
{ "status": "DECLINE_GROUP", "next": 2 },
{ "status": "TIMEOUT", "next": 2 }
]
},
{ "index": 2, "provider_id": "ADYEN", "connection_id": "b2c4d5e6-..." }
]
},
"created_at": "2026-05-12T14:30:00Z",
"updated_at": "2026-05-12T14:30:00Z"
}
]
```
```json 400 Bad Request theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"type": "invalid_request",
"code": "ROUTING_VALIDATION_FAILED",
"message": "account_id is required."
}
```
### Errors
| HTTP | `code` | When |
| ----- | --------------------------- | ------------------------------------------------------------------------------------ |
| `400` | `ROUTING_VALIDATION_FAILED` | Missing `account_id` query parameter. |
| `403` | `INSUFFICIENT_SCOPE` | API key missing `routing:read`, or `account_id` belongs to a different organization. |
# Retrieve a Routing
Source: https://docs.y.uno/reference/organizations/routing/retrieve-routing
openapi/organizations/routing/retrieve-routing.json GET /routing/{routing_id}
Returns the routing's current live configuration.
Returns the routing's current live configuration.
### Path Parameters
The id returned by [Create a Routing](/reference/organizations/routing/create-routing). Must belong to the account your API key is scoped to.
### Response
Unique identifier for the routing.
Unique identifier for the account.
The payment method this routing applies to (e.g., `CARD`).
Label for the routing.
The default routing logic.
Optional conditional logic.
ISO 8601 timestamp.
ISO 8601 timestamp.
Optional list of non-blocking orchestration warnings (e.g., `MONITOR_REDISTRIBUTION_DEFERRED`).
```bash cURL theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
curl -X GET 'https://api.y.uno/v1/routing/r_8f2c1d3e-4b5a-6c7d-8e9f-0a1b2c3d4e5f' \
-H 'public-api-key: ' \
-H 'private-secret-key: '
```
```json 200 OK theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"id": "r_8f2c1d3e-4b5a-6c7d-8e9f-0a1b2c3d4e5f",
"account_id": "acc-uuid",
"payment_method": "CARD",
"name": "Card routing — Stripe primary, Adyen fallback",
"default_route": {
"steps": [
{
"index": 1,
"provider_id": "STRIPE",
"connection_id": "f1a3c4d5-7b8e-4a2c-9d1e-3f4a5b6c7d8e",
"output": [
{ "status": "DECLINE_GROUP", "next": 2 },
{ "status": "TIMEOUT", "next": 2 }
]
},
{ "index": 2, "provider_id": "ADYEN", "connection_id": "b2c4d5e6-..." }
]
},
"created_at": "2026-05-12T14:30:00Z",
"updated_at": "2026-05-12T14:30:00Z"
}
```
```json 404 Not Found theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"type": "not_found",
"code": "ROUTING_NOT_FOUND",
"message": "Routing '...' was not found",
"details": { "routing_id": "..." }
}
```
### Errors
| HTTP | `code` | When |
| ----- | -------------------- | ----------------------------------------------------------- |
| `404` | `ROUTING_NOT_FOUND` | Unknown `routing_id`, or id belongs to a different account. |
| `403` | `INSUFFICIENT_SCOPE` | API key missing `routing:read`. |
# Routing Conditions
Source: https://docs.y.uno/reference/organizations/routing/routing-conditions
A condition matches against an attribute of the incoming payment.
A condition matches against an attribute of the incoming payment.
```jsonc theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"condition_type": "",
"conditional": "",
"values": ["..."],
// Required only on specific condition_types — see "Special cases" below
"key": "", // METADATA only
"currency": "" // AMOUNT only
}
```
Conditions inside the same `condition_sets[].conditions[]` are combined with **logical AND**. For OR semantics, split into multiple condition sets ordered by `sort_number`.
#### `condition_type` catalog
| `condition_type` | Matches against | Value shape | Applicable `conditional`s | Card-only? |
| ------------------ | -------------------------------- | ---------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | ---------- |
| `COUNTRY` | Buyer's billing country | ISO 3166-1 alpha-2 (e.g. `"US"`, `"BR"`) | `EQUAL`, `NOT_EQUAL`, `ONE_OF`, `NOT_ONE_OF` | no |
| `ISSUER_COUNTRY` | Card-issuing bank's country | ISO 3166-1 alpha-2 | `EQUAL`, `NOT_EQUAL`, `ONE_OF`, `NOT_ONE_OF` | yes |
| `CURRENCY` | Transaction currency | ISO 4217 (e.g. `"USD"`) | `EQUAL`, `NOT_EQUAL`, `ONE_OF`, `NOT_ONE_OF` | no |
| `AMOUNT` | Transaction amount | Decimal as **string** (e.g. `"100.00"`); requires sibling `currency` | `EQUAL`, `NOT_EQUAL`, `GREATER_THAN`, `LESS_THAN`, `BETWEEN`, `NOT_BETWEEN` | no |
| `CARD_TYPE` | Card funding source | `CREDIT`, `DEBIT`, `PREPAID` | `EQUAL`, `NOT_EQUAL`, `ONE_OF`, `NOT_ONE_OF` | yes |
| `CARD_BRAND` | Card scheme | `VISA`, `MASTERCARD`, `AMEX`, `ELO`, `HIPERCARD`, `DINERS`, `DISCOVER`, `JCB`, `UNIONPAY`, `MAESTRO`, `CB` | `EQUAL`, `NOT_EQUAL`, `ONE_OF`, `NOT_ONE_OF` | yes |
| `CARD_BIN` | First 6–8 digits of the PAN | 6–8 digit numeric string | `EQUAL`, `NOT_EQUAL`, `ONE_OF`, `NOT_ONE_OF` | yes |
| `INSTALLMENTS` | Number of installments requested | Integer as string | `EQUAL`, `NOT_EQUAL`, `GREATER_THAN`, `LESS_THAN`, `BETWEEN`, `NOT_BETWEEN` | no |
| `TRANSACTION_TYPE` | Payment intent type | `PURCHASE`, `AUTHORIZATION`, `RECURRING`, `MIT`, `CIT` | `EQUAL`, `NOT_EQUAL`, `ONE_OF`, `NOT_ONE_OF` | no |
| `METADATA` | `payment.metadata[]` | Any string the merchant sets; requires sibling `key` | `EQUAL`, `NOT_EQUAL`, `ONE_OF`, `NOT_ONE_OF` | no |
#### `conditional` operators
| Operator | Cardinality of `values[]` | Semantics |
| -------------- | ------------------------- | ------------------------------- |
| `EQUAL` | exactly 1 | `attribute == values[0]` |
| `NOT_EQUAL` | exactly 1 | `attribute != values[0]` |
| `ONE_OF` | ≥ 1 | `attribute ∈ values` |
| `NOT_ONE_OF` | ≥ 1 | `attribute ∉ values` |
| `GREATER_THAN` | exactly 1 | numeric `attribute > values[0]` |
| `LESS_THAN` | exactly 1 | numeric `attribute < values[0]` |
| `BETWEEN` | exactly 2 | inclusive on both ends |
| `NOT_BETWEEN` | exactly 2 | inverse of `BETWEEN` |
#### Special cases
* **`AMOUNT` requires `currency`.** Comparisons are FX-naive; only payments whose currency matches the rule's `currency` are evaluated.
* **`METADATA` requires `key`.** Compares `payment.metadata[key]`. If the key is absent on the payment, the condition does **not** match — absence is not equality.
* **Card-only condition types** (`ISSUER_COUNTRY`, `CARD_TYPE`, `CARD_BRAND`, `CARD_BIN`) are only valid when `payment_method = "CARD"`.
* **Numeric values are submitted as strings** to match the `values: string[]` schema. Yuno parses them based on the `condition_type`.
# Routing Resource Shape
Source: https://docs.y.uno/reference/organizations/routing/routing-resource-shape
Each routing is a single atomic resource on the public API: one HTTP call creates or replaces the full configuration.
A routing tells Yuno, for one `payment_method` on one account, which connection to use — and lets you branch by buyer attributes (country, currency, amount, card brand, custom metadata, …).
### Resource shape
```json theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"id": "r_8f2c1d3e-…",
"account_id": "acc-uuid",
"payment_method": "CARD",
"name": "Card routing",
"default_route": {
"steps": [
{ "index": 1, "provider_id": "STRIPE", "connection_id": "f1a3c4d5-…" }
]
},
"condition_sets": [
{
"sort_number": 1,
"name": "US & Canada — high value",
"description": "Route US/CA credit card transactions over $500",
"conditions": [
{ "condition_type": "COUNTRY", "conditional": "ONE_OF", "values": ["US", "CA"] },
{ "condition_type": "AMOUNT", "conditional": "GREATER_THAN", "values": ["500"], "currency": "USD" }
],
"route": {
"steps": [
{ "index": 1, "provider_id": "STRIPE", "connection_id": "f1a3c4d5-…",
"output": [{ "status": "DECLINED", "next": 2 }] },
{ "index": 2, "provider_id": "ADYEN", "connection_id": "b2c4d5e6-…" }
]
}
}
],
"created_at": "2026-05-12T12:00:00Z",
"updated_at": "2026-05-12T12:00:00Z"
}
```
**Top-level fields**
| Field | Type | Notes |
| -------------------------- | ------------------- | --------------------------------------------------------------------------------------------------------- |
| `id` | UUID | Server-assigned. The same value is referenced as `routing_id` in URL paths. |
| `account_id` | string | Inferred from your API key. Not supplied in request bodies. |
| `payment_method` | enum | E.g., `CARD`, `PIX`, `WALLET`. Immutable per routing — to route a different method, create a new routing. |
| `name` | string | Free-form label. |
| `default_route` | object | The route used when no `condition_sets[]` matches. **Required.** |
| `condition_sets[]` | object\[] | Optional. Ordered by `sort_number` — first matching set wins. Each has one `route`. |
| `created_at`, `updated_at` | ISO-8601 timestamps | Server-managed. |
**`route.steps[]`**
Each step is one provider attempt. `index` values are contiguous starting at 1.
| Field | Type | Required | Notes |
| --------------- | --------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `index` | int | yes | Step ordinal within the route. Cycles are forbidden — `output[].next` must point to a higher index. |
| `provider_id` | string | yes | Must match the `provider_id` of the referenced connection. |
| `connection_id` | UUID | yes | Must be `ACTIVE`, in the same account, and support the routing's `payment_method`. |
| `output[]` | object\[] | no | Per-outcome handlers. **Omit for terminal steps with no chaining or per-decline customization** — the route will just run the step and terminate with whatever the provider returned. |
**`output[]` entries**
| Field | Type | Required | Notes |
| ---------------------- | ----------- | ----------------------------------------------- | ----------------------------------------------------- |
| `status` | enum | yes | What outcome this entry reacts to. See enum below. |
| `decline_types[]` | string\[] | only with `status = DECLINE_GROUP` | Subset of Yuno's normalized decline taxonomy. |
| `error_rate_threshold` | object | only with `status = ERROR_RATE` | `{ threshold_percent: int, window_seconds: int }`. |
| `next` | int \| null | yes | Index of the step to jump to, or `null` to terminate. |
**`status` enum**
| Value | Triggers when | Companion field |
| ---------------- | --------------------------------------------------------------------------------------------------- | ---------------------- |
| `APPROVED` | The provider returned success. Implicit by default; list explicitly only for post-approval routing. | — |
| `DECLINED` | Any decline (catch-all). Place last in the array. | — |
| `DECLINE_GROUP` | Decline whose normalized code is in `decline_types[]`. | `decline_types[]` |
| `ERROR_RATE` | The step's rolling error rate exceeds `error_rate_threshold`. | `error_rate_threshold` |
| `TIMEOUT` | The provider didn't respond within Yuno's per-step timeout. | — |
| `INTERNAL_ERROR` | The provider returned a 5xx or connection error before reaching the issuer. | — |
**Evaluation rules**
1. The route enters at `index: 1`.
2. The provider call runs.
3. Yuno walks `output[]` top-to-bottom; the first entry whose `status` (plus optional `decline_types` / `error_rate_threshold` predicate) matches the outcome wins.
4. If the matched entry's `next` is an integer, jump to that step. If `null` or no entry matches, the route terminates with the actual provider outcome.
# Update a Routing
Source: https://docs.y.uno/reference/organizations/routing/update-routing
openapi/organizations/routing/update-routing.json PATCH /routing/{routing_id}
Replaces the routing's full configuration.
Replaces the routing's full configuration. The body has the same shape as [Create a Routing](/reference/organizations/routing/create-routing) — the new `default_route` and `condition_sets[]` entirely supersede the previous live state. **There is no field-level merge.**
`account_id` and `payment_method` are sticky to the `routing_id` — they're set at creation and cannot be changed by `PATCH`.
### Path Parameters
The id returned by [Create a Routing](/reference/organizations/routing/create-routing).
### Body
Free-form label.
The route used when no `condition_sets[]` matches.
Each step is one provider attempt. `index` values are contiguous starting at 1.
Step ordinal.
Must match the provider of the connection.
Must be `ACTIVE` and support the `payment_method`.
Defines how to handle each possible outcome of this step.
The outcome status that triggers this rule (e.g., `APPROVED`, `DECLINED`, `DECLINE_GROUP`, `TIMEOUT`, `INTERNAL_ERROR`).
Required when `status` is `DECLINE_GROUP`. Specifies which decline subtypes trigger this rule (e.g., `INSUFFICIENT_FUNDS`, `DECLINED_BY_BANK`).
The `index` of the next step to execute. Omit if no fallback is needed.
Optional. Ordered by `sort_number` — first matching set wins.
Priority of the condition set.
Label for the set.
List of [Conditions](/reference/organizations/routing/routing-conditions) that must match.
The steps to execute if this set matches.
### Response
Unique identifier for the routing.
Unique identifier for the account.
The payment method this routing applies to (e.g., `CARD`).
Label for the routing.
The default routing logic.
Optional conditional logic.
ISO 8601 timestamp.
ISO 8601 timestamp.
```bash cURL theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
curl -X PATCH 'https://api.y.uno/v1/routing/r_8f2c1d3e-4b5a-6c7d-8e9f-0a1b2c3d4e5f' \
-H 'public-api-key: ' \
-H 'private-secret-key: ' \
-H 'Content-Type: application/json' \
-H 'X-Idempotency-Key: ' \
-d '{
"payment_method": "CARD",
"name": "Card routing v2 — adds BR installments rule",
"default_route": {
"steps": [
{
"index": 1,
"provider_id": "STRIPE",
"connection_id": "f1a3c4d5-7b8e-4a2c-9d1e-3f4a5b6c7d8e",
"output": [
{ "status": "DECLINED", "next": 2 }
]
},
{
"index": 2,
"provider_id": "ADYEN",
"connection_id": "b2c4d5e6-1a2b-3c4d-5e6f-7a8b9c0d1e2f"
}
]
},
"condition_sets": [
{
"sort_number": 1,
"name": "Brazil — 3 to 6 installments via Adyen",
"description": "BR card transactions with 3–6 installments go to Adyen directly",
"conditions": [
{ "condition_type": "COUNTRY", "conditional": "EQUAL", "values": ["BR"] },
{ "condition_type": "INSTALLMENTS", "conditional": "BETWEEN", "values": ["3", "6"] }
],
"route": {
"steps": [
{ "index": 1, "provider_id": "ADYEN", "connection_id": "b2c4d5e6-..." }
]
}
}
]
}'
```
```json 200 OK — Updated theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"id": "r_8f2c1d3e-4b5a-6c7d-8e9f-0a1b2c3d4e5f",
"account_id": "acc-uuid",
"payment_method": "CARD",
"name": "Card routing v2 — adds BR installments rule",
"default_route": {
"steps": [
{
"index": 1,
"provider_id": "STRIPE",
"connection_id": "f1a3c4d5-7b8e-4a2c-9d1e-3f4a5b6c7d8e",
"output": [ { "status": "DECLINED", "next": 2 } ]
},
{ "index": 2, "provider_id": "ADYEN", "connection_id": "b2c4d5e6-..." }
]
},
"condition_sets": [
{
"sort_number": 1,
"name": "Brazil — 3 to 6 installments via Adyen",
"conditions": [
{ "condition_type": "COUNTRY", "conditional": "EQUAL", "values": ["BR"] }
],
"route": { "steps": ["..."] }
}
],
"created_at": "2026-05-12T14:30:00Z",
"updated_at": "2026-05-13T09:18:42Z"
}
```
```json 400 — Immutable Payment Method theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"type": "validation_error",
"code": "ROUTING_PAYMENT_METHOD_IMMUTABLE",
"message": "payment_method cannot be changed on an existing routing",
"details": {
"routing_id": "r_...",
"current_payment_method": "CARD",
"received_payment_method": "PIX"
}
}
```
### Errors
| HTTP | `code` |
| ----- | ------------------------------------------------------------------------------------------------------------- |
| `404` | `ROUTING_NOT_FOUND` Unknown `routing_id`, or id belongs to a different account. |
| `400` | `ROUTING_VALIDATION_FAILED` Schema or rule violation. |
| `400` | `ROUTING_PROVIDER_NOT_AVAILABLE` A step references an inactive/unknown connection. |
| `400` | `ROUTING_PAYMENT_METHOD_IMMUTABLE` Body's `payment_method` doesn't match the routing's `payment_method`. |
| `409` | `ROUTING_VERSION_CONFLICT` Another concurrent `PATCH` won the publish race. |
| `403` | `INSUFFICIENT_SCOPE` API key missing `routing:write`. |
# Update Account
Source: https://docs.y.uno/reference/organizations/update-account
openapi/organizations/update-account.json PATCH /organizations/accounts/{account_id}
Updates the name or other details of an existing merchant account
Updates the name or other details of an existing account.
# Update Account Group
Source: https://docs.y.uno/reference/organizations/update-account-group
openapi/organizations/update-account-group.json PATCH /organizations/account-groups/{account_group_id}
Updates the name or merchant ID of an existing account group
Updates the details of an existing account group, such as its name or merchant ID.
# Update Role
Source: https://docs.y.uno/reference/organizations/update-role
openapi/organizations/update-role.json PATCH /organizations/roles/{role_id}
Partially updates a custom role's permissions without changing its role type
Partial update of a custom role. Note that `role_type` is immutable.
# Update User
Source: https://docs.y.uno/reference/organizations/update-user
openapi/organizations/update-user.json PATCH /organizations/users/{user_id}
Updates the first or last name of an existing user
Updates the first or last name of an existing user.
# Update User Account Group Permissions
Source: https://docs.y.uno/reference/organizations/update-user-account-group-permissions
openapi/organizations/update-user-account-group-permissions.json PATCH /organizations/users/{user_id}/account-group-permissions
Adds or updates account group permissions for a user without removing existing ones
Partially updates account group permissions. Adds or updates without removing existing ones.
# Update User Account Permissions
Source: https://docs.y.uno/reference/organizations/update-user-account-permissions
openapi/organizations/update-user-account-permissions.json PATCH /organizations/users/{user_id}/account-permissions
Adds or updates account permissions for a user without removing existing ones
Partially updates account permissions. Adds or updates the specified entries without removing existing ones.
# Cancel Payment Link
Source: https://docs.y.uno/reference/payment-links/cancel-payment-link
openapi/payment-links/cancel-payment-link.json POST /payment-links/{code}/cancel
Cancels an active payment link, preventing further use for collecting payment
# Create Payment Link
Source: https://docs.y.uno/reference/payment-links/create-payment-link
openapi/payment-links/create-payment-link.json POST /payment-links
Creates a shareable payment link for collecting a payment from a customer
# Retrieve Payment Link
Source: https://docs.y.uno/reference/payment-links/retrieve-payment-link
openapi/payment-links/retrieve-payment-link.json GET /payment-links/{code}
Retrieves the details and current status of a specific payment link by code
# Payment Link Status
Source: https://docs.y.uno/reference/payment-links/status-payment-links
Describes the possible statuses of a payment link and how they transition
Yuno's payment links solution enables businesses to accept payments effortlessly and offer subscriptions without additional websites or applications. These versatile links can be shared across various platforms, including social media, emails, and websites. Supporting diverse payment methods like credit and debit cards, Apple Pay, and Google Pay, payment links provide a secure and rapid way to collect payments.
## Workflow
In the following workflow, you can find the different payment link statuses and how they can be updated.
## Payment links status
The payment links can have the status described in the table below.
| Status | Description |
| -------- | ------------------------------------------------------------- |
| CREATED | The payment link is active and can be used to make a payment. |
| USED | The payment link has already been used. |
| CANCELED | Payment link canceled. |
| EXPIRED | The link expired before your customer was able to pay for it. |
| ERROR | An error occurred in the process. |
# The Payment Link Object
Source: https://docs.y.uno/reference/payment-links/the-payment-link-object
Describes the attributes returned in a payment link object, including customer and amount data
## Attributes
This object represents a payment link that can be associated with a customer.
The unique identifier of the customer (MAX 64 ; MIN 36).
Example: 8546df3a-b83e-4bb5-a4b3-57aa6385924f
The unique identifier of the account (MAX 64; MIN 36).
Example: 9104911d-5df9-429e-8488-ad41abea1a4b
The description of the payment link (MAX 255; MIN 3).
Example: Marketplace payment
Country where the transaction must be processed (MAX 2; MIN 2; ISO 3166-1 ).
Possible enum values: Check the Country reference.
The status of the Payment link (MAX 255; MIN 3) (CREATED, USED, CANCELED, EXPIRED, ERROR).
Example: ACTIVE
Identification of the payment link (MAX 255; MIN 3).
Example: 432245
The date and time when the payment link was created.
Example: 2022-05-09T20:46:54.786342Z
The date and time of last update for the payment link.
Example: 2022-05-09T20:46:54.786342Z
Decides whether to authorize the payment or capture it. Authorizing a card payment allows you to reserve
funds in a customer's bank account. If the field is not sent, we will take it as true. You can later capture the
payment vía Yuno's dashboard or API method .
Example: true
Specifies the payment amount object, with the value and currency.
The currency used to make the payment (MAX 3; MIN 3; ISO 4217 ).
Possible enum values: Check the Country reference.
The payment amount (multiple of 0.0001).
Example: 12100.00
Specifies customer object for payments links.
The unique identifier of the customer at
Yuno platform (MAX 255; MIN 3).
Example: faa89e18-5a11-11ed-9b6a-0242ac120002
The unique identifier of the customer in the external merchant (MAX 255; MIN 3).
Example: 23456
The customer's first name (MAX 255; MIN 3).
Example: John
The customer's last name (MAX 255; MIN 3).
Example: Doe
The customer's gender (MAX 2; MIN 1; (M=Male/F=Female/NA=Not applicable/NK=Not Known)).
Possible enum values: `M`, `F`, `NA`, or `NK`.
The customer's date of birth in the YYYY-MM-DD format (Length: 10).
Example: 1990-02-28
The customer's e-mail (MAX 255; MIN 3).
Example: [john.doe@email.com](mailto:john.doe@email.com)
The customer's nationality (MAX 2; MIN 2; ISO 3166-1 ).
Possible enum values: Check the Country reference.
Specifies the customer's document object, including its number and type.
The customer's document number (MAX 40; MIN 3).
Example: 1093333333
The customer's document type (MAX 6, MIN 2).
Possible enum values: Check the
Country reference.
Specifies the customer's phone object, including number and code.
The customer's phone number (MAX 40; MIN 3).
Example: 11992149494
The country calling code of the customer's phone (MAX 3; MIN 1)
Possible values: Check the
Country reference.
Specifies the customer's billing address object.
The primary billing address line of the customer (MAX 255; MIN 3).
Example: Calle 34 # 56 - 78
The secondary billing address line of the customer (MAX 255; MIN 3).
Example: Apartamento 502, Torre I
The city considered for the billing address (MAX 255; MIN 3).
Example: Bogotá
The country considered for the billing address (MAX 2; MIN 2; ISO
3166-1 ).
Possible enum values: Check the Country reference.
The state considered for the billing address (MAX 255; MIN 3).
Example: Cundinamarca
The zipcode considered for the billing address (MAX 11; MIN 4).
Example: 111111
Specifies the customer's shipping address object.
The primary shipping address line of the customer (MAX 255; MIN 3).
Example: Calle 34 # 56 - 78
The secondary shipping address line of the customer (MAX 255; MIN 3).
Example: Apartamento 502, Torre I
The city considered for the shipping address (MAX 255; MIN 3).
Example: Bogotá
The country considered for the shipping address (MAX 2; MIN 2; ISO
3166-1 ).
Possible enum values: Check the Country reference.
The state considered for the shipping address (MAX 255; MIN 3).
Example: Cundinamarca
The zipcode considered for the shipping address (MAX 11; MIN 4).
Example: 111111
Specifies the additional\_data object. This object is not mandatory. However, if you send this information, the
payment experience will be enhanced for your user.
Specifies the airline object. Passengers and tickets should have the same order information.
Passenger name record (MAX 10; MIN 1).
Example: 1P-2UUGJW
Specifies the legs array of objects.
IATA airport code (MAX 3; MIN 3). See [http://www.iata.org](http://www.iata.org) .
Example: AMS
The transaction amount, excluding taxes and fees, the smallest unit of currency (multiple of
0.0001).
Example: 23.5676
The currency used to transaction amount (MAX 3; MIN 3; ISO 4217 ).
Example: Check the Country reference.
IATA carrier code (MAX 2; MIN 2). See [http://www.iata.org](http://www.iata.org) .
Example: KL
IATA code (MAX 3; MIN 3). See [http://www.iata.org](http://www.iata.org) .
Example: EZE
Airport timezone (MAX 6; MIN 6).
Example: -03:00
The departure date and time in local time at the departure airport.
Example: 2022-05-09T20:46:54.786342Z
Code base rate provides specific information on the fare in addition to the class service, both
required for booking (MAX 15; MIN 1).
Example: HL7LNR
The fare class code of the airline (MAX 1; MIN 1). The values can be a letter (A-Z) but may vary
depending on the airline's definition.
Example: C
The flight number assigned by the airline carrier (MAX 5; MIN 1).
Example: 842
The stopover code (1-letter code that indicates whether the passenger is allowed to make a
stopover.
Only two types of characters are allowed: O: Stopover allowed (the letter “O”, not zero) / X: Stopover
not
allowed).
Example: O
Specifies the array of objects that represents the passengers associated to the tickets.
Specifies the document object for the passenger.
The passenger's document number (MAX 40; MIN 3).
Example: 1093333333
The passenger's document type (MAX 6, MIN 2).
Possible enum values: Check the
Country reference.
Country where the document was issued (MAX 2; MIN 2; ISO
3166-1 ).
Possible enum values: Check the Country reference.
The passenger's date of birth in the YYYY-MM-DD format (MAX 10; MIN 10).
Example: 1990-02-28
The passenger's email (MAX 255; MIN 3).
Example: [John.Doe@gmail.com](mailto:John.Doe@gmail.com)
The passenger's first name (MAX 255; MIN 3).
Example: John
The passenger's last name (MAX 255; MIN 3).
Example: Doe
Number of passenger loyalty program (MAX 20, MIN 1).
Example: 254587547
Tier of passenger loyalty program (MAX 255; MIN 3).
Possible enum values: Check the
Loyalty tier.
The passenger's middle name (MAX 255; MIN 3).
Example: Charles
The passenger's nationality (MAX 2; MIN 2; ISO 3166-1 ).
Possible enum values: Check the Country reference.
The type of passenger (MAX 1; MIN 1).
Possible enum values: Check the Passenger type list.
Specifies the array of tickets associated with the passengers.
Ticket number (MAX 14; MIN 1).
Example: 7411823255523
Is this an e-ticket?
Possible values: `True` or `False`
Indicates if the ticket is refunfable or not.
Possible values: `True` or `False`
Total fare amount in the smallest unit of currency (multiple of 0.0001).
Example: 80000
Total taxes amount in the smallest unit of currency (multiple of 0.0001).
Example: 14800
Total fee amount in the smallest unit of currency (multiple of 0.0001).
Example: 25200
Specifies the issue object.
Address of the agent who sold the ticket (MAX 255; MIN 3).
Example: Apartamento 502, Torre I
Issuing or Validating carrier. This is the AWB Prefix (Air waybill) IATA 3-numeric code (MAX
3; MIN
3\).
Example: 044
City name of the agent who sold the ticket (MAX 255; MIN 3).
Example: Bogotá
Country code where the ticket was issued (MAX 2; MIN 2; ISO
3166-1 ).
Possible enum values: Check the Country code
list.
Ticket issuing date.
Example: 1979-01-12
Code of the travel agent issuing the ticket.
Example: 10655823
The name under which the point of sale appears on the agency list or franchise name (MAX 32;
MIN
1\).
Example: ACME Agency Inc
Specifies the order object.
The fee amount of the order (multiple of 0.0001).
Example: 1
The shipping amount of the order (multiple of 0.0001).
Example: 1
Specifies the item's object.
The unique identifier of the item (MAX 255; MIN 3).
Example: 3214
The name of the item (MAX 255; MIN 3).
Example: iPhone 12 Pro Max
The quantity of the item (MAX 999; MIN 1).
Example: 1
The unit amount of the item (multiple of 0.0001).
Example: 550
The category of the item (MAX 255; MIN 3).
Possible values: Check the Item category list.
The brand of the item (MAX 255; MIN 3).
Example: Apple
The stock keeping unit (SKU) of the item (MAX 255; MIN 3).
Example: A2342
The manufacture part number of the item (MAX 255; MIN 3).
Example: 345621234
The picture of the item (MAX 255; MIN 3).
Example: https\://www\.merchant\_url.com/items/:id
Specifies the seller's details object.
The seller's legal name (MAX 255; MIN 3).
Example: Jhon Doe
The seller's e-mail (MAX 255; MIN 3).
Example: [jhondoe@business.com](mailto:jhondoe@business.com)
The seller's identification code (MAX 255; MIN 3).
Example: Seller
The seller's website URL (MAX 255; MIN 3).
Example: [https://www.test.com/1231324](https://www.test.com/1231324)
The seller's industry (MAX 255; MIN 3).
Possible enum values: Check the Industry category.
The seller's country (MAX 255; MIN 3).
Possible enum values: Check the Country code list.
Specifies the document object of the seller.
The seller's document number (MAX 40; MIN 3).
Example: 1093333333
The seller's document type (MAX 6, MIN 2).
Possible enum values: Check the
Country reference.
Specifies the seller's phone number object.
The country calling code of the seller's phone (MAX 3; MIN 1). Possible values: Check the
Country reference .
Example: 57
The seller's phone number, without the country code (MAX 32; MIN 1).
Example: 3132450765
Specifies the seller's address object.
The primary address line of the seller (MAX 255; MIN 3).
Example: Calle 34 # 56 - 78
The secondary billing address line of the seller (MAX 255; MIN 3).
Example: Apartamento 502, Torre I
The city considered for the seller's address (MAX 255; MIN 3).
Example: Bogotá
The country considered for the seller's address (MAX 2; MIN 2, ISO
3166-1 ).
Possible enum values: Check the Country code
list.
The state considered for the seller's address (MAX 255; MIN 3).
Example: Cundinamarca
The zipcode considered for the seller's address (MAX 11; MIN 4).
Example: 111111
Specifies the order's tax object.
Type of the tax.
Example: VAT
The amount base to apply the tax defined.
Example: 10000
The amount of the tax.
Example: 2100
The percentage of the tax.
Example: 21
Single Link: For a single collection with defined product, amount and customer information.
Multiple Link: To use and share as many times as necessary, with defined amount and product.
Options: false allows only one use, true multiple payments.
Specifies the availability object. Refers to the Payment Link expiration date.
Start of the validity period of the payment link.
Example: 2022-05-09T20:46:54.786342Z
End of the validity period of the payment link.
Example: 2022-05-09T20:46:54.786342Z
URL to redirect your customer after the payment (MAX 255; MIN 3).
Example: [https://www.your-site.com/](https://www.your-site.com/)
Payment Link URL (MAX 255; MIN 3).
Example: [https://checkout.y.uno/payment\_links/id](https://checkout.y.uno/payment_links/id)
The list of types of payment methods that customers can use. If no value is passed, Yuno will display the
payment methods defined in the dashboard.
Array of Payment objects
Specifies a list of metadata objects. You can add up to 50 metadata objects.
Specifies a metadata key and the respective value.
Specifies one metadata key.
Example: age
Specifies the value for the defined metadata key.
Example: 28
Flag to enroll the card after a successful payment. False by default.
Example: false
# Enroll Payment Method
Source: https://docs.y.uno/reference/payment-methods-checkout/enroll-payment-method-checkout
openapi/payment-methods-checkout/enroll-payment-method-checkout.json POST /customers/sessions/{customer_session}/payment-methods
Enrolls a customer's selected payment method for future use during checkout
This request enrolls a payment method for a customer. With the information provided by Yuno after the customer selects the payment method to enroll, you will be able to save it for future purchases in the payment method object created.
Note that this request requires an `X-Idempotency-Key`. Check the [Authentication](/reference/authentication#idempotency).
**Webhooks**
We recommend listening to [Webhooks](/docs/configure-webhooks) to stay up to date with the state of the enrolled payment methods of your customers.
In case a customer enrolls the same card twice but with new expiration date or cardholder info, we will unenroll the previously enrolled card and keep the new one.
## Available payment methods for enrollment
The following payment methods can be enrolled using this endpoint:
| Payment Method | Type |
| ------------------------ | ---------------------- |
| **Cards** | `CARD` |
| **Nupay** | `NU_PAY_ENROLLMENT` |
| **PayPal** | `PAYPAL_ENROLLMENT` |
| **Daviplata** | `DAVIPLATA_ENROLLMENT` |
| **MercadoPago Wallet** | `WALLET_CONNECT` |
| **dLocal Yape** | `YAPE_ENROLLMENT` |
| **dLocal Smart PIX** | `SMART_PIX` |
| **Astropay** | `ASTROPAY_ENROLLABLE` |
| **Adyen PIX Biométrico** | `PIX_BIOMETRICO` |
**Payment Method Availability**
When you retrieve the payment methods available to enroll, only the ones which you have connected, created a route, and added to your checkout will be present. For more information about enrollment workflows, see the [Enroll Payment Methods](/docs/enroll-payment-methods) guide.
# Retrieve Payment Method by ID
Source: https://docs.y.uno/reference/payment-methods-checkout/retrieve-payment-method-by-id-checkout
openapi/payment-methods-checkout/retrieve-payment-method-by-id-checkout.json GET /payment-methods/{payment_method_id}
Retrieves details of a specific enrolled payment method by its ID
Retrieve information about a payment method based on its `payment_method_id`, which needs to be provided in the request path.
# Retrieve Payment Methods to Enroll
Source: https://docs.y.uno/reference/payment-methods-checkout/retrieve-payment-methods-to-enroll-checkout
openapi/payment-methods-checkout/retrieve-payment-methods-to-enroll-checkout.json GET /checkout/customers/sessions/{customer_session}/payment-methods
Retrieves the payment methods available for a customer to enroll during checkout
Get the list of payment methods the user has available for enrollment.
# The Payment Method Object
Source: https://docs.y.uno/reference/payment-methods-checkout/the-payment-method-object-checkout
Describes the attributes returned in a payment method object, including provider and enrollment data
## Attributes
This object represents a payment method that can be associated with a customer.
The unique identifier of the payment method (MAX 64; MIN 36).
Example: 693ed90e-5aa9-11ed-9b6a-0242ac120002
The unique identifier of the account (MAX 64; MIN 36).
Example: 8caa8bf4-5aa9-11ed-9b6a-0242ac120002
The payment method name (MAX 255; MIN 3).
Example: Mercado Pago - Wallet
The payment method description (MAX 255; MIN 3).
Example: Mercado Pago - Wallet, the best!
The payment method type (MAX 255; MIN 3).
Possible enum values: Check the
Payment type list.
The payment method category (MAX 255; MIN 3).
Example: CARD
The customer's country (MAX 2; MIN 2; ISO 3166-1 ).
Possible enum values: Check the Country reference.
Indicates whether to verify the payment with a verify transaction or not. You’ll need to have a provider defined in your CARD route.
Indicates whether to verify the payment with a verify transaction or not. False by default.
Currency of the card verification.(MAX 3; MIN 3; ISO 4217 ).
Possible enum values: Check the Country reference.
Status of the payment method (MAX 255; MIN 5).
Possible enum values: Check the Payment method status.
Payment method creation date and time (MAX 27; MIN 27; ISO 8601 ).
Example: 2022-05-09T20:46:54.786342Z
Last payment method update date and time (MAX 27; MIN 27; ISO 8601 ).
Example: 2022-05-09T20:46:54.786342Z
Specifies enrollment object.
The customer session that has been created for the payment method (MAX 64; MIN 36).
Example: 9104911d-5df9-429e-8488-ad41abea1a4b
Required action to call the SDK.
Possible values: `True` or `False`
Specifies provider object.
The provider type.
Example: BANK
The status of the provider (MAX 255; MIN 3).
Example: OK
The unique identifier of the enrollment (MAX 64; MIN 36).
Example: a079d524-c3df-4470-b3c8-7f290f5a0ba4
The token returned from the provider (MAX 64; MIN 36).
Example: a079d524-c3df-4470-b3c8-7f290f5a0ba4
# Unenroll Payment Method
Source: https://docs.y.uno/reference/payment-methods-checkout/unenroll-payment-method-checkout
openapi/payment-methods-checkout/unenroll-payment-method-checkout.json POST /customers/payment-methods/{payment_method_id}/unenroll
Unenrolls a previously saved payment method, marking it inactive for future transactions
Unenroll a previously saved payment method for a customer.
To perform this action, provide the `payment_method_id` in the request path. Once the request is successful, the payment method's status will be updated to `UNENROLLED`, making it inactive and no longer available for use in future transactions.
# Enroll Payment Method
Source: https://docs.y.uno/reference/payment-methods-direct-workflow/enroll-payment-method-api
openapi/payment-methods-direct-workflow/enroll-payment-method-api.json POST /customers/{customer_id}/payment-methods
Enrolls a customer's payment method and returns a vaulted token for future use
This request enrolls a payment method for a customer. With the information provided by Yuno after the customer selects the payment method to enroll, you will be able to save that information for future purchases using the payment method object created.
Check the [Available payment methods in Yuno](/reference/payment-type-list). You'll need to set your credentials for each payment method in the Yuno dashboard in order to to be able to use them.
Note that this request requires an `X-Idempotency-Key`. Check the [Authentication](/reference/authentication#idempotency) page for more information.
**Webhooks**
We recommend listening to [Webhooks](/docs/configure-webhooks) to stay up to date with the state of the enrolled payment methods of your customers.
If a customer enrolls the same card multiple times, Yuno creates a new enrollment each time and returns a distinct `vaulted_token`. Use the card `fingerprint` in the enrollment response to detect duplicates on your side (the fingerprint may be `null` for some providers). See [Card Fingerprint](/docs/fingerprint).
**Only available for PCI certified merchants.**
# Reassign a Payment Method to Another Customer
Source: https://docs.y.uno/reference/payment-methods-direct-workflow/reassign-payment-method-api
openapi/payment-methods-direct-workflow/reassign-payment-method-api.json PATCH /payment-methods/{payment_method_id}
Reassigns an enrolled payment method to a different customer of the same account
Reassign an enrolled payment method to a different customer of the same account. Send the `customer_id` of the target customer in the request body. Only card payment methods can be reassigned. The response returns the payment method in the same shape as the [Enroll Payment Method](/reference/enroll-payment-method-api) response, with the new owner in the `customer_id` field.
To reassign the payment method, you need to provide the `payment_method_id`, which is the `vaulted_token` received when using the [Enroll Payment Method](/reference/enroll-payment-method-api) endpoint.
A payment method that is already assigned to a customer that has data cannot be reassigned, and the request is rejected with `409 CONFLICT`.
After a payment method is reassigned, the merchant is responsible for updating the customer identifier wherever the payment method was already used. This includes any subscription created with it, the merchant's own mapping between a user and the `vaulted_token`, and any stored pair of customer and payment method. Yuno reassigns the payment method to the new customer, but it does not update those references on the merchant side.
# Register Stored Cards for Account Updater
Source: https://docs.y.uno/reference/payment-methods-direct-workflow/register-cards-for-account-updater-api
openapi/payment-methods-direct-workflow/register-cards-for-account-updater-api.json POST /payment-methods/account-updater
Registers up to 100 stored cards for Card Account Updater in a single request
Register a batch of already-stored cards for [Card Account Updater](/docs/additional-services/card-account-updater), so their details are kept current automatically. Send the payment method ids (the `vaulted_token` received when enrolling each card) in a single request.
**How registration behaves**
* You can register between **1 and 100** cards per request; each id must be a valid `vaulted_token`.
* Validation is **all-or-nothing**: if any id is invalid, the whole request is rejected.
* Registration runs **asynchronously**. A `200` response with `accepted` confirms the cards were accepted, not that the update already happened — updates are notified later through the enrollment webhook.
* Your account must be enabled for Card Account Updater. Otherwise the request returns `403`.
# Retrieve Enrolled Payment Method by ID
Source: https://docs.y.uno/reference/payment-methods-direct-workflow/retrieve-enrolled-payment-method-by-id-api
openapi/payment-methods-direct-workflow/retrieve-enrolled-payment-method-by-id-api.json GET /customers/{customer_id}/payment-methods/{payment_method_id}
Retrieves a specific payment method a customer has enrolled, by its vaulted token
Retrieve a specific payment method that a user has enrolled in.
**Retrieve Enrolled Payment Method**
To recover the enrolled payment method information, you need to provide the `payment_method_id`, which is the `vaulted_token` received when using the [Enroll Payment Method](#enroll-payment-method-api) endpoint.
# Retrieve Enrolled Payment Method by ID PCI Data
Source: https://docs.y.uno/reference/payment-methods-direct-workflow/retrieve-enrolled-payment-method-by-id-pci-api
openapi/payment-methods-direct-workflow/retrieve-enrolled-payment-method-by-id-pci-api.json GET /customers/{customer_id}/payment-methods/{payment_method_id}
Retrieves an enrolled payment method including the full card number, PCI merchants only
Retrieve a specific payment method that a user has enrolled in, including the full card number in the response.
**Retrieve Enrolled Payment Method**
To retrieve the enrolled payment method information, you need to provide the `payment_method_id`, which is the `vaulted_token` received when using the [Enroll Payment Method](#enroll-payment-method-api) endpoint.
**PCI merchants only**
This endpoint is only available for PCI-certified merchants. To enable it, contact your Key Account Manager (KAM).
# Retrieve Enrolled Payment Methods
Source: https://docs.y.uno/reference/payment-methods-direct-workflow/retrieve-enrolled-payment-methods-api
openapi/payment-methods-direct-workflow/retrieve-enrolled-payment-methods-api.json GET /customers/{customer_id}/payment-methods
Retrieves the list of payment methods a customer has enrolled
Get the list of payment methods the user has enrolled.
# The Payment Method Object
Source: https://docs.y.uno/reference/payment-methods-direct-workflow/the-payment-method-object-api
Describes the payment method object's attributes for back to back payment integrations
## Attributes
This object represents a payment method that can be associated with a customer for back-to-back payments.
The unique identifier of the payment method (MAX 64; MIN 36).
Example: 693ed90e-5aa9-11ed-9b6a-0242ac120002
The payment method name (MAX 255; MIN 3).
Example: CARD
The payment method description (MAX 255; MIN 3).
Example: CARD
The payment method type (MAX 255; MIN 3).
Possible enum values: Check the
Payment type list.
The payment method category (MAX 255; MIN 3).
Example: CARD
The customer's country (MAX 2; MIN 2; ISO 3166-1 ).
Possible enum values: Check the Country reference.
Indicates if the enrolled payment method was the last successfully used by the customer ).
Example: True
Indicates the date of the last succeeded payment if the enrolled payment method was the last successfully
used by the customer ).
Example: "2023-01-24T12:50:43.938087Z"
The payment workflow indicates whether the integration will use Yuno´s SDK or will be a back to back
connection.
Possible enum values: If `CHECKOUT` you will use Yuno SDK. If `DIRECT` you
will back to back integration.
Specifies the details of the card.
The issuer indentificarion number (IIN) refers to the first few digits of the payment card number issued
by a financial insituition (MAX 8; MIN 6).
Example: 45079900
The last four digits of the card (MAX 4; MIN 4).
Example: 0010
The expiraton month of the card (MAX 2; MIN 2) - only available for PCI certified merchants.
Example: 12
The expiraton year of the card (MAX 2; MIN 2) - only available for PCI certified merchants.
Example: 12
The length of the card's number (MAX 19; MIN 8).
Example: 41961111
The length of the card's security code (MAX 4; MIN 3).
Example: 123
The card's brand information (MAX 255; MIN 3).
Example: VISA
The card's issuer (MAX 255; MIN 3).
Example: Banco Galicia
The category of the card's issuer (MAX 255; MIN 3).
Example: Gold
The type of the card's issuer (MAX 255; MIN 3).
Example: CREDIT, DEBIT, or PREPAID
URL to return the customer after an enrollment in a provider´s environment. Only necessary for alternative
payment methods integrations (MAX: 64; MIN: 36).
Example: [https://www.company.com/customer\_1231324](https://www.company.com/customer_1231324)
Indicates whether to verify the payment with a verify transaction or not. You’ll need to have a provider
defined in your CARD route.
Indicates whether to verify the payment with a verify transaction or not. False by default.
Currency of the card verification.(MAX 3; MIN 3; ISO 4217 ).
Possible enum values: Check the Country reference.
The status of the payment method (MAX 255; MIN 5).
Possible enum values: Check the Payment method
status.
The vaulted token for the previously enrolled payment method (MAX 64; MIN 36).
Example: 321c12f6-42c2-45b7-bf0c-f2f767b31948
Payment method creation date and time (MAX 27; MIN 27; ISO
8601 ).
Example: 2022-05-09T20:46:54.786342Z
Last payment method update date and time (MAX 27; MIN 27; ISO 8601 ).
Example: 2022-05-09T20:46:54.786342Z
# Unenroll Payment Method
Source: https://docs.y.uno/reference/payment-methods-direct-workflow/unenroll-payment-method-api
openapi/payment-methods-direct-workflow/unenroll-payment-method-api.json POST /customers/{customer_id}/payment-methods/{payment_method_id}/unenroll
Unenrolls a customer's saved payment method and sets its status to UNENROLLED
Unenroll a saved payment method for the user. Once you've done the POST to the unenrollment endpoint, the payment method status will be changed to UNENROLLED.
**Unenrollment Information**
To unenroll the payment method, you need to provide the `payment_method_id`, which is the `vaulted_token` received when using the [Enroll Payment Method](#enroll-payment-method-api) endpoint.
# Payment Type
Source: https://docs.y.uno/reference/payment-type-list
Lists all payment methods, providers, and categories supported by the Yuno API
This reference lists all payment methods supported by Yuno's API, organized by category and provider. Use the `payment_method_type`, `category`, and `provider` values when creating payments or enrolling payment methods.
**Updated regularly** with new payment methods and providers as they become available.
# Authorize Payment
Source: https://docs.y.uno/reference/payments/authorize-payment
openapi/payments/authorize-payment.json POST /payments
Authorizes a payment amount on a card without charging the customer immediately.
This request allows you to authorize a payment after you created a checkout session. It just authorizes the amount on the `credit_card` (the client is not charged). If you want to make an authorization for a payment, you will need to send the `capture` as "false" within the card object, which is located inside the `payment_method` object.
# Cancel or Refund a Payment
Source: https://docs.y.uno/reference/payments/cancel-or-refund-a-payment
openapi/payments/cancel-or-refund-a-payment.json POST /payments/{payment_id}/cancel-or-refund
Cancels or refunds an existing payment automatically based on its current transaction status.
Do not execute a refund while another is in progress. Wait for the current operation to complete before starting a new one.
This service allows you to cancel or refund an existing payment. Our system will identify if a cancellation or a refund is necessary based on the payment, no `transaction_id` is needed in this case. This service performs the following functions based on the status of the transaction:
* **Cancels** the payment if it has not been captured.
* **Refunds** the payment if it has been captured.
**Refunds**
If you fill out the amount field, the refund will be partial. Otherwise, it will create a complete refund. The funds will be refunded to the payment method that was originally charged.
Note that this request requires an `X-Idempotency-Key`. Check the [Authentication](/reference/authentication#idempotency) page for more information.
# Cancel or Refund a Payment with Transaction
Source: https://docs.y.uno/reference/payments/cancel-or-refund-payment-with-transaction
openapi/payments/cancel-or-refund-payment-with-transaction.json POST /payments/{payment_id}/transactions/{transaction_id}/cancel-or-refund
Cancels or refunds a payment based on the status of a specific transaction ID.
Do not execute a refund while another is in progress. Wait for the current operation to complete before starting a new one.
This service allows you to cancel or refund an existing payment. Our system will identify if a cancellation or a refund is necessary based on the transaction status related to the `transaction_id` provided on the request. This is for certain scenarios where you want to be more specific about the actions taken on the payments lifecycle. This service performs the following functions based on the status of the transaction:
* **Cancels** the payment if it has not been captured.
* **Refunds** the payment if it has been captured.
**Refunds**
If you fill out the amount field, the refund will be partial. Otherwise, it will create a complete refund. The funds will be refunded to the payment method that was originally charged.
Note that this request requires an `X-Idempotency-Key`. Check the [Authentication](/reference/authentication#idempotency) page for more information.
# Cancel Payment
Source: https://docs.y.uno/reference/payments/cancel-payment
openapi/payments/cancel-payment.json POST /payments/{payment_id}/transactions/{transaction_id}/cancel
Cancels a pending payment before it completes, updating its status to cancelled.
A payment with a **PENDING** status due to an **AUTHORIZE** transaction status can be canceled before it is completed if the payment is no longer required. Sending a cancel request will update the payment status to **CANCELLED**.
**3DS Payments**
Payments in a **PENDING** status due to 3DS authentication cannot be canceled. These payments are in a temporary state awaiting user authentication. The payment status will automatically update to either **FRAUD VERIFIED** or **CANCELLED** based on the outcome of the authentication process.
**Alternative Payment Methods**
Alternative payment methods such as PIX also support payment cancellation with a PENDING status. Reach out to your technical account manager for more information.
If you need a receipt for the canceled transaction, you can retrieve it after it has been created. To do this, use the [Retrieve Payment by ID](/reference/retrieve-payment-by-id) endpoint and check the `receipt_url` field in the `payment.transaction` object. See [The Payment Object](/reference/the-payment-object) for `receipt`, `receipt_url`, and `receipt_language`.
To use this endpoint, you have to provide an `X-Idempotency-Key` in your request. Check the [Authentication](/reference/authentication#idempotency) page for more information.
# Capture Authorization
Source: https://docs.y.uno/reference/payments/capture-authorization
openapi/payments/capture-authorization.json POST /payments/{payment_id}/transactions/{transaction_id}/capture
Captures a previously authorized payment, partially or in full depending on the provider.
Do not execute a capture while another is in progress. Wait for the current operation to complete before starting a new one.
This request captures a payment that was previously authorized. This action is required to finalize a payment when an authorization was created with the capture option set `false`. Depending on the payment provider, the capture could be partial (including multiple captures) or total.
Note that this request requires an `X-Idempotency-Key`. Check the [Authentication](/reference/authentication#idempotency) page for more information.
# Create Payment
Source: https://docs.y.uno/reference/payments/create-payment
openapi/payments/create-payment.json POST /payments
Create a payment with Yuno. Supports various payment methods, card vaulting, and 3DS configurations.
This request creates a payment after you created a checkout session.
**Important**
Although certain objects are not mandatory when creating a **Payment**, the user’s payment experience can be enhanced if you provide this information.
**3DS Payments**
Check the [3D Secure](/docs/security-and-compliance/3d-secure) page to learn how to create payments using 3DS on Yuno.
If you want to process payments in a Single Step (Authorization and Capture simultaneously), send `payment_method.detail.card.capture` as `true`.
To test all possible transaction outcomes within Yuno in **Sandbox**, refer to the [test data documentation](/docs/direct-integration-use-cases/yuno-testing-gateway#4-provide-the-payment-method-information).
**Metadata and routing logic**
If you use metadata to drive routing logic, it must also be set in the **[Checkout Session](/reference/checkout-sessions/create-checkout-session)**. Filling it only in the Payment object will not activate route logic.
**`vaulted_token` overrides device fingerprint**
If `payment_method.vaulted_token` is provided alongside `payment_method.token`, the `vaulted_token` replaces all payment data, including the device fingerprint (`third_party_session_id`). If you need fraud screening with a device fingerprint, do not send both fields together.
For Two-Step payments (Authorization then Capture), send `payment_method.detail.card.capture` as `false`, then use the [Capture Authorization](/reference/payments/capture-authorization) endpoint.
This request requires an `X-Idempotency-Key`. See [Authentication](/reference/authentication#idempotency) for details.
# Dispute a Chargeback
Source: https://docs.y.uno/reference/payments/disputes
openapi/payments/disputes.json POST /payments/{payment_id}/transactions/{transaction_id}/dispute
Submits chargeback dispute evidence for Yuno to forward to the issuer for processing.
This request enables clients to [submit dispute documentation for chargeback management](/docs/chargeback-management), allowing Yuno to forward these documents to the appropriate issuers for processing.
The endpoint returns a standard payment response structure containing the updated payment information, including the chargeback/dispute status.
**Evidence requirements**
The uploaded files must meet the following criteria:
*Format*: File must be in PDF format, encoded as base64.\
*Size*: File must be no larger than 1 MB in size.\
*Language*: Dispute should be written in English or the country's local language.
Note that this request requires an `X-Idempotency-Key`. Check the [Authentication](/reference/authentication#idempotency) page for more information.
# Payments
Source: https://docs.y.uno/reference/payments/manage-payments
Overview of the Payments API, covering endpoints, status handling, and integration workflows.
The Payments API lets you create and manage payments through Yuno. Here you’ll find details on request and response formats, available endpoints, common objects, and example payloads. Use this reference to understand workflows, status handling, and how to integrate payments seamlessly into your application. To refund a payment, see [Refund payments](/docs/refund-payments) and the [Refund payment](/reference/refund-payment) API.
# Notify Fulfillment
Source: https://docs.y.uno/reference/payments/notify-fulfillments
openapi/payments/notify-fulfillments.json POST /payments/{payment_id}/fulfillments
Adds fulfillments to an order to notify fraud prevention providers after payment.
This endpoint allows you to add multiple fulfillments to an order to notify fraud prevention providers. Any fulfillments provided will be appended to the ones that already exist.
# Bank Transfer
Source: https://docs.y.uno/reference/payments/payment-examples/bank-transfer
Request and response examples for creating bank transfer payments across supported providers.
This page presents examples of requests and responses for creating Bank Transfer payments using the [Create Payment](/reference/create-payment) endpoint.
To test the creation of each payment, you can copy the content from the request code and use it on your machine or paste it on the [Create Payment](/reference/create-payment) endpoint to test using Readme.
**Important**
Some payment methods and providers may only be available in specific countries and/or currencies. Make sure you choose the right provider for your needs.
## Bank Transfer available examples
### Arcus
Example of a request for a Cash payment using Arcus. Below are examples of a request and the received response for successful payment creation. The request is presented using the cURL format, and the response is a JSON object.
```sh Request (cURL) theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
curl --request POST \
--url https://api-sandbox.y.uno/v1/payments \
--header 'X-Idempotency-Key: ' \
--header 'accept: application/json' \
--header 'content-type: application/json' \
--header 'private-secret-key: ' \
--header 'public-api-key: '\
--data '{
"description": "Payment with Arcus",
"account_id":"",
"merchant_order_id": "0000022",
"country": "MX",
"amount": {
"currency": "MXN",
"value": 52000
},
"customer_payer": {
"merchant_customer_id": "1789123456",
"first_name": "John",
"last_name": "Smith",
"email": "john.smith@example.com",
"document": {
"document_type": "PAS",
"document_number": "123456789"
},
"phone": {
"number": "5551234567",
"country_code": "1"
}
},
"payment_method": {
"type": "CASH"
},
"workflow":"REDIRECT",
"callback_url":"www.y.uno"
}'
```
```json Response (JSON) theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"id": "f190cf86-de16-4b6d-b634-ab478bb6da01",
"account_id": "5beead35-0cd5-4e1c-9a13-b8f48f7f8f3a",
"description": "Payment with Arcus",
"country": "MX",
"status": "READY_TO_PAY",
"sub_status": "CREATED",
"merchant_order_id": "0000022",
"created_at": "2025-06-20T13:00:30.417457Z",
"updated_at": "2025-06-20T13:00:30.696683Z",
"amount": {
"captured": 0.00,
"currency": "MXN",
"currency_conversion": null,
"refunded": 0.00,
"value": 52000.00
},
"checkout": {
"session": "1c57438e-f854-4d01-9b04-4c7338372a81",
"sdk_action_required": true
},
"payment_method": {
"vaulted_token": "",
"type": "CASH",
"vault_on_success": false,
"token": "",
"parent_payment_method_type": null,
"payment_method_detail": {
"ticket": {
"type": null,
"benefit_type": null,
"date_of_expiration": null,
"payment_instruction": null,
"provider_number": "AP001123456761082788244884910249",
"provider_barcode": null,
"provider_logo": null,
"provider_format": null,
"redirect_url": "https://checkout.sandbox.y.uno/payment?session=278f85d1-71f4-4d9a-bc02-e34421302097",
"expires_at": null
}
}
},
"customer_payer": {
"id": null,
"merchant_customer_id": "1789123456",
"first_name": "John",
"last_name": "Smith",
"gender": null,
"date_of_birth": null,
"email": "john.smith@example.com",
"nationality": null,
"ip_address": null,
"device_fingerprint": null,
"device_fingerprints": [],
"browser_info": {
"user_agent": "",
"accept_header": "",
"accept_content": null,
"accept_browser": null,
"color_depth": "",
"screen_height": "",
"screen_width": "",
"javascript_enabled": null,
"java_enabled": null,
"browser_time_difference": null,
"language": "",
"platform": null
},
"document": {
"document_type": "PAS",
"document_number": "123456789"
},
"phone": {
"number": "5551234567",
"country_code": "1"
},
"billing_address": null,
"shipping_address": null,
"merchant_customer_created_at": null
},
"additional_data": null,
"transactions": {
"id": "36609e7c-cd92-48a1-b520-edaa1c1bf026",
"type": "PURCHASE",
"status": "CREATED",
"category": "TICKET",
"amount": 52000.00,
"provider_id": "ARCUS",
"payment_method": {
"vaulted_token": "",
"type": "CASH",
"vault_on_success": false,
"token": "",
"parent_payment_method_type": null,
"detail": {
"ticket": {
"type": null,
"benefit_type": null,
"date_of_expiration": null,
"payment_instruction": null,
"provider_number": "AP001123456761082788244884910249",
"provider_barcode": null,
"provider_logo": null,
"provider_format": null,
"redirect_url": "https://checkout.sandbox.y.uno/payment?session=278f85d1-71f4-4d9a-bc02-e34421302097",
"expires_at": null
}
}
},
"response_code": "SUCCEEDED",
"response_message": "Transaction successful",
"reason": null,
"description": "Payment with Arcus",
"merchant_reference": "0000022",
"provider_data": {
"id": "ARCUS",
"transaction_id": "AP001123456761082788244884910249",
"account_id": "",
"status": "",
"sub_status": "",
"status_detail": "",
"response_message": null,
"response_code": null,
"raw_response": null,
"third_party_transaction_id": "",
"third_party_account_id": null,
"iso8583_response_code": null,
"iso8583_response_message": null
},
"connection_data": {
"id": "48425c89-8fd0-4c6f-a8f3-17a25e5ac7ce",
"name": null
},
"created_at": "2025-06-20T13:00:30.553544Z",
"updated_at": "2025-06-20T13:00:30.626338Z"
},
"transactions_history": [
{
"id": "36609e7c-cd92-48a1-b520-edaa1c1bf026",
"type": "PURCHASE",
"status": "CREATED",
"category": "TICKET",
"amount": 52000.00,
"provider_id": "ARCUS",
"payment_method": {
"vaulted_token": "",
"type": "CASH",
"vault_on_success": false,
"token": "",
"parent_payment_method_type": null,
"detail": {
"ticket": {
"type": null,
"benefit_type": null,
"date_of_expiration": null,
"payment_instruction": null,
"provider_number": "AP001123456761082788244884910249",
"provider_barcode": null,
"provider_logo": null,
"provider_format": null,
"redirect_url": "https://checkout.sandbox.y.uno/payment?session=278f85d1-71f4-4d9a-bc02-e34421302097",
"expires_at": null
}
}
},
"response_code": "SUCCEEDED",
"response_message": "Transaction successful",
"reason": null,
"description": "Payment with Arcus",
"merchant_reference": "0000022",
"provider_data": {
"id": "ARCUS",
"transaction_id": "AP001123456761082788244884910249",
"account_id": "",
"status": "",
"sub_status": "",
"status_detail": "",
"response_message": null,
"response_code": null,
"raw_response": null,
"third_party_transaction_id": "",
"third_party_account_id": null,
"iso8583_response_code": null,
"iso8583_response_message": null
},
"connection_data": {
"id": "48425c89-8fd0-4c6f-a8f3-17a25e5ac7ce",
"name": null
},
"created_at": "2025-06-20T13:00:30.553544Z",
"updated_at": "2025-06-20T13:00:30.626338Z"
}
],
"callback_url": "www.y.uno",
"workflow": "REDIRECT",
"metadata": [],
"fraud_screening": null,
"payment_link_id": "",
"subscription_code": null,
"routing_rules": {
"smart_routing": false,
"monitors": false,
"condition": {
"id": 191919,
"name": null,
"description": null
}
},
"simplified_mode": false
}
```
### Efecty
Example of a request for a Ticket payment using Efecty. Below you find the JSON body request example.
```sh Request (cURL) theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
curl --request POST \
--url https://api-sandbox.y.uno/v1/payments \
--header 'X-Idempotency-Key: ' \
--header 'accept: application/json' \
--header 'content-type: application/json' \
--header 'private-secret-key: ' \
--header 'public-api-key: '\
--data '
{
"description": "Payment with Efecty",
"account_id":"",
"merchant_order_id": "0000022",
"country": "CO",
"amount": {
"currency": "COP",
"value": 52000
},
"customer_payer": {
"merchant_customer_id": "1234567",
"first_name": "John",
"last_name": "Smith",
"email": "john.smith@example.com",
"document": {
"document_type": "PAS",
"document_number": "1012345678"
},
},
"payment_method": {
"type": "EFECTY"
},
"workflow":"REDIRECT",
"callback_url":"www.google.com"
}'
```
```json Response (JSON) theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"id": "1c109200-3236-43f3-ab44-9a317991a288",
"account_id": "493e9374-510a-4201-9e09-de669d75f256",
"description": "Payment with Efecty",
"country": "CO",
"status": "READY_TO_PAY",
"sub_status": "CREATED",
"merchant_order_id": "0000022",
"created_at": "2023-07-23T23:35:25.021285Z",
"updated_at": "2023-07-23T23:35:26.067120Z",
"amount": {
"captured": 0.00,
"currency": "COP",
"refunded": 0.00,
"value": 52000.00
},
"checkout": {
"session": "3faeb04f-0a52-41fc-9aba-33e535386776",
"sdk_action_required": true
},
"payment_method": {
"vaulted_token": "",
"type": "EFECTY",
"vault_on_success": false,
"token": "",
"payment_method_detail": {
"ticket": {
"type": null,
"date_of_expiration": null,
"provider_number": "762c4604-d4ba-4a8f-ba2f-5d39931e9ed8",
"provider_barcode": null,
"provider_logo": null,
"provider_format": null,
"redirect_url": "https://checkout.sandbox.y.uno/payment?session=3feff49c-a422-434a-9fad-eca87e2193d5"
}
}
},
"customer_payer": {
"id": null,
"merchant_customer_id": "1690155316",
"first_name": "John",
"last_name": "Smith",
"gender": null,
"date_of_birth": null,
"email": "john.smith@example.com",
"nationality": null,
"ip_address": null,
"device_fingerprint": null,
"browser_info": {
"user_agent": "",
"accept_header": "",
"accept_content": null,
"accept_browser": null,
"color_depth": "",
"screen_height": "",
"screen_width": "",
"javascript_enabled": null,
"java_enabled": null,
"browser_time_difference": null,
"language": ""
},
"document": null,
"phone": null,
"billing_address": null,
"shipping_address": null
},
"additional_data": null,
"taxes": null,
"transactions": {
"id": "762c4604-d4ba-4a8f-ba2f-5d39931e9ed8",
"type": "PURCHASE",
"status": "CREATED",
"category": "TICKET",
"amount": 52000.00,
"provider_id": "UNLIMINT",
"payment_method": {
"vaulted_token": "",
"type": "EFECTY",
"vault_on_success": false,
"token": "",
"detail": {}
},
"response_code": "SUCCEEDED",
"response_message": "Transaction successful",
"reason": null,
"description": "Payment with Efecty",
"merchant_reference": null,
"provider_data": {
"id": "UNLIMINT",
"transaction_id": "",
"account_id": "",
"status": "",
"sub_status": "",
"status_detail": "",
"response_message": "",
"raw_response": {
"redirect_url": "https://sandbox.cardpay.com/MI/payment.html?uuid=a6cfEG0H3c1Hf42f23HhH3Ch"
},
"third_party_transaction_id": ""
},
"created_at": "2023-07-23T23:35:25.116858Z",
"updated_at": "2023-07-23T23:35:25.988725Z"
},
"split": [],
"callback_url": "www.google.com",
"workflow": "REDIRECT",
"metadata": []
}
```
### Oxxo
Example of a request for a Ticket payment using Oxxo. Below you find the JSON body request example.
```sh Request (cURL) theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
curl --request POST \
--url https://api-sandbox.y.uno/v1/payments \
--header 'X-Idempotency-Key: ' \
--header 'accept: application/json' \
--header 'content-type: application/json' \
--header 'private-secret-key: ' \
--header 'public-api-key: '\
--data '{
"description": "Payment with Oxxo",
"account_id":"",
"merchant_order_id": "0000022",
"country": "MX",
"amount": {
"currency": "MXN",
"value": 5200
},
"customer_payer": {
"merchant_customer_id": "1690155799",
"first_name": "John",
"last_name": "Smith",
"email": "john.smith@example.com"
},
"payment_method": {
"type": "OXXO"
},
"workflow":"REDIRECT",
"callback_url":"www.google.com"
}'
```
```json Response (JSON) theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"id": "f36a1e5d-7073-4a6d-88ab-b26f69de7a01",
"account_id": "493e9374-510a-4201-9e09-de669d75f256",
"description": "Payment with Oxxo",
"country": "MX",
"status": "PURCHASE",
"sub_status": "SUCCEEDED",
"merchant_order_id": "0000022",
"created_at": "2023-07-23T23:48:18.014380Z",
"updated_at": "2023-07-23T23:48:18.758261Z",
"amount": {
"captured": 0.00,
"currency": "MXN",
"refunded": 0.00,
"value": 5200.00
},
"checkout": {
"session": "2a3cd0a7-9bdc-46b7-859b-0e13ab91f2ff",
"sdk_action_required": true
},
"payment_method": {
"vaulted_token": "",
"type": "OXXO",
"vault_on_success": false,
"token": "",
"payment_method_detail": {
"ticket": {
"type": null,
"date_of_expiration": null,
"provider_number": "",
"provider_barcode": null,
"provider_logo": null,
"provider_format": null,
"redirect_url": "https://checkout.sandbox.y.uno/payment?session=f7c986c5-d66e-4e52-8c02-9a90b73fb9a5"
}
}
},
"customer_payer": {
"id": null,
"merchant_customer_id": "1690156096",
"first_name": "John",
"last_name": "Smith",
"gender": null,
"date_of_birth": null,
"email": "john.smith@example.com",
"nationality": null,
"ip_address": null,
"device_fingerprint": null,
"browser_info": {
"user_agent": "",
"accept_header": "",
"accept_content": null,
"accept_browser": null,
"color_depth": "",
"screen_height": "",
"screen_width": "",
"javascript_enabled": null,
"java_enabled": null,
"browser_time_difference": null,
"language": ""
},
"document": null,
"phone": null,
"billing_address": null,
"shipping_address": null
},
"additional_data": null,
"taxes": null,
"transactions": {
"id": "1946defd-3312-4bdf-86b6-751a1aff94d0",
"type": "PURCHASE",
"status": "CREATED",
"category": "TICKET",
"amount": 5200.00,
"provider_id": "DLOCAL",
"payment_method": {
"vaulted_token": "",
"type": "OXXO",
"vault_on_success": false,
"token": "",
"detail": {}
},
"response_code": "",
"response_message": "",
"reason": null,
"description": "Payment with Oxxo",
"merchant_reference": "0000022",
"provider_data": {
"id": "DLOCAL",
"transaction_id": "",
"account_id": "",
"status": "",
"sub_status": "",
"status_detail": "",
"response_message": null,
"raw_response": null,
"third_party_transaction_id": null
},
"three_d_secure_action_required": null,
"created_at": "2023-07-23T23:48:18.186301Z",
"updated_at": "2023-07-23T23:48:18.693131Z"
},
"split": [],
"callback_url": "www.google.com",
"workflow": "REDIRECT",
"metadata": [],
"fraud_screening": null,
"payment_link_code": ""
}
```
# Wallet
Source: https://docs.y.uno/reference/payments/payment-examples/wallet
Request and response examples for creating payments using wallet payment providers.
This page presents examples of requests and responses for creating payments using the [Create Payment](/reference/create-payment) endpoint and Wallet as payment method.
To test the creation of each payment, you can copy the content from the request code and use it on your machine or paste it on the [Create Payment](/reference/create-payment) endpoint to test using Readme.
**Important**
Some payment methods and providers may only be available in specific countries and/or currencies. Make sure you choose the right provider for your needs.
## Wallet available examples
## Mercado Pago Checkout Pro
Example of a request for a payment using Mercado Pago Checkout Pro. Below are examples of a request and the received response for successful payment creation. The request is presented using the cURL format, and the response is a JSON object.
```sh Request (cURL) theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
curl --request POST \
--url https://api-sandbox.y.uno/v1/payments \
--header 'X-Idempotency-Key: ' \
--header 'accept: application/json' \
--header 'content-type: application/json' \
--header 'private-secret-key: ' \
--header 'public-api-key: ' \
--data '
{
"description": "Payment with Mercado Pago Pro",
"account_id": "",
"merchant_order_id": "0000023",
"country": "CO",
"merchant_reference": "reference-0001",
"additional_data": {
"order": {
"items": [
{
"id": "123AD",
"name": "Skirt",
"quantity": 1,
"unit_amount": 3000
}
]
}
},
"amount": {
"currency": "COP",
"value": 3000
},
"customer_payer": {
"email": "john.smith@example.com",
"first_name": "John",
"last_name": "Smith"
},
"payment_method": {
"type": "MERCADO_PAGO_CHECKOUT_PRO"
},
"workflow": "REDIRECT",
"callback_url":"www.y.uno"
}
'
```
```json Response (JSON) theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"id": "d0ff19c2-cf55-4015-a613-e35f22da0233",
"account_id": "",
"description": "Payment with Mercado Pago Pro",
"country": "CO",
"status": "READY_TO_PAY",
"sub_status": "CREATED",
"merchant_order_id": "0000023",
"created_at": "2023-07-23T23:02:39.401790Z",
"updated_at": "2023-07-23T23:02:40.312593Z",
"amount": {
"captured": 0.00,
"currency": "COP",
"refunded": 0.00,
"value": 3000.00
},
"checkout": {
"session": "b7e15362-4ac0-4e23-886e-329695933ecb",
"sdk_action_required": true
},
"payment_method": {
"vaulted_token": "",
"type": "MERCADO_PAGO_CHECKOUT_PRO",
"vault_on_success": false,
"token": "",
"payment_method_detail": {
"wallet": {
"verify": false,
"capture": false,
"installments": null,
"payment_method_id": null,
"payment_method_detail": null,
"date_of_expiration": null,
"money_release_date": null,
"sponsor_id": null,
"authorization_code": null,
"customer_data": null,
"card_data": null,
"redirect_url": "https://checkout.sandbox.y.uno/payment?session=e93d8431-f55c-43a3-a4e4-0c7a4bcc7e27"
}
}
},
"customer_payer": {
"id": null,
"merchant_customer_id": null,
"first_name": "John",
"last_name": "Smith",
"gender": null,
"date_of_birth": null,
"email": "john.smith@example.com",
"nationality": null,
"ip_address": null,
"device_fingerprint": null,
"browser_info": {
"user_agent": "",
"accept_header": "",
"accept_content": null,
"accept_browser": null,
"color_depth": "",
"screen_height": "",
"screen_width": "",
"javascript_enabled": null,
"java_enabled": null,
"browser_time_difference": null,
"language": ""
},
"document": null,
"phone": null,
"billing_address": null,
"shipping_address": null
},
"additional_data": {
"airline": null,
"order": {
"fee_amount": null,
"shipping_amount": null,
"items": [
{
"id": "123AD",
"name": "Skirt",
"quantity": 1,
"unit_amount": 3000,
"category": null,
"brand": null,
"sku_code": null,
"manufacture_part_number": null
}
]
},
"seller_details": null
},
"taxes": null,
"transactions": {
"id": "286ad833-7cbc-4e66-92f9-01019eb7d7a3",
"type": "PURCHASE",
"status": "CREATED",
"category": "WALLET",
"amount": 3000.00,
"provider_id": "MERCADO_PAGO",
"payment_method": {
"vaulted_token": "",
"type": "MERCADO_PAGO_CHECKOUT_PRO",
"vault_on_success": false,
"token": "",
"detail": {
"wallet": {
"verify": false,
"capture": false,
"installments": null,
"payment_method_id": null,
"payment_method_detail": null,
"date_of_expiration": null,
"money_release_date": null,
"sponsor_id": null,
"authorization_code": null,
"customer_data": null,
"card_data": null,
"redirect_url": "https://checkout.sandbox.y.uno/payment?session=e93d8431-f55c-43a3-a4e4-0c7a4bcc7e27"
}
}
},
"response_code": "SUCCEEDED",
"response_message": "Transaction successful",
"reason": null,
"description": "Payment with Mercado Pago Pro",
"merchant_reference": "reference-d2b08e8e-c87a-4806-b1ea-b35a19a36a6d",
"provider_data": {
"id": "MERCADO_PAGO",
"transaction_id": "",
"account_id": "",
"status": "",
"sub_status": "",
"status_detail": "",
"response_message": "",
"raw_response": {
"value":"{\"additional_info\":\"\",\"auto_return\":\"approved\",\"back_urls\":{\"failure\":\"http://www.y.uno\",\"pending\":\"http://www.y.uno\",\"success\":\"http://www.y.uno\"},\"binary_mode\":true,\"client_id\":\"3615163740385056\",\"collector_id\":1131498549,\"coupon_code\":null,\"coupon_labels\":null,\"date_created\":\"2023-07-23T19:02:40.082-04:00\",\"date_of_expiration\":null,\"expiration_date_from\":null,\"expiration_date_to\":null,\"expires\":false,\"external_reference\":\"286ad833-7cbc-4e66-92f9-01019eb7d7a3\",\"id\":\"1131498549-ef2fc547-72b3-4e19-acce-83f94c70609a\",\"init_point\":\"https://www.mercadopago.com.ar/checkout/v1/redirect?pref_id=1131498549-ef2fc547-72b3-4e19-acce-83f94c70609a\",\"internal_metadata\":null,\"items\":[{\"id\":\"123AD\",\"category_id\":\"others\",\"currency_id\":\"ARS\",\"description\":\"\",\"title\":\"Skirt\",\"quantity\":1,\"unit_price\":3000}],\"marketplace\":\"MP-MKT-3615163740385056\",\"marketplace_fee\":0,\"metadata\":{},\"notification_url\":\"https://sandbox.y.uno/mercadopago-webhook/v1/checkout-pro/events?source_news=webhooks\&transaction=286ad833-7cbc-4e66-92f9-01019eb7d7a3\",\"operation_type\":\"regular_payment\",\"payer\":{\"phone\":{\"area_code\":\"\",\"number\":\"\"},\"address\":{\"zip_code\":\"\",\"street_name\":\"\",\"street_number\":null},\"email\":\"john.smith@y.uno\",\"identification\":{\"number\":\"\",\"type\":\"\"},\"name\":\"John\",\"surname\":\"Smith\",\"date_created\":null,\"last_purchase\":null},\"payment_methods\":{\"default_card_id\":null,\"default_payment_method_id\":null,\"excluded_payment_methods\":[{\"id\":\"\"}],\"excluded_payment_types\":[{\"id\":\"ticket\"},{\"id\":\"atm\"}],\"installments\":null,\"default_installments\":null},\"processing_modes\":null,\"product_id\":null,\"redirect_urls\":{\"failure\":\"\",\"pending\":\"\",\"success\":\"\"},\"sandbox_init_point\":\"https://sandbox.mercadopago.com.ar/checkout/v1/redirect?pref_id=1131498549-ef2fc547-72b3-4e19-acce-83f94c70609a\",\"site_id\":\"MLA\",\"shipments\":{\"mode\":\"not_specified\",\"default_shipping_method\":null,\"cost\":0,\"receiver_address\":{\"zip_code\":\"\",\"street_name\":\"\",\"street_number\":null,\"floor\":\"\",\"apartment\":\"\",\"city_name\":null,\"state_name\":null,\"country_name\":null}},\"total_amount\":null,\"last_updated\":null}"
},
"third_party_transaction_id": ""
},
"created_at": "2023-07-23T23:02:39.582570Z",
"updated_at": "2023-07-23T23:02:40.227158Z"
},
"split": [],
"callback_url": "www.y.uno",
"workflow": "REDIRECT",
"metadata": []
}
```
## Astropay
Example of a request for a payment using Astropay. Below are examples of a request and the received response for successful payment creation. The request is presented using the cURL format, and the response is a JSON object.
```sh Request (cURL) theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
curl --location 'https://api-sandbox.y.uno/v1/payments' \
--header 'X-idempotency-key: ' \
--header 'public-api-key: ' \
--header 'private-secret-key: ' \
--header 'Content-Type: application/json' \
--data '{
"description": "Payment with Astropay",
"account_id": "",
"country": "US",
"amount": {
"currency": "USD",
"value": 300
},
"checkout": {
"session": ""
},
"payment_method": {
"type": "ASTROPAY"
},
"customer_payer": {
"id": ""
},
"merchant_order_id": "000022",
"workflow": "REDIRECT"
}'
```
```json Response (JSON) theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"id": "245e360c-3bd7-4a8d-9258-8a8839087f7e",
"account_id": "",
"description": "Payment with Astropay",
"country": "US",
"status": "READY_TO_PAY",
"sub_status": "CREATED",
"merchant_order_id": "000022",
"created_at": "2024-03-22T11:48:45.772202Z",
"updated_at": "2024-03-22T11:48:46.402414Z",
"amount": {
"captured": 0.00,
"currency": "USD",
"refunded": 0.00,
"value": 300.00
},
"checkout": {
"session": "a5e36fa7-e635-417b-aa87-8cda1adbe24e",
"sdk_action_required": true
},
"payment_method": {
"vaulted_token": "",
"type": "ASTROPAY",
"vault_on_success": false,
"token": "",
"payment_method_detail": {
"wallet": {
"verify": false,
"capture": false,
"installments": null,
"payment_method_id": null,
"payment_method_detail": null,
"date_of_expiration": null,
"money_release_date": null,
"sponsor_id": null,
"authorization_code": null,
"customer_data": null,
"card_data": {
"holder_name": "",
"iin": "",
"lfd": "",
"number_length": 0,
"security_code_length": 0,
"brand": "",
"issuer_name": "",
"issuer_code": null,
"category": null,
"type": ""
},
"redirect_url": "https://checkout.sandbox.y.uno/payment?session=4da1aa74-a2c7-457d-8b21-f823fe8cf5b8"
}
}
},
"customer_payer": {
"id": "",
"merchant_customer_id": "1234567",
"first_name": "John",
"last_name": "Doe",
"gender": "M",
"date_of_birth": "1990-02-28",
"email": "john.doe@example.com",
"nationality": "US",
"ip_address": null,
"device_fingerprint": null,
"browser_info": {
"user_agent": "",
"accept_header": "",
"accept_content": null,
"accept_browser": null,
"color_depth": "",
"screen_height": "",
"screen_width": "",
"javascript_enabled": null,
"java_enabled": null,
"browser_time_difference": null,
"language": ""
},
"document": {
"document_type": "PASSPORT",
"document_number": "123456789"
},
"phone": {
"number": "2125551234",
"country_code": "1"
},
"billing_address": {
"address_line_1": "123 Main Street",
"address_line_2": "Apt 4B",
"country": "US",
"state": "NY",
"city": "New York",
"zip_code": "10001",
"neighborhood": "Manhattan"
},
"shipping_address": {
"address_line_1": "456 Oak Avenue",
"address_line_2": null,
"country": "US",
"state": "CA",
"city": "Los Angeles",
"zip_code": "90210",
"neighborhood": "Beverly Hills"
}
"merchant_customer_created_at": null
},
"additional_data": null,
"taxes": null,
"transactions": {
"id": "0b258b77-1785-4b64-9094-c1f7e714e460",
"type": "PURCHASE",
"status": "CREATED",
"category": "WALLET",
"amount": 300.00,
"provider_id": "ASTROPAY",
"payment_method": {
"vaulted_token": "",
"type": "ASTROPAY",
"vault_on_success": false,
"token": "",
"detail": {
"wallet": {
"verify": false,
"capture": false,
"installments": null,
"payment_method_id": null,
"payment_method_detail": null,
"date_of_expiration": null,
"money_release_date": null,
"sponsor_id": null,
"authorization_code": null,
"customer_data": null,
"card_data": {
"holder_name": "",
"iin": "",
"lfd": "",
"number_length": 0,
"security_code_length": 0,
"brand": "",
"issuer_name": "",
"issuer_code": null,
"category": null,
"type": ""
},
"redirect_url": "https://checkout.sandbox.y.uno/payment?session=4da1aa74-a2c7-457d-8b21-f823fe8cf5b8"
}
}
},
"response_code": "SUCCEEDED",
"response_message": "Transaction successful",
"reason": null,
"description": "Payment with Astropay",
"merchant_reference": "000022",
"provider_data": {
"id": "ASTROPAY",
"transaction_id": "qW10WwSpwtTY8vLAqiTBY1D3FT4fTutdLCbFtiBy",
"account_id": "",
"status": "PENDING",
"sub_status": "",
"status_detail": "",
"response_message": "",
"response_code": "200",
"raw_response": {
"deposit_external_id": "{{deposit_external_id}}",
"merchant_deposit_id": "{{merchant_deposit_id}}",
"status": "PENDING",
"type": "default",
"url": "https://onetouch-sandbox.astropay.com/deposit/qW10WwSpwtTY8vLAqiTBY1D3FT4fTutdLCbFtiBy"
},
"third_party_transaction_id": "",
"third_party_account_id": ""
},
"created_at": "2024-03-22T11:48:45.874280Z",
"updated_at": "2024-03-22T11:48:46.361673Z"
},
"transactions_history": [
{
"id": "0b258b77-1785-4b64-9094-c1f7e714e460",
"type": "PURCHASE",
"status": "CREATED",
"category": "WALLET",
"amount": 283.00,
"provider_id": "ASTROPAY",
"payment_method": {
"vaulted_token": "",
"type": "ASTROPAY",
"vault_on_success": false,
"token": "",
"detail": {
"wallet": {
"verify": false,
"capture": false,
"installments": null,
"payment_method_id": null,
"payment_method_detail": null,
"date_of_expiration": null,
"money_release_date": null,
"sponsor_id": null,
"authorization_code": null,
"customer_data": null,
"card_data": {
"holder_name": "",
"iin": "",
"lfd": "",
"number_length": 0,
"security_code_length": 0,
"brand": "",
"issuer_name": "",
"issuer_code": null,
"category": null,
"type": ""
},
"redirect_url": "https://checkout.sandbox.y.uno/payment?session=4da1aa74-a2c7-457d-8b21-f823fe8cf5b8"
}
}
},
"response_code": "SUCCEEDED",
"response_message": "Transaction successful",
"reason": null,
"description": "Payment with Astropay",
"merchant_reference": "000022",
"provider_data": {
"id": "ASTROPAY",
"transaction_id": "qW10WwSpwtTY8vLAqiTBY1D3FT4fTutdLCbFtiBy",
"account_id": "",
"status": "PENDING",
"sub_status": "",
"status_detail": "",
"response_message": "",
"response_code": "200",
"raw_response": {
"deposit_external_id": "{{deposit_external_id}}",
"merchant_deposit_id": "{{merchant_deposit_id}}",
"status": "PENDING",
"type": "default",
"url": "https://onetouch-sandbox.astropay.com/deposit/qW10WwSpwtTY8vLAqiTBY1D3FT4fTutdLCbFtiBy"
},
"third_party_transaction_id": "",
"third_party_account_id": ""
},
"created_at": "2024-03-22T11:48:45.874280Z",
"updated_at": "2024-03-22T11:48:46.361673Z"
}
],
"split": [],
"workflow": "REDIRECT",
"metadata": [],
"fraud_screening": null,
"payment_link_id": "",
"subscription_code": null
}
```
## Apple Pay
Example of a request for a payment using Apple Pay and enabling card verification flow (e.g., zero-dollar auth). Below are examples of a request and the received response for successful payment creation.
```sh Request (cURL) theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
curl --request POST \
--url https://api-sandbox.y.uno/v1/payments \
--header 'X-Idempotency-Key: ' \
--header 'accept: application/json' \
--header 'content-type: application/json' \
--header 'private-secret-key: ' \
--header 'public-api-key: ' \
--data '
{
"description": "Apple Pay Verification",
"account_id": "",
"merchant_order_id": "order-001",
"country": "US",
"amount": {
"currency": "USD",
"value": 0
},
"customer_payer": {
"id": ""
},
"payment_method": {
"type": "APPLE_PAY",
"detail": {
"wallet": {
"merchant_id": "merchant_456",
"payment_token": "token_value",
"capture": false,
"verify": true
}
}
}
}
'
```
### Field Reference
| Property | Type | Required | Description |
| -------- | --------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `verify` | `boolean` | No | Enables card verification flow through the wallet. When `true`, a verification transaction (e.g., zero-dollar auth) is performed instead of a regular payment. |
The `verify` field already existed for `CARD` payment method type. This change extends the same capability to `APPLE_PAY`.
## Nupay Enrollment
Example of a request for creating a payment using Nupay Enrollment. Below are examples of a request and the received response for successful payment creation. The request is presented using the cURL format, and the response is a JSON object.
```sh Request (cURL) theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
curl --location 'https://api-sandbox.y.uno/v1/payments' \
--header 'X-idempotency-key: ' \
--header 'public-api-key: ' \
--header 'private-secret-key: ' \
--header 'Content-Type: application/json' \
--data '{
"description": "Payment with NuPay",
"account_id": "",
"merchant_order_id": "000022",
"country": "US",
"amount": {
"currency": "USD",
"value": 20
},
"checkout": {
"session": ""
},
"customer_payer": {
"id": ""
},
"workflow": "DIRECT",
"payment_method": {
"type": "NU_PAY_ENROLLMENT",
"vaulted_token": "",
"detail": {
"wallet": {
"card_data": {
"card_type": "CREDIT"
}
}
}
}
}'
```
```json Response (JSON) theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"id": "db24dc85-1ce3-48bc-a77b-b768c2b45c58",
"account_id": "7ae52512-1234-1234-1234-db973de67640",
"description": "Payment with NuPay",
"country": "US",
"status": "PENDING",
"sub_status": "PENDING_PROVIDER_CONFIRMATION",
"merchant_order_id": "000022",
"created_at": "2024-08-03T00:41:31.729501Z",
"updated_at": "2024-08-03T00:41:36.469759Z",
"amount": {
"captured": 0,
"currency": "USD",
"currency_conversion": null,
"refunded": 0,
"value": 20
},
"checkout": {
"session": "4351f6f4-1234-1234-1234-fd1388c3d55d",
"sdk_action_required": false
},
"payment_method": {
"vaulted_token": "1f3d74a0-1234-1234-1234-f5ccd42b27dc",
"type": "NU_PAY_ENROLLMENT",
"vault_on_success": false,
"token": "",
"payment_method_detail": {
"wallet": {
"verify": false,
"capture": false,
"installments": null,
"payment_method_id": null,
"payment_method_detail": null,
"date_of_expiration": null,
"money_release_date": null,
"sponsor_id": null,
"authorization_code": null,
"customer_data": null,
"card_data": {
"holder_name": "",
"iin": "",
"lfd": "",
"number_length": 0,
"security_code_length": 0,
"brand": "",
"issuer_name": "",
"issuer_code": null,
"category": null,
"type": "CREDIT",
"fingerprint": null
},
"redirect_url": ""
}
}
},
"customer_payer": {
"id": "45ad52b6-a094-41ab-933e-2e75a7ad4bf9",
"merchant_customer_id": "123456789012",
"first_name": "John",
"last_name": "Doe",
"gender": null,
"date_of_birth": null,
"email": "john.doe@email.com",
"nationality": null,
"ip_address": null,
"device_fingerprint": null,
"browser_info": {
"user_agent": "",
"accept_header": "",
"accept_content": null,
"accept_browser": null,
"color_depth": "",
"screen_height": "",
"screen_width": "",
"javascript_enabled": null,
"java_enabled": null,
"browser_time_difference": null,
"language": ""
},
"document": {
"document_type": "PASSPORT",
"document_number": "01234567891"
},
"phone": null,
"billing_address": null,
"shipping_address": null,
"merchant_customer_created_at": null
},
"additional_data": null,
"transactions": {
"id": "0bcc0b37-d863-4139-a9ae-44110c3253d8",
"type": "PURCHASE",
"status": "PENDING",
"category": "WALLET",
"amount": 20,
"provider_id": "SPINPAY",
"payment_method": {
"vaulted_token": "1f3d74a0-1234-1234-1234-f5ccd42b27dc",
"type": "NU_PAY_ENROLLMENT",
"vault_on_success": false,
"token": "",
"detail": {
"wallet": {
"verify": false,
"capture": false,
"installments": null,
"payment_method_id": null,
"payment_method_detail": null,
"date_of_expiration": null,
"money_release_date": null,
"sponsor_id": null,
"authorization_code": null,
"customer_data": null,
"card_data": {
"holder_name": "",
"iin": "",
"lfd": "",
"number_length": 0,
"security_code_length": 0,
"brand": "",
"issuer_name": "",
"issuer_code": null,
"category": null,
"type": "CREDIT",
"fingerprint": null
},
"redirect_url": ""
}
}
},
"response_code": "PENDING_PROVIDER_CONFIRMATION",
"response_message": "Transaction waiting confirmation",
"reason": null,
"description": "Payment with NuPay",
"merchant_reference": "000022",
"provider_data": {
"id": "SPINPAY",
"transaction_id": "512b4695-cc8e-48c6-a72c-36db3ba2e47d",
"account_id": "5864724921505",
"status": "WAITING_PAYMENT_METHOD",
"sub_status": "",
"status_detail": "",
"response_message": null,
"response_code": null,
"raw_response": {
"value": "{\"paymentMethodType\":\"nupay\",\"status\":\"WAITING_PAYMENT_METHOD\",\"pspReferenceId\":\"512b4695-cc8e-48c6-a72c-36db3ba2e47d\",\"referenceId\":\"0bcc0b37-d863-4139-a9ae-44110c3253d8\"}"
},
"third_party_transaction_id": "",
"third_party_account_id": null
},
"created_at": "2024-08-03T00:41:31.928075Z",
"updated_at": "2024-08-03T00:41:36.379150Z"
},
"transactions_history": [
{
"id": "0bcc0b37-d863-4139-a9ae-44110c3253d8",
"type": "PURCHASE",
"status": "PENDING",
"category": "WALLET",
"amount": 20,
"provider_id": "SPINPAY",
"payment_method": {
"vaulted_token": "1f3d74a0-1234-1234-1234-f5ccd42b27dc",
"type": "NU_PAY_ENROLLMENT",
"vault_on_success": false,
"token": "",
"detail": {
"wallet": {
"verify": false,
"capture": false,
"installments": null,
"payment_method_id": null,
"payment_method_detail": null,
"date_of_expiration": null,
"money_release_date": null,
"sponsor_id": null,
"authorization_code": null,
"customer_data": null,
"card_data": {
"holder_name": "",
"iin": "",
"lfd": "",
"number_length": 0,
"security_code_length": 0,
"brand": "",
"issuer_name": "",
"issuer_code": null,
"category": null,
"type": "CREDIT",
"fingerprint": null
},
"redirect_url": ""
}
}
},
"response_code": "PENDING_PROVIDER_CONFIRMATION",
"response_message": "Transaction waiting confirmation",
"reason": null,
"description": "Payment with NuPay",
"merchant_reference": "000022",
"provider_data": {
"id": "SPINPAY",
"transaction_id": "512b4695-cc8e-48c6-a72c-36db3ba2e47d",
"account_id": "5864724921505",
"status": "WAITING_PAYMENT_METHOD",
"sub_status": "",
"status_detail": "",
"response_message": null,
"response_code": null,
"raw_response": {
"value": "{\"paymentMethodType\":\"nupay\",\"status\":\"WAITING_PAYMENT_METHOD\",\"pspReferenceId\":\"512b4695-cc8e-48c6-a72c-36db3ba2e47d\",\"referenceId\":\"0bcc0b37-d863-4139-a9ae-44110c3253d8\"}"
},
"third_party_transaction_id": "",
"third_party_account_id": null
},
"created_at": "2024-08-03T00:41:31.928075Z",
"updated_at": "2024-08-03T00:41:36.379150Z"
}
],
"split": [],
"workflow": "DIRECT",
"metadata": [],
"fraud_screening": null,
"payment_link_id": "",
"subscription_code": null,
"routing_rules": {
"condition": {
"id": 95706,
"name": null,
"description": null
}
},
"simplified_mode": false
}
```
## Nequi
Below is an example of a payment request using Nequi. This example demonstrates how to create a payment operation using the cURL format.
```sh Request (cURL) theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
curl --location 'https://api-sandbox.y.uno/v1/payments' \
--header 'X-idempotency-key: ' \
--header 'public-api-key: ' \
--header 'Content-Type: application/json' \
--data-raw '{
"description": "Payment with Nequi",
"account_id":"",
"merchant_order_id": "0000022",
"country": "CO",
"amount": {
"currency": "COP",
"value": 52000
},
"customer_payer": {
"merchant_customer_id": "1737124506",
"first_name": "John",
"last_name": "Smith",
"email": "john.smith@example.com",
"document":{
"document_type": "CC",
"document_number": "1032765432"
},
"phone": {
"country_code": "57",
"number": "3991111111"
}
},
"payment_method": {
"type": "NEQUI"
},
"workflow":"REDIRECT",
"callback_url":"www.google.com"
}'
```
```json Response (JSON) theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"id": "340c1be8-05b9-4e37-aabf-4e57f098bf03",
"account_id": "493e9374-510a-4201-9e09-de669d75f256",
"description": "Payment with Nequi",
"country": "CO",
"status": "READY_TO_PAY",
"sub_status": "CREATED",
"merchant_order_id": "0000022",
"created_at": "2025-01-17T14:35:08.157837Z",
"updated_at": "2025-01-17T14:35:18.879785Z",
"amount": {
"captured": 0.00,
"currency": "COP",
"currency_conversion": null,
"refunded": 0.00,
"value": 52000.00
},
"checkout": {
"session": "b1792599-fa77-44ac-a31e-87f2af2e30ac",
"sdk_action_required": true
},
"payment_method": {
"vaulted_token": "",
"type": "NEQUI",
"vault_on_success": false,
"token": "",
"parent_payment_method_type": null,
"payment_method_detail": {
"wallet": {
"verify": false,
"capture": false,
"installments": 0,
"installments_plan_id": null,
"first_installment_deferral": 0,
"installments_type": "MERCHANT",
"installment_amount": null,
"payment_method_id": null,
"payment_method_detail": null,
"date_of_expiration": null,
"money_release_date": null,
"sponsor_id": null,
"authorization_code": null,
"customer_data": null,
"card_data": {
"holder_name": "",
"iin": "",
"lfd": "",
"number_length": 0,
"security_code_length": 0,
"brand": "",
"issuer_name": "",
"issuer_code": null,
"country_code": "",
"category": null,
"type": "",
"fingerprint": null,
"expiration_month": null,
"expiration_year": null
},
"redirect_url": "https://checkout.sandbox.y.uno/payment?session=cd627381-11ea-45d7-8918-ee703098c265"
}
}
},
"customer_payer": {
"id": null,
"merchant_customer_id": "1737124506",
"first_name": "John",
"last_name": "Smith",
"gender": null,
"date_of_birth": null,
"email": "john.smith@example.com",
"nationality": null,
"ip_address": null,
"device_fingerprint": null,
"device_fingerprints": [],
"browser_info": {
"user_agent": "",
"accept_header": "",
"accept_content": null,
"accept_browser": null,
"color_depth": "",
"screen_height": "",
"screen_width": "",
"javascript_enabled": null,
"java_enabled": null,
"browser_time_difference": null,
"language": ""
},
"document": {
"document_type": "CC",
"document_number": "1032765432"
},
"phone": {
"number": "3991111111",
"country_code": "57"
},
"billing_address": null,
"shipping_address": null,
"merchant_customer_created_at": null
},
"additional_data": null,
"transactions": {
"id": "a55a645d-4fcd-4720-9128-abbcbe739d81",
"type": "PURCHASE",
"status": "CREATED",
"category": "WALLET",
"amount": 52000.00,
"provider_id": "DLOCAL",
"payment_method": {
"vaulted_token": "",
"type": "NEQUI",
"vault_on_success": false,
"token": "",
"parent_payment_method_type": null,
"detail": {
"wallet": {
"verify": false,
"capture": false,
"installments": 0,
"installments_plan_id": null,
"first_installment_deferral": 0,
"installments_type": "MERCHANT",
"installment_amount": null,
"payment_method_id": null,
"payment_method_detail": null,
"date_of_expiration": null,
"money_release_date": null,
"sponsor_id": null,
"authorization_code": null,
"customer_data": null,
"card_data": {
"holder_name": "",
"iin": "",
"lfd": "",
"number_length": 0,
"security_code_length": 0,
"brand": "",
"issuer_name": "",
"issuer_code": null,
"country_code": "",
"category": null,
"type": "",
"fingerprint": null,
"expiration_month": null,
"expiration_year": null
},
"redirect_url": "https://checkout.sandbox.y.uno/payment?session=cd627381-11ea-45d7-8918-ee703098c265"
}
}
},
"response_code": "SUCCEEDED",
"response_message": "Transaction successful",
"reason": null,
"description": "Payment with Nequi",
"merchant_reference": "0000022",
"provider_data": {
"id": "DLOCAL",
"transaction_id": "F-385928-c8516ec5-5b49-4ccf-9fc9-89000f3935bd",
"account_id": "1OABfzqFOD",
"status": "PENDING",
"sub_status": "",
"status_detail": "",
"response_message": "The payment is pending.",
"response_code": "100",
"raw_response": {
"value": "{\"id\":\"F-385928-c8516ec5-5b49-4ccf-9fc9-89000f3935bd\",\"amount\":52000,\"currency\":\"COP\",\"payment_method_id\":\"QP\",\"payment_method_type\":\"WALLET\",\"payment_method_flow\":\"REDIRECT\",\"country\":\"CO\",\"created_date\":\"2025-01-17T14:35:09.000+0000\",\"status\":\"PENDING\",\"status_detail\":\"The payment is pending.\",\"status_code\":\"100\",\"order_id\":\"a55a645d-4fcd-4720-9128-abbcbe739d81\",\"notification_url\":\"https://sandbox.y.uno/dlocal-webhook/v1/confirmations\"}"
},
"third_party_transaction_id": "",
"third_party_account_id": "",
"iso8583_response_code": null,
"iso8583_response_message": null
},
"connection_data": {
"id": "c3f18893-9318-4652-90f6-7bb9d12cc160",
"name": null
},
"device_fingerprint": null,
"created_at": "2025-01-17T14:35:08.314925Z",
"updated_at": "2025-01-17T14:35:18.832995Z"
},
"transactions_history": [
{
"id": "a55a645d-4fcd-4720-9128-abbcbe739d81",
"type": "PURCHASE",
"status": "CREATED",
"category": "WALLET",
"amount": 52000.00,
"provider_id": "DLOCAL",
"payment_method": {
"vaulted_token": "",
"type": "NEQUI",
"vault_on_success": false,
"token": "",
"parent_payment_method_type": null,
"detail": {
"wallet": {
"verify": false,
"capture": false,
"installments": 0,
"installments_plan_id": null,
"first_installment_deferral": 0,
"installments_type": "MERCHANT",
"installment_amount": null,
"payment_method_id": null,
"payment_method_detail": null,
"date_of_expiration": null,
"money_release_date": null,
"sponsor_id": null,
"authorization_code": null,
"customer_data": null,
"card_data": {
"holder_name": "",
"iin": "",
"lfd": "",
"number_length": 0,
"security_code_length": 0,
"brand": "",
"issuer_name": "",
"issuer_code": null,
"country_code": "",
"category": null,
"type": "",
"fingerprint": null,
"expiration_month": null,
"expiration_year": null
},
"redirect_url": "https://checkout.sandbox.y.uno/payment?session=cd627381-11ea-45d7-8918-ee703098c265"
}
}
},
"response_code": "SUCCEEDED",
"response_message": "Transaction successful",
"reason": null,
"description": "Payment with Nequi",
"merchant_reference": "0000022",
"provider_data": {
"id": "DLOCAL",
"transaction_id": "F-385928-c8516ec5-5b49-4ccf-9fc9-89000f3935bd",
"account_id": "1OABfzqFOD",
"status": "PENDING",
"sub_status": "",
"status_detail": "",
"response_message": "The payment is pending.",
"response_code": "100",
"raw_response": {
"value": "{\"id\":\"F-385928-c8516ec5-5b49-4ccf-9fc9-89000f3935bd\",\"amount\":52000,\"currency\":\"COP\",\"payment_method_id\":\"QP\",\"payment_method_type\":\"WALLET\",\"payment_method_flow\":\"REDIRECT\",\"country\":\"CO\",\"created_date\":\"2025-01-17T14:35:09.000+0000\",\"status\":\"PENDING\",\"status_detail\":\"The payment is pending.\",\"status_code\":\"100\",\"order_id\":\"a55a645d-4fcd-4720-9128-abbcbe739d81\",\"notification_url\":\"https://sandbox.y.uno/dlocal-webhook/v1/confirmations\"}"
},
"third_party_transaction_id": "",
"third_party_account_id": "",
"iso8583_response_code": null,
"iso8583_response_message": null
},
"connection_data": {
"id": "c3f18893-9318-4652-90f6-7bb9d12cc160",
"name": null
},
"device_fingerprint": null,
"created_at": "2025-01-17T14:35:08.314925Z",
"updated_at": "2025-01-17T14:35:18.832995Z"
}
],
"callback_url": "www.google.com",
"workflow": "REDIRECT",
"metadata": [],
"fraud_screening": null,
"payment_link_id": "",
"subscription_code": null,
"routing_rules": {
"smart_routing": false,
"condition": {
"id": 130132,
"name": null,
"description": null
}
},
"simplified_mode": false
}
```
## DolarApp
Example of a request for a payment using DolarApp. Below are examples of a request and the received response for successful payment creation. The request is presented using the cURL format, and the response is a JSON object.
```sh Request (cURL) theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
curl --location 'https://api-sandbox.y.uno/v1/payments' \
--header 'X-idempotency-key: ' \
--header 'public-api-key: ' \
--header 'private-secret-key: ' \
--header 'Content-Type: application/json' \
--data '{
"account_id": "",
"amount": {
"currency": "MXN",
"value": 5
},
"checkout": {
"session": ""
},
"payment_method": {
"token": "",
"detail": {
"card": {
"capture": true
},
"wallet": {
"capture": true
}
},
"vault_on_success": false
},
"customer_payer": {
"id": "",
"nationality": "MX",
"browser_info": {
"user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36",
"accept_header": "application/json",
"accept_content": "*/*",
"accept_browser": "*/*",
"color_depth": "8",
"screen_height": "8",
"screen_width": "8",
"javascript_enabled": true,
"java_enabled": false,
"browser_time_difference": "300",
"language": "en",
"platform": "WEB"
}
},
"merchant_order_id": "1780501099353",
"country": "MX",
"description": "Payment with DolarApp"
}'
```
```json Response (JSON) theme={"theme":{"light":"github-dark","dark":"github-dark-dimmed"}}
{
"id": "48b4aa34-4006-4f5b-b444-8e0c0f54f3ea",
"account_id": "",
"description": "Payment with DolarApp",
"country": "MX",
"status": "PENDING",
"sub_status": "PENDING_PROVIDER_CONFIRMATION",
"merchant_order_id": "1780501099353",
"created_at": "2026-06-03T15:46:05.027450Z",
"updated_at": "2026-06-03T15:46:05.774028Z",
"amount": {
"captured": 0,
"currency": "MXN",
"currency_conversion": null,
"refunded": 0,
"value": 5
},
"checkout": {
"session": "",
"sdk_action_required": true
},
"payment_method": {
"vaulted_token": "",
"type": "DOLARAPP",
"vault_on_success": false,
"vault_on_decline": false,
"token": "",
"parent_payment_method_type": null,
"otp": {},
"payment_method_detail": {
"wallet": {
"verify": null,
"capture": true,
"installments": 0,
"installments_plan_id": null,
"first_installment_deferral": 0,
"installments_type": "",
"installment_amount": null,
"installments_total_amount": null,
"payment_method_id": null,
"payment_method_detail": null,
"date_of_expiration": null,
"money_release_date": null,
"sponsor_id": null,
"authorization_code": null,
"customer_data": null,
"card_data": {
"holder_name": "",
"iin": "",
"lfd": "",
"number_length": 0,
"security_code_length": 0,
"brand": "",
"scheme": "",
"issuer_name": "",
"issuer_code": null,
"country_code": null,
"category": null,
"type": "",
"fingerprint": null,
"expiration_month": null,
"expiration_year": null
},
"redirect_url": null,
"expires_at": null
}
}
},
"customer_payer": {
"id": "",
"merchant_customer_id": "1780428489539",
"first_name": "John",
"last_name": "Doe",
"gender": "",
"date_of_birth": "1990-02-28",
"email": "john.doe@email.com",
"nationality": "MX",
"ip_address": "190.18.30.39",
"device_fingerprint": null,
"device_fingerprints": [],
"browser_info": {
"user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36",
"accept_header": "application/json",
"accept_content": "*/*",
"accept_browser": "*/*",
"color_depth": "8",
"screen_height": "8",
"screen_width": "8",
"javascript_enabled": true,
"java_enabled": false,
"browser_time_difference": "300",
"language": "en",
"platform": "WEB"
},
"document": {
"document_type": "RFC",
"document_number": "IESF960301230"
},
"phone": {
"number": "3991111111",
"country_code": "52"
},
"billing_address": null,
"shipping_address": null,
"merchant_customer_created_at": null,
"merchant_customer_validations": {
"account_is_verified": true,
"email_is_verified": true,
"phone_is_verified": true
}
},
"additional_data": null,
"transactions": {
"id": "2b8ab4d0-27ff-4641-be49-a706d1617a50",
"type": "PURCHASE",
"status": "PENDING",
"category": "WALLET",
"amount": 5,
"provider_id": "DOLARAPP",
"response_code": "PENDING_PROVIDER_CONFIRMATION",
"response_message": "Transaction waiting confirmation",
"reason": null,
"description": "Payment with DolarApp",
"merchant_reference": "1780501099353",
"provider_data": {
"id": "DOLARAPP",
"transaction_id": "2b8ab4d0-27ff-4641-be49-a706d1617a50",
"account_id": "",
"status": "PENDING",
"sub_status": "",
"status_detail": "",
"response_message": "Transaction waiting confirmation",
"response_code": "200",
"raw_response": null,
"third_party_transaction_id": "",
"third_party_account_id": null,
"iso8583_response_code": null,
"iso8583_response_message": null,
"merchant_advice_code": null,
"merchant_advice_code_message": null,
"reason_code": null,
"reason_description": null
},
"connection_data": {
"id": "",
"name": ""
},
"created_at": "2026-06-03T15:46:05.167801Z",
"updated_at": "2026-06-03T15:46:05.721788Z",
"split_marketplace": [],
"merchant_advice_code": null,
"merchant_advice_code_message": null
},
"callback_url": "https://demo.dev.y.uno/testing/checkout/status?checkoutSession=",
"workflow": "SDK_CHECKOUT",
"metadata": [],
"fraud_screening": null,
"payment_link_id": "",
"subscription_code": null,
"routing_rules": {
"smart_routing": false,
"monitors": false,
"condition": {
"id": 122903,
"name": null,
"description": null
}
},
"simplified_mode": false
}
```
# Refund Payment
Source: https://docs.y.uno/reference/payments/refund-payment
openapi/payments/refund-payment.json POST /payments/{id}/transactions/{transaction_id}/refund
Issues a partial or full refund for an existing payment transaction.
Do not execute a refund while another is in progress. Wait for the current operation to complete before starting a new one.
This endpoint allows you to issue a refund for an existing payment.
If you specify an `amount`, a **partial refund** will be created. If the `amount` is omitted, a **full refund** of the original payment will be processed.
Refunds can only be created for charges that have not been refunded yet. The refunded amount will be returned to the original payment method used in the transaction.
Note that this request requires an `X-Idempotency-Key`. Check the [Authentication](/reference/authentication#idempotency) page for more information.
# Retrieve Issuers
Source: https://docs.y.uno/reference/payments/retrieve-issuers
openapi/payments/retrieve-issuers.json GET /issuers
Retrieves the list of issuers that support a specific payment method.
This endpoint retrieves a list of all issuers that support the specific payment method. It allows you to filter issuers based on their compatibility with a particular payment method.
# Retrieve Payment by ID
Source: https://docs.y.uno/reference/payments/retrieve-payment-by-id-v2
openapi/payments/retrieve-payment-by-id-v2.json GET /payments/{payment_id}
Retrieves payment details using the payment ID provided in the request path.
This request enables you to retrieve details of payments based on their `id`, which needs to be provided in the request path.
# Retrieve Payment by Merchant Order ID
Source: https://docs.y.uno/reference/payments/retrieve-payment-by-merchant-order-id
openapi/payments/retrieve-payment-by-merchant-order-id.json GET /payments
Retrieves payment details using the merchant order ID provided in the request.
This request enables you to retrieve details of payments based on their `merchant_order_id`, which needs to be provided in the request path.
# Merchant Advice Codes (MAC)
Source: https://docs.y.uno/reference/payments/status-and-response-codes/merchant-advice-codes-mac
Maps normalized merchant advice codes to network equivalents to guide retry decisions.
When a transaction is declined, Merchant Advice Codes (MACs) provide clear guidance on whether and when a retry is appropriate. To support transparency and informed decision-making, Yuno’s public APIs include both normalized and raw response codes. By understanding MACs, merchants can quickly identify the reason for a decline and determine the best actions to take, such as updating routing or customer information before attempting a retry.
## MACs list
This table maps Yuno’s normalized Merchant Advice Codes (`merchant_advice_code`, with its human-readable `merchant_advice_code_message` shown beneath each code) to their equivalents from Mastercard, Visa, and Elo. Use it as a reference to interpret decline reasons, set retry rules, and apply consistent routing strategies across networks.
| `merchant_advice_code` | Mastercard | Visa | Elo |
| :--------------------------------------------------------------------------------------- | :----------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------- |
| `UPDATE_INFORMATION` Updated/additional information needed | `01` – Updated account information available | – | – |
| `TRY_AGAIN_LATER` Retry within 30 days | `02` – Try again later | `3, 19, 39` `51, 52, 53` `59, 60, 61` `62, 65, 75` `78, 86, 91` `93, 96, N3` `N4, Z5, 5C` `9G` | `51, 59, 04` `06, 38, 61` `62, 65, 75` `78, 91` |
| `DO_NOT_TRY_AGAIN` Do not try again | `03` – Do not try again | `4, 7, 12` `14, 15, 41` `43, 46, 57` `R0, R1, R3` | `57, 14, 56` `46, FM, 19` `12, 30, 13` `23, 41, 43` `64, 83, 76` `77` |
| `REQUIREMENTS_NOT_FULFILLED` Token requirements not fulfilled | `04` – Token requirements not fulfilled | – | – |
| `NO_RETRY_LIFE_CYCLE` No retry life cycle | `21` – Recurring plan cancelled | – | – |
| `RETRY_AFTER_1_H` Retry after 1 hours | `24` – Retry after 1 hours (insufficient funds) | – | – |
| `RETRY_AFTER_24_H` Retry after 24 hours | `25` – Retry after 24 hours (insufficient funds) | – | – |
| `RETRY_AFTER_2_D` Retry after 2 days | `26` – Retry after 2 days (insufficient funds) | – | – |
| `RETRY_AFTER_4_D` Retry after 4 days | `27` – Retry after 4 days (insufficient funds) | – | – |
| `RETRY_AFTER_6_D` Retry after 6 days | `28` – Retry after 6 days (insufficient funds) | – | – |
| `RETRY_AFTER_8_D` Retry after 8 days | `29` – Retry after 8 days (insufficient funds) | – | – |
| `RETRY_AFTER_10_D` Retry after 10 days | `30` – Retry after 10 days (insufficient funds) | – | – |
| `NO_RETRY_POLICY` No retry policy | `40` – Non-rechargeable prepaid card | – | – |
| `NO_RETRY_SECURITY` No retry security | `42` – Sanction score exceeded | – | – |
| `MULTIPLE_USE_CARD` Multiple-use virtual card | `43` – Multiple-use virtual card | – | – |
| `INVALID_DATA` Incorrect payment information; merchant must revalidate before retry | – | `54, 55, 82` `N7, 1A, 70` `6P` | `54, 55, 82` `63` |
## MAC fields in transactions
Yuno’s public API includes dedicated fields to facilitate the use of Merchant Advice Codes.
### Normalized MACs
Yuno provides a standardized set of Merchant Advice Codes that simplify provider responses. These codes let you build retry logic and routing rules without needing to manage every provider’s unique variations.
* **`transactions.merchant_advice_code`**: A Yuno-normalized MAC returned when a transaction is declined. This code helps you understand the reason for the denial, whether a retry is possible, and what actions to take before reattempting the payment.
* **`transactions.merchant_advice_code_message`**: This fields complements the `merchant_advice_code` seen above, providing an explanation of the code in human‑readable terms. This message will allow you to act on the information without having to memorize the meaning of each code.
### Raw MACs
Alongside normalized values, Yuno also exposes the original codes and messages returned by providers. These raw fields ensure full transparency and allow you to troubleshoot or follow provider-specific guidance when needed.
* **`transactions.provider_data.merchant_advice_code`**: The original Merchant Advice Code returned directly from the payment provider. This field gives you access to the raw code for full transparency and troubleshooting.
* **`transactions.provider_data.merchant_advice_code_message`**: A human-readable message from the provider that explains the meaning of the raw MAC. Use this message to understand provider-specific guidance without needing to interpret code values.
Please note these fields are located inside the `transactions` object in API responses.
## About retries
When a card purchase is declined, any subsequent attempt to complete the purchase using the same card is a retry. Fees and thresholds for retries are defined by each card network. How many times you can retry before fees apply varies by brand. Merchants that don’t comply may be charged fees for exceeded transactions.
The payments industry, together with ABECS, standardized response codes for card transaction declines. These attempts are categorized into two types:
* **Reversible**: A potentially temporary denial that may change over time. The issuer may deny the transaction due to insufficient funds, system issues, or too many unsuccessful PIN attempts.
* **Irreversible**: Any authorization after an irreversible decline that doesn’t change message fields will fail. This could mean the card has been cancelled or fraud has been confirmed.
Visa, Mastercard, and Elo updated their policies to limit authorization retry attempts after a decline, and they charge fees for attempts beyond those limits. See each brand’s rules below.
* [Mastercard](#mastercard)
* [Visa](#visa)
* [Elo](#elo)
* [Other brands](#other-brands)
## Mastercard
Mastercard handles MACs as part of its Transaction Processing Excellence (TPE) program, which has two main components:
### Excessive Authorization Attempts
Mastercard’s Excessive Authorization Attempts TPE aims to constantly monitor network utilization to detect and prevent too many authorization requests. Mastercard also monitors approved transactions for very small amounts (less than one unit of currency) that are later refunded, as these can indicate card testing activity.
This monitoring applies to both declined and approved purchases. A retry is defined as any new attempt to authorize a payment using the same card and merchant. Mastercard’s rules set daily and monthly thresholds depending on the region (for example, no more than 10 attempts per day or 35 retries in a month). Exceeding either limit can result in additional fees.
### Mastercard Merchant Advice Codes (MACs)
Mastercard uses MACs to help merchants understand when it’s appropriate to retry a transaction. Some declines are irreversible, meaning the transaction should not be retried, often because the card is closed or fraud is confirmed.
The TPE program specifically tracks retries after these irreversible declines, focusing on two codes: MAC 03 (“Do not try again”) and MAC 21 (“No retry life cycle”). If you try to process the same card and amount again after receiving one of these codes, Mastercard may charge you a fee.
Other MACs, such as those indicating a temporary issue or insufficient funds, don’t trigger MAC Transaction Excellence fees, but you could still be charged under the Excessive Authorization Attempts program if you exceed retry limits.
In some cases, MACs will recommend waiting a specific amount of time before retrying (for example, “Retry after 24 hours”). These help you choose the best moment to try again.
View all Mastercard MACs and their Yuno-normalized equivalents in the [MACs list](#macs-list).
## Visa
Visa's MACs are organized in four categories. The goal is to keep the ecosystem balanced, reduce unnecessary retries, and require issuers to use precise, non‑generic decline codes.
**Visa Fees**
Since they are irreversible, category 1 codes incur a charge from the 2nd attempt. Categories 2, 3, and 4 allow up to 20 attempts within 30 days, with fees starting from the 21st attempt. After 30 days from the first attempt, any retry is charged. Visa's fees are as follows:
* **Domestic**: USD 0.10 + 13.83% tax
* **Cross border**: USD 0.25 + 13.83% tax
### Category 1 (issuer will never approve)
Irreversible, signals the card was canceled or never existed, or that the denial is the result of a permanent restriction or error that will block future approval. Fees from the second attempt.
* Common category 1 codes may include: `04`, `07`, `12`, `15`, `41`, `43`, `46`, `57`, `R0`, `R1`, `R3`
### Category 2 (issuer cannot approve at this time)
Reversible, means the denial results from a temporary condition such as credit risk or other card restrictions that may allow a retry of the transaction to be approved. Some cases require action by the cardholder or issuer to remove the restriction before approval.
* Common category 2 codes may include: `03`, `19`, `39`, `51`, `52`, `53`, `59`, `61`, `62`, `65`, `75`, `78`, `86`, `91`, `93`, `96`, `N3`, `N4`, `Z5`, `5C`, `9G`
### Category 3 (data quality)
Reversible, is triggered by a data error identified by the issuer. Merchants must revalidate payment data before retrying. These denial codes may signal potential fraud risks to merchants.
* Common category 3 codes may include: `14`, `54`, `55`, `70`, `82`, `1A`, `6P`, `N7`
**Category 3 Charges**
Merchants can have up to 25,000 declined transactions with data quality errors (category 3) in a 30-day period. If you go over this limit, Visa will charge a fee for every additional declined transaction in this category.
### Category 4 (generic response codes)
Reversible, includes all other decline response codes not in categories 1, 2, and 3, as there may be cases where there is no response code value for a specific decline. Issuers may use other response code values defined in the VisaNet Technical Specifications. However, minimal use is advised.
All Visa MACs and their Yuno-normalized equivalents are available in the [MACs list](#macs-list).
## Elo
Elo implemented rules in January 2025, aiming to reduce unnecessary retries by merchants and acquirers. Transactions are counted from the 1st to the last calendar day of the month.
**Elo Fees**
BRL 0.80 per attempt that exceeds the group limit.
### Elo groups and retry rules
Elo classifies reversible and irreversible codes into three separate groups:
| Group | Description | Charge rule |
| :--------------------- | :--------------------------------------------------------------------------------------------- | :--------------------------------------------------------------- |
| Group 1 (Irreversible) | Transactions denied with irreversible codes (same card, same establishment CNPJ, same amount) | Charged from the 2nd attempt within the month of assessment |
| Group 2 (Reversible) | Transactions declined with reversible codes | Charged from the 16th attempt within the month of assessment |
| Group 3 (Data quality) | Declines with characteristics of brute‑force attacks (considering the same merchant Root CNPJ) | Charged from 10,001 denied transactions if >5% of total refusals |
“CNPJ” refers to the Brazilian business taxpayer identification for the establishment (Root CNPJ at the group level).
Refer to the for all Elo [MACs list](#macs-list)and Yuno-normalized equivalents.
## Other brands
* **Reversible codes**: Retry attempts are allowed for the same customer and card. There is no limit or pre-established time limit.
**Attention**
Before attempting again, follow the guidance received in the denied transaction response.
* **Irreversible Codes**: Authorizations for the same card or establishment will not be allowed after receiving the first refusal response from the issuer.
## Routing with MAC
Retry behavior should be implemented via [routing](/docs/routing) conditions. Update routes to include the new MAC conditions.
When creating a decline group in the [Yuno dashboard](https://dashboard.y.uno/), you can choose to add conditions by Response Code or by MAC Code.
**Transition Period**
Until all integrations emit MAC separately, some MAC values will appear under both Response Codes and MAC Codes. This is expected while the feature's rollout completes.
# Payment Status and Response Codes
Source: https://docs.y.uno/reference/payments/status-and-response-codes/payment
Lists payment statuses, substatuses, and their corresponding transaction states and descriptions.
Payments have all the essential information about the order, including customer information, amount, currency, items, shipping info, etc. You can always refer to the transaction details for more details about the order and the payment interactions.
## Workflow
In the following workflow, you can find the different payment statuses and how they can be updated.
For every implementation, we recommend taking the payment status and sub\_status as the main reference for the payment's state. A payment could have different [transactions](/reference/transaction) associated with it. By focusing on the payment status / sub\_status, you can have the latest state regardless of how many transactions were made, giving you clear inputs for decision-making.
## Payments status
The payments can have the following status and sub status.
Status
Substatus
Transaction type
Transaction status
Description
Initial state at the time of creating a payment.
Purchase
Created
Initial state at the time of creating a payment. Waiting for customer action
Authorize
Succeeded
Card authorizations
Purchase
Created
The client has been redirected to the provider and we are waiting for the completion of the payment.
Purchase
Pending
3DS/Second factor
Authorize
Pending
3DS/Second factor for authorization flow
Purchase
Pending
Wating for providers payment confirmation.
Fraud
Pending
Transaction is being analyzed by fraud provider
Purchase
Pending
Initial status upon payment creation
Verify
Succeeded
Zero amount card authorizations
Purchase
Expired
The offline payment method reaches its expiration date.
Authorize
Expired
Authorization expires
Purchase
Rejected
Rejected by Yuno
Capture
Error
Capture rejection by Yuno
Purchase
Declined
Providers rejection
Capture
Declined
Providers capture rejection
Fraud screening
Declined
Declined fraud screening
Purchase
Succeeded
Partial payment (payment with 2 cards)
Purchase
Succeeded
Successful payment
Capture
Succeeded
Successful capture
Capture
Succeeded
Successful partial capture
Refund
Error/Declined
Remains approved due to error in refund / cancellation
Chargeback
Error/Declined
Remains approved due to rejection in chargeback
Refund
Succeeded
Successful partial refund
Chargeback
Succeeded
Successful partial chargeback
Fraud screening
Declined
Fraud screening declined. Can occur before or after provider authorization. Payment succeeded and funds have moved.
Refund
Declined
Transaction was declined and is waiting for retry.
Capture
Declined
Transaction was declined and is waiting for retry.
Capture
Declined
Transaction was declined and retry scheme it's finished.
Refund
Pending
Refund Pending
Refund
Succeeded
Successful refund
Cancel
Pending
Cancel Pending
Cancel
Succeeded
Successful cancelation
Chargeback
Created
Chargeback or Inquiry received. Decision or documentation must be provided
Chargeback
Pending
In\_review
Chargeback
Prevented
Predispute deflected by provider/network. Payment reflects lost funds.
Example: timeout.
Fraud
Succeeded
Transaction verified by fraud provider during stand alone fraud verification
`PREVENTED` is a transaction status only for `type = CHARGEBACK` when the provider/network reports a [predispute deflection](/docs/chargeback-management). In these scenarios, only the chargeback webhook is sent; no refund webhook is emitted.
`REVIEW_WON` is a chargeback transaction status only. When a chargeback is won, the payment returns to its previous status (for example, `SUCCEEDED` / `APPROVED`) and no new payment status is emitted.
### Possible states for sync and async flows
Use the diagram that matches your integration type to understand which payment states and transitions to expect.
#### Synchronous flow
In a synchronous flow, the payment moves from `CREATED` directly to a terminal status — such as `SUCCEEDED`, `DECLINED`, or `REJECTED` — within the same API response. There is no intermediate `PENDING` phase. `ERROR` is transversal and can occur at any point in the flow.
#### Asynchronous flow
In an asynchronous flow, the payment passes through a `PENDING` phase after creation before reaching a terminal status. During this phase, substates such as `IN_PROCESS`, `AUTHORIZED`, and `WAITING_ADDITIONAL_STEP` reflect ongoing processing. The final status is delivered via webhook once processing completes. Payments initiated via direct async APMs may also enter a `READY_TO_PAY` state, which can transition to `EXPIRED` if not completed. `ERROR` is transversal and can occur at any point in the flow.
# Transaction Status and Response Codes
Source: https://docs.y.uno/reference/payments/status-and-response-codes/transaction
Lists transaction types, response codes, and their descriptions for processed transactions.
Each payment has one or more associated transactions. The following documentation covers transaction types, status codes, and descriptions after an HTTP 200 status is obtained and a transaction is processed.
## Workflow
## Types of transactions
| Type | Description |
| :------------------------ | :------------------------------------------------------------------- |
| `PURCHASE` | A direct purchase transaction. |
| `AUTHORIZE` | Transaction associated with authorization. Mainly for card payments. |
| `CAPTURE` | A capture of a previously authorized transaction. |
| `REFUND` | A refund of a previously approved transaction. |
| `CANCEL` | A cancelation of a previously pending transaction. |
| `VERIFY` | Transaction associated with a credit card verification. |
| `CHARGEBACK` | Transaction associated with a chargeback. |
| `THREE_D_SECURE` | A 3DS verification transaction for an initial purchase. |
| `FRAUD_SCREENING` | Fraud screening is associated with fraud verification. |
| `SPLIT_TRANSFER_REVERSAL` | A transfer reversal linked to a specific payment transaction. |
| `SPLIT_TRANSFER` | A standalone forward transfer within a Marketplace. |
| `SPLIT_TRANSFER_REVERSE` | A standalone reverse transfer within a Marketplace. |
## Transaction codes
With every transaction, you´ll receive a `response_code` detailing more info about it. The details related to each status are presented below. Use the following buttons to navigate to the desired content.
### Succeeded status
SUCCEEDED status details>}>
| response\_code | Description | Hard/Soft decline | ISO 8583 code |
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------- | ------------- |
| `ACTION_REQUIRED` | Payment created but requires additional user action. This occurs in 3D Secure authentication flows, payment method redirections, Headless SDK flows requiring continuePayment, or async payment methods with additional steps. Check the `redirect_url` or `sdk_action_required` field for next steps. | N/A | - |
| `SUCCEEDED` | Transaction created successfully | N/A | - |
| `RECEIVED` | Transaction received | N/A | - |
### Pending status
PENDING status details>}>
| response\_code | Description | Hard/Soft decline | ISO 8583 code |
| ------------------------------- | ----------------------------------------------------------------------- | ----------------- | ------------- |
| `CHALLENGE_REQUIRED` | Transaction waiting for the challenge completion | N/A | - |
| `IN_REVIEW` | Chargeback documentation was sent to the provider and is being analyzed | N/A | - |
| `PENDING_FRAUD_REVIEW` | Transaction is being analyzed by fraud provider | N/A | - |
| `PENDING_PROVIDER_CONFIRMATION` | Transaction waiting confirmation | N/A | - |
| `PENDING_REVIEW` | Transaction waiting fraud review confirmation | N/A | - |
### Declined status
Some declines include a `merchant_advice_code` (MAC) that indicates whether and when to retry. See [Merchant Advice Codes (MAC)](#merchant-advice-codes-mac).
DECLINED status details>}>
| response\_code | Description | Hard/Soft decline | ISO 8583 code |
| -------------------------------------- | --------------------------------------------------------------------------------------- | ----------------- | ---------------------- |
| `ACCOUNT_STATUS` | Contact your fraud provider to verify your account status. | N/A | - |
| `ACQUIRE_CONTINGENCY` | Acquire service unavailable | SOFT | 22, 80, 90, 91, 92, 96 |
| `AUTHENTICATION_ATTEMPT` | Authentication attempt without completion | N/A | - |
| `AUTHENTICATION_FAILED_THREE_D_SECURE` | 3D validation failed | N/A | - |
| `BAD_FILLED_INFO` | Card does not match the parameters from the issuer | HARD | 30,89 |
| `BANK_NOT_SUPPORTED` | Bank not supported by switch | SOFT | 31 |
| `CALL_FOR_AUTHORIZE` | Card acceptor call acquirer's security department | SOFT | 66 |
| `CANCELLED_BY_USER` | Cancelled by user | SOFT | 17 |
| `COUNTRY_NOT_SUPPORTED` | This transaction cannot be processed due to an unsupported country | HARD | - |
| `CURRENCY_NOT_ALLOWED` | Currency not allowed | HARD | - |
| `DECLINED_BY_BANK` | Rejected by the bank. Refer to card issuer | SOFT | - |
| `DECLINED_BY_PROVIDER` | Rejected by the provider. Refer to the provider\_data | SOFT | - |
| `DISABLED` | Restricted card | SOFT | - |
| `DO_NOT_HONOR` | Do not honor | SOFT | 5 |
| `DUPLICATED_TRANSACTION` | Duplicate transmission of the transaction | SOFT | 26,94 |
| `EXPIRED` | Expired alternative payment method | SOFT | |
| `EXPIRED_CARD` | Expired card | HARD | 33,54 |
| `FIRST_USE` | Blocked first use | SOFT | 78 |
| `FRAUD_VALIDATION` | Security violation | SOFT | 34, 59, 63, 64 |
| `FRAUD_VERIFICATION_DECLINED` | - | - | - |
| `INSUFFICIENT_FUNDS` | Not sufficient funds | SOFT | 51 |
| `INVALID_AMOUNT` | Invalid amount | SOFT | 13,64 |
| `INVALID_CARD_DATA` | Card does not match the parameters from the issuer. | HARD | 56 |
| `INVALID_CARD_NUMBER` | Card does not match the parameters from the issuer. | HARD | 14 |
| `INVALID_API` | Trying to verify the payment with an unauthorized IP address | HARD | - |
| `INVALID_API_VERSION` | Invalid API version | HARD | - |
| `INVALID_CREDENTIALS` | Fraud provider invalid credentials set in Yuno. | HARD | - |
| `INVALID_ISSUER` | Invalid issuer | SOFT | 15 |
| `INVALID_MERCHANT` | Invalid merchant or service provider | SOFT | 3 |
| `INVALID_PARAMETERS` | Invalid parameters | HARD | - |
| `INVALID_SECURITY_CODE` | Invalid card's security code | HARD | 56,82 |
| `INVALID_STATUS` | Invalid status | SOFT | - |
| `INVALID_RESPONSE_FORMAT` | The response body returned by the provider has an invalid format | SOFT | - |
| `INVALID_TRANSACTION` | The transaction being attempted is invalid | HARD | 12,23 |
| `ISSUER_VIOLATION` | The issuing bank rejected the transaction due to some violation related to the account. | SOFT | 93 |
| `MISSING_PARAMETERS` | Missing parameters | HARD | - |
| `NO_RETRY_LIFE_CYCLE` | No retry life cycle | HARD | 79 |
| `NO_RETRY_POLICY` | No retry policy | HARD | 82 |
| `NO_RETRY_SECURITY` | No retry security | HARD | 83 |
| `RETRY_AFTER_1_H` | Retry after 1 hours | HARD | |
| `RETRY_AFTER_24_H` | Retry after 24 hours | HARD | |
| `RETRY_AFTER_2_D` | Retry after 2 days | HARD | |
| `RETRY_AFTER_4_D` | Retry after 4 days | HARD | |
| `RETRY_AFTER_6_D` | Retry after 6 days | HARD | |
| `RETRY_AFTER_8_D` | Retry after 8 days | HARD | |
| `RETRY_AFTER_10_D` | Retry after 10 days | HARD | |
| `REJECTED_THREE_D_SECURE_REQUIRED` | 3DS validation rejection | SOFT | - |
| `REFER_TO_CARD_ISSUER` | Rejected by the bank. Refer to card issuer | SOFT | 01 |
| `REPORTED_LOST` | Lost card | HARD | 41 |
| `REPORTED_STOLEN` | Stolen card, pick-up | HARD | 43 |
| `REQUESTS_EXCEEDED` | Requests limit for the provider account reached. | SOFT | - |
| `RESTRICTED_BY_BANK` | Rejected by the bank. Refer to card issuer's special conditions | SOFT | 62 |
| `TERMINAL_ERROR` | Your merchant account is not properly configured for the transaction | SOFT | 58 |
| `THREE_D_SECURE_REQUIRED` | Antifraud provider requires a 3DS challenge for further validation. | SOFT | |
| `TRANSACTION_NOT_FOUND` | Transaction not found | HARD | 25 |
| `UNAVAILABLE_PAYMENT_METHOD` | Requested function not supported | HARD | - |
| `UNSUPPORTED_OPERATION` | Requested function not supported | HARD | 40 |
| `UNKNOWN_ERROR` | Unknown error | SOFT | - |
| `USER_RESTRICTION` | Transaction not permitted for cardholder | HARD | 57 |
### Merchant Advice Codes (MAC)
These codes will provide useful guidance when dealing with declined transactions. You may find these fields in our public API responses:
* **`transactions.merchant_advice_code` and `transactions.merchant_advice_code_message`**: Yuno-normalized fields providing standardized codes and explanations regarding the denial.
* **`transactions.provider_data.merchant_advice_code` and `transactions.merchant_advice_code_message`**: Raw code and message from the provider.
Please refer to [Merchant Advice Codes (MAC)](#merchant-advice-codes-mac) for more information.
Merchant Advice Codes provide guidance from issuers/providers about retry behavior and policy. When present on a decline, use the MAC to determine whether to retry and the recommended timing.
| merchant\_advice\_code | Description | Provider MAC code |
| ---------------------------- | ------------------------------------- | ---------------------------------------------- |
| `UPDATE_INFORMATION` | Updated/additional information needed | 01 – Updated account information available |
| `TRY_AGAIN_LATER` | Retry after 10 days | 02 – Try again later |
| `DO_NOT_TRY_AGAIN` | Do not try again | 03 – Do not try again |
| `REQUIREMENTS_NOT_FULFILLED` | Token requirements not fulfilled | 04 – Token requirements not fulfilled |
| `NO_RETRY_LIFE_CYCLE` | No retry life cycle | 21 – Recurring plan cancelled |
| `RETRY_AFTER_1_H` | Retry after 1 hour | 24 – Retry after 1 hour (insufficient funds) |
| `RETRY_AFTER_24_H` | Retry after 24 hours | 25 – Retry after 24 hours (insufficient funds) |
| `RETRY_AFTER_2_D` | Retry after 2 days | 26 – Retry after 2 days (insufficient funds) |
| `RETRY_AFTER_4_D` | Retry after 4 days | 27 – Retry after 4 days (insufficient funds) |
| `RETRY_AFTER_6_D` | Retry after 6 days | 28 – Retry after 6 days (insufficient funds) |
| `RETRY_AFTER_8_D` | Retry after 8 days | 29 – Retry after 8 days (insufficient funds) |
| `RETRY_AFTER_10_D` | Retry after 10 days | 30 – Retry after 10 days (insufficient funds) |
| `NO_RETRY_POLICY` | No retry policy | 40 – Non‑rechargeable prepaid card |
| `NO_RETRY_SECURITY` | No retry security | 42 – Sanction score exceeded |
| `MULTIPLE_USE_CARD` | Multiple‑use virtual card | 43 – Multiple‑use virtual card |
`PREVENTED` is only applicable to transactions with `type = CHARGEBACK` when the provider/network indicates a predispute deflection. In these scenarios, Yuno emits only the chargeback webhook; no refund webhook is sent.
***
### Chargebacks specific response\_codes
For more details, please refer to the [reason codes page](/docs/reason-codes) in the [Chargeback guides](/docs/chargeback-management) section.
CREATED status details>}>
| response\_code | Category | Description |
| ------------------------------------------------------------------------------------ | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `EMV_LIABILITY_SHIFT_COUNTERFEIT` EMV Liability Shift Counterfeit Fraud | Fraud | The cardholder is claiming that they did not authorize or participate in a transaction that you processed. |
| `EMV_LIABILITY_SHIFT_NOT_COUNTERFEIT` EMV Liability Shift Non-Counterfeit Fraud | Fraud | The cardholder is claiming that they did not authorize or participate in a transaction that you processed. |
| `CARD_PRESENT_FRAUD` Other Fraud – Card-Present Environment | Fraud | The cardholder is claiming that they did not authorize or participate in a key-entered or unattended transaction conducted in a card-present environment. |
| `NON_CARD_PRESENT_FRAUD` Other Fraud – Card-Absent Environment | Fraud | The cardholder did not authorize or participate in a transaction conducted in a card-not-present environment, such as internet, mail-order, phone-order, and others. |
| `SCHEME_MONITORING_PROGRAM` Other Fraud - Scheme Monitoring Program | Fraud | Scheme Fraud Monitoring program |
| `NO_AUTHORIZATION` No Authorization | Authorization | Correct and valid authorization was not obtained by the merchant. |
| `DECLINED_AUTHORIZATION` Declined Authorization | Authorization | Authorization request received a Decline response and the merchant completed the transaction. |
| `LATE_PRESENTMENT` Late Presentment | Processing Errors | The transaction was not sent to Visa within the timeframe required. |
| `INCORRECT_TRANSACTION_CODE` Incorrect Transaction Code | Processing Errors | The cardholder is claiming that the converted amount of charge on an international transaction is incorrect. |
| `INCORRECT_CURRENCY` Incorrect Currency | Processing Errors | The merchant made one or more errors related to the transaction currency |
| `INCORRECT_ACCOUNT_NUMBER` Incorrect Account Number | Processing Errors | The account number in the authorization does not match the account number used in the transaction. |
| `INCORRECT_AMOUNT` Incorrect Amount | Processing Errors | The cardholder is claiming that the amount they agreed to pay differs from the amount charged. |
| `DUPLICATE_PROCESSING` Duplicate Processing/Paid by Other Means | Processing Errors | A single transaction was processed two or more times. |
| `INVALID_DATA` Invalid Data | Processing Errors | The authorization was obtained using invalid or incorrect data. |
| `PRODUCT_OR_SERVICE_NOT_RECEIVED` Merchandise/Services Not Received | Customer Disputes | The cardholder is claiming that merchandise or services that they ordered were not received. |
| `CANCELED_RECURRING_TRANSACTION` Cancelled Recurring Transaction | Customer Disputes | A recurring transaction was processed after it was cancelled. |
| `PRODUCT_OR_SERVICE_ISSUE` Not as Described or Defective Merchandise/Services | Customer Disputes | The cardholder is claiming the goods were not as described. |
| `COUNTERFEIT_MERCHANDISE` Counterfeit Merchandise | Customer Disputes | The merchandise was identified as counterfeit. |
| `MISREPRESENTATION` Misrepresentation | Customer Disputes | The cardholder’s bank received a notice from the cardholder is claiming misrepresented terms of sale. |
| `CREDIT_NOT_PROCESSED` Credit Not Processed | Customer Disputes | The cardholder’s bank received a notice from the cardholder claiming that they received authorization, credit or voided transaction receipt that has not been processed. |
| `PRODUCT_OR_SERVICE_CANCELED` Cancelled Merchandise/Services | Customer Disputes | The cardholder’s bank received a notice from the cardholder stating that they returned merchandise or cancelled services, but the credit has not appeared on the cardholder’s Visa statement. |
| `ORIGINAL_TRANSACTION_NOT_ACCEPTED` Original Credit Transaction Not Accepted | Customer Disputes | The original credit was not accepted. |
| `CASH_TRANSACTION_VALUE` Non-Receipt of Cash or Load Transaction Value | Customer Disputes | Cardholder did not receive the full cash withdrawal at an ATM. |
| `CUSTOMER_AGREEMENT` Proof of customer transaction or agreement required. | Customer Disputes | The issuer asks the merchant for a copy of the receipt signed by the cardholder or any other documentation that verifies the customers agreement for the purchase. Usually to verify a card-present transaction the cardholder disputes or doesn’t recognize. |
# The Payment Object
Source: https://docs.y.uno/reference/payments/the-payment-object
Reference for the payment object fields returned after creating a checkout session.
This object represents the payment created after generating the checkout session for a customer. To refund a payment, see [Refund payments](/docs/refund-payments) and the [Refund payment](/reference/refund-payment) API.
**Metadata and routing logic**
For routing logic to work correctly, metadata must **also** be set at the [Checkout Session](/reference/the-checkout-session-object) level. Setting it only on the Payment object will not trigger route logic.
The unique identifier of the customer (MAX 64 ; MIN 36).
Example: 8546df3a-b83e-4bb5-a4b3-57aa6385924f
The unique identifier of the account (MAX 64; MIN 36).
Example: 9104911d-5df9-429e-8488-ad41abea1a4b
The description of the payment (MAX 255; MIN 3).
Example: Purchase on web
Country where the transaction must be processed (MAX 2; MIN 2; ISO 3166-1 ).
Possible enum values: Check the Country reference.
The status of the transaction.
Example: SUCCEEDED
It is a complement to the status information.
Example: DECLINED
The unique identifier of the customer's order (MAX 255; MIN 3).
Example: 0000023
The date and time when the payment was created.
Example: 2022-05-09T20:46:54.786342Z
The date and time of last update for the payment.
Example: 2022-05-09T20:46:54.786342Z
optional
The idempotency key sent when creating the payment; present when the payment was created with an idempotency key.
Example: fc0d89a1-8d18-4759-8d0a-ee1c6d0386e2
optional
The account code associated with the payment (account identifier).
Example: 26a6626c-d3ec-4caa-bf7c-a994b145dc00
optional
Present when the payment was created via a payment link; identifies the payment link used.
Example: (empty string when not from a payment link)
optional
Present when the payment is associated with a subscription; the subscription identifier.
Example: null
optional
Indicates whether the payment was created in simplified mode (e.g. for certain flows such as subscription or retry).
Example: false
Specifies the payment amount object, with the value and currency.
The currency used to make the payment (MAX 3; MIN 3; ISO 4217 ).
Possible enum values: Check the Country reference.
The payment amount (multiple of 0.0001).
Example: 111111
Specifies the currency conversion object.
The unique identifier of the conversion rate query from the provider (MAX 526 ; MIN 3).
Example: 9104911d-5df9-429e-8488-ad41abea1a4b
The currency to make the conversion (ISO 4217 MAX 3; MIN 3).
Example: USD
Amount of the payment before conversion
Example: 100
The refund amount (multiple of 0.0001).
Example: 111111
The captured amount (multiple of 0.0001).
Example: 111111
Specifies the checkout object. This object is not mandatory for back to back payments. Required when
`WORKFLOW` is defined as `CHECKOUT` or is not sent. Not required for `DIRECT`
payments.
The checkout session has been created for the payment (MAX 64; MIN 36).
Example: 757eefc7-e28c-4333-9a07-3b16e610745d
Defines if the payment is asynchronous and requires additional steps based on a request to the SDK.
Example: false
Specifies a list of custom key–value pairs associated with the payment (for internal references, segmentation, or workflow tags). You can add up to 120 metadata objects.
Specifies a metadata key and the respective value.
Use to attach merchant-defined context (for example: `order_id`, `customer_tier`). Avoid sending sensitive or personal data.
Specifies one metadata key (MAX 48).
Example: age
Specifies the value for the defined metadata key (MAX 512).
Example: 28
Specifies the payment\_method object.
The vaulted\_token represents a securely stored payment\_method associated with a previous transaction. When
utilizing a vaulted\_token for creating a payment, there is no need to send an additional token; it can be set as
null (MAX: 64; MIN: 36).
This field is returned in the payment response when `vault_on_success = true` and the payment status is `SUCCEEDED`, provided the payment references an existing Yuno customer through `customer_payer.id`.
Example: 8604911d-5ds9-229e-8468-bd41abear14s
Payment method type. Mandatory for `DIRECT` or `REDIRECT` workflow. Required when integrating wallets, even when using the SDK.
Possible enum values:
Possible enum values: check the payment type reference.
Flag to enroll the card after a successful payment. Requires the payment to reference an existing Yuno customer through `customer_payer.id` .
When set to `true` and the payment status is `SUCCEEDED`, the payment response will include a `vaulted_token` that can be used for future transactions. Without a customer ID no vaulting occurs and no `vaulted_token` is returned, even if customer details are included inline.
Possible values: `True` or `False`
The one time use payment method token provided by Yuno sdk . If a payment is created using a token,
it is not necessary to send a vaulted\_token as well, it can be defined as null. Not necessary for back to back
payments (MAX: 64; MIN: 36).
Example: 5104911d-5df9-229e-8468-bd41abea1a4s
Specifies the payment method detail object, which provides details of the different transaction category
types that are part of the payment method object.
Specifies the details of the payment method when using a card.
Using amount = 0 and verify = true, you can verify the user's card without authorizing a real
amount.
Possible values: `True` or `False`
Decides whether to authorize the payment or capture it. Authorizing a card payment allows you to
reserve funds in a customer's bank account.
Possible values: `True` or `False`
The card installments (MAX 50; MIN 1).
Example: 3
Number of months to wait to debit the first installment.
Example: 1
Defines the type of installments.
Example: string
The installment amount includes interests associated with the installment and the information is
defined by the provider.
Example: 3
The descriptor passed per transaction to out platform. It will be presented on the customer's
physical bank statement (MAX 15; MIN 0).
Example: COMPANY1
The acquirer's response code.
Example: 742A64
The unique identifier assigned by an acquirer to an authorization. In case of Brazil, you'll receive the nsu.
Example: 200000000012
The unique identifier assigned by the card acquirer to track the transaction through the card network. Used for reconciliation and chargebacks.
For providers that return an acquirer reference (for example, Adyen), this field carries that value, and `retrieval_reference_number` may be empty for those providers.
Example: 7C9F8E2A1B3D
The unique identifier of the payment receipt assigned by the issuing bank for a card transaction.
This field is empty if the gateway does not provide information about the transaction (MAX 255; MIN 3).
Example: 43564
Specifies the details of the card.