Integration GuideAPI Reference
Integration Guide

H2H: Card Tokenization via API

Save a customer's card and receive a paymentInstrumentToken starting with pi_. Use this token for future CIT and MIT payments and to list, retrieve or delete saved cards.

You can save a card during a purchase or authorise it without a purchase. A successful payment and a successful card save are separate results: check both before offering the saved card to the customer.

For saving cards on a hosted form, see Payment Instrument Tokenization in Checkout.

Before you start

📘

Ask the integration team to enable H2H tokenization for your settlement account. Card saving in Hosted Checkout is enabled separately in the checkout configuration.

Endpoint paths below are relative to the processing base URL for your environment. See Access URLs and API Authentication.

Request headers
HeaderValue
AuthorizationBearer <access_token>
settlement-account-idYour settlement account ID, such as SA204264682781298688
Content-Typeapplication/json for requests with a JSON body

Supported methods

Availability depends on the methods enabled for your account. Card saving and payment by token have separate availability.

Payment methodSave a cardCIT by tokenMIT by token
BankCardRUSupportedSupportedSupported
BankCardKZSupportedNot availableNot available
BankCardUZSupportedNot availableNot available

The examples use BankCardRU and RUB.

Identifiers and token scope

IdentifierPurpose
paymentInstrumentTokenThe reusable saved-card token, such as pi_01J8ZC4M7QK3T5V9XB2NDR6HAG. Supply it to pay with or manage the saved card
paymentInstrument.idThe instrument identifier returned with a payment, such as PI204264682781298690. It is not the reusable pi_ token
merchantPayerReferenceYour stable customer identifier. Required when saving a card or paying by token. Use a nonblank string of up to 256 characters and keep the value unchanged for the same customer
payerIdThe platform's payer identifier, starting with PAYR. An alternative customer selector for the saved-card list and deletion endpoints
settlement-account-idThe account within which the card is saved and used
clientReferenceIdYour reference for a particular Intent. Use a new value for a new Intent; this is separate from the stable customer reference
Intent and payment IDsPlatform identifiers of individual operations. Use them to retrieve results and manage the relevant payment
API access tokenThe credential used in the Authorization header. It is separate from the saved-card token

A saved card belongs to a settlement account and a merchantPayerReference. A token saved for customer 12345 in account A cannot be used for another customer or account B. Use the payment method associated with that token. Sandbox and production tokens are separate.

Send the customer reference belonging to the authenticated user in your application. Your application is responsible for mapping its users to the correct references.

Saving lifecycle

This diagram shows a typical asynchronous flow. The initial response may also contain an already available result.

sequenceDiagram
    participant Customer
    participant Merchant
    participant API as Payment API
    Merchant->>API: POST Intent with savePaymentInstrument=true
    API-->>Merchant: Intent and payment IDs, savingRequested=true
    opt Cardholder verification required
        Merchant->>Customer: Open the returned verification URL
        Customer->>API: Complete verification, including 3DS if required
    end
    Note over API: Successful authorisation allows card saving
    par Saving
        API->>API: Record the card-saving result
    and Payment notification
        API-->>Merchant: Webhook, saving result may still be pending
    end
    Merchant->>API: GET Intent or payment
    API-->>Merchant: Payment status and current saving result
    Note over Merchant: Check isSaved and paymentInstrumentToken separately from payment status

Save a card during a payment

Create an Intent containing a card payment. Set savePaymentInstrument to true on the payment and pass payer.merchantPayerReference.

This example covers a standard card payment. Include any additional fields required by your account, business category or payment method.

Endpoint: POST /api/v1/intents

