Skip to main content

Versioning

J.P. Morgan Payments Platform APIs will evolve over time for a number of reasons including, but not limited to, strategic shifts in business operations and/or the evolution of our software platforms.

To ensure a durable and predictable client experience we will:

  • Adhere to a clear API versioning strategy.
  • Provide clear and succinct documentation and client communications.
  • Be fully transparent when functionality is due to be deprecated and/or decommissioned. 

Versioning strategy

J.P. Morgan's Payments Platform versioning strategy allows for our APIs to evolve in without breaking client integrations (subject to guidance below) as such changes are rolled out. We follow the Semantic Versioning approach to identify breaking and non-breaking changes.

Integration expectations

  • Our versioning model allows for API responses to evolve over time. This means that integrations must tolerate the presence of previously unexpected JSON properties in response payloads.
  • Clients should also monitor for the existence of the following HTTP headers:
    • Deprecation – Indicates that the capability is, or will be, deprecated.
    • Sunset – Indicates when the capability is due to be removed.

How it works

A common numbering scheme is illustrated in the following image:

Common Numbering Scheme Example
  • Major version: This number increments if a non-backward compatible change is made. For example, a change to version 1.2.4 will result in a new version 2.0.0.
  • Minor version: This number increments when a backward-compatible change is made, e.g. adding a new operations to an existing API. For example, a change to version 1.2.4 will result in a new version 1.3.0. 
  • Patch version: This number is incremented for compatible bug fixes, e.g., changing and clarifying the documentation in an API contract. For example, a compatible bug fix to version 1.2.4 will result in a new version 1.2.5.

Types of changes

Non-breaking changes

Non-breaking changes typically don't break your existing application using the API. These include minor bug fixes and non-breaking feature updates. 

Your application should be resilient to non-breaking changes which may include minor bug fixes and feature additions. The following API changes are considered non-breaking and should not cause errors or introduce compatibility issues: 

  • Adding a new:
    • API endpoint
    • Optional field
    • Optional query parameter
    • Optional HTTP header to an API request
    • Field or HTTP header to a response
    • Enum value in an API request    
  • Making required fields, query parameters, or HTTP headers non-required in an API request.
  • Expanding the range of allowed values for a field, query parameter, or HTTP header in an API request.
  • Changes to the order of fields returned within a response
  • Bug fixes on existing APIs
  • Deprecating an existing API

This is how non-breaking changes are handled:

  • No new (URL-level) version will be created.
  • Version number will be updated as follows:
    • First set of number to be consistent with the (URL) version of the API.
    • Second set of number to indicate minor changes.
    • Third set of number to indicate secondary minor changes (a patch, fixing issue). 

Breaking changes

The introduction of a new major API version will cause future disruption to your existing applications. We recommend migrating to the new version of the API as soon as possible. The following are a few examples of changes we consider as breaking:

  • Removal of a mandatory request or response field
  • Addition of a required/optional request field without default values
  • Changes to the intended functionality of an endpoint
  • Introduction of a new field validation
  • Changing data type of an existing field
  • Removing or renaming the URL of an endpoint
  • Adding a required header to an existing endpoint
  • Changing existing error codes/messages
  • Introducing new features such as payload signing, additional encryption etc. 
  • Modifying the existing payload of webhooks or async callbacks
  • Retiring an API

This is how breaking changes are handled:

  • A new version of the API will be created and swagger documentation for the new version will be published on Developer Portal. 
  • Version number (within Information section) will be updated as:
    • First set of number to indicate major changes and be consistent with the (URL) version of the API.
    • Second set of number to indicate minor changes

How to code for non-breaking changes

In JSON-based REST APIs, additive changes are considered non-breaking. J.P. Morgan implements new features and changes to our APIs in a backward-compatible fashion.

It's the developer’s responsibility to develop their applications to handle new fields in API responses without causing any errors and exceptions. In this guide, you will learn about:

  • Non-breaking API changes
  • What to do when code breaks
  • Best practices

When code breaks

The code shouldn't break when a non-breaking change is made to an OpenAPI specification. However, if it does, the following are potential reasons for your breakage may include:

  • Misunderstanding of "non-breaking" - Perceiving a non-breaking API code change as a provider. An unexpected new field can cause an application to throw errors or exceptions.
  • Over-specificity - The code is overly specific or rigid and expects an exact response order or structure. For example, adopting strict mode parsing in Java leads to an exception during parsing if the object (POJO) does not exactly match the incoming JSON response. 
    • The below code of a Java Jackson deserializer provides an example that would not accept the addition of a new object property in a response. 
Example of strict mode parsing in Jackson deserializer
Java
new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true);
  • Undefined Behavior - If an application was relying on behavior that was not specified in the original OpenAPI spec but just happened to work, changes to the API can break this.
  • Lack of Testing - Testing did not account for future changes to the API schema.

