Visa Recurrent APIs for issuers
Getting started — issuers
The Visa Recurrent API enables issuers to access and manage recurring order details linked to cardholders' cards.
The API provides these operations to issuers:
- View Recurring Payment Orders – Retrieve paginated lists of recurring orders based on card number (PAN), Visa Recurrent Reference ID (VRR ID), subscriptionTransactionId, or status
- Update Recurring Payment Order Status – Cancel or reactivate recurring orders with update reasons. Cancellation applies payment blocks; reactivation removes them
- Remove Payment Stop from Recurring Payment Order – Remove payment blocks from cancelled recurring orders while keeping the order status as CANCELLED, allowing payment processing to resume
- List Transactions for Recurring Payment Order – Retrieve transaction history for a VRR ID.
Enrollment
The enrollment form captures business and technical configuration details required for Visa to provision Visa Recurrent. By submitting the enrollment form, the issuer authorizes Visa to make the configuration changes specified in the form.
Enrollment forms are provided by the issuer's Visa representative or can be downloaded from Visa Access under the Client Information Questionnaires section. You may need to search or navigate to this section, as enrollment forms are not directly accessible from the Visa Access landing page.
The enrollment process involves the following steps:
- Download the enrollment form from Visa Access.
- Complete the enrollment form with the required configuration and
integration details:
- Select the target environment (sandbox or production).
- Provide a requested effective date for service activation.
- Indicate whether to link a processor. A linked processor can access and manage Visa Recurrent on behalf of the issuer.
- For Visa Recurrent APIs, register and enroll in Visa Recurrent on Visa Developer Center (VDC) to access the APIs in the sandbox environment and production environment, including entering into an applicable Visa Developer API Agreement with Visa.
- For Visa Recurrent UI, request access to Visa Recurrent on Visa Access. In the Europe region, work with Visa Access Manager (VAM). In other regions, follow the Visa Online "Request Service" process.
Review the relevant regional Visa Fee Schedule on Visa Access for implementation, usage, and other fees that may apply.
The enrollment form includes these sections:
- Issuer Information – Business name, Business ID, contact name, email, phone, region, country, environment, requested effective date, and type of Visa Recurrent request.
- Processor Information – Processor business name, Business ID, contact details, and whether to link or unlink the issuer and processor.
- Organization Preferences – Billing entity and Business ID (BID), default stop instruction duration (1 – 60 months), participation in seller redirects, access method (API, UI, or both), and VDC application ID (for API clients).
Prerequisites
Before integrating with Visa Recurrent APIs, ensure all prerequisites are in place.
- Visa Developer Center (VDC) Account – Developers register and then log in to Visa Developer Center to obtain credentials, including API Keys and cryptographic key material.
- PACE – Confirm the client can host HTTPS webhook endpoints with mTLS for PACE callback delivery and has the capability to implement MLE for API calls.
- Sandbox Environment – Visa Recurrent APIs are available in the sandbox after registration and acceptance of VDC terms and conditions.
- Production Environment – Only participating issuers with an applicable and current Visa Developer API agreement can use Visa Recurrent APIs in the production environment.
Issuers must ensure that their organization has the required platform access, technical infrastructure, and security configurations in place for Visa Recurrent implementation.
- Verify platform access requirements
- Active Visa Developer Center account – Required for issuer API clients
- Approved Visa Recurrent enrollment – Complete enrollment process. See Enrollment.
- Verify technical infrastructure requirements
- Ability to consume REST APIs over HTTPS
- Support for JSON payloads
- Client-managed infrastructure for API execution and data storage
- Capability to receive Visa Recurrent notification events
- Configure authentication and network security
- Configure environment access
Visa Recurrent provides Sandbox, Certification (optional), and Production environments.
- Set up credential and secret management
Recurring Orders can have the following statuses:
- ACTIVE – Order is operational and eligible for recurring order processing
- CANCELLED – Order has been terminated, payment blocks may be active
Remove Payment Stop from Recurring Payment Order Status
This status is independent from recurring order status and indicates whether payment blocks are active:
- ACTIVE – Payment blocks are in place, transactions will be stopped
- INACTIVE – No payment blocks, transactions will be processed
Issuer Confirmation Status
When issuers cancel orders, merchants can confirm the cancellation status:
- RETAINED – Merchant successfully retained the recurring order
- CANCELLED – Merchant confirmed the cancellation
- NONE – No confirmation received from merchant
Sandbox Environment
The Visa Recurrent API provides a dedicated sandbox environment for development, testing, and integration verification before production deployment.
The Visa Recurrent API is available in these environments:
- Sandbox – https://sandbox.api.visa.com/vr/v1/issuer/
- Certification (CERT) –
- Production – https://api.visa.com/vr/v1/issuer/
Sandbox Environment Details:
- API Base Path – /vr/v1/issuer/
- View Recurring Payment Orders Endpoint – https://sandbox.api.visa.com/vr/v1/issuer/card/recurringPaymentOrders/list
- Update Recurring Payment Order Status Endpoint – https://sandbox.api.visa.com/vr/v1/issuer/card/recurringPaymentOrders/{visaRecurrentReferenceId}/status
- Remove Payment Stop from Recurring Payment Order Endpoint – https://sandbox.api.visa.com/vr/v1/issuer/card/recurringPaymentOrders/{visaRecurrentReferenceId}/paymentStop/removal
- List Transactions for Recurring Payment Order Endpoint – https://sandbox.api.visa.com/vr/v1/issuer/card/recurringPaymentOrders/{visaRecurrentReferenceId}/transactions
Sandbox Capabilities:
- All Authentication Methods – Two-way SSL authentication is supported
- Complete Operations – View, update status, and remove payment stop operations available for testing
- MLE Support – Full Message Level Encryption implementation
- Error Simulation – Test various error scenarios and response codes
Sandbox Limitations: The VDC sandbox does not support authorization and clearing test cases for cancelled or reactivated recurring orders, end-to-end payment processing, or notification testing. Clients access APIs through VDC and receive webhook notifications through PACE. While WSI acts as the Visa notification infrastructure behind the scenes, clients integrate only with PACE.
General Testing Approach:
- Use the dummy dates and search criteria included in the sandbox sample payloads to test different search scenarios.
- Verify pagination with different page sizes
- Test status update operations with both CANCELLED and ACTIVE target statuses
- Test payment stop removal with cancelled orders that have active payment blocks
Certification Environment: The Certification (CERT) environment is available for connectivity testing.
Transitioning to Production
Production URL: https://api.visa.com/vr/v1/issuer/
Before moving to production (VDC and PACE)
- Complete comprehensive testing in sandbox.
- Verify all error handling scenarios.
- Confirm performance meets requirements.
- Complete and sign the required product terms.
- Update base URLs to production endpoints.
- Switch to production credentials.
Additional requirement for PACE
- Validate webhook notification processing.
- Confirm webhook callbacks are successfully received and acknowledged.
Additional requirement for VDC
- Test all API operations with production data.
How to use — issuers
Visa Recurrent provides API workflows for issuers that work together to manage cardholder recurring orders.
- View Recurring Payment Orders Workflow – Use POST /vr/v1/issuer/card/recurringPaymentOrders/list to display a list of unique recurring orders when cardholders contact customer service or use the issuer app to view recurring charges on their accounts.
- Update Recurring Payment Order Status Workflow – Use PATCH /vr/v1/issuer/card/recurringPaymentOrders/{visaRecurrentReferenceId}/status to cancel recurring orders (which applies payment blocks) or reactivate them (which removes payment blocks) when charges are unauthorized, disputed, voluntarily cancelled, or need to be reinstated.
- Remove Payment Stop from Recurring Payment Order Workflow – Use POST /vr/v1/issuer/card/recurringPaymentOrders/{visaRecurrentReferenceId}/paymentStop/removal to remove payment blocks from cancelled recurring orders while keeping the order status as CANCELLED. This action will allow payment processing to resume.
- List Transactions for Recurring Payment Order – Use POST /vr/v1/issuer/card/recurringPaymentOrders/{visaRecurrentReferenceId}/transactions to retrieve transaction ID for a VRR ID.
- Notifications – PACE notification configuration covers the full issuer event set – recurring order creation and seller status update (seller cancellation or retention confirmation). Provide notification URLs for delivery. PACE notifications currently support only masked Primary Account Numbers (PANs).
Make Your First API Call
Making your first API call verifies that your connectivity and authentication are configured correctly before you communicate with the Visa Recurrent API.
Prerequisites:
Before making your first API call, ensure you have completed:
- Completed all prerequisite setup requirements
- Configured your chosen authentication method
- Implemented Message Level Encryption (MLE)
- Obtained access to the sandbox environment (sandbox.api.visa.com)
Your first API call should be a simple view operation to verify that your authentication, MLE implementation, and basic connectivity are working correctly. The view endpoint is ideal for initial testing as it requires minimal parameters and provides clear success/failure feedback.
Steps:
- Set up the basic request structure for the view endpoint.
- HTTP Method – POST
- URL – https://sandbox.api.visa.com/vr/v1/issuer/card/recurringPaymentOrders/list
- Content-Type – application/json
- Configure authentication headers based on your chosen method.
- For X-Pay-Token – Generate X-Pay-Token header using your API Key and Shared Secret
- For Two-way SSL – Configure SSL client certificate in your HTTP client
- Add required headers for tracking and correlation.
- Ex-Correlation-Id – Generate unique UUID for request tracking
- Accept – application/json
- Create a minimal view request payload.
Use basic search criteria such as:
{
"pan": "4111111111111111"
}
Encrypt the entire request payload using MLE being sending.
5. Send the request and verify the response.
Expected Success Response:
- HTTP Status: 200 OK
- Response body with encrypted payload
- Ex-Correlation-Id header echoed back
6. Decrypt and validate the response payload.
The decrypted response should contain:
- Pagination metadata
- Content array (may be empty if no recurring orders found)
- Standard pagination fields
Result:
A successful first API call confirms:
- Authentication configuration is correct
- MLE encryption/decryption is working properly
- Network connectivity to Visa APIs is established
- Request/response cycle is functioning as expected
Next Steps:
After successful completion:
- Test error scenarios
- Implement proper error handling in your application
- Test the update status operation to cancel or reactivate orders
- Test the remove payment stop operation if your use case requires it
- Set up webhook endpoints if using callback notifications. Notifications are configured outside the Visa Developer Center (VDC).
View Recurring Payment Orders Workflow
The View Recurring Payment Orders Workflow supports the scenario in which cardholders contact customer service or use the issuer application to view recurring charges on their accounts.
Use POST /vr/v1/issuer/card/recurringPaymentOrders/list.
Prerequisites:
- Valid authentication credentials configured
- MLE encryption properly implemented
- At least one search parameter: PAN or visaRecurrentReferenceId
Steps:
- Identify Search Criteria – Determine which identifier to use based on the
information needed:
- PAN (card number) – Use to retrieve a list of VRR IDs associated with a cardholder's account. This can be used to provide cardholders with a consolidated view of recurring orders or to help customer service representatives identify the recurring order being referenced.
- visaRecurrentReferenceId (VRR ID) – Use to retrieve information for a specific recurring order. This can be used when a cardholder selects a recurring order and wants to view additional details.
- subscriptionTransactionId – Optionally use this field to refine search results.
- recurringPaymentOrderStatus – Optionally use to filter recurring payment orders by status (ACTIVE or CANCELLED). This can be used to distinguish between active and cancelled recurring payment orders and display them separately.
- Prepare Request Payload – Create request with required identifier and optional filters. Set pagination parameters (page: 0-999, size: 1-1000, default 100).
- Encrypt Request – Apply MLE encryption to the entire request payload before sending.
- Execute API Call – Send POST request to /vr/v1/issuer/card/recurringPaymentOrders/list with encrypted payload.
- Decrypt and Parse Response – Decrypt response payload and extract recurring order details including pan, visaRecurrentReferenceId, status, paymentInfo, merchantInfo, auditInfo.
- Present to Cardholder – Display recurring orders. Show merchant details, payment frequency, amounts, and current status including merchantConfirmationStatus and paymentStopStatus if applicable.
Response Details:
Successful response (HTTP 200) contains pagination metadata and content array with recurring orders sorted by creation date (most recent first). Each order includes:
- visaRecurrentReferenceId – Unique VRR ID identifier
- recurringPaymentOrderStatus – ACTIVE or CANCELLED
- paymentInfo – Currency, amounts, frequency, transaction type, dates
- merchantInfo – Merchant names, VMIDs, card acceptor IDs
- auditInfo – Lifecycle events with timestamps and channels
- merchantConfirmationStatus – RETAINED, CANCELLED, or NONE (if applicable)
- paymentStopStatus – ACTIVE or INACTIVE (if applicable)
Update Recurring Payment Order Status Workflow
Update the status of recurring orders to cancel (with payment blocks) or reactivate (removing payment blocks).
Use PATCH /vr/v1/issuer/card/recurringPaymentOrders/{visaRecurrentReferenceId}/status.
Prerequisites:
- Valid visaRecurrentReferenceId from View API
- For CANCELLED status, order must be in ACTIVE status
- For ACTIVE status, order must be in CANCELLED status
- The eligible date for the recurring payment order must be null or earlier than the current date.
Cancellation Steps:
- Obtain VRR ID – Retrieve visaRecurrentReferenceId from View API for the order to cancel.
- Verify Current Status – Confirm order is currently in ACTIVE status.
- Prepare Cancel Request – Create request with recurringPaymentOrderStatus set to "CANCELLED" and updateReason describing why cancellation is needed.
- Generate Idempotency Key – Include V-C-Idempotency-Key header with unique UUID.
- Encrypt and Execute – Encrypt payload and send PATCH request to status endpoint.
- Process Response – Verify HTTP 200 response with updated status. Payment blocks are now active. Response may include unsubscribeURL for the cardholder to initiate cancellation with merchant. If the response includes an unsubscribeURL, the issuer must redirect the cardholder to the URL so the cardholder can initiate cancellation with the merchant.
- Merchant Notification – If merchant has opted in, they receive notification of cancellation and can confirm status (RETAINED or CANCELLED).
Reactivation Steps:
- Obtain VRR ID – Retrieve visaRecurrentReferenceId for the cancelled order to reactivate.
- Verify Current Status – Confirm order is currently in CANCELLED status.
- Prepare Reactivation Request – Create a request with recurringPaymentOrderStatus set to ACTIVE and provide an updateReason explaining why reactivation is needed. The updateReason is shared with participating merchants and can help them better understand the reason for reactivation. It can also help issuers support future cardholder inquiries and operational investigations. Because this information may be shared with merchants, do not include sensitive cardholder, account, or case-related information in the updateReason field.
- Encrypt and Execute – Encrypt payload and send PATCH request to status endpoint.
- Process Response – Verify HTTP 200 response with updated status. Payment blocks are now removed and order is active again.
Cancellation and Service Cancellation
Cancelling a recurring order places a payment block and updates the VRR ID status to CANCELLED. The notification sent to the merchant can also serves as a request to cancel the associated service agreement, if applicable. Depending on the merchant's processes, additional actions may be required to fully terminate the service, and the cardholder may still need to cancel directly with the merchant. For merchants with an integrationMode of NOTIFICATION_ONLY or REDIRECT_AND_NOTIFICATION, Visa sends a notification to the merchant, who may confirm the outcome as either RETAINED or CANCELLED. If the merchant does not confirm within 7 days, the status will remain cancelled with the payment block status as active.
Remove Payment Stop Workflow
Remove payment blocks from cancelled recurring orders while keeping the order status as CANCELLED. This will allow payment processing to resume if the merchant retries, while maintaining the cancellation record.
Use POST /vr/v1/issuer/card/recurringPaymentOrders/{visaRecurrentReferenceId}/paymentStop/removal.
Prerequisites:
- Recurring payment order must exist and be in CANCELLED status
- An active payment stop must be present (paymentStopStatus = ACTIVE)
- Valid visaRecurrentReferenceId
Use Cases:
- Cardholder decides to continue recurring payments after cancellation
- Merchant negotiates retention with customer
The issuer removes the payment block while retaining the recurring order's cancellation record when the cardholder agrees to continue payments
- Billing dispute resolved in favor of merchant
Steps:
- Identify Order – Obtain visaRecurrentReferenceId for the cancelled order with active payment stop.
- Verify Eligibility – Confirm order status is CANCELLED and paymentStopStatus is ACTIVE using View API.
- Prepare Request – Create request with removeReason field explaining why payment stop should be removed (required, max 100 characters).
- Generate Idempotency Key – Include V-C-Idempotency-Key header with unique UUID.
- Encrypt and Execute – Encrypt payload and send POST request to paymentStop/removal endpoint.
- Verify Success – Confirm HTTP 204 No Content response indicating successful removal.
Important Notes:
- Order status remains CANCELLED after payment stop removal
- Payment processing can resume for the associated merchant, if the merchant retries
- Merchants are not notified of payment block removal.
- Payment block status changes from ACTIVE to INACTIVE
- Audit trail records the stop removal event
- Returns HTTP 404 if order not found or already has inactive payment stop
- Returns HTTP 409 if prerequisites not met (for example, order not cancelled)
List Transactions for Recurring Payment Order Workflow
The List Transactions for Recurring Payment Order Workflow supports the scenario in which issuers need to retrieve the transaction history for a specific recurring order, such as when investigating a cardholder dispute, verifying payment history, or reconciling charges tied to a VRR ID. Transaction history can be searched for up to the previous 13 months.
Use POST /vr/v1/issuer/card/recurringPaymentOrders/{visaRecurrentReferenceId}/transactions.
Prerequisites:
- Valid visaRecurrentReferenceId from View API
- MLE encryption properly implemented
Steps:
- Obtain VRR ID – Retrieve visaRecurrentReferenceId from View API for the recurring order.
- Prepare Request Payload – Optionally set startDate and endDate to filter by transaction date, and transactionSource (AUTH, CLEARING, or AUTH_AND_CLEARING; default AUTH). If no date range is provided, the search defaults to the last 90 days.
- Set Pagination Parameters – Include page (0-999, default 0) and size (1-1000, default 100) query parameters.
- Encrypt Request – Apply MLE encryption to the entire request payload before sending.
- Execute API Call – Send POST request to the transactions endpoint with the encrypted payload.
- Decrypt and Parse Response – Decrypt response payload and extract transaction details including transactionId, transactionDate, transactionAmount, transactionCurrency, transactionType, merchantName, cardAcceptorId.
- Present Results – Display the transaction history to support the dispute investigation, reconciliation, or customer service inquiry.
Response Details:
Successful response (HTTP 200) contains pagination metadata and a content array of transactions (0-1000 items, empty if no match is found). Each transaction includes:
- transactionId – Unique identifier for the transaction
- transactionDate – Date the transaction occurred
- transactionAmount – Amount charged for the transaction
- transactionCurrency – Currency of the transaction
- transactionType – INSTALLMENT, RECURRING, or UNSCHEDULED_CARD_ON_FILE
- transactionSource – AUTH or CLEARING
- merchantName – Name of the merchant
- cardAcceptorId – Card Acceptor ID
- sharedCaid – Indicates whether the Card Acceptor ID is suspected to be shared
- merchantCategoryCode – Merchant Category Code
- respCode – Response code from the transaction authorization
- paymentFacilitator – Payment Facilitator ID and sub-merchant ID (if applicable)
Important Notes:
- Returns HTTP 404 if the recurring payment order is not found
- Returns HTTP 400 (Bad Request) if the request is invalid or prerequisites are not met. For example, an invalid date range.
- The maximum search range is 3 months; the earliest supported start date is 13 months prior to the current date
Notifications
Issuers receive webhook callbacks via PACE for the following events:
- RECURRING_PAYMENT_ORDER_CREATION – New order registered from transaction data. This is only for new transactions and not past transactions
- RECURRING_PAYMENT_ORDER_CANCELLATION – Order cancelled by issuer or cardholder
- RECURRING_PAYMENT_ORDER_REACTIVATION – Canceled order reactivated
- RECURRING_PAYMENT_ORDER_STATUS_UPDATE – Recurring payment stop removed
- RECURRING_PAYMENT_ORDER_MERCHANT_STATUS_UPDATE – Merchant confirmed cancellation status
- List Transaction API
Notification callbacks include complete order details with visaRecurrentReferenceId, pan, subscriptionDetails, status, merchantConfirmationStatus, and paymentStopStatus.
Visa includes the X-Message-Tracking-Id header in every notification callback. Log this value for traceability and support requests.
Authentication: Notification callbacks use mTLS (mutual TLS) as the currently supported authentication method. The X-Pay-Token header is not operative for outbound notifications at this time; it applies only after migration to the VDC outbound gateway.
Recurring Order Reference
Data structure reference for recurring orders in the Visa Recurrent API.
The Recurring Payment Order represents the recurring payment relationship tracked by Visa Recurrent. Orders are automatically created from transaction data and may contain complete payment, merchant, and lifecycle information, to the extent applicable and available.
Key Attributes
| Attribute | Type | Context | Description |
|---|---|---|---|
| visaRecurrentReferenceId | String | Response | Visa-generated unique identifier (VRR ID) for the recurring payment order. 26-character format. Required in all API operations. |
| pan | String | Request/Response | Primary Account Number (card number). Used in View API requests. Masked in responses (16-19 characters). |
| recurringPaymentOrderStatus | String | Response | Current order state: ACTIVE or CANCELLED |
| merchantConfirmationStatus | String | Response | Merchant's confirmation of cancellation: RETAINED, CANCELLED, or NONE |
| merchantConfirmationStatusDateTime | DateTime | Response | Timestamp when merchant confirmed the status (ISO 8601 format) |
| paymentStopStatus | String | Response | Status of payment blocks: ACTIVE (blocks in place) or INACTIVE (no blocks) |
| subscriptionTransactionId | String | Request/Response | Unique transaction ID tracking the recurring payment. For Visa cards, this is the Original Transaction Identifier (OTID) from MIT transactions. 1-36 characters. |
Status Values
| Status | Description |
|---|---|
| ACTIVE | Order is operational and eligible for recurring payments |
| CANCELLED | Order terminated by issuer or cardholder request. May have active payment blocks. |
Payment Information Structure
The paymentInfo object contains:
- currencyCode (String, required) – ISO 4217 currency code (e.g., "USD")
- minAmount (Integer, required) – Minimum payment amount in minor units (cents for USD)
- maxAmount (Integer, optional) – Maximum payment amount in minor units
- frequency (String) – Payment frequency: DAILY, WEEKLY, MONTHLY, QUARTERLY, YEARLY, BIWEEKLY, BIMONTHLY, BIYEARLY
- transactionType (String) – Type: RECURRING, INSTALLMENT, or UNSCHEDULED_COF
- subscriptionTransactionId (String) – Unique transaction identifier
- startDate (Date) – Recurring payment start date (YYYY-MM-DD)
- endDate (Date, optional) – Recurring payment end date
- firstPaymentDate (Date) – Date of first recorded payment
- latestPaymentDate (Date, required) – Date of most recent payment
Merchant Information Structure
The merchantInfo object contains:
- nameList (Array) – List of merchant names (up to 6, max 50 chars each)
- vmidList (Array) – Visa-generated Brand IDs (up to 6, max 10 chars each)
- cardAcceptorIdList (Array) – Card Acceptor IDs (up to 6, 1-15 chars each)
- paymentFacilitatorList (Array, optional) – Payment facilitator details with paymentFacilitatorId and subMerchantId
- category (String) – Merchant Category Code (3-4 digits)
- imageLogoURL (String, optional) – Merchant logo URL (10-255 chars)
- integrationMode (String) – Indicates how the merchant handles
cancellation notifications:
- NOTIFICATION_ONLY – Visa notifies the merchant via the notification API; the merchant confirms using the Merchant Status Confirmation API
- REDIRECT_ONLY – The cancellation response includes an unsubscribeURL redirecting the cardholder to the merchant's cancellation page
- REDIRECT_AND_NOTIFICATION – Both redirect and notification methods are used
Audit Information Structure
The auditInfo array contains lifecycle events with:
- eventType (String, required) – CREATE, CANCEL, REACTIVATE, STOP_REMOVAL, or MERCHANT_STATUS_CONFIRMATION
- dateTime (DateTime, required) – ISO 8601 timestamp of the event
- reason (String, optional) – Reason for the event (max 100 chars)
- channel (String, required) – Channel: UI, API, or SYSTEM
- user (String, optional) – User or system identifier that triggered the event (max 100 chars)
Search Parameters
The View API accepts these search parameters:
- pan (String, conditional) – Card number for search. Required if visaRecurrentReferenceId not provided.
- visaRecurrentReferenceId (String, conditional) – VRR ID for direct lookup. Required if pan not provided.
- subscriptionTransactionId (String, optional) – Filter by recurring payment transaction ID
- recurringPaymentOrderStatus (String, optional) – Filter by status
- page (Integer, optional) – Page number (0-999, default 0)
- size (Integer, optional) – Results per page (1-1000, default 100)
Best Practices
Implementing these best practices, which are non-comprehensive and illustrative only, can help ensure reliable, secure, and efficient integration with the Visa Recurrent APIs. Issuers should clearly explain the consequences of each action and obtain cardholder consent, where required, and remain responsible for complying with all applicable laws and regulations. This includes notifying merchants of cancellation requests and using any third-party services involved in processing cancellations or related workflows.
API Integration – Guidelines for robust and maintainable API integrations:
- Always include Ex-Correlation-Id headers with unique values
- Log correlation IDs for troubleshooting and support requests
- Maintain request/response audit trails
- Implement proper pagination logic for search operations
- Use reasonable page sizes (100-500 items) for performance
- Handle empty result sets gracefully
- Monitor totalCount for data volume planning
- The maximum search range is 3 months; the earliest supported start date is 18 months ago
- Use specific date ranges to optimize query performance
- Handle timezone considerations in date calculations
- Validate date ranges before API calls
Authentication and Security – Follow security best practices for API authentication:
- Store API keys and shared secrets securely using encryption
- Use environment variables or secure key management systems
- Rotate credentials regularly according to security policies
- Never expose credentials in client-side code or logs
- Implement MLE correctly for all request and response payloads
- Validate encryption/decryption before production deployment
- Handle MLE key lifecycle and rotation properly
- Test MLE implementation with various payload sizes
- Always use HTTPS/TLS for API communications
- Validate SSL certificates properly
- Use TLS 1.2 or higher versions
- Implement certificate pinning where appropriate
Error Handling – Implement comprehensive error handling for reliable operations:
- Implement exponential backoff for retryable errors (503, 429)
- Respect Retry-After headers when provided
- Set maximum retry limits to avoid infinite loops
- Do not retry non-retryable errors (400, 401, 403)
- Parse error response details arrays for specific field issues
- Log complete error responses for troubleshooting
- Use reason codes for programmatic error handling
- Provide meaningful error messages to end users
- Set appropriate connection and read timeouts
- Handle timeout scenarios gracefully
- Implement circuit breaker patterns for resilience
- Monitor timeout rates and adjust as needed
Performance Optimization – Optimize API integration for performance and efficiency:
- Reuse HTTP connections where possible
- Group related operations when applicable
- Cache frequently accessed data appropriately
- Implement client-side rate limiting to avoid 429 errors
- Track API response times and success rates
Data Management Best Practices – Follow best practices for sensitive data handling:
- Follow data protection regulations
- Minimize data storage and retention periods
- Encrypt sensitive data at rest and in transit
- Implement proper data access controls
- Validate all input parameters before API calls
- Handle data format conversions properly (dates, amounts)
- Verify card number formats and checksums
- Sanitize data for logging and display
Operational – Establish operational excellence for production environments:
- Set up comprehensive monitoring for API health and performance
- Implement structured logging with appropriate detail levels
- Maintain comprehensive test coverage for all scenarios
- Use staged deployments with proper validation
- Keep integration documentation current and accessible
- Establish clear procedures for incident response and support
Authentication methods — issuers
All APIs require either X-Pay-Token or Two-way SSL (Mutual TLS) authentication. All request and response payloads use Message Level Encryption (MLE) to protect sensitive data including card numbers and payment details.
Visa Developer Center (VDC):
- X-Pay-Token – Using API Key and Shared Secret
- Two-way SSL – Certificate-based mutual authentication
X-Pay-Token Authentication
X-Pay-Token provides strong security through HMAC-SHA-256 signatures with timestamp-based replay protection and 480-second token expiration.
Prerequisites:
Before implementing X-Pay-Token authentication, ensure you have:
- API Key from your Visa Developer Center (VDC) project
- Shared Secret from your VDC project credentials
- HMAC-SHA-256 cryptographic capability in your development environment
- UTC timestamp generation functionality
Steps:
- Generate the UTC timestamp for the request.
This timestamp must be within 8 minutes of the current time when the request reaches Visa servers. For example, 1587756817 (UTC seconds).
- Prepare the API name component.
The API name is the resource path without the leading slash:
- View endpoint – vr/v1/issuer/card/recurringPaymentOrders/list
- Update Status endpoint – vr/v1/issuer/card/recurringPaymentOrders/{visaRecurrentReferenceId}/status
- Remove Payment Stop endpoint – vr/v1/issuer/card/recurringPaymentOrders/{visaRecurrentReferenceId}/paymentStop/removal
- Construct the query string component.
Concatenate all query string parameters (including apiKey) as URL-encoded UTF-8 characters:
- Sort parameters lexicographically by name
- Format as name=value pairs separated by &
- URL-encode values per RFC 3986 (uppercase hex characters)
- Do not URL-encode unreserved characters: - . _ ~
For example, apiKey=M93HLKI2M55ST8QR9RYW3PUFG42mrpN0CsMeLNWbFWPAteAGA&page=0&size=100
- Prepare the request body with the raw JSON payload.
- Include the entire MLE-encrypted request body
- Use exact string representation
- Create the signature string.
Concatenate the components in this order – signatureString = timestamp + apiName + queryString + entityBody.
Ensure that there are no separators between components.
- Generate the HMAC-SHA-256 signature using:
- Key – Shared secret from VDC
- Message – The signature string from previous step
- Output – Hexadecimal representation (lowercase)
- Construct the X-Pay-Token header value.
Format the token as X-Pay-Token: xv2:{timestamp}:{hmacSignature}
For example, xv2:1587756817:2e1dbb9d10dcb8f22913a1900b3f985220fedb5918e9e8d192fa49a3f2c8a76c
- Add the X-Pay-Token header to your API request along with other required headers.
- Content-Type: application/json
- Accept: application/json
- Ex-Correlation-Id: {unique-uuid}
Result:
Successful X-Pay-Token implementation provides:
- Strong authentication with HMAC-SHA-256 cryptographic signatures
- Replay attack protection through timestamp validation
- Request integrity verification
- 480-second token lifetime for security
Next Steps:
After implementing X-Pay-Token authentication:
- Test with various request types and payloads
- Verify proper error handling for expired tokens
- Implement token regeneration for failed requests
- Monitor timestamp accuracy to prevent authentication failures
Two-way SSL Authentication
Two-way SSL provides certificate-based authentication where both client and server verify each other's identities. This method is suitable for high-security environments and system-to-system integrations.
Prerequisites:
Before implementing Two-way SSL authentication, ensure that you have:
- Valid client certificate from Visa Developer Center
- Private key corresponding to your client certificate
- Certificate Authority root certificate (DigiCert Global Root CA)
- SSL/TLS client configuration capability in your development environment
Steps:
- Obtain and prepare your client certificate.
- Download and configure the DigiCert Global Root CA certificate.
- Download URL – https://dl.cacerts.digicert.com/DigiCertGlobalRootCA.crt
- Convert to PEM format if needed using OpenSSL or Windows Certificate Manager
- Install in trust store of your HTTP client or system
- Set up your private key securely.
Ensure proper private key management:
- Store private key in secure location with restricted access
- Consider using hardware security modules (HSMs) for production
- Implement key rotation procedures per security policies
- Configure SSL/TLS settings in your HTTP client.
- Client Certificate – Specify path to client certificate file
- Private Key – Specify path to private key file
- CA Bundle – Include DigiCert root certificate
- Certificate Verification – Enable full certificate chain validation
- Verify proper SSL configuration before API calls.
- Client requests access to Visa API endpoint.
- Server presents its certificate to client.
- Client verifies server certificate against CA.
- Client sends its certificate to server.
- Server validates client certificate and signature.
- Successful handshake enables encrypted communication.
- Execute API calls with Two-way SSL authentication.
- No additional authentication headers required
- Include standard headers
- SSL certificate authentication occurs automatically during connection
- Verify successful authentication through 200 OK responses
Result:
Successful Two-way SSL implementation provides:
- Strong mutual authentication between client and server
- Certificate-based identity verification
- Encrypted communication channel
- Non-repudiation through digital signatures
Next Steps:
After implementing Two-way SSL authentication:
- Monitor certificate expiration dates and plan renewals
- Test certificate validation error scenarios
- Implement proper error handling for SSL handshake failures
- Document certificate management procedures
- Consider certificate revocation list (CRL) checking
Certificate management is critical for Two-way SSL. Ensure proper procedures for certificate lifecycle, renewal, and revocation.
Error codes — issuers
The Visa Recurrent API returns standard HTTP status codes with detailed error response structures to help diagnose and resolve issues.
Most errors use the same basic response shape:
{ "errorResponse": { "status": 404, "reason": "notFound" } }
Most status codes (401, 403, 500, 503, and others) are generic and apply the same way across any Visa API. Only 404 and 409 carry meaning specific to recurring orders — and even then, the reason text alone won't identify exactly what went wrong; you'll need to know which endpoint you called and check the order's current state.
Before contacting Visa Support, have the following ready:
- The exact request you sent (method, URL, body, and headers — excluding secrets)
- The full error response, including the Ex-Correlation-Id header if present
- Whether the issue is reproducible or intermittent
Codes you can usually resolve yourself: 400, 401, 404, 406, 409, 410, and 413 — these are almost always something to fix in your own request, credentials, or logic.
Contact Visa Support at [email protected] if:
- You get a 500 or 503 that persists after retrying with backoff
- You get a 403 or 429 and your account/project setup looks correct
- You're unsure whether a 404 or 409 reflects a real data issue on Visa's side versus your own request — send the correlation ID and Visa can check
HTTP Status Codes
Complete reference of HTTP status codes returned by the Visa Recurrent API with detailed descriptions and recommended actions.
Success Status Codes
| Status Code | Description | Details and Usage |
|---|---|---|
| 200 | OK | Request successful. Response contains requested data for view operations or the updated order for status update operations. |
| 204 | No Content | Payment stop successfully removed. Returned by the Remove Payment Stop endpoint. No response body. |
Client Error Status Codes (4xx)
| Code | Description | Common Causes | Recommended Actions |
|---|---|---|---|
| 400 | Bad Request | On the order-lookup call (POST recurringPaymentOrders/list): missing both pan and visaRecurrentReferenceId — one of the two is required pan outside the 16–19 character range, or a masked PAN (for example 411111******1111) sent instead of the full number visaRecurrentReferenceId not exactly 26 characters — check the full value was copied without truncation or reformatting Invalid recurringPaymentOrderStatus filter value | Confirm exactly one of pan or visaRecurrentReferenceId is set, and that neither is malformed Check field formats and constraints Review error response details array Fix validation errors before retry — this is usually a quick fix on your end |
| 401 | Unauthorized | Invalid X-Pay-Token signature Timestamp beyond 8-minute window — often caused by generating the token once and reusing it across calls instead of generating a fresh one per call Inactive or invalid API Key, or sandbox credentials used against production (or vice versa) Signature (HMAC) mismatch caused by a subtle difference between the exact bytes signed and the exact bytes sent — for example, pretty-printed vs. compact JSON, or incorrect parameter sorting/encoding More than one authentication method sent on the same request | Regenerate authentication token fresh for every request Verify timestamp synchronization Check API Key configuration and confirm you're using the right credentials for the right environment Double-check signature construction against Visa's documentation Use only one authentication method per request |
| 403 | Forbidden | API not in VDC project configuration Insufficient permissions Resource access restrictions Sandbox credentials used against production, or vice versa | Verify VDC project configuration Check API access permissions Confirm the correct sandbox/production credentials are in use Contact Visa support if needed |
| 404 | Not Found | Recurring order not found Invalid order ID format Order not owned by issuer | Verify order ID format Confirm issuer ownership Handle as valid business scenario Check search criteria accuracy |
| 406 | Not Acceptable | Unsupported API version requested Invalid Accept header values Version newer than available Attempting to request a specific API version via the Accept header — this API is versioned by URL path (for example /vr/v1/...), not by an Accept header, so this should not occur in normal use | Check API version in URL path Verify Accept header format Use supported API version (v1) Confirm you're sending Accept: application/json rather than requesting a version via a header Review API versioning documentation |
| 409 | Conflict | Duplicate operation request Invalid state transition Already cancelled recurring order | Check current order status Verify operation validity Handle as business logic scenario Use idempotency keys properly |
| 410 | Gone | API version end-of-life Deprecated endpoint accessed Resource permanently removed | Upgrade to supported API version Check Content-Type header for version info Review API migration guides Update integration to current version |
| 413 | Payload Too Large | Request body exceeds size limits Client-side bug — for example, accidentally nesting a prior response into the next request, resulting in a much larger body than intended | Reduce request payload size Check for client-side bugs that inflate the request body unintentionally Optimize search criteria |
| 429 | Too Many Requests | Rate limit exceeded Too many concurrent requests VDC project limits reached Polling the order-lookup endpoint in a tight loop instead of relying on webhook notifications Batch jobs firing many requests at once without spacing them out | Implement exponential backoff with jitter Respect Retry-After header Reduce request frequency Prefer webhook notifications over polling wherever possible Contact Visa for limit increases if you have a legitimate high-volume use case |
Server Error Status Codes (5xx)
| Code | Description | Common Causes | Recommended Actions |
|---|---|---|---|
| 500 | Internal Server Error | Visa system errors Unexpected server conditions Processing failures | Retry with exponential backoff Contact Visa support with correlation ID Monitor error frequency |
| 503 | Service Unavailable | Temporary system overload Maintenance periods Server capacity issues | Retry with exponential backoff Check Retry-After header If your own webhook receiver was down for an extended period, reconcile any missed updates afterward using the order-lookup endpoint rather than assuming the webhook caught everything |
Response Headers
Important response headers to monitor and utilize:
- Ex-Correlation-Id – Echoed back from request for tracking and support purposes. Always log this value for troubleshooting.
- Retry-After – Provided with 503 and 429 errors to indicate recommended wait time before retry. Format can be HTTP date or seconds.
- Content-Type – With 410 errors, indicates the latest supported API version for migration guidance.
Status Code Handling Best Practices
- Categorize Responses: Group status codes into success (2xx), client error (4xx), and server error (5xx) for different handling approaches
- Preserve Context: Always log the correlation ID, request details, and complete error response for debugging
- Implement Retries Selectively: Only retry 5xx errors and 429 rate limiting errors
- Handle Business Logic: Treat 404 and 409 as valid business scenarios, not system failures
- Monitor Patterns: Track error rate trends to identify systemic issues
Business Logic Errors
- Search Operation Errors
- Date range exceeds 3-month maximum search range or start date is earlier than 13 months ago
- Invalid card account number format
- Missing required search criteria
- Invalid status enum values
- Cancellation Errors
- Recurring order already cancelled or expired
- Invalid recurring order ID
- Insufficient permissions for cancellation
- Order not owned by requesting issuer
Recurring Order Error Semantics
These two codes carry meaning specific to recurring orders, worth understanding in more depth than the generic platform errors above.
404 Not Found
- Applies to cancel/reactivate, payment-stop removal, transaction history, and the legacy cancel endpoint. It does not apply to the order-lookup endpoint — searching and getting zero matches is a normal, successful response (200 with an empty list), not an error.
- Watch for confusing the legacy "Agreement" ID with the current "Order" reference ID — they use the same format, so a value from one flow can look valid but fail against the other endpoint. If unsure, use PATCH .../status, not the legacy DELETE .../cancel.
- On the payment-stop-removal endpoint specifically, this same 404 can also mean the order exists but isn't in the right state, or has no active payment block to remove — the response doesn't distinguish these. If the ID is confirmed correct, check the order's current status and payment-stop state before assuming it's a lookup problem.
409 Conflict
- The response text will just say something generic like "Duplicate Data" — this does not mean anything was actually duplicated; it means a state precondition wasn't met.
- Cancelling or reactivating an order (PATCH .../status): you can only cancel an order that's currently ACTIVE, and only reactivate an order that's currently CANCELLED. If the order is already in the requested state (or some other state), you'll get a 409.
- Removing a payment stop (POST .../paymentStop/removal): the order must be CANCELLED and must currently have an active payment block. If either condition isn't true, you'll get a 409 — the response won't indicate which is the actual cause.
- Retrying a 409 without changes will just fail again with the same request. Look up the order's current status first, confirm what state it's actually in, and only send the transition that's valid from that state.
Deprecation note: DELETE .../recurringPaymentAgreements/{id}/cancel is deprecated. Use PATCH .../recurringPaymentOrders/{id}/status instead for new integrations.
Webhook Error Handling
Webhook authentication failures are not retried — ever. If your webhook receiver rejects a Visa notification with 401 or 403, that notification is gone permanently, with no visibility on Visa's side into why it failed. Visa only retries a callback on a 5xx server error or a 404 — 2 retries, spaced randomly 1–30 minutes apart.
- Set up alerting on your own receiver for any 401 or 403 it emits — this is the one failure mode with no safety net.
- You must opt in during onboarding to receive notifications, and separately opt in for token-based authentication on the callback — confirm both are configured correctly, ideally with a test call, before relying on production traffic to surface a misconfiguration.
- If your receiver is down for an extended period and misses notifications, reconcile afterward using the order-lookup endpoint rather than assuming you'll eventually get everything via the webhook.
Retry and Recovery Guidelines
Implement appropriate retry logic based on error types.
- Retry Errors
- 503 Service Unavailable – Retry with exponential backoff, respect Retry-After header
- 429 Too Many Requests – Implement rate limiting backoff, check Retry-After header
- 500 Internal Server Error – Limited retries with backoff for transient issues
- Non-Retry Errors
- 400 Bad Request – Fix request format and validation errors before retry
- 401 Unauthorized – Refresh credentials or fix authentication configuration
- 403 Forbidden – Verify VDC project configuration and permissions
- 404 Not Found – Handle as business logic
Sample payloads — issuers
Sample request and response payloads for the Visa Recurrent API endpoints used by issuers.
View Recurring Payment Orders
POST /vr/v1/issuer/card/recurringPaymentOrders/list
Sample request
{
"pan": "4111111145551140",
"recurringPaymentOrderStatus": "ACTIVE"
}
Sample response (200 OK)
{
"empty": false,
"first": true,
"last": true,
"number": 1,
"resultsCount": 1,
"totalCount": 1,
"totalPages": 1,
"content": [
{
"pan": "4111111145551140",
"visaRecurrentReferenceId": "7mJP0TDZcTxi2ETZFYKtjMg-01",
"recurringPaymentOrderStatus": "ACTIVE",
"paymentInfo": {
"currencyCode": "USD",
"minAmount": 999,
"frequency": "MONTHLY",
"transactionType": "RECURRING",
"subscriptionTransactionId": "541267812345672",
"startDate": "2025-01-01",
"latestPaymentDate": "2026-04-01"
},
"merchantInfo": {
"nameList": ["Test Merchant Ltd", "Test Merchant Inc."],
"vmidList": ["VM123456"]
},
"auditInfo": [
{
"eventType": "CREATE",
"dateTime": "2025-01-01T10:30:00Z",
"channel": "SYSTEM"
}
]
}
]
}
Cancel Recurring Payment Agreement (Deprecated)
DELETE /vr/v1/issuer/card/recurringPaymentAgreements/{vRecurringPaymentAgreementId}/cancel
Sample request
{
"cancelReason": "User requested cancellation"
}
Sample response (200 OK)
{
"vRecurringPaymentAgreementID": "7mJP0TDZcTxi2ETZFYKtjMg-01",
"status": "CANCELLED",
"unsubscribeURL": "https://example.com/unsubscribe"
}
Update Recurring Payment Order Status
PATCH /vr/v1/issuer/card/recurringPaymentOrders/{visaRecurrentReferenceId}/status
Sample request
{
"recurringPaymentOrderStatus": "CANCELLED",
"updateReason": "User requested cancellation"
}
Sample response (200 OK)
{
"visaRecurrentReferenceId": "7mJP0TDZcTxi2ETZFYKtjMg-01",
"recurringPaymentOrderStatus": "CANCELLED",
"unsubscribeURL": "https://example.com/unsubscribe"
}
Remove Payment Stop from Recurring Payment Order
POST /vr/v1/issuer/card/recurringPaymentOrders/{visaRecurrentReferenceId}/paymentStop/removal
Sample request
{
"removeReason": "New subscription plan selected by the user"
}
A successful request returns an HTTP 204 status code with no response body.
List Transactions for Recurring Payment Order
POST /vr/v1/issuer/card/recurringPaymentOrders/{visaRecurrentReferenceId}/transactions
Sample request
{
"startDate": "2026-06-01",
"endDate": "2026-09-01",
"transactionSource": "AUTH_AND_CLEARING"
}
Sample response (200 OK)
{
"empty": false,
"first": true,
"last": true,
"number": 1,
"resultsCount": 1,
"totalCount": 1,
"totalPages": 1,
"content": [
{
"cardAcceptorId": "CA789012",
"sharedCaid": false,
"merchantCategoryCode": "5411",
"merchantName": "Test Merchant Ltd",
"transactionAmount": 999,
"transactionCurrency": "USD",
"transactionDate": "2026-08-01",
"transactionId": "541267812345",
"transactionSource": "AUTH",
"transactionType": "RECURRING",
"respCode": "00"
}
]
}
Recurring Payment Order Notification
POST {postbackNotificationUrl}
Visa sends this webhook to the issuer's configured postbackNotificationUrl when there is a change to a recurring payment order. This callback is sent only if the issuer has opted in for notifications and configured a callback URL in the issuer profile.
Sample request body
{
"messageMetadata": {
"vMessageId": "173e4567-e89b-12d3-a456-426614174000",
"createdDateTime": "2026-09-10T16:15:21Z",
"type": "RECURRING_PAYMENT_ORDER_STATUS_UPDATE"
},
"pan": "411111******1140",
"visaRecurrentReferenceId": "7mJP0TDZcTxi2ETZFYKtjMg-01",
"recurringPaymentOrderStatus": "CANCELLED",
"merchantConfirmationStatus": "CANCELLED",
"merchantConfirmationStatusDateTime": "2026-09-10T16:00:00Z",
"paymentStopStatus": "ACTIVE",
"subscriptionDetails": {
"paymentInfo": {
"currencyCode": "USD",
"minAmount": 999,
"frequency": "MONTHLY",
"transactionType": "RECURRING",
"subscriptionTransactionId": "541267812345672",
"startDate": "2025-01-01",
"latestPaymentDate": "2026-08-01"
},
"merchantInfo": {
"nameList": ["Test Merchant Ltd"],
"vmidList": ["VM123456"]
},
"auditInfo": [
{
"eventType": "CANCEL",
"dateTime": "2026-09-10T16:00:00Z",
"channel": "API",
"reason": "User requested cancellation",
"user": "[email protected]"
}
]
}
}
The issuer returns an HTTP 2XX status code to acknowledge successful processing. Visa retries the callback up to two times, at random intervals between 1 and 30 minutes, if the issuer returns a 5XX or 404 status code.