Document updated on Oct 25, 2022
Document your endpoints with OpenAPI
The OpenAPI documentation (formerly Swagger) is automatically generated by the KrakenD Enterprise binary when you use the krakend openapi export
command (see Exporting to OpenAPI).
OpenAPI configuration
The OpenAPI documentation configuration has two different placements that you can use:
service
level: Defines the general business information and metadata that provides context about your company and how to get in touch with you as an end-user, it is common to all endpoints.endpoint
level: Defines the documentation and metadata for a specific endpoint.
Both configuration placements are optional, and when you don’t provide the information, KrakenD sets defaults.
Setting the basic API information
At the service level (the root of the configuration file), you can declare an extra_config
with the documentation/openapi
to declare the general API information for your developers. All the fields are optional.
The available fields are self-explanatory by seeing the following example:
{
"version": 3,
"name": "Your KrakenD API",
"extra_config": {
"documentation/openapi": {
"description": "This is a sample server. You can find out more about at [http://blah](http://blah.blah.com)",
"version": "1.0.0",
"host": "my.api.com",
"base_path": "/v1",
"terms_of_service": "http://url.to/tos",
"contact_name": "The wonderful API department",
"contact_email": "[email protected]",
"contact_url": "https://your.company/developers",
"license_name": "MIT",
"license_url": "https://opensource.org/licenses/MIT",
"tag_definition": [
{
"name": "Admin",
"description": "All endpoints for administrative users"
}
],
"schemes": ["http","https"],
"components_schemas": {
"Pet": {
"type": "object",
"required": ["id","name"],
"properties": {
"id": {
"type": "integer",
"format": "int64"
},
"name": {
"type": "string"
},
"tag": {
"type": "string"
}
}
},
"Pets": {
"type": "array",
"maxItems": 100,
"items": {
"$ref": "#/components/schemas/Pet"
}
}
}
}
}
}
Fields of "documentation/openapi"
base_path
string- A starting path that is appended to any endpoint.Example:
"/v1"
components_schemas
object- The JSON Schemas you can reuse inside endpoint definitions using
ref
. You can either pass the JSON Schema object, or a bas64 string.Example:{"Pet":{"required":["id","name"],"type":"object"}}
Properties of
components_schemas
can use a name matching the pattern.*
, and their content is an[string object]
contact_email
string- Email where users of your API can write to.Example:
"/v1"
contact_name
string- Contact name.Example:
"/v1"
contact_url
string- Contact URL that users of your API can read.Example:
"/v1"
description
string- An introductory, optionally verbose, explanation supporting CommonMark syntax. If you’d like to load an external markdown file, you can use flexible configuration, for instance
"description": {{include "openapi/intro.md" | toJson }}
Example:"Hi there, I am [OpenAPI](https://www.krakend.io/docs/enterprise/endpoints/openapi/)"
host
string- The hostname where you will publish your API.Example:
"my.api.com"
jwt_key
string- When generating an OpenAPI spec, the name of the JWT key used under components securitySchemes.Defaults to
"KrakenD-JWT"
license_name
string- The license name (e.g.: Apache License)Example:
"/v1"
license_url
string- The URL where the license is hostedExample:
"/v1"
schemes
array- The list of schemes supported by the API, e.g.
http
orhttps
Example:["https","http"]
Defaults to["http"]
tag_definition
array- Sets a description for the tags classifiying endpoints when generating the OpenAPI spec.Example:
[{"description":"Description of tag1","name":"Tag1"}]
Each item of tag_definition accepts the following properties:description
string- Describe what this tag is grouping
name
string- The name of the tag. You will use this name in each endpoint.
terms_of_service
string- The URL to the terms of service for using this API.Example:
"/v1"
version
string- The version numbering you want to apply to this release of API., e.g.:
1.0
.Example:"1.0"
The name
specified in the root of the configuration (outside the OpenAPI’s extra_config
) is used as the title of your API. If none is present, the string KrakenD - API Gateway
is the default.
If you want to include a full markdown file in the introduction, you can use flexible configuration to ease this process. For instance, if you write a markdown file, under partials/openapi/intro.md
you can load it automatically as follows:
{
"version": 3,
"name": "Your KrakenD API",
"extra_config": {
"documentation/openapi": {
"description": {{include "openapi/intro.md" | toJson }},
}
}
}
Documenting endpoints
In addition to setting global metadata for the whole API, you can insert additional information to each endpoint, so users can have an explanation of what every endpoint does. All fields are optional:
Fields of "documentation/openapi"
audience
array- The list of audiences that will consume this endpoint. These values do not define the gateway logic in any way. They are a way to group endpoints and filter them out when generating the OpenAPI documentation. Use
*
to indicate an endpoint will be present in any audience generated.Example:["gold","silver","*"]
description
string- An introductory, optionally verbose, explanation supporting CommonMark syntax. If you’d like to load an external markdown file, you can use flexible configuration, for instance
"description": {{include "openapi/intro.md" | toJson }}
Example:"Hi there, I am [OpenAPI](https://www.krakend.io/docs/enterprise/endpoints/openapi/)"
example
object, string- Deprecated in OAS3 (use
response_definition
instead). A free form JSON object or a string you would like to show as a sample response of the endpoint. The examples assume they are JSON content types except when using theoutput_encoding=string
. operation_id
string- A unique string identifying the operation identifier. Usually the method + the endpoint. If provided, these IDs must be unique among all operations described in your API.Example:
"GET/foo"
param_definition
array- Sets a description for the URL parameters (e.g.:
/foo/{param}
) required in the endpoint. Make sure to include to write the param exactly as in the endpoint definition.Example:[{"description":"The unique user ID","name":"id_user"}]
Each item of param_definition accepts the following properties:description
string- The description of the parameter
name
string- The name of the parameter, as declared in
endpoint
without the curly braces{}
query_definition
array- Sets a description for the query strings allowed in the endpoint. Make sure to include the same strings in the endpoint’s
input_query_strings
.Example:[{"description":"The number of the page","name":"page"}]
Each item of query_definition accepts the following properties:description
string- The description of the querystring
name
string- The name of the querystring, as declared in
input_query_strings
required
boolean- Set to
true
when this query string is required
request_definition
array- Describes the payload needed to consume the endpoint. If a JSON Schema validation exists, it takes precedence when generating the documentation. An example use case is when you need to document a
multipart/form-data
request body.This property is an array because you can document requests with multiple content types.Example:[{"content_type":"application/json","description":"Updates the user","example":{"first_name":"Mary","id_user":33}}]
Each item of request_definition accepts the following properties:content_type
string- The content type returned by this error, e.g.,
application/json
. You cannot repeat this content type in another item. description
string- The description of the payload this endpoint accepts.
example
string, object, array, boolean, integer, null, number- A free form JSON object or a string you would like to show as a sample response of the endpoint. The examples assume they are JSON content types except when using the
output_encoding=string
. example_schema
string, object- A JSON schema that describes the request format for the accepted payload in the endpoint. Use either example or example_schema, but not both.
ref
string- The relative reference to the
components/schema
OpenAPI definition that will be used as definition of the accepted request. Notice that the path#/components/schemas/
is not needed.Example:"your_schema_name"
response_definition
object- Describes the different status codes returned by this endpoint. Each key is the definition of the status code, represented by a string. E.g.,
200
(success),500
(internal error), etc.Example:{"404":{"@comment":"Some comment","content_type":"application/json","description":"Page not found","example":{"status":"KO"}}}
Properties of
response_definition
can use a name matching the patterndefault|^[0-9]+$
, and their content is anobject
with the following properties:content_type
string- The content type returned by this error, e.g.,
application/json
description
string- The description of this error code, e.g.,
Page not found
. example
string, object, array, boolean, integer, null, number- A free form JSON object or a string you would like to show as a sample response of the endpoint. The examples assume they are JSON content types except when using the
output_encoding=string
. example_schema
string, object- A JSON schema that describes the response format for the endpoint, directly as a JSON object, or encoded as a base64 string. Use either example or example_schema, but not both.
ref
string- The relative reference to the
components/schema
OpenAPI definition that will be used as definition of the accepted request. Notice that the path#/components/schemas/
is not needed.Example:"your_schema_name"
summary
string- A short summary for the endpoint. Use the description field for the longest explanation.
tags
array- You can assign a list of tags to each API operation. If you declare tags in the
tag_definition
at the OpenAPI service level, they will have a description in the documentation. Tagged operations may be handled differently by tools and libraries. For example, Swagger UI uses tags to group the displayed operations.
The example below sets a rich OpenAPI documentation for two endpoints. Notice that:
- For the
GET /users
we want to add descriptions to the?page
query string, and we provide a full example response underresponse_definition
- For the
PUT /users/{id_user}
we also add arequest_definition
that defines the payload the user will need to send.
Have a look at the different parameters:
{
"version": 3,
"$schema": "https://www.krakend.io/schema/krakend.json",
"host": [
"http://localhost:8080"
],
"debug_endpoint": true,
"echo_endpoint": true,
"endpoints": [
{
"endpoint": "/users",
"method": "GET",
"extra_config": {
"documentation/openapi": {
"description": "Lists all user in the system, paginated in blocks of 50 users",
"summary": "List all users",
"operation_id": "GET/users/id_user",
"tags": [
"users"
],
"audience": [
"internal"
],
"query_definition": [
{
"name": "page",
"required": false,
"description": "Pass a ?page= if you want to use the pagination"
}
],
"response_definition": {
"200": {
"content_type": "application/json",
"example": {
"users": [
{
"id": 1,
"first_name": "Juliana",
"last_name": "Claire",
"email": "[email protected]"
},
{
"id": 2,
"first_name": "Jeannette",
"last_name": "Hugonneau",
"email": "[email protected]"
}
]
}
}
}
}
},
"backend": [
{
"url_pattern": "/api/1.0/users/list"
}
]
},
{
"endpoint": "/users/{id_user}",
"method": "PUT",
"extra_config": {
"documentation/openapi": {
"description": "The PUT method updates the data for the given id_user. You only need to pass the fields you want to update.",
"summary": "Updates the user data",
"operation_id": "PUT/users/id_user",
"tags": [
"users"
],
"audience": [
"internal"
],
"request_definition": [
{
"content_type": "application/json",
"description": "Updates provided fields. All fields are optional, id_user taken from the URL",
"example": {
"address": "Suite 543 907 Green Forks, Wavamouth, CT 10807-8479",
"first_name": "Felix",
"last_name": "Richardson"
}
}
],
"response_definition": {
"200": {
"content_type": "application/json",
"example": {
"id_user": 33007,
"status": "success"
}
}
}
}
},
"backend": [
{
"url_pattern": "/api/1.0/users/update/{id_user}"
}
]
}
]
}
Quite verbose for two endpoints right? The example above does not even have all possible options to document endpoints. Remember that you can move any bit of the configuration to an external file using Flexible Configuration. You can still generate the OpenAPI file without any of this, but a rich and detailed documentation is always aprreciated by consumers. This is in an example on how you could move out the documentation from the endpoint definition, but there are more ways of doing it:
{
"endpoints": [
{
"endpoint": "/users",
"method": "GET",
"extra_config": {
"documentation/openapi": {
"$ref": "./documentation/GET_users.json"
}
},
"backend": [
{
"url_pattern": "/api/1.0/users/list"
}
]
},
{
"endpoint": "/users/{id_user}",
"method": "PUT",
"extra_config": {
"documentation/openapi": {
"$ref": "./documentation/PUT_users_id_user.json"
}
},
"backend": [
{
"url_pattern": "/api/1.0/users/update/{id_user}"
}
]
}
]
}
Integration with JSON Schema
When your endpoint uses a validation/json-schema
, all write methods (POST
, PUT
, PATCH
, DELETE
) add in the documentation automatically its validation conditions.
There is nothing else that you need to add in the configuration, but of course you can explain the payloads using the request_definition
property.
Define different audiences of your OpenAPI
When you declare your endpoints, you might want to restrict some of them from appearing in the final documentation export because the audience consuming them doesn’t need to be aware of their existence.
For instance, let’s say your API exposes endpoints like /user
, /cart
, or /admin
, where the administration endpoint is for internal usage. Why would you document it for your end-users if they are not supposed to use it or know its existence?
For cases like this, you might want to add definitions of specific audiences to the endpoints. For instance:
[
{
"endpoint": "/user",
"extra_config": {
"documentation/openapi": {
"description": "The user endppoint",
"audience": [
"public",
"internal"
]
}
}
},
{
"endpoint": "/cart",
"extra_config": {
"documentation/openapi": {
"description": "The cart endpoint",
"audience": [
"public",
"internal"
]
}
}
},
{
"endpoint": "/admin",
"extra_config": {
"documentation/openapi": {
"description": "The admin endpoint",
"audience": [
"internal"
]
}
}
},
{
"endpoint": "/no-audience",
"extra_config": {
"documentation/openapi": {
"description": "The admin endpoint"
}
}
}
]
Then, when generating the documentation, you can filter out the /admin
endpoint and exclude it from the final documentation with krakend openapi export -c krakend.json -a public
. The command would document /user
, /cart
, and /no-audience
.
It is important to notice that when you filter by audience, all endpoints without defining one, will appear in the final documentation.
Similarly, using krakend openapi export -c krakend.json -a internal
would generate the documentation for all the endpoints, but not specifying the -a
flag would have produced the same effect.
Notice that the audience
attribute lets you exclude endpoints from the final documentation, but they exist anyway in the service, and you must protect them against unwanted usage.
Documenting response examples and errors
The response_definition
object allows you to set examples of the response an API endpoint will deliver. For instance:
{
"endpoint": "/cart",
"extra_config": {
"documentation/openapi": {
"description": "The cart endpoint",
"response_definition": {
"200": {
"example": {
"status": "OK",
"message": "Product added to the cart!"
}
},
"500": {
"example": {
"status": "KO",
"message": "Couldn't add the product to the cart!"
}
}
}
}
}
}
When the examples are long, you might want to have the example responses in a separate file (like settings or partial) using Flexible Configuration, so the endpoint template keeps being readable. For instance
{
"endpoint": "/cart",
"extra_config": {
"documentation/openapi": {
"description": "The cart endpoint",
"response_definition": {
"200": {
"example": {{- include openapi_cart_response.json -}}
}
}
}
}
}
You can also use define an example using the example_schema
(schema takes precedence), in base64. There are different ways you can alliviate the burden of writing code in base64. For instance:
{
"endpoint": "/cart",
"extra_config": {
"documentation/openapi": {
"description": "The cart endpoint",
"response_definition": {
"200": {
"example_schema": {{- include cart_schema.json | b64enc -}}
}
}
}
}
}
Or writing the schema inline, escaped with backticks:
{
"endpoint": "/cart",
"extra_config": {
"documentation/openapi": {
"description": "The cart endpoint",
"response_definition": {
"200": {
"example_schema":: "{{ `{
"type": "object",
"title": "This is the response"
}` | b64enc }}"
}
}
}
}
}