Best practices

J.P. Morgan recommends the following approaches during implementation to avoid a scenario where the code breaks:

  • Strong testing
  • Flexible parsing

Strong testing

Ensure you have a robust suite of tests for your application. Run tests and identify potential issues when a new API update is introduced.

Flexible parsing

Design a flexible application to avoid breaks when new fields are added to the resources. This ensures the application can handle unexpected fields or changes in the structure without crashing or malfunctioning. 

Your webhook/callback listener should handle new or unfamiliar event types. By adopting flexible parsing techniques, developers can make their applications more resilient to changes in API responses to ensure a better user experience and less maintenance overhead.

Use the following techniques for flexible parsing:

  • Robust field handling
  • Default values for missing fields
  • Scheme validation
  • Resilient data processing
  • Decoupling and data mapping

Robust field handling

Use robust field handling to ignore unexpected fields to by designing your parser to ignore fields it doesn't recognize rather than raising errors. The following example shows an application ignoring an additional location field when it is expecting a JSON object with name and age to process the response.

Example unexpected fields in payload (using Java and JavaScript)

Handle unexpected fields correctly
// Configure ObjectMapper not to fail when encountering unknown properties.

new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)

Expected output

Expected output
Json
{"name": "Alice", "age": 30}

Provide default values for missing fields

Assign default values to fields missing values from the response. The following example assumes the default value of 0 if a product's discount field is missing.

Example of a missing field code 

Missing field
Javascript
const missingDiscountProduct = {
    "product_name": "Laptop",
    "price": 1000
 // discount field is missing
}

function parseProduct(product) {
    const { product_name, price, discount = 0 } = product;
    return { product_name, price, discount };
}

// When called with {"product_name": "Laptop", "price": 1000},
parseProduct(missingDiscountProduct)
// returns {"product_name": "Laptop", "price": 1000, "discount": 0}

Schema validation

Use Schema Validation tools to check the response against the expected schema. The following example shows how Ajv (for JavaScript) validates and reports discrepancies for the incoming data against the JSON schema. 

Example Ajv schema validation

Schema validation
Javascript
const Ajv = require('ajv');
const ajv = new Ajv();
const validate = ajv.compile(schema);

function validateResponse(response) {
    const valid = validate(response);
    if (!valid) console.error(validate.errors);
    return valid;
}
// Usage: validateResponse(response)

Resilient data processing

Use explicit error handling to anticipate and handle potential parsing errors. This type of error handling provides the application with useful error messages or prompts. The following example shows an “Unable to parse the date. Please check the format” error message instead of crashing if a date in the response is not parsed.

Example of explicit error handling

Explicit error handling
Javascript
function parseDate(dateStr) {
    const date = new Date(dateStr);
    if (isNaN(date)) throw new Error('Unable to parse the date. Please check the format.');
    return date;
}
// Usage: 
try {
    parseDate(dateStr);
}
catch (error) {
    console.error(error.message);
}

Decoupling and data mapping

Use decoupling or data mapping techniques to create flexible parsing. Use Data Transfer Objects (DTOs) or similar patterns to map API responses to internal data structures. This decouples the application's internal representation from the API's data structure. The below example shows how an application can flatten a nested object into a more convenient structure using a DTO or a mapper function.

Example of DTOs

Employ DTOs
Javascript
class UserDTO {
    constructor(apiResponse) {
        this.name = apiResponse.user.name;
        this.age = apiResponse.user.details.age;
    }
}

// Usage: 
UserDTO userDTO = new UserDTO(apiResponse)

Communication

As J.P. Morgan Payments Platform APIs evolve, J.P. Morgan will make reasonable efforts to notify you of breaking changes in advance with sufficient time to adapt to these changes.

  • Changelog on the Developer Portal will be updated with technical specifications.
  • Email communication will be sent to client contacts.
Tip

We may make changes without prior notice if the change is considered non-breaking, or if it is a breaking change being made to address critical product bugs or legal, security, or privacy concerns.  

Deprecation strategy

Tip

Generally our deprecation period is 18 months.  

Release States Example

Release states

Active

The API is ready for Production use. APIs are fully supported with new features and bug fixes in subsequent releases. The complete API documentation will be available on the developer portal.

Deprecated

Deprecation is the first step toward retirement of an API version, this can be as a result of a new major version becoming available, or a future curtailment of service.

  • Functionality is typically maintained for a period of 18 months prior to permanent retirement. 
  • Functionality is operational and fully supported, new integrations are strongly discouraged, and may be prohibited in some situations.
  • No new features will be added, existing applications should update to the active version of the API to prevent future service interruption.

Retired

Retired APIs are no longer available, supported, or documented.