Designing APIs for a Payment Orchestrator – Fetching Available Payment Methods

Designing APIs for a Payment Orchestrator – Fetching Available Payment Methods

Apr 17, 2025 · 6 min read

Background

The initial step in any payment flow involves retrieving the list of available payment methods. This list can be filtered based on various criteria, such as customer type, region, or currency.

This article examines the design of an effective API for fetching available payment methods.

The Request

Headers

Similar to the headers used in a payment request, the following headers are typically included when requesting a list of available payment methods:

  • Authentication, e.g., Authorization: Bearer {token}, X-API-KEY: {api-key}
  • Content Negotiation, e.g., Content-Type: application/json, Accept: application/x-www-form-urlencoded
  • Merchant/Partner Identifier, e.g., X-Merchant-Code: {merchant-code}, X-Partner-ID: {partner-id}
  • Payload Integrity Validation, e.g., X-Signature: sha256={signature}
  • Rate Limiting, e.g., X-RateLimit-Limit: {limit}, X-RateLimit-Remaining: {remaining}
Headers to exclude
  • X-Idempotency-Key, e.g. ,X-Idempotency-Key: {idempotency-key}

    Idempotency keys are used to safely retry state-changing operations such as POST, PUT, or DELETE. Since fetching payment methods is a read-only operation with no side effects, this header is not needed.

  • Caching, Cache-Control: no-cache

    Similar to the initiate request, responses for available payment methods should not be cached to ensure merchants always receive the most up-to-date list.

Body

In comparison to an initiate payment request, the options request is relatively straightforward. We recommend a flat structure for the request payload, which can be submitted in formats such as JSON, XML, or form-data.

- Payload
  - **amount** | `amount`: Details regarding the transaction amount and currency.
  - **shopperCountry** | `string`: The shopper’s country in ISO 3166-1 alpha-2 format.
  - **shopperLocale** | `string`: A combination of language and country codes to define the locale.
  - **shopperReference** | `string`: A unique reference identifying the shopper. Used to include store tokens in response.
  - **device** | `device`: Information about the device used to initiate the transaction.

Path

The request path should indicate the following:

  • Resource identifier, e.g., /options
  • API versioning, e.g., /v1/options

Query Parameter

Although query parameters are not frequently utilized in PSP APIs, they can serve specific purposes:

  • Filtering & Search, to narrow down results based on specific criteria, e.g., ?allowed=card,alipay&blocked=upi
  • Pagination & Limits, to control the volume of data returned, e.g., ?limit=50, ?offset=100
  • Sorting & Ordering, to specify how the data list in results are sorted, e.g., ?sort=type, ?order=desc

The Response

HTTP Status Code

The response code should consistently be 200 OK.

Body

- **Options Response**
  - **altopusId** | `string`: A unique reference for the request.
  - **options** | `[]Option`: A list of available payment options.

Each Option contains details of a payment option:

- **Option**
    - **variant** | `string`: Unique identifier for the payment variant.
    - **name** | `string`: User-friendly name for the payment variant.
    - **tokens** | `[]TokenDetail`: A list of stored tokens associated with this payment variant.

Each TokenDetail provides additional information about a stored token:

- **TokenDetail**
  - **reference** | `string`: The unique identifier for the stored token.
  - **useCases** | `[]string`: Supported use cases for this token.
  - **details** | `map`: Additional metadata related to the token.

The details field contains variant-specific data. Some keys may be shared across variants, such as mandate information.

  • Token detail for card-based methods
- CardTokenDetail
  - **expiryMonth** | `string`: Two-digit expiration month of the card.
  - **expiryYear** | `string`: Last two digits of the expiration year.
  - **holderName** | `string`: Name of the cardholder.
  - **summary** | `string`: Last four digits of the card number.
  • (More details to be added)

Behind the Scene

As a payment orchestrator, we do not offer our own payment methods. Instead, we depend on connected Payment Service Providers (PSPs) to provide these options. The orchestrator’s role is to aggregate and filter the methods available from the PSPs; it cannot expose any methods that are not supported by them.

If the orchestrator does not cache the available methods, it must query each PSP for every incoming options request. While this ensures real-time accuracy, it results in significant operational overhead, particularly when a merchant is integrated with multiple PSPs. Since payment methods typically change infrequently, this approach can be inefficient.

A more scalable approach is to cache the available payment methods and return the cached data when responding to the merchant. To keep the cache synchronized with the PSPs, here are a few common strategies.

Webhook-Based Sync

PSPs send a webhook notification to the orchestrator when their payment method configuration changes.

Pros:

  • Real-time updates
  • Minimal network traffic
  • Scales effectively with multiple PSPs

Cons:

  • Relies on PSPs supporting webhooks
  • Requires reliable error handling and retry mechanisms
  • Necessitates secure verification and authentication

Periodic Polling

The orchestrator periodically queries each PSP (e.g., hourly) to refresh the available payment method configurations.

Pros:

  • Easy to implement
  • No reliance on webhook infrastructure

Cons:

  • Data may become outdated between polling intervals
  • Increased load if polling frequency is high
  • Less efficient with a large number of PSPs

Manual Trigger

Synchronization is initiated manually, either by the merchant or through internal tools.

Pros:

  • Low maintenance and operational cost
  • Suitable for configurations that change infrequently

Cons:

  • Risk of stale or outdated data
  • Dependent on human intervention
  • Not ideal for dynamic or rapidly changing environments

The manual trigger will be covered in more detail in the dedicated section below.

Sync on First Access / Lazy Loading

The orchestrator synchronizes payment methods on demand—only when a merchant or PSP is accessed and the cache is missing or expired.

Pros:

  • Minimizes unnecessary synchronization
  • Efficient for merchants with low traffic
  • Works well with time-to-live (TTL) based caching strategies

Cons:

  • Slower response for the first request (cold start)
  • Requires careful management of cache expiration and invalidation
  • Potential for inconsistent experiences if merchants receive updates at different times

Token Vault

Tokens can be stored on either the orchestrator’s side, the PSP’s side, or in some cases, a combination of both.

The main benefit of storing tokens within the orchestrator is enhanced interoperability. For example, in a Card-on-File (COF) scenario, if card details are kept with the orchestrator, it can direct the transaction to the most suitable PSP (assuming that PSP supports the card brand). If the first attempt fails, the orchestrator has the option to retry with a different PSP, which can enhance overall reliability and success rates.

However, this advantage comes with limitations. Its effectiveness depends heavily on the broader payment ecosystem’s support for interoperability. In practice, such flexibility is generally supported by major card schemes, while alternative and bank-based payment methods offer limited or no support.

Most importantly, since PSPs interact directly with banks or wallets, the tokens they create are typically only usable through that specific PSP. Furthermore, many PSPs do not disclose or share the actual token generated at the scheme, issuer, or wallet level, which further restricts the orchestrator’s ability to operate independently.

Trigger Options Synchronization