Swagger documentation

A Swagger API documentation is automatically generated and available on your API root but you need to provide some details with the @api.doc() decorator.

Documenting with the @api.doc() decorator

This decorator allows you specify some details about your API. They will be used in the Swagger API declarations.

You can document a class or a method.

@api.route('/my-resource/<id>', endpoint='my-resource')
@api.doc(params={'id': 'An ID'})
class MyResource(Resource):
    def get(self, id):
        return {}

    @api.doc(responses={403: 'Not Authorized'})
    def post(self, id):
        api.abort(403)

Automatically documented models

All models instanciated with model(), clone() and inherit() will be automatically documented in your swagger specifications

The inherit() will register both the parent and the child in the Swagger models definitions.

parent = api.model('Parent', {
    'name': fields.String,
    'class': fields.String(discriminator=True)
})

child = api.inherit('Child', parent, {
    'extra': fields.String
})

Will produce the following Swagger definitions:

"Parent": {
    "properties": {
        "name": {"type": "string"},
        "class": {"type": "string"}
    },
    "discriminator": "class",
    "required": ["class"]
},
"Child": {
    "allOf": [{
            "$ref": "#/definitions/Parent"
        }, {
            "properties": {
                "extra": {"type": "string"}
            }
        }
    ]
}

The @api.marshal_with() decorator

This decorator works like the raw marshal_with() decorator with the difference that it documents the methods. The optional parameter code allows you to specify the expected HTTP status code (200 by default). The optional parameter as_list allows you to specify whether or not the objects are returned as a list.

resource_fields = api.model('Resource', {
    'name': fields.String,
})

@api.route('/my-resource/<id>', endpoint='my-resource')
class MyResource(Resource):
    @api.marshal_with(resource_fields, as_list=True)
    def get(self):
        return get_objects()

    @api.marshal_with(resource_fields, code=201)
    def post(self):
        return create_object(), 201

The Api.marshal_list_with() decorator is strictly equivalent to Api.marshal_with(fields, as_list=True)().

resource_fields = api.model('Resource', {
    'name': fields.String,
})

@api.route('/my-resource/<id>', endpoint='my-resource')
class MyResource(Resource):
    @api.marshal_list_with(resource_fields)
    def get(self):
        return get_objects()

    @api.marshal_with(resource_fields)
    def post(self):
        return create_object()

The @api.expect() decorator

The @api.expect() decorator allows you to specify the expected input fields. It accepts an optional boolean parameter validate defining wether or not the payload should be validated. The validation behavior can be customized globally by either setting the RESTPLUS_VALIDATE configuration to True or passing validate=True to the API constructor.

The following syntaxes are equivalents:

resource_fields = api.model('Resource', {
    'name': fields.String,
})

@api.route('/my-resource/<id>')
class MyResource(Resource):
    @api.expect(resource_fields)
    def get(self):
        pass
resource_fields = api.model('Resource', {
    'name': fields.String,
})

@api.route('/my-resource/<id>')
class MyResource(Resource):
    @api.doc(body=resource_fields)
    def get(self):
        pass

It allows you specify lists as expected input too:

resource_fields = api.model('Resource', {
    'name': fields.String,
})

@api.route('/my-resource/<id>')
class MyResource(Resource):
    @api.expect([resource_fields])
    def get(self):
        pass

Or a RequestParser:

parser = api.parser()
parser.add_argument('param', type=int, help='Some param', location='form')
parser.add_argument('in_files', type=FileStorage, location='files')


@api.route('/with-parser/', endpoint='with-parser')
class WithParserResource(restplus.Resource):
    @api.expect(parser)
    def get(self):
        return {}

An exemple of on-demand validation:

resource_fields = api.model('Resource', {
    'name': fields.String,
})

@api.route('/my-resource/<id>')
class MyResource(Resource):
    # Payload validation disabled
    @api.expect(resource_fields)
    def post(self):
        pass

    # Payload validation enabled
    @api.expect(resource_fields, validate=True)
    def post(self):
        pass

An exemple of application-wide validation by config:

app.config['RESTPLUS_VALIDATE'] = True

api = Api(app)

resource_fields = api.model('Resource', {
    'name': fields.String,
})

