Skip to main content

Overview

Card payments are the most widely used payment method on Yuno, supporting Visa, Mastercard, Amex, and local card brands across all supported countries. This guide covers the full card payment lifecycle, from tokenization through authorization, capture, and recurring payments.

Card Payment Flow

A typical card payment follows these steps:
  1. Tokenize the card using the Yuno SDK (client-side) to obtain a one-time token
  2. Create a payment using the token via the API (server-side)
  3. Handle 3DS if a challenge is triggered (automatic via SDK)
  4. Receive confirmation via synchronous response and webhook
Sending raw card numbers via the API requires PCI DSS Level 1 compliance. Use the Yuno SDK tokenization flow to keep your integration out of PCI scope.

Tokenization

One-Time Tokens (SDK)

The Yuno Web or Mobile SDK collects card details in a secure iframe and returns a one-time token. This token is valid for a single payment and expires after 10 minutes.
// Client-side: Initialize Yuno SDK and tokenize
const yuno = await Yuno.initialize({
  publicApiKey: 'your-public-api-key',
  countryCode: 'US',
});

const token = await yuno.createToken({
  cardNumber: '4111111111111111',
  expirationMonth: '12',
  expirationYear: '2028',
  securityCode: '123',
  holderName: 'JOHN SMITH',
});
// Use token.token in the server-side payment request

Vaulted Tokens (Returning Customers)

To save a card for future use, include vaulted_token: true and a customer_id in the payment request. The response returns a vaulted_token_id that can be used for subsequent payments without re-entering card details.
{
  "payment_method": {
    "type": "CARD",
    "token": "one-time-token",
    "vaulted_token": true
  },
  "customer_id": "cust_abc123"
}
For subsequent payments, use the vaulted token directly:
{
  "payment_method": {
    "type": "CARD",
    "vaulted_token_id": "vt_xyz789"
  }
}

Creating a Card Payment

const response = await fetch('https://api-sandbox.y.uno/v1/payments', {
  method: 'POST',
  headers: {
    'public-api-key': process.env.YUNO_PUBLIC_KEY,
    'private-secret-key': process.env.YUNO_PRIVATE_KEY,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    checkout_session: 'session-id',
    payment_method: {
      type: 'CARD',
      token: 'one-time-token-from-sdk',
    },
    amount: { currency: 'USD', value: 50.00 },
    country: 'US',
    customer: {
      email: 'customer@example.com',
      first_name: 'Dee',
      last_name: 'Hock',
    },
    description: 'Order #123',
  }),
});
const payment = await response.json();

Card Payment (Europe)

Node.js
const response = await fetch('https://api-sandbox.y.uno/v1/payments', {
  method: 'POST',
  headers: {
    'public-api-key': process.env.YUNO_PUBLIC_KEY,
    'private-secret-key': process.env.YUNO_PRIVATE_KEY,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    checkout_session: 'session-id',
    payment_method: {
      type: 'CARD',
      token: 'one-time-token-from-sdk',
    },
    amount: { currency: 'EUR', value: 50.00 },
    country: 'DE',
    customer: {
      email: 'customer@example.com',
      first_name: 'Hans',
      last_name: 'Mueller',
      billing_address: {
        address_line_1: 'Friedrichstrasse 100',
        city: 'Berlin',
        country: 'DE',
        zip_code: '10117',
      },
    },
    description: 'Order #456',
  }),
});
const payment = await response.json();
In Europe, 3DS authentication is mandatory under PSD2/SCA regulations. Yuno handles this automatically when the issuer requires it.

3DS Authentication

Yuno handles 3D Secure (3DS) automatically when required by the card issuer or configured by the merchant.

How It Works

  1. Frictionless flow: The issuer authenticates the cardholder without interaction. The payment proceeds automatically and the response includes three_d_secure.status = "AUTHENTICATED".
  2. Challenge flow: The issuer requires cardholder verification (OTP, biometric, or password). The Yuno SDK renders the challenge UI automatically. After the cardholder completes the challenge, the payment continues.

3DS Response Fields

{
  "payment_method": {
    "three_d_secure": {
      "version": "2.2.0",
      "status": "AUTHENTICATED",
      "eci": "05",
      "cavv": "AAABBBCCCDDDeeeFFFF"
    }
  }
}
FieldDescription
version3DS protocol version (2.1.0 or 2.2.0)
statusAUTHENTICATED, ATTEMPTED, FAILED, REJECTED
eciElectronic Commerce Indicator
cavvCardholder Authentication Verification Value
3DS is mandatory in certain markets (e.g., Europe under PSD2). Yuno applies 3DS rules based on your merchant configuration and the issuer’s requirements. Configure 3DS preferences in Dashboard > Settings > Security.

Card Brand Detection and Routing

Yuno automatically detects the card brand from the BIN (first 6-8 digits) and routes the transaction to the optimal provider based on your routing rules.
BIN RangeBrand
4xxxxxVisa
51-55xxxx, 2221-2720Mastercard
34xxxx, 37xxxxAmerican Express
6011, 644-649, 65xxxxDiscover
3528-3589JCB
62xxxxUnionPay
300-305, 36xxxx, 38xxxxDiners Club
636368, 438935, 504175Elo (Brazil)
606282Hipercard (Brazil)
60xxxx, 65xxxx, 81xxxx, 82xxxxRuPay (India)
4xxxxx, 5xxxxx (FR-issued)Cartes Bancaires (France)
2200-2204Mir (Russia)
9792Troy (Turkey)
6054, 6062Naranja (Argentina)
603493Cabal (Argentina)
5895, 6042, 6043Redcompra (Chile)
Configure provider routing rules in Dashboard > Routing to prioritize providers by card brand, country, or amount.