{
  "clientReferenceId": "order-1001",
  "payments": [
    {
      "payer": {
        "merchantPayerReference": "12345"
      },
      "paymentInstrument": {
        "paymentMethodName": "BankCardRU",
        "incomingDetails": {
          "number": "4462603043025620",
          "expiryMonth": "12",
          "expiryYear": "2028",
          "cvv": "123",
          "holderName": "TEST CUSTOMER",
          "redirectUrl": "https://merchant.example/payment/return",
          "failureUrl": "https://merchant.example/payment/failure"
        }
      },
      "submittedAmount": {
        "value": 100,
        "currency": "RUB"
      },
      "authCurrencyCode": "RUB",
      "savePaymentInstrument": true,
      "webhookUrl": "https://merchant.example/webhooks/payments"
    }
  ]
}
Intent request body
FieldDescription
clientReferenceIdYour reference for this Intent. Use a new value for a new Intent
paymentsThe payment array. This example creates one card payment
payments[]
FieldDescription
savePaymentInstrumentSet to true to request saving after authorisation
payerThe customer to whom the saved card will belong
paymentInstrumentThe payment method and card details
submittedAmount, authCurrencyCodeThe amount and currency information, described below
webhookUrlYour endpoint for payment notifications
payments[].payer
FieldDescription
merchantPayerReferenceRequired for saving. Your stable, nonblank customer reference, up to 256 characters

Include any additional payer fields required by the payment method or your account.

payments[].paymentInstrument
FieldDescription
paymentMethodNameBankCardRU in this example
incomingDetailsCard details and return URLs for this authorisation

A new-card saving request does not contain paymentInstrumentToken or tokenPaymentReason.

payments[].paymentInstrument.incomingDetails
FieldDescription
numberThe card number. The example uses a sandbox test card
expiryMonth, expiryYearStrings in MM and YYYY format
cvv, holderNameCard verification and cardholder data for the initial authorisation
redirectUrl, failureUrlURLs used by the BankCardRU payment flow

See BankCardRU for the complete method-specific requirements and test data.

payments[].submittedAmount and authCurrencyCode
FieldDescription
submittedAmount.valueThe amount submitted for the payment
submittedAmount.currencyThe submitted currency code; RUB in this example
authCurrencyCodeThe authorisation currency code; RUB in this example

The ordinary payment amount and currency rules apply. For binding without a purchase, see the zero amount and nonzero authorisation flows.

Open the returned additionalData.details.url and follow the BankCardRU authorisation flow. This step is required even if the customer is not asked to complete a 3DS challenge. The example URL is illustrative.

⚠️

Do not combine savePaymentInstrument: true with a payment by an existing token. An HTTP success response alone does not confirm that the card was saved.

Retrieve the saving result

The platform saves the card after successful authorisation. You can read the result using GET /api/v1/intents/{intentId} or GET /api/v1/payments/{paymentId}. The result can also appear in a payment webhook.

Endpoint: GET /api/v1/intents/204264682781298700

No request body is required. Use the request headers described above.

Path parameters
ParameterDescription
intentIdThe Intent ID returned by POST /api/v1/intents

Keep the returned token with the corresponding customer and settlement account. Do not infer saving success from the payment status or from the presence of masked card details.

Receive the result by webhook

Payment webhooks can include the same saving fields. The following event excerpt illustrates a payment notification after a purchase has completed and the card has been saved:

{
  "transactionType": "PAYMENT",
  "transactionId": "204264682781298701",
  "intentId": "204264682781298700",
  "status": "CAPTURED",
  "isStoredCredential": false,
  "paymentInstrument": {
    "paymentMethodName": "BankCardRU",
    "savingRequested": true,
    "isSaved": true,
    "paymentInstrumentToken": "pi_01J8ZC4M7QK3T5V9XB2NDR6HAG"
  }
}
Payment webhook fields
FieldDescription
transactionTypePAYMENT for a payment notification
transactionIdThe payment ID
intentIdThe containing Intent ID
statusThe payment status; this example shows a completed purchase
isStoredCredentialWhether the payment used a previously saved card. It does not indicate whether this payment saved a new card
paymentInstrument

The webhook's top-level paymentInstrument contains the same saving fields described under Retrieve the saving result: savingRequested, isSaved, paymentInstrumentToken and, when applicable, notSavedReason. It can also identify the payment method.

In this example, isSaved: true and paymentInstrumentToken confirm the available saved-card record.

⚠️

A payment webhook, including one reporting AUTHORIZED or CAPTURED, may be sent before the saving result is available. If it reports savingRequested: true without isSaved or a token, retrieve the updated Intent or payment. Do not rely on a separate card-saved notification.

See Webhooks for delivery and handling rules.


Save a card without a purchase

