API Definitions as Developer Contracts
Developers are at the core of everything we do at Microsoft. Our Azure service teams are constantly working to improve the clarity and consistency of API definitions. We believe it’s important that there’s a single, accurate, and clear “source of truth” for how our API will work. For Azure, that source of truth is the Azure REST API specs GitHub repository.
Furthermore, our API definitions are a key input to a large swath of our downstream tooling and code generation. For example, we use the OpenAPI document as the basis to generate client libraries, CLIs, and REST API documentation. Due to significant investment in tooling, and some customizations, Azure continues to use the OpenAPI v2 format in our API definition files.
Because the API definitions drive numerous downstream artifacts, one of our key goals is to provide a consistent experience across all Azure services. The challenges are the pace at which services evolve and the increasing number of services. We created the Azure REST API Guidelines, along with a companion set of documents to help our service teams reach these goals. Some of the areas of clarity and consistency we focus on are:
- Documentation of error responses: The Azure convention is to use the “default” response to describe all error conditions. Using a single “default” error significantly reduces verbosity without much loss in information. We also recommend that teams use meaningful error text rather than simply repeating what you get from HTTP. For example, documenting a particular error status code is useful, such as
409 Conflict, to describe specific conditions that cause this response.
- Specific formats/constraints for parameters and properties: A common problem is date fields that don’t specify
format: date-time, and thus aren’t defined properly in client libraries. Another common problem is string parameters that don’t clearly document restrictions on length or characters allowed.
- More rigor on “descriptions” everywhere in the API definition: Every operation, parameter, and schema property should have a clear description. We also want descriptions on response headers, security definitions, individual values of extensible enums, and elsewhere. We use linting tools to verify that descriptions are present in these places, and strive to ensure that they’re clear and complete. These descriptions feed directly into our generated developer docs, so it’s important we get them right.
- Security definitions should be complete and accurate: In particular, the security scheme(s) should be accurately described. For example, which OAuth2 flows and scopes are required. Also, each operation should reference at least one security scheme.
Whether you use our APIs through one of our SDKs, or directly from your own tools, we’d love to learn more about how you’re using our APIs. Tell us what works, what’s frustrating, and share your ideas on how we can improve. Let’s start a conversation. Contact us at firstname.lastname@example.org.
-Mark & Mike
The Azure convention is to use the “default” response to describe all error conditions.
Can you elaborate on that a bit how it relates to HTTP status codes? I read the section in the guidelines but I am still not sure if I got it.
My current understanding would be to preferably use a single HTTP status codes to report errors and only divert from it if necessary.
Thanks for your comment!
In Azure we use “default” to cover all the standard 4XX and 5XX HTTP status codes. Typically there is little information value to specifying these individually, since it often mimics the standard error description. For example, a 401 means “Unauthorized” and since this is an HTTP standard there is no need to repeat this in our API definitions. In addition, the _absence_ of any of these status codes cannot be taken by the user to mean that such a code will not be returned, since middleware may inject these responses without the involvement of the service.
Adding a bit to what Mike pointed out, here’s the section on errors in our Considerations for Service Design document. It goes deeper into the rationale behind why we recommend handling errors this way. Let us know if this is helpful for you as well.
Thanks Mike and Mark for the quick reply!
Now it makes sense – instead of interpreting “default” literally as the default response in an OpenAPI spec, I interpreted it in a more general way and thus was confused why someone would choose to smash all error responses in a single HTTP code (that’s why I asked :)).
Thanks again for the clarification.