Classic Cloud Token Framework
Overview
The Cloud Token Framework (CTF) is the framework for binding a device and a network token. CTF enables merchants to perform one-time issuer identification and verification and securely binds a user's device to a Visa network token. CTF reduces fraud rates and improves transaction conversion.
Use Classic CTF when your app requires device-level cryptographic binding to a Visa network token in a mobile in-app environment. If your integration instead requires FIDO-based passkey authentication for e-commerce checkout (browser or mobile web), use Payment Passkey instead.
Prerequisites
To send device binding requests, you must have a self-signed certificate associated with your merchant account. See Cloud Token Framework Key Generation.
A token requestor must pass local authentication information. The token requestor can select up to two of these authentication factors for the cardholder to verify their identity at checkout:
Knowledge — Knowledge verification factors include information that only the cardholder knows. For example, a password.
Possession — Possession verification factors include something that only the cardholder has. For example, a pre-registered mobile phone, a card reader, or a key generation device.
Inherence — Inherence verification factors include something that the cardholder is. For example, biometric data. Biometric data includes facial recognition, a fingerprint, voice recognition, or a behavioral biometric.
Cloud Token Framework Key Generation
Follow these steps to generate the credentials required to send device binding requests:
When you follow these steps you create these files:
root-ca-private-key.pemroot-ca-certificate.pemdevice-signing-private-key.pemdevice-signing.csrdevice-signing-certificate.pem
| File Name | Description and Usage |
|---|---|
root-ca-private-key. | Private CA key. Keep this key offline and do not share it. |
root-ca-certificate. | Self-signed CA public certificate. This certificate must be associated with the token requestor account to establish the trust anchor for device-issued certificates. |
device-signing-private-key. | Device-signing private key. This key stays on the device or secure storage and is used to sign the authenticatedIdentities data that is sent in these API requests: POST /tms/v2/tokenized-cards/{id}/bindings, POST /tms/v2/tokens/{id}/payment-credentials, POST /pts/v2/payments |
device-signing. | Certificate signing request (CSR) for the device-signing key. This can be discarded post-issuance. |
device-signing-certificate. | Issued device-signing certificate. This certificate is submitted in the POST /tms/v2/devices API request. |
Create Your Master Key and Certificate
Create your master key (root-ca-private-key.pem) and certificate (root-ca-certificate.pem).
Example command:
# Private CA key (keep offline, never share)openssl genrsa -out root-ca-private-key.pem 2048# Self-signed CA certificate (public) with proper CA extensionsopenssl req -x509 -new -nodes -key root-ca-private-key.pem -days 3650 -out root-ca-certificate.pemGenerate a Signing Key Pair for Each Device
Generate a signing key pair for each device. This creates device-signing-private-key.pem, device-signing.csr, and device-signing-certificate.pem.
# Device signing private keyopenssl genrsa -out device-signing-private-key.pem 2048# Certificate signing request (CSR) for the device signing keyopenssl req -new -key device-signing-private-key.pem -out device-signing.csr# Issue the device signing certificate from your CAopenssl x509 -req -in device-signing.csr -CA root-ca-certificate.pem -CAkey root-ca-private-key.pem -CAcreateserial -out device-signing-certificate.pem -days 500 -outform PEM(Optional) Validate Your Certificates
Validate your certificates.
Example command:
# Verify that device-signing-certificate.pem chains to root-ca-certificate.pemopenssl verify -CAfile root-ca-certificate.pem device-signing-certificate.pem# Verify that data signed with device-signing-private-key.pem matches device-signing-certificate.pemopenssl x509 -in device-signing-certificate.pem -pubkey -noout > device-signing-public-key.pemecho 'test' > message.txtopenssl dgst -sha256 -sign device-signing-private-key.pem -out message.sig message.txtopenssl dgst -sha256 -verify device-signing-public-key.pem -signature message.sig message.txtEndpoints
Production:
POST /tms/v2/devicesPOST /tms/v2/tokenized-cards/{id}/bindingsPOST /tms/v2/tokens/{id}/payment-credentialsDELETE /tms/v2/tokenized-cards/{id}/bindings/{clientDeviceID}POST /pts/v2/paymentsTest:
POST /tms/v2/devicesPOST /tms/v2/tokenized-cards/{id}/bindingsPOST /tms/v2/tokens/{id}/payment-credentialsDELETE /tms/v2/tokenized-cards/{id}/bindings/{clientDeviceID}POST /pts/v2/paymentsBind a Device
This section contains the information required to bind a device to a network token.
Device Binding Workflow
- The customer sends a request to the merchant that they consent to bind the device.
- If the device is not enrolled, the merchant sends a request to to enroll the device.
- Test:
POST {{token:api-test-url-rest}}/tms/v2/devices
- Test:
- If the device is enrolled, the merchant sends a request to to bind the device using the device ID.
- Test:
POST {{token:api-test-url-rest}}/tms/v2/tokenized-cards/{id}/bindings
- Test:
- sends a binding request to the issuer with the binding ID.
- The issuer sends a response to with the binding status.
- If authentication is valid, binds the token to the device.
- The issuer notifies that binding was successful.
- sends a response to the merchant that the binding is completed.
- The merchant notifies the customer that their device binding is complete.
Create a Device
This section describes how to create a device.
Endpoint
POST /tms/v2/devices
POST /tms/v2/devices
POST /tms/v2/devices
POST /tms/v2/devices
POST /tms/v2/devices
Example
{ "clientDeviceID": "<CLIENT_DEVICE_ID>", "clientDeviceName": "U0lUIERldmljZSBqV0JW", "category": "PHONE", "manufacturer": "Apple", "brand": "iPhone", "model": "iPhone 15 Pro Max", "operatingSystem": { "type": "IOS", "version": "26.1", "buildId": "23B5044I" }, "certificates": [ { "usage": "SIGNATURE", "format": "X509_PEM", "value": "<DEVICE_CERTIFICATE>" }, { "usage": "ENCRYPTION", "format": "X509_PEM", "value": "<DEVICE_CERTIFICATE>" } ]}A successful request returns an empty HTTP 204 No Content status.
Required Fields for Create a Device
clientDeviceID
clientDeviceName
category
operatingSytem.type
certificates[].buildId
certificates[].format
certificates[].value
Optional Fields for Create a Device
manufacturer
brand
model
operatingSytem.version
operatingSytem.buildId
Bind the Device
This section describes how to bind a device.
Endpoint
POST /tms/v2/tokenized-cards/{id}/bindings
POST /tms/v2/tokenized-cards/{id}/bindings
POST /tms/v2/tokenized-cards/{id}/bindings
POST /tms/v2/tokenized-cards/{id}/bindings
POST /tms/v2/tokenized-cards/{id}/bindings
Example
{ "authenticatedIdentities": [ { "data": "<JWS>", "provider": "CLIENT_DEVICE_CERT_JWS" } ], "deviceInformation": { "platformType": "WEB" }}{ "action": "BINDING_COMPLETED"}{ "action": "STEP_UP_AUTHENTICATE", "stepUpOptions": [ { "method": "OTP_SMS", "value": "...", "source": "...", "id": "..." }, { "method": "OTP_EMAIL", "value": "...", "source": "...", "id": "..." }, { "method": "OTP_ONLINE_BANKING", "value": "...", "source": "...", "id": "..." }, { "method": "APP_TO_APP", "value": "...", "source": "...", "id": "...", "requestPayload": "..." }, { "method": "CUSTOMER_SERVICE", "value": "...", "id": "..." }, { "method": "OUTBOUND_CALL", "value": "...", "id": "..." } ]}Required Fields for Bind the Device
deviceInformation.platformType
authenticatedIdentities.data
When authenticatedIdentities.provider is set to CLIENT_DEVICE_CERT_JWS, this field is a JSON Web Signature (JWS). When authenticatedIdentities.provider is set to VISA_PAYMENT_PASSKEY, the value of this field is from the iframe.
authenticatedIdentities.provider
Bind a Device with Step-Up Authentication
This section contains the information required to bind a device to a network token with step-up authentication.
Device Binding Workflow with Step-Up Authentication
- The customer sends a request to the merchant that they consent to bind the device.
- If the device is not enrolled, the merchant sends a request to to enroll the device.
- Test:
POST {{token:api-test-url-rest}}/tms/v2/devices
- Test:
- If the device is enrolled, the merchant sends a request to to bind the device using the device ID.
- Test:
POST {{token:api-test-url-rest}}/tms/v2/tokenized-cards/{id}/bindings
- Test:
- sends a binding request to the issuer with the binding ID.
- The issuer sends a response to with a step-up authentication binding status.
- sends a request to the issuer for authentication methods.
- The issuer sends a list of authentication methods that are passed on to the customer.
- The customer selects their authentication method and it is sent to the issuer.
- The issuer initiates authentication method.
- If authentication is valid, binds the token to the device.
- The issuer notifies that binding was successful.
- sends a response to the merchant that the binding is completed.
- The merchant notifies the customer that their device binding is complete.
Step-Up Authentication Flow
This workflow shows the possible options for step-up authentication after you send a request to /tokenized-cards/{id}/bindings.
This table lists every step-up method and the authenticatorType value that identifies it:
| Step-Up Method | Description | authenticatorType |
|---|---|---|
| Web Application or Phone | Step-up authentication options available for web applications and phone-based authentication. | APP_TO_APP, CUSTOMER_SERVICE, OUTBOUND_CALL |
| External Web Application | Step-up authentication options available when redirecting to an external web application. | WEB |
| One-Time Passwords (OTP) | Step-up authentication using one-time passwords sent by email, SMS, or issuer account login. | OTP_SMS, OTP_EMAIL, OTP_ONLINE_BANKING |
Select the step-up method that matches the authenticatorType value returned in your binding response to see its complete flow.
Follow these steps to bind a device and network token combination for these step-up methods:
APP_TO_APPCUSTOMER_SERVICEOUTBOUND_CALL
Step 1: Create a Device
Required Fields for Step 1: Create a Device
clientDeviceID
clientDeviceName
category
operatingSytem.type
certificates[].buildId
certificates[].format
certificates[].value
See Create a Device for the full endpoint and example.
Step 2: Bind a Device
Endpoint
POST /tms/v2/tokenized-cards/{id}/bindings
POST /tms/v2/tokenized-cards/{id}/bindings
POST /tms/v2/tokenized-cards/{id}/bindings
POST /tms/v2/tokenized-cards/{id}/bindings
POST /tms/v2/tokenized-cards/{id}/bindings
Required Fields for Step 2: Bind a Device
deviceInformation.platformType
authenticatedIdentities.data
When authenticatedIdentities.provider is set to CLIENT_DEVICE_CERT_JWS, this field is a JSON Web Signature (JWS). When authenticatedIdentities.provider is set to VISA_PAYMENT_PASSKEY, the value of this field is from the iframe.
authenticatedIdentities.provider
The response action field returns BINDING_COMPLETED or STEP_UP_AUTHENTICATE with a stepUpOptions list whose method values include APP_TO_APP, CUSTOMER_SERVICE, and OUTBOUND_CALL for this step-up method. See Bind the Device for the full example.
Follow these steps to bind a device and network token combination for external web application step-up authentication methods.
Step 1: Create a Device
Required Fields for Step 1: Create a Device
clientDeviceID
clientDeviceName
category
operatingSytem.type
certificates[].buildId
certificates[].format
certificates[].value
See Create a Device for the full endpoint and example.
Step 2: Bind a Device
Endpoint
POST /tms/v2/tokenized-cards/{id}/bindings
POST /tms/v2/tokenized-cards/{id}/bindings
POST /tms/v2/tokenized-cards/{id}/bindings
POST /tms/v2/tokenized-cards/{id}/bindings
POST /tms/v2/tokenized-cards/{id}/bindings
Required Fields for Step 2: Bind a Device
deviceInformation.platformType
authenticatedIdentities.data
When authenticatedIdentities.provider is set to CLIENT_DEVICE_CERT_JWS, this field is a JSON Web Signature (JWS). When authenticatedIdentities.provider is set to VISA_PAYMENT_PASSKEY, the value of this field is from the iframe.
authenticatedIdentities.provider
The response action field returns STEP_UP_AUTHENTICATE with a stepUpOptions.method value of WEB to redirect the cardholder to the external web application. See Bind the Device for the full example.
Step 3: Validate the One-Time Password or Issuer Authentication Code
When the cardholder receives their OTP or an issuer authentication code from their banking application, verify it using this endpoint.
Endpoint
POST /tms/v2/tokenized-cards/{tokenId}/authentication-options/validate
POST /tms/v2/tokenized-cards/{tokenId}/authentication-options/validate
POST /tms/v2/tokenized-cards/{tokenId}/authentication-options/validate
POST /tms/v2/tokenized-cards/{tokenId}/authentication-options/validate
POST /tms/v2/tokenized-cards/{tokenId}/authentication-options/validate
The {tokenId} is the identifier of the tokenized card.
{ "clientCorrelationId": "aB3cD4eF5gH6iJ7kL8mN9oP0qR1sT2uV3wX", "stepUpOption": { "id": "YWEwMjFhZmFkZDU4ZWI0NDJjYTM0MzY4OTY1YjdhMDE=" }, "otp": "456789", "issuerAuthCode": "HTZlY2YwOWQ3MDZmYWZj4GMww2Y0YjllZWFkODZkHJI="}{ "action": "AUTHENTICATION_REGISTRATION"}Required Fields for Step 3: Validate the One-Time Password or Issuer Authentication Code
clientCorrelationId
Set to the client reference ID.
issuerAuthCode
Required when otp is not included in the request.
otp
Required when issuerAuthCode is not included in the request.
stepUpOption.id
Follow these steps to bind a device and network token combination with the Visa Payment Passkey for these one-time password methods: OTP_EMAIL, OTP_ONLINE_BANKING, OTP_SMS.
Step 1: Create a Device
Required Fields for Step 1: Create a Device
clientDeviceID
clientDeviceName
category
operatingSytem.type
certificates[].buildId
certificates[].format
certificates[].value
See Create a Device for the full endpoint and example.
Step 2: Bind a Device
Endpoint
POST /tms/v2/tokenized-cards/{id}/bindings
POST /tms/v2/tokenized-cards/{id}/bindings
POST /tms/v2/tokenized-cards/{id}/bindings
POST /tms/v2/tokenized-cards/{id}/bindings
POST /tms/v2/tokenized-cards/{id}/bindings
Required Fields for Step 2: Bind a Device
deviceInformation.platformType
authenticatedIdentities.data
When authenticatedIdentities.provider is set to CLIENT_DEVICE_CERT_JWS, this field is a JSON Web Signature (JWS). When authenticatedIdentities.provider is set to VISA_PAYMENT_PASSKEY, the value of this field is from the iframe.
authenticatedIdentities.provider
The response action field returns STEP_UP_AUTHENTICATE with a stepUpOptions.method value of OTP_SMS, OTP_EMAIL, or OTP_ONLINE_BANKING for this step-up method. See Bind the Device for the full example.
Step 3: Send OTP Request
Request a one-time password. The issuer sends the OTP to the cardholder by email, SMS, or issuer account login. Before you send this request, you must receive the STEP_UP_AUTHENTICATE value in the action field from the bind-a-device request.
Endpoint
POST /tms/v2/tokenized-cards/{tokenId}/authentication-options/one-time-passwords
POST /tms/v2/tokenized-cards/{tokenId}/authentication-options/one-time-passwords
POST /tms/v2/tokenized-cards/{tokenId}/authentication-options/one-time-passwords
POST /tms/v2/tokenized-cards/{tokenId}/authentication-options/one-time-passwords
POST /tms/v2/tokenized-cards/{tokenId}/authentication-options/one-time-passwords
The {tokenId} is the identifier of the tokenized card.
{ "clientCorrelationId": "aB3cD4eF5gH6iJ7kL8mN9oP0qR1sT2uV3wX", "stepUpOption": { "id": "YWEwMjFhZmFkZDU4ZWI0NDJjYTM0MzY4OTY1YjdhMDE=" }}{ "maxRequestsAllowed": 0, "maxVerificationAllowed": 0, "codeExpiration": 0}Required Fields for Step 3: Send OTP Request
clientCorrelationId
Set to the client reference ID.
stepUpOption.id
Step 4: Validate the One-Time Password Code
Verify the OTP that the cardholder received.
Endpoint
POST /tms/v2/tokenized-cards/{tokenId}/authentication-options/validate
POST /tms/v2/tokenized-cards/{tokenId}/authentication-options/validate
POST /tms/v2/tokenized-cards/{tokenId}/authentication-options/validate
POST /tms/v2/tokenized-cards/{tokenId}/authentication-options/validate
POST /tms/v2/tokenized-cards/{tokenId}/authentication-options/validate
{ "clientCorrelationId": "aB3cD4eF5gH6iJ7kL8mN9oP0qR1sT2uV3wX", "stepUpOption": { "id": "YWEwMjFhZmFkZDU4ZWI0NDJjYTM0MzY4OTY1YjdhMDE=" }, "otp": "456789", "issuerAuthCode": "HTZlY2YwOWQ3MDZmYWZj4GMww2Y0YjllZWFkODZkHJI="}{ "action": "AUTHENTICATION_REGISTRATION"}Required Fields for Step 4: Validate the One-Time Password Code
clientCorrelationId
Set to the client reference ID.
issuerAuthCode
Required when otp is not included in the request.
otp
Required when issuerAuthCode is not included in the request.
stepUpOption.id
Create Payment Credentials with Device Signed JWS
This section describes how to create payment credentials with device-signed JSON Web Signature (JWS).
Endpoint
POST /tms/v2/tokens/{id}/payment-credentials
POST /tms/v2/tokens/{id}/payment-credentials
POST /tms/v2/tokens/{id}/payment-credentials
POST /tms/v2/tokens/{id}/payment-credentials
POST /tms/v2/tokens/{id}/payment-credentials
Required Fields for Create Payment Credentials with Device Signed JWS
deviceInformation.ipAddress
merchantInformation.merchantDescriptor.name
merchantInformation.merchantDescriptor.url
orderInformation.amountDetails.currency
orderInformation.amountDetails.totalAmount
orderInformation.billTo.address1
orderInformation.billTo.administrativeArea
orderInformation.billTo.country
orderInformation.billTo.email
orderInformation.billTo.firstName
orderInformation.billTo.lastName
orderInformation.billTo.locailty
orderInformation.billTo.postalCode
tokenInformation.tokenAuthenticationInformation.authenticatedIdentities.data
tokenInformation.tokenAuthenticationInformation.authenticatedIdentities.provider
tokenInformation.tokenAuthenticationInformation.authenticatedIdentities.userAuthenticationMethod
Required when tokenInformation.tokenAuthenticationInformation.authenticatedIdentities.provider is set to CLIENT_DEVICE_CERT_JWS.
transactionType
{ "clientReferenceInformation": { "code": "abc" }, "paymentInformation": { "customer": { "id": "<id in payment-credentials url>" } }, "orderInformation": { "amountDetails": { "totalAmount": "<orderInformation.amountDetails.totalAmount>", "currency": "<orderInformation.amountDetails.currency>" }, "billTo": { "firstName": "<orderInformation.billTo.firstName>", "lastName": "<orderInformation.billTo.lastName>", "address1": "<orderInformation.billTo.address1>", "locality": "<orderInformation.billTo.locality>", "administrativeArea": "<orderInformation.billTo.administrativeArea>", "postalCode": "<orderInformation.billTo.postalCode>", "country": "<orderInformation.billTo.country>", "email": "<orderInformation.billTo.email>", "phoneNumber": "<orderInformation.billTo.phoneNumber>" } }, "deviceInformation": { "ipAddress": "<deviceInformation.ipAddress>" }, "merchantInformation": { "merchantDescriptor": { "name": "<merchantInformation.merchantDescriptor.name>", "url": "<merchantInformation.merchantDescriptor.url>" } }, "tokenInformation": { "tokenAuthenticationInformation": { "authenticatedIdentities": [ { "data": "<authenticatedIdentities[].data>", "provider": "CLIENT_DEVICE_CERT_JWS", "userAuthenticationMethod": "<authenticatedIdentities[].userAuthenticationMethod>" } ] } }}Optional Fields for Create Payment Credentials with Device Signed JWS
orderInformation.billTo.firstName
orderInformation.billTo.lastName
orderInformation.billTo.email
orderInformation.billTo.address1
orderInformation.billTo.locality
orderInformation.billTo.administrativeArea
orderInformation.billTo.postalCode
orderInformation.billTo.country
deviceInformation.ipAddress
Delete Binding
This section describes how to delete a device binding.
Endpoint
DELETE /tms/v2/tokenized-cards/{id}/bindings/{clientDeviceID}
DELETE /tms/v2/tokenized-cards/{id}/bindings/{clientDeviceID}
DELETE /tms/v2/tokenized-cards/{id}/bindings/{clientDeviceID}
DELETE /tms/v2/tokenized-cards/{id}/bindings/{clientDeviceID}
DELETE /tms/v2/tokenized-cards/{id}/bindings/{clientDeviceID}
The {id} is the identifier of the tokenized card and {clientDeviceID} is the identifier of the device.
Required Fields for Delete Binding
{id}
Identifier of the tokenized card, included in the URL path.
{clientDeviceID}
Identifier of the device binding to delete, included in the URL path.
Create Payment Credentials with Payment Passkey
This section describes how to create tokenized card payment credentials with Payment Passkey.
Endpoint
POST /pts/v2/payments
POST /pts/v2/payments
POST /pts/v2/payments
Required Fields for Create Payment Credentials with Payment Passkey
authenticatedIdentities.provider
authenticatedIdentities.userAuthenticationMethod
Required if authenticatedIdentities.provider is set to CLIENT_DEVICE_CERT_JWS.
{ "processingInformation": { "authorizationOptions": { "aftIndicator": "<true = transactionType: AFT>" } }, "paymentInformation": { "customer": { "id": "<id in payment-credentials url>" } }, "orderInformation": { "amountDetails": { "totalAmount": "<orderInformation.amountDetails.totalAmount>", "currency": "<orderInformation.amountDetails.currency>" }, "billTo": { "firstName": "<orderInformation.billTo.firstName>", "lastName": "<orderInformation.billTo.lastName>", "address1": "<orderInformation.billTo.address1>", "locality": "<orderInformation.billTo.locality>", "administrativeArea": "<orderInformation.billTo.administrativeArea>", "postalCode": "<orderInformation.billTo.postalCode>", "country": "<orderInformation.billTo.country>", "email": "<orderInformation.billTo.email>", "phoneNumber": "<orderInformation.billTo.phoneNumber>" } }, "deviceInformation": { "ipAddress": "<deviceInformation.ipAddress>", "httpAcceptContent": "<deviceInformation.httpAcceptContent>", "httpBrowserLanguage": "<deviceInformation.httpBrowserLanguage>", "httpBrowserJavaEnabled": "<deviceInformation.httpBrowserJavaEnabled>", "httpBrowserJavaScriptEnabled": "<deviceInformation.httpBrowserJavaScriptEnabled>", "httpBrowserColorDepth": "<deviceInformation.httpBrowserColorDepth>", "httpBrowserScreenHeight": "<deviceInformation.httpBrowserScreenHeight>", "httpBrowserScreenWidth": "<deviceInformation.httpBrowserScreenWidth>", "httpBrowserTimeDifference": "<deviceInformation.httpBrowserTimeDifference>", "userAgentBrowserValue": "<deviceInformation.userAgentBrowserValue>" }, "merchantInformation": { "merchantDescriptor": { "name": "<merchantInformation.merchantDescriptor.name>", "url": "<merchantInformation.merchantDescriptor.url>" } }, "tokenInformation": { "clientCorrelationId": "<clientCorrelationId>", "tokenAuthenticationInformation": { "authenticatedIdentities": [ { "data": "<authenticatedIdentities[].data>", "provider": "<authenticatedIdentities[].provider>", "id": "<authenticatedIdentities[].id>", "relyingPartyId": "<authenticatedIdentities[].relyingPartyId>", "userAuthenticationMethod": "<authenticatedIdentities[].userAuthenticationMethod>" } ] } }}Optional Fields for Create Payment Credentials with Payment Passkey
transactionType
deviceInformation.ipAddress
clientCorrelationId
authenticatedIdentities.data
When authenticatedIdentities.provider is set to CLIENT_DEVICE_CERT_JWS, this field is a JSON Web Signature (JWS). When authenticatedIdentities.provider is set to VISA_PAYMENT_PASSKEY, the value of this field is from the iframe.
orderInformation.amountDetails.totalAmount
orderInformation.amountDetails.currency
Thanks for your feedback!
Last published: October 28, 2026