@api.route('/my-resource/<id>')
class MyResource(Resource):
    # Payload validation enabled
    @api.expect(resource_fields)
    def post(self):
        pass

    # Payload validation disabled
    @api.expect(resource_fields, validate=False)
    def post(self):
        pass

An exemple of application-wide validation by constructor:

api = Api(app, validate=True)

resource_fields = api.model('Resource', {
    'name': fields.String,
})

@api.route('/my-resource/<id>')
class MyResource(Resource):
    # Payload validation enabled
    @api.expect(resource_fields)
    def post(self):
        pass

    # Payload validation disabled
    @api.expect(resource_fields, validate=False)
    def post(self):
        pass

Documenting with the @api.response() decorator

The @api.response() decorator allows you to document the known responses and is a shortcut for @api.doc(responses='...').

The following synatxes are equivalents:

@api.route('/my-resource/')
class MyResource(Resource):
    @api.response(200, 'Success')
    @api.response(400, 'Validation Error')
    def get(self):
        pass


@api.route('/my-resource/')
class MyResource(Resource):
    @api.doc(responses={
        200: 'Success',
        400: 'Validation Error'
    })
    def get(self):
        pass

You can optionally specify a response model as third argument:

model = api.model('Model', {
    'name': fields.String,
})

@api.route('/my-resource/')
class MyResource(Resource):
    @api.response(200, 'Success', model)
    def get(self):
        pass

If you use the @api.marshal_with() decorator, it automatically document the response:

model = api.model('Model', {
    'name': fields.String,
})

@api.route('/my-resource/')
class MyResource(Resource):
    @api.response(400, 'Validation error')
    @api.marshal_with(model, code=201, description='Object created')
    def post(self):
        pass

At least, you can specify a default response sent without knowing the response code

@api.route('/my-resource/')
class MyResource(Resource):
    @api.response('default', 'Error')
    def get(self):
        pass

The @api.route() decorator

You can provide class-wide documentation by using the Api.route()‘s’ doc parameter. It accept the same attribute/syntax than the Api.doc() decorator.

By example, these two declaration are equivalents:

@api.route('/my-resource/<id>', endpoint='my-resource')
@api.doc(params={'id': 'An ID'})
class MyResource(Resource):
    def get(self, id):
        return {}
@api.route('/my-resource/<id>', endpoint='my-resource', doc={params:{'id': 'An ID'}})
class MyResource(Resource):
    def get(self, id):
        return {}

Documenting the fields

Every Flask-Restplus fields accepts optional arguments used to document the field:

  • required: a boolean indicating if the field is always set (default: False)
  • description: some details about the field (default: None)
  • example: an example to use when displaying (default: None)

There is also field specific attributes.

The String field accept the following optional arguments:

  • enum: an array restricting the authorized values.
  • min_length: the minimum length expected
  • max_length: the maximum length expected
  • pattern: a RegExp pattern the string need to validate

The Integer, Float and Arbitrary fields accept the following optional arguments:

  • min: restrict the minimum accepted value.
  • max: restrict the maximum accepted value.
  • exclusiveMin: if True, minimum value is not in allowed interval.
  • exclusiveMax: if True, maximum value is not in allowed interval.
  • multiple: specify that the number must be a multiple of this value.