Authorization vs. Capture

By default, card payments are authorized and captured in a single step. For two-step flows (hold funds, then capture later), set capture: false:
{
  "payment_method": { "type": "CARD", "token": "token-id" },
  "amount": { "currency": "USD", "value": 100.00 },
  "capture": false
}
  • Authorize: Validates the card and holds funds. Payment status is AUTHORIZED.
  • Capture: Settles the held funds. Use POST /v1/payments/{id}/capture.
  • Void: Release held funds without capturing. Use POST /v1/payments/{id}/cancel.
Authorizations typically expire after 7 days (varies by issuer). Capture before expiration to avoid auth reversals. See the Capture and Cancel guide for details.

AVS and CVV Verification

Address Verification Service (AVS) and CVV verification provide additional fraud signals:
CheckResult CodesDescription
AVSMATCH, PARTIAL, NO_MATCH, NOT_SUPPORTEDCompares billing address with issuer records
CVVMATCH, NO_MATCH, NOT_PROCESSEDValidates the card security code
AVS and CVV results are returned in the payment response under payment_method.verification:
{
  "payment_method": {
    "verification": {
      "avs_result": "MATCH",
      "cvv_result": "MATCH"
    }
  }
}

Customer-Initiated vs. Merchant-Initiated Transactions

Card networks distinguish between Customer-Initiated Transactions (CIT) and Merchant-Initiated Transactions (MIT). Correctly flagging these improves approval rates and ensures compliance.

CIT (Customer-Initiated)

The cardholder actively authorizes the payment. E.g., entering card details at checkout or clicking “Pay Now” with a saved card. CITs typically have higher approval rates because the issuer can verify the cardholder is present.

MIT (Merchant-Initiated)

The merchant charges a stored card without the cardholder being present. E.g., recurring billing, subscription renewals, or delayed charges. MITs require:
  • A prior CIT that established the stored credential agreement
  • The network_transaction_id from the initial CIT
  • Proper stored_credential flags in the API request
Incorrectly flagging an MIT as a CIT (or vice versa) can result in higher decline rates, compliance violations, and potential fines from card networks. Always use the stored_credential object to flag transaction types correctly.

Recurring Card Payments

For subscriptions and recurring billing, use stored credentials with the appropriate transaction type. See Stored Credentials for the full framework. The initial payment (cardholder-initiated):
{
  "payment_method": {
    "type": "CARD",
    "token": "one-time-token",
    "vaulted_token": true
  },
  "stored_credential": {
    "type": "RECURRING",
    "initiator": "CARDHOLDER"
  },
  "customer_id": "cust_abc123"
}
Subsequent payments (merchant-initiated):
{
  "payment_method": {
    "type": "CARD",
    "vaulted_token_id": "vt_xyz789"
  },
  "stored_credential": {
    "type": "RECURRING",
    "initiator": "MERCHANT",
    "network_transaction_id": "ntid-from-initial-payment"
  }
}
Always store the network_transaction_id returned in the initial CIT payment response. This identifier enables: (1) higher approval rates on subsequent MIT charges, (2) the ability to switch payment providers without re-enrolling the card, and (3) compliance with Visa and Mastercard stored credential mandates.
Card networks (Visa, Mastercard) mandate that merchants pass stored credential indicators for all recurring and merchant-initiated transactions. Non-compliance may result in higher decline rates or penalties.

Card Response Handling

Success

A successful card payment returns status SUCCEEDED (auto-capture) or AUTHORIZED (manual capture):
{
  "id": "pay_abc123",
  "status": "SUCCEEDED",
  "payment_method": {
    "type": "CARD",
    "brand": "VISA",
    "last_four": "1111",
    "verification": { "avs_result": "MATCH", "cvv_result": "MATCH" },
    "three_d_secure": { "version": "2.2.0", "status": "AUTHENTICATED", "eci": "05" }
  }
}

Common Decline Reasons

Decline CodeMeaningRetryable?Suggested Action
INSUFFICIENT_FUNDSCard has insufficient balanceYes (soft decline)Ask customer to use another card or try later
DO_NOT_HONORIssuer declined without specific reasonMaybeRetry once; if repeated, ask customer to contact issuer
EXPIRED_CARDCard has expiredNo (hard decline)Ask customer to update card details
STOLEN_CARDCard reported stolenNo (hard decline)Do not retry; flag for review
INVALID_CVVCVV mismatchNoAsk customer to re-enter card details
3DS_AUTHENTICATION_FAILEDCardholder failed 3DS challengeNoAsk customer to retry or use another card

3DS Challenge Response

When 3DS requires a challenge, the initial response includes redirect information. The Yuno SDK handles this automatically, but for Direct API integrations:
{
  "id": "pay_abc123",
  "status": "PENDING",
  "payment_method": {
    "three_d_secure": {
      "status": "CHALLENGE_REQUIRED",
      "redirect_url": "https://acs.issuer.com/challenge/..."
    }
  }
}
Redirect the customer to redirect_url. After completing the challenge, the payment status updates via webhook.