Zero amount authorisation

For BankCardRU, authorise an amount of zero with savePaymentInstrument: true. This verifies and saves the card without reserving a purchase amount.

Endpoint: POST /api/v1/intents

{
  "clientReferenceId": "card-binding-1001",
  "payments": [
    {
      "payer": {
        "merchantPayerReference": "12345"
      },
      "paymentInstrument": {
        "paymentMethodName": "BankCardRU",
        "incomingDetails": {
          "number": "4462603043025620",
          "expiryMonth": "12",
          "expiryYear": "2028",
          "cvv": "123",
          "holderName": "TEST CUSTOMER",
          "redirectUrl": "https://merchant.example/cards/return",
          "failureUrl": "https://merchant.example/cards/failure"
        }
      },
      "submittedAmount": {
        "value": 0,
        "currency": "RUB"
      },
      "authCurrencyCode": "RUB",
      "savePaymentInstrument": true,
      "webhookUrl": "https://merchant.example/webhooks/payments"
    }
  ]
}
payments[].submittedAmount and saving fields
FieldValue for zero amount binding
submittedAmount.value0
submittedAmount.currencyRUB
authCurrencyCodeRUB
savePaymentInstrumenttrue

The payer and paymentInstrument objects follow the saving request above. Use a new top-level clientReferenceId for this Intent.

Open the returned URL and complete the authorisation flow, then retrieve the saving result using this operation's Intent or payment ID. A successful zero amount authorisation uses the normal AUTHORIZED status. Check paymentInstrument.isSaved and paymentInstrument.paymentInstrumentToken separately; authorisation success does not guarantee saving success.

📘

After a successful zero amount authorisation, no capture or cancellation request is required.


Authorisation with a nonzero amount

You can also save the card using a temporary authorisation for a nonzero amount supported by your account. Use the same saving request with a nonzero amount and a new clientReferenceId.

⚠️

After successful authorisation, you must cancel the authorisation to release the hold, whether or not saving succeeded.

Endpoint: PATCH /api/v1/payments/{paymentId}

{
  "status": "CANCELLED"
}
Path parameters
ParameterDescription
paymentIdThe ID returned in payments[].id for the nonzero card-binding authorisation
Request body
FieldValue
statusCANCELLED, requesting release of the authorisation

See Cancel Authorized Amount for the cancellation endpoint and conditions.


When saving does not succeed

A payment can succeed while saving the card fails. For example, an otherwise successful payment may contain this result excerpt:

{
  "paymentInstrument": {
    "savingRequested": true,
    "isSaved": false,
    "notSavedReason": "LIMIT_REACHED"
  }
}
paymentInstrument.notSavedReason
notSavedReasonMeaning and next step
LIMIT_REACHEDThe customer's saved-card limit has been reached. An existing card can be removed before saving another
CAPABILITY_DISABLEDCard saving is not enabled for this account or flow. Contact the integration team
TEMPORARY_ERRORSaving could not be completed. Check the payment result independently; do not repeat the purchase just to obtain a token
AUTH_DECLINEDAuthorisation failed, so the card was not saved. Use the payment's decline information

For H2H, the default limit is five usable saved cards per customer within a settlement account. The integration team can configure the limit from 1 to 100. It is shared across payment methods. Deleted cards and cards recognised as invalid do not consume a place in this limit.

Reusing and managing a saved card

Saving a card that is already saved for the same customer and settlement account returns the existing token. Saving the card again after deleting its token produces a new token.

After deletion, reading the original saving payment can show isSaved: false. A historical payment response is not proof that its token is still usable; retrieve the saved card to check its current state.

The token has no fixed expiry period of its own. It may stop being usable if it is deleted or the underlying card becomes unavailable. A saved card's ACTIVE status does not guarantee that a payment will be approved; validity also depends on the issuing bank and payment method.

Cards saved through Hosted Checkout can be retrieved and used through the API for the same settlement account and merchantPayerReference, with H2H tokenization enabled and a supported payment method. The same saved-card collection is available to Checkout when its saving feature is enabled. You do not need to collect the card details again solely because the integration channel changes.

Continue with Payments with Saved Cards or Manage Saved Cards.


Did this page help you?