The DateTime field also accept the min, max`, ``exclusiveMin and exclusiveMax optional arguments but they should be date or datetime (either as ISO strings or native objects).

my_fields = api.model('MyModel', {
    'name': fields.String(description='The name', required=True),
    'type': fields.String(description='The object type', enum=['A', 'B']),
    'age': fields.Integer(min=0),
})

Documenting the methods

Each resource will be documented as a Swagger path.

Each resource method (get, post, put, delete, path, options, head) will be documented as a swagger operation.

You can specify the Swagger unique operationId with the id documentation.

@api.route('/my-resource/')
class MyResource(Resource):
    @api.doc(id='get_something')
    def get(self):
        return {}

You can also use the first argument for the same purpose:

@api.route('/my-resource/')
class MyResource(Resource):
    @api.doc('get_something')
    def get(self):
        return {}

If not specified, a default operationId is provided with the following pattern:

{{verb}}_{{resource class name | camelCase2dashes }}

In the previous example, the default generated operationId will be get_my_resource

You can override the default operationId generator by giving a callable as default_id parameter to your API. This callable will receive two positional arguments:

  • the resource class name
  • this lower cased HTTP method
def default_id(resource, method):
    return ''.join((method, resource))

api = Api(app, default_id=default_id)

In the previous example, the generated operationId will be getMyResource

Each operation will automatically receive the namespace tag. If the resource is attached to the root API, it will receive the default namespace tag.

Method parameters

For each method, the path parameter are automatically extracted. You can provide additional parameters (from query parameters, body or form) or additional details on path parameters with the params documentation.

Input and output models

You can specify the serialized output model with the model documentation.

You can specify an input format for POST and PUT with the body documentation.

fields = api.model('MyModel', {
    'name': fields.String(description='The name', required=True),
    'type': fields.String(description='The object type', enum=['A', 'B']),
    'age': fields.Integer(min=0),
})


@api.model(fields={'name': fields.String, 'age': fields.Integer})
class Person(fields.Raw):
    def format(self, value):
        return {'name': value.name, 'age': value.age}


@api.route('/my-resource/<id>', endpoint='my-resource')
@api.doc(params={'id': 'An ID'})
class MyResource(Resource):
    @api.doc(model=fields)
    def get(self, id):
        return {}

    @api.doc(model='MyModel', body=Person)
    def post(self, id):
        return {}

You can’t have body and form or file parameters at the same time, it will raise a SpecsError.

Models can be specified with a RequestParser.

parser = api.parser()
parser.add_argument('param', type=int, help='Some param', location='form')
parser.add_argument('in_files', type=FileStorage, location='files')

@api.route('/with-parser/', endpoint='with-parser')
class WithParserResource(restplus.Resource):
    @api.doc(parser=parser)
    def get(self):
        return {}

Note

The decoded payload will be available as a dictionary in the payload attribute in the request context.

@api.route('/my-resource/')
class MyResource(Resource):
    def get(self):
        data = api.payload

Headers

You can document headers with the @api.header decorator shortcut.

@api.route('/with-headers/')
@api.header('X-Header', 'Some expected header', required=True)
class WithHeaderResource(restplus.Resource):
    @api.header('X-Collection', type=[str], collectionType='csv')
    def get(self):
        pass

Cascading

Documentation handling is done in cascade. Method documentation override class-wide documentation. Inherited documentation override parent one.

By example, these two declaration are equivalents:

@api.route('/my-resource/<id>', endpoint='my-resource')
@api.doc(params={'id': 'An ID'})
class MyResource(Resource):
    def get(self, id):
        return {}
@api.route('/my-resource/<id>', endpoint='my-resource')
@api.doc(params={'id': 'Class-wide description'})
class MyResource(Resource):
    @api.doc(params={'id': 'An ID'})
    def get(self, id):
        return {}

You can also provide method specific documentation from a class decoration. The following example will produce the same documentation than the two previous examples:

@api.route('/my-resource/<id>', endpoint='my-resource')
@api.doc(params={'id': 'Class-wide description'})
@api.doc(get={'params': {'id': 'An ID'}})
class MyResource(Resource):
    def get(self, id):
        return {}

Marking as deprecated

You can mark as deprecated some resources or methods with the @api.deprecated decorator:

# Deprecate the full resource
@api.deprecated
@api.route('/resource1/')
class Resource1(Resource):
    def get(self):
        return {}

# Hide methods
@api.route('/resource4/')
class Resource4(Resource):
    def get(self):
        return {}

    @api.deprecated
    def post(self):
        return {}

    def put(self):
        return {}

Hiding from documentation

You can hide some resources or methods from documentation using one of the following syntaxes:

# Hide the full resource
@api.route('/resource1/', doc=False)
class Resource1(Resource):
    def get(self):
        return {}

@api.route('/resource2/')
@api.doc(False)
class Resource2(Resource):
    def get(self):
        return {}

@api.route('/resource3/')
@api.hide
class Resource3(Resource):
    def get(self):
        return {}

# Hide methods
@api.route('/resource4/')
@api.doc(delete=False)
class Resource4(Resource):
    def get(self):
        return {}

    @api.doc(False)
    def post(self):
        return {}

    @api.hide
    def put(self):
        return {}

    def delete(self):
        return {}

Documenting autorizations

In order to document an authorization you can provide an authorization dictionary to the API constructor:

authorizations = {
    'apikey': {
        'type': 'apiKey',
        'in': 'header',
        'name': 'X-API-KEY'
    }
}
api = Api(app, authorizations=authorizations)

Next, you need to set the authorization documentation on each resource/method requiring it. You can use a decorator to make it easier:

def apikey(func):
    return api.doc(security='apikey')(func)

@api.route('/resource/')
class Resource1(Resource):
    @apikey
    def get(self):
        pass

    @api.doc(security='apikey')
    def post(self):
        pass

You can apply this requirement globally with the security constructor parameter:

authorizations = {
    'apikey': {
        'type': 'apiKey',
        'in': 'header',
        'name': 'X-API-KEY'
    }
}
api = Api(app, authorizations=authorizations, security='apikey')

You can have multiple security schemes:

authorizations = {
    'apikey': {
        'type': 'apiKey',
        'in': 'header',
        'name': 'X-API'
    },
    'oauth2': {
        'type': 'oauth2',
        'flow': 'accessCode',
        'tokenUrl': 'https://somewhere.com/token',
        'scopes': {
            'read': 'Grant read-only access',
            'write': 'Grant read-write access',
        }
    }
}
api = Api(self.app, security=['apikey', {'oauth2': 'read'}], authorizations=authorizations)

And compose/override them at method level:

@api.route('/authorizations/')
class Authorized(Resource):
    @api.doc(security=[{'oauth2': ['read', 'write']}])
    def get(self):
        return {}

You can disable security on a given resource/method by passing None or an empty list as security parameter:

@api.route('/without-authorization/')
class WithoutAuthorization(Resource):
    @api.doc(security=[])
    def get(self):
        return {}

    @api.doc(security=None)
    def post(self):
        return {}

Export Swagger specifications

You can export the Swagger specififcations corresponding to your API.

from flask import json

from myapp import api

print(json.dumps(api.__schema__))

Swagger UI

By default flask-restplus provide a Swagger UI documentation on your API root.

from flask import Flask
from flask_restplus import Api, Resource, fields

app = Flask(__name__)
api = Api(app, version='1.0', title='Sample API',
    description='A sample API',
)

@api.route('/my-resource/<id>')
@api.doc(params={'id': 'An ID'})
class MyResource(Resource):
    def get(self, id):
        return {}

    @api.response(403, 'Not Authorized')
    def post(self, id):
        api.abort(403)


if __name__ == '__main__':
    app.run(debug=True)

If you run the code below and visit your API root URL (http://localhost:5000) you will have an automatically generated SwaggerUI documentation.

_images/screenshot-apidoc-quickstart.png

Customization

You can control the Swagger UI path with the doc parameter (default to the API root):

from flask import Flask, Blueprint
from flask_restplus import Api

app = Flask(__name__)
blueprint = Blueprint('api', __name__, url_prefix='/api')
api = Api(blueprint, doc='/doc/')

app.register_blueprint(blueprint)

assert url_for('api.doc') == '/api/doc/'

You can specify a custom validator url by setting config.SWAGGER_VALIDATOR_URL:

from flask import Flask
from flask_restplus import Api

app = Flask(__name__)
app.config.SWAGGER_VALIDATOR_URL = 'http://domain.com/validator'

api = Api(app)

You can also specify the initial expansion state with the config.SWAGGER_UI_DOC_EXPANSION setting (none, list or full):

from flask import Flask
from flask_restplus import Api

app = Flask(__name__)
app.config.SWAGGER_UI_DOC_EXPANSION = 'list'

api = Api(app)

Latest version of Swagger UI added an optionnal JSON editor which can be enabled with with the config.SWAGGER_UI_JSONEDITOR:

from flask import Flask
from flask_restplus import Api

app = Flask(__name__)
app.config.SWAGGER_UI_JSONEDITOR = True

api = Api(app)

If you need a custom UI, you can register a custom view function with the documentation() decorator. You can provide a custom UI by reusing the apidoc blueprint or rolling your own from scratch.

from flask import Flask
from flask_restplus import API, apidoc

app = Flask(__name__)
api = Api(app)

@api.documentation
def custom_ui():
    return apidoc.ui_for(api)

Disabling the documentation

You can totally disable the generated Swagger UI by setting doc=False:

from flask import Flask
from flask_restplus import Api

app = Flask(__name__)
api = Api(app, doc=False)