- Introduction
- Compatible changes
- Adding a new operation to the service
- Adding a new optional parameter to the end of the parameter list for an operation
- Adding a new optional property to a model after previously existing properties
- Changing the description of an operation, parameter, model, or property
- Adding a new value to an enum.
- Adding, removing, or changing a "documentation-only" attribute of a parameter or property
- Possibly compatible changes
- Incompatible changes
- Removal of a operation
- Removal of a parameter from an operation
- Changing the operationId of an operation
- Reordering of the parameters of an operation
- Adding a required parameter to an operation
- Adding a parameter to an operation anywhere except after the last existing parameter
- Changing the name of a model
- Removal of a model
- Replacing an "inner model" with a ref to a new top-level model
- Removal of any property of a model
- Changing a property from required to optional or vice-versa
- Removing an enum value
This document describes how changes to an OpenAPI (nee Swagger) API document will affect the compatibility of SDKs generated from this document. The incompatible changes listed below should be avoided whenever possible to maintain SDK compatibility.
For the purpose of this document, we consider the newly generated SDK to be incompatible if a program previously developed using the previous version of the SDK will either not compile or function incorrectly if built with the newly generated version of the SDK.
All SDKs adhere to the Semantic Versioning standard, which only allows backwards-incompatible changes in a new major version of the SDK.
Services with a version-date parameter can introduce "minor breaking changes" into a service with a new version-date value. Nevertheless, the swagger document should, whenever possible, faithfully describe the API for all possible values of version-date, not just the most recent. This may mean that certain aspects of service behavior cannot be expressed formally in the swagger, and must instead be conveyed informally in description fields of operations, parameters, models, or properties. This is a tradeoff between completeness and simplicity of the interface description: we should strive for completeness in most cases but exceptions may be made if circumstances warrant.
The following are changes that can be made to the swagger that result in fully compatible SDKs.
New operations are compatible and can be introduced without a version-date change.
New optional parameters are compatible from an API perspective so long as the default behavior of the service matches the behavior prior to the change. A version-date change is not required in this case.
Further, a property can be added elsewhere in a model if the model is not used as a request body. New properties must be added to the end of request bodies because some languages "explode" the request body, meaning that the properties are converted to parameters on the associated methods.
Descriptions in the API document become comments in the SDKs.
The SDKs intentionally avoid using the enum values for validation so as to allow new enum values to be added.
The SDKs consider the following parameter/property attributes as "documentation only":
- default
- maximum
- exclusiveMaximum
- minimum
- exclusiveMinimum
- maxLength
- minLength
- pattern
- maxItems
- minItems
- uniqueItems
- multipleOf
Need to think through these
A new required property will result in a new member variable of the corresponding class in the SDK, and additional data in the objects of that class.
This change is probably compatible so long as the service always includes the new property in its responses regardless of the version-date specified on the request.
Reordering of properties in a request model is likely incompatible because it will change the order of the parameters in the constructor for the class or potentially the associated operation, since the generator may convert the model properties into parameters for some SDKs.
But if the model is not used as a request body, then it may be allowable to reorder the parameters.
The following changes will result in an incompatible change to the SDK and thus should be avoided. Some items provide advice for alternative approaches that will maintain SDK compatibility.
General exceptions: the rules below apply only to operations that have not been excluded from the SDKs
using the x-sdk-exclude
annotation and models that have not been pruned from the SDKs.
As a general rule, operations should be formally deprecated for some period of time before being removed. Within this deprecation period, new major versions of the SDK can eliminate the operation since incompatible changes are permitted in a major version SDK release.
To maintain SDK compatibility, leave the operation in place but have the service return an error return code.
OpenAPI v2 allows an operation to be flagged as deprecated with the boolean deprecated
attribute.
To maintain compatibility, the parameter should be retained but marked as deprecated. The description should be updated to document that its value is ignored. Within this deprecation period, new major versions of the SDK can eliminate the parameter.
The operationId
is used as the name of the SDK method (adapted to the language naming conventions)
for the operation.
Changing the operationId
for an operation will likely change the method name in the SDK,
which will break any applications that use the previous method name.
Changing the order of parameters to an operation causes a breaking change in the Python and Swift SDKs.
The Python and Swift SDKs have service methods that accept all parameters in the same order as they appear in the API document.
Changing the order of parameters in the API doc will alter the signatures of these methods, which will be a breaking change.
The exception to this rule is that required parameters can be moved before optional parameters, because the SDK generator already makes this modification because it is required by the Python and Swift languages.
This will break existing applications because they don't provide a value for this parameter.
The Python and Swift SDKs have service methods that accept all parameters in the same order as they appear in the API document.
Adding a new parameter into the middle of the parameter list, even if it is optional, which change the method signature in a way that could break existing invocations of the method.
The model name is the basis for the corresponding class name in the SDKs.
This can be made compatible by adding an x-alternate-name
annotation to retain the previous model name in all affected SDKs.
Removing a model will remove the corresponding class from the newly generated SDK. Since this class was present in prior versions of the SDK, applications could contain references to that class, which will cause build failures when compiled with the new SDK.
To maintain SDK compatibility, leave the model in place but mark it as deprecated.
OpenAPI v3 allows a model(schema) to be marked as deprecated with the boolean deprecated
attribute.
The SDK generator for some languages creates classes for "inner models", so this change will be incompatible unless the new top-level model has a name that is mapped to the previously generated classes.
This change can also be made compatible by adding an x-alternate-name
annotation to retain the previous model name in all affected SDKs.
Example: The QueryResultMetadata
model in Discovery.
To maintain compatibility, the swagger should retain the property but mark it as deprecated.
If the property is an optional property of a response model, the service can drop the property from its responses but it must remain defined in the API document.
Some languages, e.g. Swift, have language support for defining optional types -- meaning the value may or may not be present. Optional types are an elegant way to distinguish required from optional properties in response models -- optional properties are declared with optional types whereas required properties are not.
Unfortunately, this means that once defined in the API spec, a property cannot change from required to optional or vice-versa without resulting in an incompatible change to the generated SDK.
Some languages generate constants for enum values. If an enum value is removed, any application that references the constant for that enum value will fail to compile after updating to the new SDK.