Repository: falconry/falcon
Pull request #1592 (2019-10-26 16:35:20)

refactor(Api): Renamed API class, and all related docs.
# Summary of Changes
Renamed the `falcon.API` class to `falcon.App`, also added `API` alias, and updated all related docs and tests.

# Related Issues
https://github.com/falconry/falcon/issues/1579

# Pull Request Checklist

This is just a reminder about the most common mistakes.  Please make sure that you tick all *appropriate* boxes.  But please read our [contribution guide](https://github.com/falconry/falcon/blob/master/CONTRIBUTING.md) at least once; it will save you a few review cycles!

If an item doesn't apply to your pull request, **check it anyway** to make it apparent that there's nothing to do.

- [ ] Added **tests** for changed code.
- [ ] Prefixed code comments with GitHub nick and an appropriate prefix.
- [x] Coding style is consistent with the rest of the framework.
- [x] Updated **documentation** for changed code.
    - [x] Added docstrings for any new classes, functions, or modules.
    - [x] Updated docstrings for any modifications to existing code.
    - [x] Added references to new classes, functions, or modules to the relevant RST file under `docs/`.
    - [x] Updated all relevant supporting documentation files under `docs/`.
    - [ ] A copyright notice is included at the top of any new modules (using your own name or the name of your organization).
    - [] Changed/added classes/methods/functions have appropriate `versionadded`, `versionchanged`, or `deprecated` [directives](http://www.sphinx-doc.org/en/stable/usage/restructuredtext/directives.html?highlight=versionadded#directive-versionadded).
- [ ] Changes (and possible deprecations) have [towncrier](https://pypi.org/project/towncrier/) news fragments under `docs/_newsfragments/`. (Run `towncrier --draft` to ensure it renders correctly.)

codecov[bot]: # [Codecov](https://codecov.io/gh/falconry/falcon/pull/1592?src=pr&el=h1) Report
> Merging [#1592](https://codecov.io/gh/falconry/falcon/pull/1592?src=pr&el=desc) into [master](https://codecov.io/gh/falconry/falcon/commit/1e7e8c0a43debb9f56cb7b53cd01a89002e9e80d?src=pr&el=desc) will **not change** coverage.
> The diff coverage is `100%`.

[![Impacted file tree graph](https://codecov.io/gh/falconry/falcon/pull/1592/graphs/tree.svg?width=650&token=zOtkfNQ3h6&height=150&src=pr)](https://codecov.io/gh/falconry/falcon/pull/1592?src=pr&el=tree)

```diff
@@          Coverage Diff           @@
##           master   #1592   +/-   ##
======================================
  Coverage     100%    100%           
======================================
  Files          39      39           
  Lines        2578    2578           
  Branches      393     393           
======================================
  Hits         2578    2578
```


| [Impacted Files](https://codecov.io/gh/falconry/falcon/pull/1592?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [falcon/testing/\_\_init\_\_.py](https://codecov.io/gh/falconry/falcon/pull/1592/diff?src=pr&el=tree#diff-ZmFsY29uL3Rlc3RpbmcvX19pbml0X18ucHk=) | `100% <ø> (ø)` | :arrow_up: |
| [falcon/request.py](https://codecov.io/gh/falconry/falcon/pull/1592/diff?src=pr&el=tree#diff-ZmFsY29uL3JlcXVlc3QucHk=) | `100% <ø> (ø)` | :arrow_up: |
| [falcon/http\_error.py](https://codecov.io/gh/falconry/falcon/pull/1592/diff?src=pr&el=tree#diff-ZmFsY29uL2h0dHBfZXJyb3IucHk=) | `100% <ø> (ø)` | :arrow_up: |
| [falcon/media/json.py](https://codecov.io/gh/falconry/falcon/pull/1592/diff?src=pr&el=tree#diff-ZmFsY29uL21lZGlhL2pzb24ucHk=) | `100% <ø> (ø)` | :arrow_up: |
| [falcon/routing/compiled.py](https://codecov.io/gh/falconry/falcon/pull/1592/diff?src=pr&el=tree#diff-ZmFsY29uL3JvdXRpbmcvY29tcGlsZWQucHk=) | `100% <ø> (ø)` | :arrow_up: |
| [falcon/response.py](https://codecov.io/gh/falconry/falcon/pull/1592/diff?src=pr&el=tree#diff-ZmFsY29uL3Jlc3BvbnNlLnB5) | `100% <ø> (ø)` | :arrow_up: |
| [falcon/api\_helpers.py](https://codecov.io/gh/falconry/falcon/pull/1592/diff?src=pr&el=tree#diff-ZmFsY29uL2FwaV9oZWxwZXJzLnB5) | `100% <100%> (ø)` | :arrow_up: |
| [falcon/testing/test\_case.py](https://codecov.io/gh/falconry/falcon/pull/1592/diff?src=pr&el=tree#diff-ZmFsY29uL3Rlc3RpbmcvdGVzdF9jYXNlLnB5) | `100% <100%> (ø)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/falconry/falcon/pull/1592?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/falconry/falcon/pull/1592?src=pr&el=footer). Last update [1e7e8c0...130580e](https://codecov.io/gh/falconry/falcon/pull/1592?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

nZac: @mikeyusko also, can you add a [news fragement](https://github.com/falconry/falcon/tree/master/docs/_newsfragments) for this?
mikeyusko: > @mikeyusko I pushed one last commit which does a last `s/api/app` in some examples, hope you don't mind.
> 
> I am good on this one now. Thanks for your effort's, really thankful for you picking this one up!

@nZac Thank you a lot for the help! I've missed those docstrings;(
vytas7: @mikeyusko I pushed some tweaks onto your branch to make Sphinx complain less while still keeping the old changelogs intact at the same time.

Check if you are OK with my approach.
mikeyusko: > @mikeyusko I pushed some tweaks onto your branch to make Sphinx complain less while still keeping the old changelogs intact at the same time.
> 
> Check if you are OK with my approach.

@vytas7 Yes, I've checked and it looks fine for me, thanks a lot!

Patch:
diff --git a/docs/api/api.rst b/docs/api/api.rst
index 529929e..9bdb6ad 100644
--- a/docs/api/api.rst
+++ b/docs/api/api.rst
@@ -1,26 +1,5 @@
-.. _api:
-
-The API Class
-=============
-
-Falcon's API class is a WSGI "application" that you can host with any
-standard-compliant WSGI server.
-
-.. code:: python
-
-    import falcon
-
-    app = falcon.API()
+:orphan:
 
 .. autoclass:: falcon.API
     :members:
-
-.. autoclass:: falcon.RequestOptions
-    :members:
-
-.. autoclass:: falcon.ResponseOptions
-    :members:
-
-.. _compiled_router_options:
-.. autoclass:: falcon.routing.CompiledRouterOptions
-    :noindex:
+    :inherited-members:
diff --git a/docs/api/app.rst b/docs/api/app.rst
new file mode 100644
index 0000000..1bcc523
--- /dev/null
+++ b/docs/api/app.rst
@@ -0,0 +1,26 @@
+.. _app:
+
+The App Class
+=============
+
+Falcon's App class is a WSGI "application" that you can host with any
+standard-compliant WSGI server.
+
+.. code:: python
+
+    import falcon
+
+    app = falcon.App()
+
+.. autoclass:: falcon.App
+    :members:
+
+.. autoclass:: falcon.RequestOptions
+    :members:
+
+.. autoclass:: falcon.ResponseOptions
+    :members:
+
+.. _compiled_router_options:
+.. autoclass:: falcon.routing.CompiledRouterOptions
+    :noindex:
diff --git a/docs/api/cookies.rst b/docs/api/cookies.rst
index 462f95a..14f3972 100644
--- a/docs/api/cookies.rst
+++ b/docs/api/cookies.rst
@@ -99,7 +99,7 @@ the request.
 When running your application in a development environment, you can
 disable this default behavior by setting
 :py:attr:`~.ResponseOptions.secure_cookies_by_default` to ``False``
-via :any:`API.resp_options`. This lets you test your app locally
+via :any:`App.resp_options`. This lets you test your app locally
 without having to set up TLS. You can make this option configurable to
 easily switch between development and production environments.
 
diff --git a/docs/api/cors.rst b/docs/api/cors.rst
index 3a03f54..24a7bee 100644
--- a/docs/api/cors.rst
+++ b/docs/api/cors.rst
@@ -10,7 +10,7 @@ browsers to prevent unauthorized requests between different domains.
 When implementing
 a web API, it is common to have to also implement a CORS policy. Therefore,
 Falcon provides an easy way to enable a simple CORS policy via a flag passed
-to :any:`falcon.API`.
+to :any:`falcon.App`.
 
 By default, Falcon's built-in CORS support is disabled, so that any cross-origin
 requests will be blocked by the browser. Passing ``cors_enabled=True`` will
diff --git a/docs/api/errors.rst b/docs/api/errors.rst
index 88f2e2e..ec63c5b 100644
--- a/docs/api/errors.rst
+++ b/docs/api/errors.rst
@@ -15,7 +15,7 @@ HTTP response. The default error serializer supports both JSON and XML.
 If the client indicates acceptance of both JSON and XML with equal
 weight, JSON will be chosen. Other media types may be supported by
 overriding the default serializer via
-:meth:`~.API.set_error_serializer`.
+:meth:`~.App.set_error_serializer`.
 
 .. note::
 
@@ -63,7 +63,7 @@ All classes are available directly in the ``falcon`` package namespace::
 Note also that any exception (not just instances of
 :class:`~.HTTPError`) can be caught, logged, and otherwise handled
 at the global level by registering one or more custom error handlers.
-See also :meth:`~.API.add_error_handler` to learn more about this
+See also :meth:`~.App.add_error_handler` to learn more about this
 feature.
 
 .. note::
@@ -88,6 +88,7 @@ Predefined Errors
 -----------------
 
 .. automodule:: falcon
+    :noindex:
     :members: HTTPBadRequest,
         HTTPInvalidHeader, HTTPMissingHeader,
         HTTPInvalidParam, HTTPMissingParam,
diff --git a/docs/api/hooks.rst b/docs/api/hooks.rst
index 6866a46..4a4c797 100644
--- a/docs/api/hooks.rst
+++ b/docs/api/hooks.rst
@@ -41,7 +41,7 @@ decorate the resource class:
 
 .. note::
     When decorating an entire resource class, all method names that resemble
-    responders, including *suffix*\ed (see also :meth:`~falcon.API.add_route`)
+    responders, including *suffix*\ed (see also :meth:`~falcon.App.add_route`)
     ones, are decorated. If, for instance, a method is called ``on_get_items``,
     but it is not meant for handling ``GET`` requests under a route with the
     *suffix* ``items``, the easiest workaround for preventing the hook function
diff --git a/docs/api/index.rst b/docs/api/index.rst
index 52622f8..f5a4ef1 100644
--- a/docs/api/index.rst
+++ b/docs/api/index.rst
@@ -4,7 +4,7 @@ Classes and Functions
 .. toctree::
    :maxdepth: 2
 
-   api
+   app
    request_and_response
    cookies
    status
diff --git a/docs/api/media.rst b/docs/api/media.rst
index 06ec166..a7f7b06 100644
--- a/docs/api/media.rst
+++ b/docs/api/media.rst
@@ -6,7 +6,7 @@ Media
 Falcon allows for easy and customizable internet media type handling. By default
 Falcon only enables a single JSON handler. However, additional handlers
 can be configured through the :any:`falcon.RequestOptions` and
-:any:`falcon.ResponseOptions` objects specified on your :any:`falcon.API`.
+:any:`falcon.ResponseOptions` objects specified on your :any:`falcon.App`.
 
 .. note::
 
@@ -72,7 +72,7 @@ middleware. Here is an example of how this can be done:
 Replacing the Default Handlers
 ------------------------------
 
-When creating your API object you can either add or completely
+When creating your App object you can either add or completely
 replace all of the handlers. For example, lets say you want to write an API
 that sends and receives MessagePack. We can easily do this by telling our
 Falcon API that we want a default media-type of ``application/msgpack`` and
@@ -89,10 +89,10 @@ a handler that can process that data.
         'application/msgpack': media.MessagePackHandler(),
     })
 
-    api = falcon.API(media_type='application/msgpack')
+    app = falcon.App(media_type='application/msgpack')
 
-    api.req_options.media_handlers = handlers
-    api.resp_options.media_handlers = handlers
+    app.req_options.media_handlers = handlers
+    app.resp_options.media_handlers = handlers
 
 Alternatively, if you would like to add an additional handler such as
 MessagePack, this can be easily done in the following manner:
@@ -107,10 +107,10 @@ MessagePack, this can be easily done in the following manner:
         'application/msgpack': media.MessagePackHandler(),
     }
 
-    api = falcon.API()
+    app = falcon.App()
 
-    api.req_options.media_handlers.update(extra_handlers)
-    api.resp_options.media_handlers.update(extra_handlers)
+    app.req_options.media_handlers.update(extra_handlers)
+    app.resp_options.media_handlers.update(extra_handlers)
 
 
 Supported Handler Types
diff --git a/docs/api/middleware.rst b/docs/api/middleware.rst
index 77576bd..d50ca67 100644
--- a/docs/api/middleware.rst
+++ b/docs/api/middleware.rst
@@ -7,10 +7,10 @@ Middleware components provide a way to execute logic before the
 framework routes each request, after each request is routed but before
 the target responder is called, or just before the response is returned
 for each request. Components are registered with the `middleware` kwarg
-when instantiating Falcon's :ref:`API class <api>`.
+when instantiating Falcon's :ref:`App class <app>`.
 
 .. Note::
-    Unlike hooks, middleware methods apply globally to the entire API.
+    Unlike hooks, middleware methods apply globally to the entire App.
 
 Falcon's middleware interface is defined as follows:
 
@@ -79,7 +79,7 @@ Falcon's middleware interface is defined as follows:
 .. Tip::
     The *process_resource* method is only called when the request matches
     a route to a resource. To take action when a route is not found, a
-    :py:meth:`sink <falcon.API.add_sink>` may be used instead.
+    :py:meth:`sink <falcon.App.add_sink>` may be used instead.
 
 .. Tip::
     In order to pass data from a middleware function to a resource function
@@ -90,7 +90,7 @@ Falcon's middleware interface is defined as follows:
 Each component's *process_request*, *process_resource*, and
 *process_response* methods are executed hierarchically, as a stack, following
 the ordering of the list passed via the `middleware` kwarg of
-:ref:`falcon.API<api>`. For example, if a list of middleware objects are
+:ref:`falcon.App<app>`. For example, if a list of middleware objects are
 passed as ``[mob1, mob2, mob3]``, the order of execution is as follows::
 
     mob1.process_request
@@ -158,7 +158,7 @@ which case the framework will use the latter exception to update the
 
     By default, the framework installs two handlers, one for
     :class:`~.HTTPError` and one for :class:`~.HTTPStatus`. These can
-    be overridden via :meth:`~.API.add_error_handler`.
+    be overridden via :meth:`~.App.add_error_handler`.
 
 Regardless, the framework will continue unwinding the middleware
 stack. For example, if *mob2.process_request* were to raise an
@@ -177,7 +177,7 @@ error, the framework would execute the stack as follows::
 As illustrated above, by default, all *process_response* methods will be
 executed, even when a *process_request*, *process_resource*, or resource
 responder raises an error. This behavior is controlled by the
-:ref:`API class's <api>` `independent_middleware` keyword argument.
+:ref:`App class's <app>` `independent_middleware` keyword argument.
 
 Finally, if one of the *process_response* methods raises an error,
 or the routed ``on_*`` responder method itself raises an error, the
diff --git a/docs/api/routing.rst b/docs/api/routing.rst
index 7d7ca9c..acabc5f 100644
--- a/docs/api/routing.rst
+++ b/docs/api/routing.rst
@@ -40,10 +40,10 @@ Here's a quick example to show how all the pieces fit together:
             # illustrate how this may be overridden as needed.
             resp.status = falcon.HTTP_200
 
-    api = application = falcon.API()
+    app = application = falcon.App()
 
     images = ImagesResource()
-    api.add_route('/images', images)
+    app.add_route('/images', images)
 
 
 Default Router
@@ -52,7 +52,7 @@ Default Router
 Falcon's default routing engine is based on a decision tree that is
 first compiled into Python code, and then evaluated by the runtime.
 
-The :meth:`~.API.add_route` method is used to associate a URI template
+The :meth:`~.App.add_route` method is used to associate a URI template
 with a resource. Falcon then maps incoming requests to resources
 based on these templates.
 
@@ -110,7 +110,7 @@ data to hooks and middleware methods.
     :class:`~.HTTPError` or :class:`~.HTTPStatus`. Falcon will
     convert these exceptions to appropriate HTTP responses.
     Alternatively, you can handle them youself via
-    :meth:`~.API.add_error_handler`.
+    :meth:`~.App.add_error_handler`.
 
 In addition to the standard `req` and `resp` parameters, if the
 route's template contains field expressions, any responder that
@@ -168,19 +168,19 @@ specifications in the URI template:
 .. code:: python
 
     # IntConverter()
-    api.add_route(
+    app.add_route(
         '/a/{some_field:int}',
         some_resource
     )
 
     # IntConverter(8)
-    api.add_route(
+    app.add_route(
         '/b/{some_field:int(8)}',
         some_resource
     )
 
     # IntConverter(8, min=10000000)
-    api.add_route(
+    app.add_route(
         '/c/{some_field:int(8, min=10000000)}',
         some_resource
     )
@@ -223,12 +223,12 @@ Custom Routers
 --------------
 
 A custom routing engine may be specified when instantiating
-:py:meth:`falcon.API`. For example:
+:py:meth:`falcon.App`. For example:
 
 .. code:: python
 
     router = MyRouter()
-    api = API(router=router)
+    app = App(router=router)
 
 Custom routers may derive from the default :py:class:`~.CompiledRouter`
 engine, or implement a completely different routing strategy (such as
@@ -261,7 +261,7 @@ A custom router is any class that implements the following interface:
                     the resource.
 
                 **kwargs (dict): Accepts any additional keyword arguments
-                    that were originally passed to the falcon.API.add_route()
+                    that were originally passed to the falcon.App.add_route()
                     method. These arguments MUST be accepted via the
                     double-star variadic pattern (**kwargs), and ignore any
                     unrecognized or unsupported arguments.
diff --git a/docs/deploy/nginx-uwsgi.rst b/docs/deploy/nginx-uwsgi.rst
index 2cc6a07..4084b1b 100644
--- a/docs/deploy/nginx-uwsgi.rst
+++ b/docs/deploy/nginx-uwsgi.rst
@@ -79,14 +79,14 @@ Preparing your Application for Service
 For the purposes of this tutorial, we'll assume that you have implemented
 a way to configure your application, such as with a
 ``create_api()`` function or a module-level script. This role of this
-function or script is to supply an instance of :any:`falcon.API`, which
+function or script is to supply an instance of :any:`falcon.App`, which
 implements the standard WSGI callable interface.
 
-You will need to expose the :any:`falcon.API` instance in some way so that
+You will need to expose the :any:`falcon.App` instance in some way so that
 uWSGI can find it. For this tutorial we recommend creating a ``wsgi.py`` file.
 Modify the logic of the following example file to properly configure your
 application.  Ensure that you expose a variable called ``application`` which
-is assigned to your :any:`falcon.API` instance.
+is assigned to your :any:`falcon.App` instance.
 
 .. code-block:: python
   :caption: /home/myproject/src/wsgi.py
diff --git a/docs/index.rst b/docs/index.rst
index 0934c65..67830a5 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -32,8 +32,8 @@ clean design that embraces HTTP and the REST architectural style.
             resp.media = quote
 
 
-    api = falcon.API()
-    api.add_route('/quote', QuoteResource())
+    app = falcon.App()
+    app.add_route('/quote', QuoteResource())
 
 What People are Saying
 ----------------------
diff --git a/docs/user/faq.rst b/docs/user/faq.rst
index 890b2e8..cf2c4ec 100644
--- a/docs/user/faq.rst
+++ b/docs/user/faq.rst
@@ -48,7 +48,7 @@ that in mind, writing a high-quality API based on Falcon requires that:
 
 .. tip:: Falcon will re-raise errors that do not inherit from
     :class:`~falcon.HTTPError` unless you have registered a custom error
-    handler for that type (see also: :ref:`falcon.API <api>`).
+    handler for that type (see also: :ref:`falcon.App <app>`).
 
 How do I generate API documentation for my Falcon API?
 ------------------------------------------------------
@@ -271,8 +271,8 @@ same resource class:
 
 
     resource = MyResource()
-    api.add_route('/resources/{id}', resource)
-    api.add_route('/resources', resource, suffix='collection')
+    app.add_route('/resources/{id}', resource)
+    app.add_route('/resources', resource, suffix='collection')
 
 What is the recommended way to map related routes to resource classes?
 ----------------------------------------------------------------------
@@ -340,7 +340,7 @@ classes:
             pass
 
 
-    api = falcon.API()
+    app = falcon.App()
 
     # Game and GameState are closely related, and so it
     # probably makes sense for them to share an object
@@ -354,9 +354,9 @@ classes:
     # layer.
     game_dao = myapp.DAL.Game(myconfig)
 
-    api.add_route('/game/ping', Ping())
-    api.add_route('/game/{game_id}', Game(game_dao))
-    api.add_route('/game/{game_id}/state', GameState(game_dao))
+    app.add_route('/game/ping', Ping())
+    app.add_route('/game/{game_id}', Game(game_dao))
+    app.add_route('/game/{game_id}/state', GameState(game_dao))
 
 Alternatively, a single resource class could implement suffixed responders in
 order to handle all three routes:
@@ -387,20 +387,20 @@ order to handle all three routes:
     # ...
 
 
-    api = falcon.API()
+    app = falcon.App()
 
     game = Game(myapp.DAL.Game(myconfig))
 
-    api.add_route('/game/{game_id}', game)
-    api.add_route('/game/{game_id}/state', game, suffix='state')
-    api.add_route('/game/ping', game, suffix='ping')
+    app.add_route('/game/{game_id}', game)
+    app.add_route('/game/{game_id}/state', game, suffix='state')
+    app.add_route('/game/ping', game, suffix='ping')
 
 Extensibility
 ~~~~~~~~~~~~~
 
 How do I use WSGI middleware with Falcon?
 -----------------------------------------
-Instances of :class:`falcon.API` are first-class WSGI apps, so you can use the
+Instances of :class:`falcon.App` are first-class WSGI apps, so you can use the
 standard pattern outlined in PEP-3333. In your main "app" file, you would
 simply wrap your api instance with a middleware app. For example:
 
@@ -409,7 +409,7 @@ simply wrap your api instance with a middleware app. For example:
     import my_restful_service
     import some_middleware
 
-    app = some_middleware.DoSomethingFancy(my_restful_service.api)
+    app = some_middleware.DoSomethingFancy(my_restful_service.app)
 
 See also the `WSGI middleware example <https://www.python.org/dev/peps/pep-3333/#middleware-components-that-play-both-sides>`_ given in PEP-3333.
 
@@ -441,7 +441,7 @@ How can I write a custom handler for 404 and 500 pages in falcon?
 ------------------------------------------------------------------
 When a route can not be found for an incoming request, Falcon uses a default
 responder that simply raises an instance of :attr:`falcon.HTTPNotFound`. You
-can use :meth:`falcon.API.add_error_handler` to register a custom error handler
+can use :meth:`falcon.App.add_error_handler` to register a custom error handler
 for this exception type. Alternatively, you may be able to configure your web
 server to transform the response for you (e.g., using Nginx's ``error_page``
 directive).
@@ -504,11 +504,11 @@ parameter being ignored.
 If you would like to recognize such parameters, you must set the
 `keep_blank_qs_values` request option to ``True``. Request options are set
 globally for each instance of :class:`falcon.API` via the
-:attr:`~falcon.API.req_options` property. For example:
+:attr:`~falcon.App.req_options` property. For example:
 
 .. code:: python
 
-    api.req_options.keep_blank_qs_values = True
+    app.req_options.keep_blank_qs_values = True
 
 Why are '+' characters in my params being converted to spaces?
 --------------------------------------------------------------
@@ -525,7 +525,7 @@ How can I access POSTed form params?
 ------------------------------------
 By default, Falcon does not consume request bodies. However, setting
 the :attr:`~RequestOptions.auto_parse_form_urlencoded` to ``True``
-on an instance of ``falcon.API``
+on an instance of ``falcon.App``
 will cause the framework to consume the request body when the
 content type is ``application/x-www-form-urlencoded``, making
 the form parameters accessible via :attr:`~.Request.params`,
@@ -533,7 +533,7 @@ the form parameters accessible via :attr:`~.Request.params`,
 
 .. code:: python
 
-    api.req_options.auto_parse_form_urlencoded = True
+    app.req_options.auto_parse_form_urlencoded = True
 
 Alternatively, :class:`falcon.media.URLEncodedFormHandler` may be
 :ref:`installed <custom_media_handlers>` to handle the
@@ -619,11 +619,11 @@ so one possible solution is to percent encode any commas that appear in your
 JSON query string. The other option is to switch the way Falcon
 handles commas in a query string by setting the
 :attr:`~falcon.RequestOptions.auto_parse_qs_csv` to ``False`` on an instance of
-:class:`falcon.API`:
+:class:`falcon.App`:
 
 .. code:: python
 
-    api.req_options.auto_parse_qs_csv = False
+    app.req_options.auto_parse_qs_csv = False
 
 When :attr:`~falcon.RequestOptions.auto_parse_qs_csv` is set to ``False``, the
 value of the query string ``?c={'a':1,'b':2}`` will be added to
@@ -687,7 +687,7 @@ types:
 
     # ...
 
-    api = falcon.API(request_type=RequestWithDictContext,
+    app = falcon.App(request_type=RequestWithDictContext,
                      response_type=ResponseWithDictContext)
 
 Response Handling
@@ -766,7 +766,7 @@ Falcon attempts to serialize the :class:`~falcon.HTTPError` instance using its
 :meth:`~falcon.HTTPError.to_json` or :meth:`~falcon.HTTPError.to_xml` methods,
 according to the Accept header in the request. If neither JSON nor XML is
 acceptable, no response body will be generated. You can override this behavior
-if needed via :meth:`~falcon.API.set_error_serializer`.
+if needed via :meth:`~falcon.App.set_error_serializer`.
 
 I'm setting a response body, but it isn't getting returned. What's going on?
 ----------------------------------------------------------------------------
@@ -809,7 +809,7 @@ Can Falcon serve static files?
 Falcon makes it easy to efficiently serve static files by simply assigning an
 open file to ``resp.stream`` :ref:`as demonstrated in the tutorial
 <tutorial-serving-images>`. You can also serve an entire directory of files via
-:meth:`falcon.API.add_static_route`. However, if possible, it is best to serve
+:meth:`falcon.App.add_static_route`. However, if possible, it is best to serve
 static files directly from a web server like Nginx, or from a CDN.
 
 Misc.
diff --git a/docs/user/quickstart.rst b/docs/user/quickstart.rst
index 5442074..8433706 100644
--- a/docs/user/quickstart.rst
+++ b/docs/user/quickstart.rst
@@ -36,9 +36,9 @@ started writing an API:
                          '    ~ Immanuel Kant\n\n')
 
 
-    # falcon.API instances are callable WSGI apps
+    # falcon.App instances are callable WSGI apps
     # in larger applications the app is created in a separate file
-    app = falcon.API()
+    app = falcon.App()
 
     # Resources are represented by long-lived class instances
     things = ThingsResource()
@@ -277,7 +277,7 @@ parameters, handling errors, and working with request and response bodies.
 
 
     # Configure your WSGI server to load "things.app" (app is a WSGI callable)
-    app = falcon.API(middleware=[
+    app = falcon.App(middleware=[
         AuthMiddleware(),
         RequireJSON(),
         JSONTranslator(),
diff --git a/docs/user/tutorial.rst b/docs/user/tutorial.rst
index 7ac9568..3341848 100644
--- a/docs/user/tutorial.rst
+++ b/docs/user/tutorial.rst
@@ -55,7 +55,7 @@ Now, open ``app.py`` in your favorite text editor and add the following lines:
 
     import falcon
 
-    api = application = falcon.API()
+    app = application = falcon.App()
 
 This code creates your WSGI application and aliases it as ``api``. You can use any
 variable names you like, but we'll use ``application`` since that is what
@@ -67,7 +67,7 @@ in the next section of the tutorial).
     you can host the application with any web server that understands the `WSGI
     protocol <http://legacy.python.org/dev/peps/pep-3333/>`_.
 
-Next let's take a look at the :class:`falcon.API` class. Install
+Next let's take a look at the :class:`falcon.App` class. Install
 `IPython <http://ipython.org/>`_ and fire it up:
 
 .. code:: bash
@@ -75,19 +75,19 @@ Next let's take a look at the :class:`falcon.API` class. Install
     $ pip install ipython
     $ ipython
 
-Now, type the following to introspect the :class:`falcon.API` callable:
+Now, type the following to introspect the :class:`falcon.App` callable:
 
 .. code:: bash
 
     In [1]: import falcon
 
-    In [2]: falcon.API.__call__?
+    In [2]: falcon.App.__call__?
 
 Alternatively, you can use the standard Python ``help()`` function:
 
 .. code:: bash
 
-    In [3]: help(falcon.API.__call__)
+    In [3]: help(falcon.App.__call__)
 
 Note the method signature. ``env`` and ``start_response`` are standard
 WSGI params. Falcon adds a thin abstraction on top of these params
@@ -129,7 +129,7 @@ since the latter doesn't work under Windows:
 .. code:: bash
 
     $ pip install waitress
-    $ waitress-serve --port=8000 look.app:api
+    $ waitress-serve --port=8000 look.app:app
 
 Now, in a different terminal, try querying the running app with curl:
 
@@ -282,10 +282,10 @@ Next let's wire up this resource and see it in action. Go back to
     from .images import Resource
 
 
-    api = application = falcon.API()
+    app = application = falcon.App()
 
     images = Resource()
-    api.add_route('/images', images)
+    app.add_route('/images', images)
 
 Now, when a request comes in for ``/images``, Falcon will call the
 responder on the images resource that corresponds to the requested
@@ -421,7 +421,7 @@ now look like this:
         ├── __init__.py
         └── test_app.py
 
-Falcon supports :ref:`testing <testing>` its :class:`~.API` object by
+Falcon supports :ref:`testing <testing>` its :class:`~.App` object by
 simulating HTTP requests.
 
 Tests can either be written using Python's standard :mod:`unittest`
@@ -447,12 +447,12 @@ Next, edit ``test_app.py`` to look like this:
     import msgpack
     import pytest
 
-    from look.app import api
+    from look.app import app
 
 
     @pytest.fixture
     def client():
-        return testing.TestClient(api)
+        return testing.TestClient(app)
 
 
     # pytest will inject the object returned by the "client" function
@@ -767,11 +767,11 @@ Hmm, it looks like we forgot to update ``app.py``. Let's do that now:
     from .images import ImageStore, Resource
 
 
-    api = application = falcon.API()
+    app = application = falcon.App()
 
     image_store = ImageStore('.')
     images = Resource(image_store)
-    api.add_route('/images', images)
+    app.add_route('/images', images)
 
 Let's try again:
 
@@ -793,9 +793,9 @@ similar to the following:
 
     def create_app(image_store):
         image_resource = Resource(image_store)
-        api = falcon.API()
-        api.add_route('/images', image_resource)
-        return api
+        app = falcon.App()
+        app.add_route('/images', image_resource)
+        return app
 
 
     def get_app():
@@ -803,7 +803,7 @@ similar to the following:
         return create_app(image_store)
 
 As you can see, the bulk of the setup logic has been moved to
-``create_app()``, which can be used to obtain an API object either
+``create_app()``, which can be used to obtain an App object either
 for testing or for hosting in production.
 ``get_app()`` takes care of instantiating additional resources and
 configuring the application for hosting.
@@ -840,8 +840,8 @@ look similar to this:
 
     @pytest.fixture
     def client(mock_store):
-        api = look.app.create_app(mock_store)
-        return testing.TestClient(api)
+        app = look.app.create_app(mock_store)
+        return testing.TestClient(app)
 
 
     def test_list_images(client):
@@ -1021,9 +1021,9 @@ the image storage directory with an environment variable:
 
     def create_app(image_store):
         image_resource = Resource(image_store)
-        api = falcon.API()
-        api.add_route('/images', image_resource)
-        return api
+        app = falcon.App()
+        app.add_route('/images', image_resource)
+        return app
 
 
     def get_app():
@@ -1179,7 +1179,7 @@ Go ahead and edit your ``images.py`` file to look something like this:
 As you can see, we renamed ``Resource`` to ``Collection`` and added a new ``Item``
 class to represent a single image resource. Alternatively, these two classes could
 be consolidated into one by using suffixed responders. (See also:
-:meth:`~falcon.API.add_route`)
+:meth:`~falcon.App.add_route`)
 
 Also, note the ``name`` parameter for the ``on_get()`` responder. Any URI
 parameters that you specify in your routes will be turned into corresponding
@@ -1213,10 +1213,10 @@ similar to the following:
 
 
     def create_app(image_store):
-        api = falcon.API()
-        api.add_route('/images', images.Collection(image_store))
-        api.add_route('/images/{name}', images.Item(image_store))
-        return api
+        app = falcon.App()
+        app.add_route('/images', images.Collection(image_store))
+        app.add_route('/images/{name}', images.Item(image_store))
+        return app
 
 
     def get_app():
@@ -1403,7 +1403,7 @@ for each error type.
     for logging and otherwise handling exceptions raised by
     responders, hooks, and middleware components.
 
-    See also: :meth:`~.API.add_error_handler`.
+    See also: :meth:`~.App.add_error_handler`.
 
 Let's see a quick example of how this works. Try requesting an invalid
 image name from your application:
diff --git a/falcon/__init__.py b/falcon/__init__.py
index 3a982c5..1ec4597 100644
--- a/falcon/__init__.py
+++ b/falcon/__init__.py
@@ -20,14 +20,14 @@ the framework's classes, functions, and variables::
 
     import falcon
 
-    app = falcon.API()
+    app = falcon.App()
 
 """
 
 # Hoist classes and functions into the falcon namespace
 from falcon.version import __version__  # NOQA
 from falcon.constants import *  # NOQA
-from falcon.api import API  # NOQA
+from falcon.app import App, API  # NOQA
 from falcon.status_codes import *  # NOQA
 from falcon.errors import *  # NOQA
 from falcon.redirects import *  # NOQA
diff --git a/falcon/api_helpers.py b/falcon/api_helpers.py
index a2e00d2..78afed9 100644
--- a/falcon/api_helpers.py
+++ b/falcon/api_helpers.py
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-"""Utilities for the API class."""
+"""Utilities for the App class."""
 
 from falcon import util
 
diff --git a/falcon/api.py b/falcon/app.py
similarity index 96%
rename from falcon/api.py
rename to falcon/app.py
index 59bd1ab..be2ef5d 100644
--- a/falcon/api.py
+++ b/falcon/app.py
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-"""Falcon API class."""
+"""Falcon App class."""
 
 from functools import wraps
 import re
@@ -44,12 +44,18 @@ _TYPELESS_STATUS_CODES = frozenset([
 ])
 
 
-class API:
+class App:
     """This class is the main entry point into a Falcon-based app.
 
-    Each API instance provides a callable WSGI interface and a routing
+    Each App instance provides a callable WSGI interface and a routing
     engine.
 
+    Note:
+        The ``API`` class was renamed to ``App`` in Falcon 3.0. The
+        old class name remains available as an alias for
+        backwards-compatibility, but will be removed in a future
+        release.
+
     Keyword Arguments:
         media_type (str): Default media type to use as the
             value for the Content-Type header on responses (default
@@ -218,9 +224,9 @@ class API:
     def __call__(self, env, start_response):  # noqa: C901
         """WSGI `app` method.
 
-        Makes instances of API callable from a WSGI server. May be used to
-        host an API or called directly in order to simulate requests when
-        testing the API.
+        Makes instances of App callable from a WSGI server. May be used to
+        host an App or called directly in order to simulate requests when
+        testing the App.
 
         (See also: PEP 3333)
 
@@ -371,7 +377,7 @@ class API:
 
         This method delegates to the configured router's ``add_route()``
         method. To override the default behavior, pass a custom router
-        object to the :class:`~.API` initializer.
+        object to the :class:`~.App` initializer.
 
         (See also: :ref:`Routing <routing>`)
 
@@ -447,8 +453,8 @@ class API:
         ``'/foo/bar'`` route, and ``'/foo/xyz/thing.js'`` being mapped to the
         ``'/foo'`` route::
 
-            api.add_static_route('/foo', foo_path)
-            api.add_static_route('/foo/bar', foobar_path)
+            app.add_static_route('/foo', foo_path)
+            app.add_static_route('/foo/bar', foobar_path)
 
         Args:
             prefix (str): The path prefix to match for this route. If the
@@ -478,7 +484,7 @@ class API:
         )
 
     def add_sink(self, sink, prefix=r'/'):
-        """Register a sink method for the API.
+        """Register a sink method for the App.
 
         If no route matches a request, but the path in the requested URI
         matches a sink prefix, Falcon will pass control to the
@@ -540,7 +546,7 @@ class API:
         standard ``Exception`` type) should be added first, to avoid
         masking more specific handlers for subclassed types. For example::
 
-            app = falcon.API()
+            app = falcon.App()
             app.add_error_handler(Exception, custom_handle_uncaught_exception)
             app.add_error_handler(falcon.HTTPError, custom_handle_http_error)
             app.add_error_handler(CustomException)
@@ -886,3 +892,22 @@ class API:
             return iterable, None
 
         return [], 0
+
+
+# TODO(mikeyusko): This class is a compatibility alias, and should be removed
+# in the next major release (4.0).
+class API(App):
+    """
+    This class is a compatibility alias of :class:`falcon.App`.
+
+    ``API`` was renamed to :class:`App <falcon.App>` in Falcon 3.0 in order to
+    reflect the breadth of applications that :class:`App <falcon.App>`, and its
+    ASGI counterpart in particular, can now be used for.
+
+    This compatibility alias should be considered deprecated; it will be
+    removed in a future release.
+    """
+
+    @misc.deprecated('API class may be removed in a future release, use falcon.App instead.')
+    def __init__(self, *args, **kwargs):
+        super().__init__(*args, **kwargs)
diff --git a/falcon/bench/create.py b/falcon/bench/create.py
index b595029..09547e4 100644
--- a/falcon/bench/create.py
+++ b/falcon/bench/create.py
@@ -20,7 +20,7 @@ def falcon(body, headers):
     import falcon
 
     path = '/hello/{account_id}/test'
-    falcon_app = falcon.API('text/plain')
+    falcon_app = falcon.App('text/plain')
 
     # def ask(req, resp, params):
     #     params['answer'] = 42
diff --git a/falcon/bench/queues/api.py b/falcon/bench/queues/api.py
index f0105c7..28690ea 100644
--- a/falcon/bench/queues/api.py
+++ b/falcon/bench/queues/api.py
@@ -61,7 +61,7 @@ def create(body, headers):
         CannedResponseComponent(body, headers),
     ]
 
-    api = falcon.API(middleware=middleware)
+    api = falcon.App(middleware=middleware)
     api.add_route('/v1/{tenant_id}/queues', queue_collection)
     api.add_route('/v1/{tenant_id}/queues/{queue_name}', queue_item)
     api.add_route('/v1/{tenant_id}/queues/{queue_name}'
diff --git a/falcon/cmd/print_routes.py b/falcon/cmd/print_routes.py
index 8dae8bb..1915212 100644
--- a/falcon/cmd/print_routes.py
+++ b/falcon/cmd/print_routes.py
@@ -13,7 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 """
-Script that prints out the routes of an API instance.
+Script that prints out the routes of an App instance.
 """
 
 from functools import partial
@@ -26,8 +26,8 @@ def print_routes(api, verbose=False):  # pragma: no cover
     """
     Initial call.
 
-    :param api: The falcon.API or callable that returns an instance to look at.
-    :type api: falcon.API or callable
+    :param api: The falcon.App or callable that returns an instance to look at.
+    :type api: falcon.App or callable
     :param verbose: If the output should be verbose.
     :type verbose: bool
     """
@@ -38,8 +38,8 @@ def traverse(roots, parent='', verbose=False):
     """
     Recursive call which also handles printing output.
 
-    :param api: The falcon.API or callable that returns an instance to look at.
-    :type api: falcon.API or callable
+    :param api: The falcon.App or callable that returns an instance to look at.
+    :type api: falcon.App or callable
     :param parent: The parent uri path to the current iteration.
     :type parent: str
     :param verbose: If the output should be verbose.
@@ -98,17 +98,17 @@ def main():
             'The api_module must include a colon between '
             'the module and instance')
     api = getattr(__import__(module, fromlist=[True]), instance)
-    if not isinstance(api, falcon.API):
+    if not isinstance(api, falcon.App):
         if callable(api):
             api = api()
-            if not isinstance(api, falcon.API):
+            if not isinstance(api, falcon.App):
                 parser.error(
-                    '{0} did not return a falcon.API instance'.format(
+                    '{0} did not return a falcon.App instance'.format(
                         args.api_module))
         else:
             parser.error(
-                'The instance must be of falcon.API or be '
-                'a callable without args that returns falcon.API')
+                'The instance must be of falcon.App or be '
+                'a callable without args that returns falcon.App')
     print_routes(api, verbose=args.verbose)
 
 
diff --git a/falcon/http_error.py b/falcon/http_error.py
index 4d97ebe..e32c5ed 100644
--- a/falcon/http_error.py
+++ b/falcon/http_error.py
@@ -29,8 +29,8 @@ class HTTPError(Exception):
     are supported by default.
 
     To customize the error presentation, implement a custom error
-    serializer and set it on the :class:`~.API` instance via
-    :meth:`~.API.set_error_serializer`.
+    serializer and set it on the :class:`~.App` instance via
+    :meth:`~.App.set_error_serializer`.
 
     To customize what data is passed to the serializer, subclass
     ``HTTPError`` and override the ``to_dict()`` method (``to_json()``
@@ -65,7 +65,7 @@ class HTTPError(Exception):
         href (str): A URL someone can visit to find out more information
             (default ``None``). Unicode characters are percent-encoded.
         href_text (str): If href is given, use this as the friendly
-            title/description for the link (default 'API documentation
+            title/description for the link (default 'App documentation
             for this error').
         code (int): An internal code that customers can reference in their
             support request or to help them when searching for knowledge
@@ -83,7 +83,7 @@ class HTTPError(Exception):
 
             Note:
                 A custom error serializer
-                (see :meth:`~.API.set_error_serializer`) may choose to set a
+                (see :meth:`~.App.set_error_serializer`) may choose to set a
                 response body regardless of the value of this property.
 
         title (str): Error title to send to the client.
diff --git a/falcon/media/json.py b/falcon/media/json.py
index 54d23c1..73e3ac7 100644
--- a/falcon/media/json.py
+++ b/falcon/media/json.py
@@ -36,9 +36,9 @@ class JSONHandler(BaseHandler):
             'application/json': json_handler,
         }
 
-        api = falcon.API()
-        api.req_options.media_handlers.update(extra_handlers)
-        api.resp_options.media_handlers.update(extra_handlers)
+        app = falcon.App()
+        app.req_options.media_handlers.update(extra_handlers)
+        app.resp_options.media_handlers.update(extra_handlers)
 
     By default, ``ensure_ascii`` is passed to the ``json.dumps`` function.
     If you override the ``dumps`` function, you will need to explicitly set
diff --git a/falcon/request.py b/falcon/request.py
index aa27d69..e389039 100644
--- a/falcon/request.py
+++ b/falcon/request.py
@@ -50,7 +50,7 @@ class Request:
             also PEP-3333.
 
     Keyword Arguments:
-        options (dict): Set of global options passed from the API handler.
+        options (dict): Set of global options passed from the App handler.
 
     Attributes:
         env (dict): Reference to the WSGI environ ``dict`` passed in from the
@@ -74,7 +74,7 @@ class Request:
             the framework will instantiate bare objects (instances of the bare
             :class:`falcon.Context` class). However, you may override this
             behavior by creating a custom child class of ``falcon.Request``,
-            and then passing that new class to `falcon.API()` by way of the
+            and then passing that new class to `falcon.App()` by way of the
             latter's `request_type` parameter.
 
             Note:
@@ -395,7 +395,7 @@ class Request:
             string, the value mapped to that parameter key will be a list of
             all the values in the order seen.
 
-        options (dict): Set of global options passed from the API handler.
+        options (dict): Set of global options passed from the App handler.
     """
 
     __slots__ = (
@@ -1162,7 +1162,7 @@ class Request:
             and merge them into the query string parameters. To enable
             this functionality, set
             :py:attr:`~.RequestOptions.auto_parse_form_urlencoded` to
-            ``True`` via :any:`API.req_options`.
+            ``True`` via :any:`App.req_options`.
 
         Note:
             Similar to the way multiple keys in form data is handled,
@@ -1793,7 +1793,7 @@ class Request:
 class RequestOptions:
     """Defines a set of configurable request options.
 
-    An instance of this class is exposed via :any:`API.req_options` for
+    An instance of this class is exposed via :any:`App.req_options` for
     configuring certain :py:class:`~.Request` behaviors.
 
     Attributes:
@@ -1849,7 +1849,7 @@ class RequestOptions:
 
         default_media_type (str): The default media-type to use when
             deserializing a response. This value is normally set to the media
-            type provided when a :class:`falcon.API` is initialized; however,
+            type provided when a :class:`falcon.App` is initialized; however,
             if created independently, this will default to the
             ``DEFAULT_MEDIA_TYPE`` specified by Falcon.
 
diff --git a/falcon/response.py b/falcon/response.py
index 4d7e0ae..1cfb607 100644
--- a/falcon/response.py
+++ b/falcon/response.py
@@ -52,7 +52,7 @@ class Response:
         `Response` is not meant to be instantiated directly by responders.
 
     Keyword Arguments:
-        options (dict): Set of global options passed from the API handler.
+        options (dict): Set of global options passed from the App handler.
 
     Attributes:
         status (str): HTTP status line (e.g., '200 OK'). Falcon requires the
@@ -125,7 +125,7 @@ class Response:
             the framework will instantiate bare objects (instances of the bare
             :class:`falcon.Context` class). However, you may override this
             behavior by creating a custom child class of ``falcon.Response``,
-            and then passing that new class to `falcon.API()` by way of the
+            and then passing that new class to `falcon.App()` by way of the
             latter's `response_type` parameter.
 
             Note:
@@ -134,7 +134,7 @@ class Response:
                 the current Response instance. Therefore the first argument is
                 the Response instance itself (self).
 
-        options (dict): Set of global options passed from the API handler.
+        options (dict): Set of global options passed from the App handler.
 
         headers (dict): Copy of all headers set for the response,
             sans cookies. Note that a new copy is created and returned each
@@ -346,7 +346,7 @@ class Response:
                     The default value for this argument is normally
                     ``True``, but can be modified by setting
                     :py:attr:`~.ResponseOptions.secure_cookies_by_default`
-                    via :any:`API.resp_options`.
+                    via :any:`App.resp_options`.
 
                 Warning:
                     For the `secure` cookie attribute to be effective,
@@ -1017,7 +1017,7 @@ class Response:
 class ResponseOptions:
     """Defines a set of configurable response options.
 
-    An instance of this class is exposed via :any:`API.resp_options` for
+    An instance of this class is exposed via :any:`App.resp_options` for
     configuring certain :py:class:`~.Response` behaviors.
 
     Attributes:
@@ -1029,7 +1029,7 @@ class ResponseOptions:
 
         default_media_type (str): The default Internet media type (RFC 2046) to
             use when deserializing a response. This value is normally set to the
-            media type provided when a :class:`falcon.API` is initialized;
+            media type provided when a :class:`falcon.App` is initialized;
             however, if created independently, this will default to the
             ``DEFAULT_MEDIA_TYPE`` specified by Falcon.
 
diff --git a/falcon/routing/compiled.py b/falcon/routing/compiled.py
index 0e70876..890788a 100644
--- a/falcon/routing/compiled.py
+++ b/falcon/routing/compiled.py
@@ -41,7 +41,7 @@ class CompiledRouter:
     """Fast URI router which compiles its routing logic to Python code.
 
     Generally you do not need to use this router class directly, as an
-    instance is created by default when the falcon.API class is initialized.
+    instance is created by default when the falcon.App class is initialized.
 
     The router treats URI paths as a tree of URI segments and searches by
     checking the URI one segment at a time. Instead of interpreting the route
@@ -668,7 +668,7 @@ class ConverterDict(UserDict):
 class CompiledRouterOptions:
     """Defines a set of configurable router options.
 
-    An instance of this class is exposed via :any:`API.router_options`
+    An instance of this class is exposed via :any:`App.router_options`
     for configuring certain :py:class:`~.CompiledRouter` behaviors.
 
     Attributes:
@@ -677,12 +677,12 @@ class CompiledRouterOptions:
             expressions. Adding additional converters is simply a
             matter of mapping an identifier to a converter class::
 
-                api.router_options.converters['mc'] = MyConverter
+                app.router_options.converters['mc'] = MyConverter
 
             The identifier can then be used to employ the converter
             within a URI template::
 
-                api.add_route('/{some_field:mc}', some_resource)
+                app.add_route('/{some_field:mc}', some_resource)
 
             Converter names may only contain ASCII letters, digits,
             and underscores, and must start with either a letter or


Test patch:
diff --git a/falcon/testing/__init__.py b/falcon/testing/__init__.py
index 14c49ec..9540d8b 100644
--- a/falcon/testing/__init__.py
+++ b/falcon/testing/__init__.py
@@ -34,7 +34,7 @@ The testing framework supports both unittest and pytest::
 
             # Assume the hypothetical `myapp` package has a
             # function called `create()` to initialize and
-            # return a `falcon.API` instance.
+            # return a `falcon.App` instance.
             self.app = myapp.create()
 
 
@@ -63,7 +63,7 @@ The testing framework supports both unittest and pytest::
     @pytest.fixture()
     def client():
         # Assume the hypothetical `myapp` package has a function called
-        # `create()` to initialize and return a `falcon.API` instance.
+        # `create()` to initialize and return a `falcon.App` instance.
         return testing.TestClient(myapp.create())
 
 
diff --git a/falcon/testing/test_case.py b/falcon/testing/test_case.py
index e929390..6f89c32 100644
--- a/falcon/testing/test_case.py
+++ b/falcon/testing/test_case.py
@@ -46,9 +46,9 @@ class TestCase(unittest.TestCase, TestClient):
 
     Attributes:
         app (object): A WSGI application to target when simulating
-            requests (default: ``falcon.API()``). When testing your
+            requests (default: ``falcon.App()``). When testing your
             application, you will need to set this to your own instance
-            of ``falcon.API``. For example::
+            of ``falcon.App``. For example::
 
                 from falcon import testing
                 import myapp
@@ -60,7 +60,7 @@ class TestCase(unittest.TestCase, TestClient):
 
                         # Assume the hypothetical `myapp` package has a
                         # function called `create()` to initialize and
-                        # return a `falcon.API` instance.
+                        # return a `falcon.App` instance.
                         self.app = myapp.create()
 
 
@@ -75,7 +75,7 @@ class TestCase(unittest.TestCase, TestClient):
     def setUp(self):
         super(TestCase, self).setUp()
 
-        app = falcon.API()
+        app = falcon.App()
 
         # NOTE(kgriffs): Don't use super() to avoid triggering
         # unittest.TestCase.__init__()
diff --git a/tests/bare_bones.py b/tests/bare_bones.py
index b6b70a6..0552b1d 100644
--- a/tests/bare_bones.py
+++ b/tests/bare_bones.py
@@ -6,7 +6,7 @@ class Things:
         pass
 
 
-api = application = falcon.API()
+api = application = falcon.App()
 api.add_route('/', Things())
 
 
diff --git a/tests/test_after_hooks.py b/tests/test_after_hooks.py
index 9cc2495..e986ae6 100644
--- a/tests/test_after_hooks.py
+++ b/tests/test_after_hooks.py
@@ -19,7 +19,7 @@ def wrapped_resource_aware():
 
 @pytest.fixture
 def client():
-    app = falcon.API()
+    app = falcon.App()
 
     resource = WrappedRespondersResource()
     app.add_route('/', resource)
@@ -356,7 +356,7 @@ class HandGame:
 
 @pytest.fixture
 def game_client():
-    app = falcon.API()
+    app = falcon.App()
     resource = HandGame()
 
     app.add_route('/seed', resource)
diff --git a/tests/test_alias.py b/tests/test_alias.py
new file mode 100644
index 0000000..b76075c
--- /dev/null
+++ b/tests/test_alias.py
@@ -0,0 +1,44 @@
+# NOTE(mikeyusko): A file contains temporary tests for API alias
+# and it will be deleted once the API alias will be removed
+
+import pytest
+
+import falcon
+import falcon.testing as testing
+
+
+class CookieResource:
+    def on_get(self, req, resp):
+        resp.set_cookie('foo', 'bar')
+
+
+@pytest.fixture
+def alias_client():
+    api = falcon.API()
+    api.add_route('/get-cookie', CookieResource())
+    return testing.TestClient(api)
+
+
+@pytest.fixture
+def app_client():
+    app = falcon.App()
+    app.add_route('/get-cookie', CookieResource())
+    return testing.TestClient(app)
+
+
+def test_cookies(alias_client, app_client):
+    alias_result = alias_client.simulate_get('/get-cookie')
+
+    alias_cookie = alias_result.cookies['foo']
+    assert alias_cookie.name == 'foo'
+    assert alias_cookie.value == 'bar'
+
+    app_client_result = app_client.simulate_get('/get-cookie')
+    app_cookie = app_client_result.cookies['foo']
+    assert app_cookie.name == 'foo'
+    assert app_cookie.value == 'bar'
+
+
+def test_alias_equals_to_app(alias_client):
+    api = falcon.API()
+    assert isinstance(api, falcon.API)
diff --git a/tests/test_before_hooks.py b/tests/test_before_hooks.py
index 9c545b4..ff9b8d3 100644
--- a/tests/test_before_hooks.py
+++ b/tests/test_before_hooks.py
@@ -240,7 +240,7 @@ def resource():
 
 @pytest.fixture
 def client(resource):
-    app = falcon.API()
+    app = falcon.App()
     app.add_route('/', resource)
     return testing.TestClient(app)
 
@@ -406,7 +406,7 @@ class PiggybackingCollection:
 def app_client():
     items = PiggybackingCollection()
 
-    app = falcon.API()
+    app = falcon.App()
     app.add_route('/items', items, suffix='collection')
     app.add_route('/items/{itemid:int}', items)
 
diff --git a/tests/test_cmd_print_api.py b/tests/test_cmd_print_api.py
index baa7c60..085fec0 100644
--- a/tests/test_cmd_print_api.py
+++ b/tests/test_cmd_print_api.py
@@ -1,6 +1,6 @@
 import io
 
-from falcon import API
+from falcon import App
 from falcon.cmd import print_routes
 from falcon.testing import redirected
 
@@ -17,7 +17,7 @@ class DummyResource:
         resp.status = '200 OK'
 
 
-_api = API()
+_api = App()
 _api.add_route('/test', DummyResource())
 
 
diff --git a/tests/test_cookies.py b/tests/test_cookies.py
index 1256e71..30d60fe 100644
--- a/tests/test_cookies.py
+++ b/tests/test_cookies.py
@@ -77,7 +77,7 @@ class CookieResourceSameSite:
 
 @pytest.fixture()
 def client():
-    app = falcon.API()
+    app = falcon.App()
     app.add_route('/', CookieResource())
     app.add_route('/test-convert', CookieResourceMaxAgeFloatString())
     app.add_route('/same-site', CookieResourceSameSite())
diff --git a/tests/test_custom_router.py b/tests/test_custom_router.py
index 79b4dac..164d43a 100644
--- a/tests/test_custom_router.py
+++ b/tests/test_custom_router.py
@@ -14,7 +14,7 @@ def test_custom_router_add_route_should_be_used():
         def find(self, uri):
             pass
 
-    app = falcon.API(router=CustomRouter())
+    app = falcon.App(router=CustomRouter())
     app.add_route('/test', 'resource')
 
     assert len(check) == 1
@@ -47,7 +47,7 @@ def test_custom_router_find_should_be_used():
             return None
 
     router = CustomRouter()
-    app = falcon.API(router=router)
+    app = falcon.App(router=router)
     client = testing.TestClient(app)
 
     response = client.simulate_request(path='/test/42')
@@ -80,7 +80,7 @@ def test_can_pass_additional_params_to_add_route():
         def find(self, uri):
             pass
 
-    app = falcon.API(router=CustomRouter())
+    app = falcon.App(router=CustomRouter())
     app.add_route('/test', 'resource', name='my-url-name')
 
     assert len(check) == 1
@@ -103,7 +103,7 @@ def test_custom_router_takes_req_positional_argument():
                 return responder, {'GET': responder}, {}, None
 
     router = CustomRouter()
-    app = falcon.API(router=router)
+    app = falcon.App(router=router)
     client = testing.TestClient(app)
     response = client.simulate_request(path='/test')
     assert response.content == b'OK'
@@ -119,7 +119,7 @@ def test_custom_router_takes_req_keyword_argument():
                 return responder, {'GET': responder}, {}, None
 
     router = CustomRouter()
-    app = falcon.API(router=router)
+    app = falcon.App(router=router)
     client = testing.TestClient(app)
     response = client.simulate_request(path='/test')
     assert response.content == b'OK'
diff --git a/tests/test_cython.py b/tests/test_cython.py
index ed9cc78..92c8210 100644
--- a/tests/test_cython.py
+++ b/tests/test_cython.py
@@ -12,4 +12,4 @@ class TestCythonized:
 
     @pytest.mark.skipif(not cython, reason='Cython not installed')
     def test_imported_from_c_modules(self):
-        assert 'falcon/api.py' not in str(falcon.api)
+        assert 'falcon/app.py' not in str(falcon.app)
diff --git a/tests/test_default_router.py b/tests/test_default_router.py
index 3ac01c4..8881fc9 100644
--- a/tests/test_default_router.py
+++ b/tests/test_default_router.py
@@ -9,7 +9,7 @@ from falcon.routing import DefaultRouter
 
 @pytest.fixture
 def client():
-    return testing.TestClient(falcon.API())
+    return testing.TestClient(falcon.App())
 
 
 @pytest.fixture
@@ -250,7 +250,7 @@ def test_user_regression_special_chars(uri_template, path, expected_params):
     object()
 ])
 def test_not_str(uri_template):
-    app = falcon.API()
+    app = falcon.App()
     with pytest.raises(TypeError):
         app.add_route(uri_template, ResourceWithId(-1))
 
diff --git a/tests/test_error_handlers.py b/tests/test_error_handlers.py
index e29e349..b46d721 100644
--- a/tests/test_error_handlers.py
+++ b/tests/test_error_handlers.py
@@ -44,7 +44,7 @@ class ErroredClassResource:
 
 @pytest.fixture
 def client():
-    app = falcon.API()
+    app = falcon.App()
     app.add_route('/', ErroredClassResource())
     return testing.TestClient(app)
 
diff --git a/tests/test_example.py b/tests/test_example.py
index cbcf638..675664b 100644
--- a/tests/test_example.py
+++ b/tests/test_example.py
@@ -190,7 +190,7 @@ class ThingsResource:
 
 
 # Configure your WSGI server to load "things.app" (app is a WSGI callable)
-app = falcon.API(middleware=[
+app = falcon.App(middleware=[
     AuthMiddleware(),
     RequireJSON(),
     JSONTranslator(),
diff --git a/tests/test_headers.py b/tests/test_headers.py
index 3d85eef..ffda9d0 100644
--- a/tests/test_headers.py
+++ b/tests/test_headers.py
@@ -12,13 +12,13 @@ SAMPLE_BODY = testing.rand_string(0, 128 * 1024)
 
 @pytest.fixture
 def client():
-    app = falcon.API()
+    app = falcon.App()
     return testing.TestClient(app)
 
 
 @pytest.fixture(scope='function')
 def cors_client():
-    app = falcon.API(cors_enable=True)
+    app = falcon.App(cors_enable=True)
     return testing.TestClient(app)
 
 
@@ -392,7 +392,7 @@ class TestHeaders:
         ('text/plain', 'Hello ISO-8859-1!'),
     ])
     def test_override_default_media_type(self, client, content_type, body):
-        client.app = falcon.API(media_type=content_type)
+        client.app = falcon.App(media_type=content_type)
         client.app.add_route('/', testing.SimpleTestResource(body=body))
         result = client.simulate_get()
 
@@ -402,7 +402,7 @@ class TestHeaders:
     def test_override_default_media_type_missing_encoding(self, client):
         body = '{"msg": "Hello Unicode! \U0001F638"}'
 
-        client.app = falcon.API(media_type='application/json')
+        client.app = falcon.App(media_type='application/json')
         client.app.add_route('/', testing.SimpleTestResource(body=body))
         result = client.simulate_get()
 
diff --git a/tests/test_hello.py b/tests/test_hello.py
index 25fba24..dcf90d7 100644
--- a/tests/test_hello.py
+++ b/tests/test_hello.py
@@ -8,7 +8,7 @@ from falcon import testing
 
 @pytest.fixture
 def client():
-    return testing.TestClient(falcon.API())
+    return testing.TestClient(falcon.App())
 
 
 # NOTE(kgriffs): Concept from Gunicorn's source (wsgi.py)
diff --git a/tests/test_http_custom_method_routing.py b/tests/test_http_custom_method_routing.py
index d8bda99..a3e403c 100644
--- a/tests/test_http_custom_method_routing.py
+++ b/tests/test_http_custom_method_routing.py
@@ -40,7 +40,7 @@ def cleanup_constants():
 def custom_http_client(cleanup_constants, resource_things):
     falcon.constants.COMBINED_METHODS += FALCON_CUSTOM_HTTP_METHODS
 
-    app = falcon.API()
+    app = falcon.App()
     app.add_route('/things', resource_things)
     return testing.TestClient(app)
 
diff --git a/tests/test_http_method_routing.py b/tests/test_http_method_routing.py
index 5586c03..f8236a1 100644
--- a/tests/test_http_method_routing.py
+++ b/tests/test_http_method_routing.py
@@ -59,7 +59,7 @@ def resource_get_with_faulty_put():
 
 @pytest.fixture
 def client():
-    app = falcon.API()
+    app = falcon.App()
 
     app.add_route('/stonewall', Stonewall())
 
diff --git a/tests/test_httperror.py b/tests/test_httperror.py
index dbddf9d..ecdba27 100644
--- a/tests/test_httperror.py
+++ b/tests/test_httperror.py
@@ -14,7 +14,7 @@ from falcon.util import json
 
 @pytest.fixture
 def client():
-    app = falcon.API()
+    app = falcon.App()
 
     resource = FaultyResource()
     app.add_route('/fail', resource)
@@ -703,7 +703,7 @@ class TestHTTPError:
         assert parsed_body['code'] == code
 
     def test_416(self, client):
-        client.app = falcon.API()
+        client.app = falcon.App()
         client.app.add_route('/416', RangeNotSatisfiableResource())
         response = client.simulate_request(path='/416', headers={'accept': 'text/xml'})
 
diff --git a/tests/test_httpstatus.py b/tests/test_httpstatus.py
index d3d8b47..c606121 100644
--- a/tests/test_httpstatus.py
+++ b/tests/test_httpstatus.py
@@ -76,7 +76,7 @@ class TestHookResource:
 class TestHTTPStatus:
     def test_raise_status_in_before_hook(self):
         """ Make sure we get the 200 raised by before hook """
-        app = falcon.API()
+        app = falcon.App()
         app.add_route('/status', TestStatusResource())
         client = testing.TestClient(app)
 
@@ -87,7 +87,7 @@ class TestHTTPStatus:
 
     def test_raise_status_in_responder(self):
         """ Make sure we get the 200 raised by responder """
-        app = falcon.API()
+        app = falcon.App()
         app.add_route('/status', TestStatusResource())
         client = testing.TestClient(app)
 
@@ -98,7 +98,7 @@ class TestHTTPStatus:
 
     def test_raise_status_runs_after_hooks(self):
         """ Make sure after hooks still run """
-        app = falcon.API()
+        app = falcon.App()
         app.add_route('/status', TestStatusResource())
         client = testing.TestClient(app)
 
@@ -109,7 +109,7 @@ class TestHTTPStatus:
 
     def test_raise_status_survives_after_hooks(self):
         """ Make sure after hook doesn't overwrite our status """
-        app = falcon.API()
+        app = falcon.App()
         app.add_route('/status', TestStatusResource())
         client = testing.TestClient(app)
 
@@ -120,7 +120,7 @@ class TestHTTPStatus:
 
     def test_raise_status_empty_body(self):
         """ Make sure passing None to body results in empty body """
-        app = falcon.API()
+        app = falcon.App()
         app.add_route('/status', TestStatusResource())
         client = testing.TestClient(app)
 
@@ -137,7 +137,7 @@ class TestHTTPStatusWithMiddleware:
                                  headers={'X-Failed': 'False'},
                                  body='Pass')
 
-        app = falcon.API(middleware=TestMiddleware())
+        app = falcon.App(middleware=TestMiddleware())
         app.add_route('/status', TestHookResource())
         client = testing.TestClient(app)
 
@@ -154,7 +154,7 @@ class TestHTTPStatusWithMiddleware:
                                  headers={'X-Failed': 'False'},
                                  body='Pass')
 
-        app = falcon.API(middleware=TestMiddleware())
+        app = falcon.App(middleware=TestMiddleware())
         app.add_route('/status', TestHookResource())
         client = testing.TestClient(app)
 
@@ -171,7 +171,7 @@ class TestHTTPStatusWithMiddleware:
                 resp.set_header('X-Failed', 'False')
                 resp.body = 'Pass'
 
-        app = falcon.API(middleware=TestMiddleware())
+        app = falcon.App(middleware=TestMiddleware())
         app.add_route('/status', TestHookResource())
         client = testing.TestClient(app)
 
diff --git a/tests/test_middleware.py b/tests/test_middleware.py
index 1c211a5..e87e634 100644
--- a/tests/test_middleware.py
+++ b/tests/test_middleware.py
@@ -154,7 +154,7 @@ class TestRequestTimeMiddleware(TestMiddleware):
 
     def test_skip_process_resource(self):
         global context
-        app = falcon.API(middleware=[RequestTimeMiddleware()])
+        app = falcon.App(middleware=[RequestTimeMiddleware()])
 
         app.add_route('/', MiddlewareClassResource())
         client = testing.TestClient(app)
@@ -174,13 +174,13 @@ class TestRequestTimeMiddleware(TestMiddleware):
 
         mw_list = [RequestTimeMiddleware(), InvalidMiddleware]
         with pytest.raises(AttributeError):
-            falcon.API(middleware=mw_list)
+            falcon.App(middleware=mw_list)
         mw_list = [RequestTimeMiddleware(), 'InvalidMiddleware']
         with pytest.raises(TypeError):
-            falcon.API(middleware=mw_list)
+            falcon.App(middleware=mw_list)
         mw_list = [{'process_request': 90}]
         with pytest.raises(TypeError):
-            falcon.API(middleware=mw_list)
+            falcon.App(middleware=mw_list)
 
     def test_response_middleware_raises_exception(self):
         """Test that error in response middleware is propagated up"""
@@ -189,7 +189,7 @@ class TestRequestTimeMiddleware(TestMiddleware):
             def process_response(self, req, resp, resource):
                 raise Exception('Always fail')
 
-        app = falcon.API(middleware=[RaiseErrorMiddleware()])
+        app = falcon.App(middleware=[RaiseErrorMiddleware()])
 
         app.add_route(TEST_ROUTE, MiddlewareClassResource())
         client = testing.TestClient(app)
@@ -201,7 +201,7 @@ class TestRequestTimeMiddleware(TestMiddleware):
     def test_log_get_request(self, independent_middleware):
         """Test that Log middleware is executed"""
         global context
-        app = falcon.API(middleware=[RequestTimeMiddleware()],
+        app = falcon.App(middleware=[RequestTimeMiddleware()],
                          independent_middleware=independent_middleware)
 
         app.add_route(TEST_ROUTE, MiddlewareClassResource())
@@ -226,7 +226,7 @@ class TestTransactionIdMiddleware(TestMiddleware):
     def test_generate_trans_id_with_request(self):
         """Test that TransactionIdmiddleware is executed"""
         global context
-        app = falcon.API(middleware=TransactionIdMiddleware())
+        app = falcon.App(middleware=TransactionIdMiddleware())
 
         app.add_route(TEST_ROUTE, MiddlewareClassResource())
         client = testing.TestClient(app)
@@ -248,7 +248,7 @@ class TestSeveralMiddlewares(TestMiddleware):
         cresp = CaptureResponseMiddleware()
 
         global context
-        app = falcon.API(independent_middleware=independent_middleware,
+        app = falcon.App(independent_middleware=independent_middleware,
                          middleware=[TransactionIdMiddleware(),
                                      RequestTimeMiddleware(),
                                      creq,
@@ -272,7 +272,7 @@ class TestSeveralMiddlewares(TestMiddleware):
 
     def test_legacy_middleware_called_with_correct_args(self):
         global context
-        app = falcon.API(middleware=[ExecutedFirstMiddleware()])
+        app = falcon.App(middleware=[ExecutedFirstMiddleware()])
         app.add_route(TEST_ROUTE, MiddlewareClassResource())
         client = testing.TestClient(app)
 
@@ -283,7 +283,7 @@ class TestSeveralMiddlewares(TestMiddleware):
 
     def test_middleware_execution_order(self):
         global context
-        app = falcon.API(independent_middleware=False,
+        app = falcon.App(independent_middleware=False,
                          middleware=[ExecutedFirstMiddleware(),
                                      ExecutedLastMiddleware()])
 
@@ -307,7 +307,7 @@ class TestSeveralMiddlewares(TestMiddleware):
 
     def test_independent_middleware_execution_order(self):
         global context
-        app = falcon.API(independent_middleware=True,
+        app = falcon.App(independent_middleware=True,
                          middleware=[ExecutedFirstMiddleware(),
                                      ExecutedLastMiddleware()])
 
@@ -348,7 +348,7 @@ class TestSeveralMiddlewares(TestMiddleware):
                 context['executed_methods'].append('process_response')
                 context['req_succeeded'].append(req_succeeded)
 
-        app = falcon.API(middleware=[ProcessResponseMiddleware(),
+        app = falcon.App(middleware=[ProcessResponseMiddleware(),
                                      RaiseErrorMiddleware(),
                                      ProcessResponseMiddleware(),
                                      RaiseStatusMiddleware(),
@@ -374,7 +374,7 @@ class TestSeveralMiddlewares(TestMiddleware):
             def process_request(self, req, resp):
                 raise Exception('Always fail')
 
-        app = falcon.API(middleware=[TransactionIdMiddleware(),
+        app = falcon.App(middleware=[TransactionIdMiddleware(),
                                      RequestTimeMiddleware(),
                                      RaiseErrorMiddleware()])
 
@@ -399,7 +399,7 @@ class TestSeveralMiddlewares(TestMiddleware):
             def process_request(self, req, resp, resource):
                 raise Exception('Always fail')
 
-        app = falcon.API(middleware=[TransactionIdMiddleware(),
+        app = falcon.App(middleware=[TransactionIdMiddleware(),
                                      RequestTimeMiddleware(),
                                      RaiseErrorMiddleware()])
 
@@ -429,7 +429,7 @@ class TestSeveralMiddlewares(TestMiddleware):
             def process_request(self, req, resp):
                 raise Exception('Always fail')
 
-        app = falcon.API(middleware=[TransactionIdMiddleware(),
+        app = falcon.App(middleware=[TransactionIdMiddleware(),
                                      RaiseErrorMiddleware(),
                                      RequestTimeMiddleware()])
 
@@ -459,7 +459,7 @@ class TestSeveralMiddlewares(TestMiddleware):
             def process_response(self, req, resp, resource):
                 raise Exception('Always fail')
 
-        app = falcon.API(middleware=[ExecutedFirstMiddleware(),
+        app = falcon.App(middleware=[ExecutedFirstMiddleware(),
                                      RaiseErrorMiddleware(),
                                      ExecutedLastMiddleware()])
 
@@ -493,7 +493,7 @@ class TestSeveralMiddlewares(TestMiddleware):
             def process_response(self, req, resp, resource):
                 raise Exception('Always fail')
 
-        app = falcon.API(independent_middleware=True,
+        app = falcon.App(independent_middleware=True,
                          middleware=[ExecutedFirstMiddleware(),
                                      RaiseErrorMiddleware(),
                                      ExecutedLastMiddleware()])
@@ -528,7 +528,7 @@ class TestSeveralMiddlewares(TestMiddleware):
             def process_request(self, req, resp):
                 raise Exception('Always fail')
 
-        app = falcon.API(middleware=[ExecutedFirstMiddleware(),
+        app = falcon.App(middleware=[ExecutedFirstMiddleware(),
                                      RaiseErrorMiddleware(),
                                      ExecutedLastMiddleware()])
 
@@ -559,7 +559,7 @@ class TestSeveralMiddlewares(TestMiddleware):
             def process_request(self, req, resp):
                 raise Exception('Always fail')
 
-        app = falcon.API(independent_middleware=True,
+        app = falcon.App(independent_middleware=True,
                          middleware=[ExecutedFirstMiddleware(),
                                      RaiseErrorMiddleware(),
                                      ExecutedLastMiddleware()])
@@ -591,7 +591,7 @@ class TestSeveralMiddlewares(TestMiddleware):
             def process_resource(self, req, resp, resource):
                 raise Exception('Always fail')
 
-        app = falcon.API(middleware=[ExecutedFirstMiddleware(),
+        app = falcon.App(middleware=[ExecutedFirstMiddleware(),
                                      RaiseErrorMiddleware(),
                                      ExecutedLastMiddleware()])
 
@@ -624,7 +624,7 @@ class TestSeveralMiddlewares(TestMiddleware):
             def process_resource(self, req, resp, resource):
                 raise Exception('Always fail')
 
-        app = falcon.API(independent_middleware=True,
+        app = falcon.App(independent_middleware=True,
                          middleware=[ExecutedFirstMiddleware(),
                                      RaiseErrorMiddleware(),
                                      ExecutedLastMiddleware()])
@@ -653,7 +653,7 @@ class TestSeveralMiddlewares(TestMiddleware):
 class TestRemoveBasePathMiddleware(TestMiddleware):
     def test_base_path_is_removed_before_routing(self):
         """Test that RemoveBasePathMiddleware is executed before routing"""
-        app = falcon.API(middleware=RemoveBasePathMiddleware())
+        app = falcon.App(middleware=RemoveBasePathMiddleware())
 
         # We dont include /base_path as it will be removed in middleware
         app.add_route('/sub_path', MiddlewareClassResource())
@@ -677,7 +677,7 @@ class TestResourceMiddleware(TestMiddleware):
             def on_get(self, req, resp, **params):
                 resp.body = json.dumps(params)
 
-        app = falcon.API(middleware=AccessParamsMiddleware(),
+        app = falcon.App(middleware=AccessParamsMiddleware(),
                          independent_middleware=independent_middleware)
         app.add_route('/path/{id}', Resource())
         client = testing.TestClient(app)
@@ -698,13 +698,13 @@ class TestEmptySignatureMiddleware(TestMiddleware):
 
         https://github.com/falconry/falcon/issues/1254
         """
-        falcon.API(middleware=EmptySignatureMiddleware())
+        falcon.App(middleware=EmptySignatureMiddleware())
 
 
 class TestErrorHandling(TestMiddleware):
     def test_error_composed_before_resp_middleware_called(self):
         mw = CaptureResponseMiddleware()
-        app = falcon.API(middleware=mw)
+        app = falcon.App(middleware=mw)
         app.add_route('/', MiddlewareClassResource())
         client = testing.TestClient(app)
 
@@ -724,7 +724,7 @@ class TestErrorHandling(TestMiddleware):
 
     def test_http_status_raised_from_error_handler(self):
         mw = CaptureResponseMiddleware()
-        app = falcon.API(middleware=mw)
+        app = falcon.App(middleware=mw)
         app.add_route('/', MiddlewareClassResource())
         client = testing.TestClient(app)
 
@@ -750,7 +750,7 @@ class TestShortCircuiting(TestMiddleware):
             ResponseCacheMiddlware(),
             TransactionIdMiddleware(),
         ]
-        app = falcon.API(middleware=mw, independent_middleware=independent_middleware)
+        app = falcon.App(middleware=mw, independent_middleware=independent_middleware)
         app.add_route('/', MiddlewareClassResource())
         app.add_route('/cached', MiddlewareClassResource())
         app.add_route('/cached/resource', MiddlewareClassResource())
@@ -821,7 +821,7 @@ class TestCORSMiddlewareWithAnotherMiddleware(TestMiddleware):
         iter([CaptureResponseMiddleware()]),
     ])
     def test_api_initialization_with_cors_enabled_and_middleware_param(self, mw):
-        app = falcon.API(middleware=mw, cors_enable=True)
+        app = falcon.App(middleware=mw, cors_enable=True)
         app.add_route('/', TestCorsResource())
         client = testing.TestClient(app)
         result = client.simulate_get()
diff --git a/tests/test_query_params.py b/tests/test_query_params.py
index 744c856..a536020 100644
--- a/tests/test_query_params.py
+++ b/tests/test_query_params.py
@@ -44,7 +44,7 @@ def resource():
 
 @pytest.fixture
 def client():
-    app = falcon.API()
+    app = falcon.App()
     app.req_options.auto_parse_form_urlencoded = True
     return testing.TestClient(app)
 
@@ -902,7 +902,7 @@ class TestPostQueryParams:
 
 class TestPostQueryParamsDefaultBehavior:
     def test_dont_auto_parse_by_default(self):
-        app = falcon.API()
+        app = falcon.App()
         resource = testing.SimpleTestResource()
         app.add_route('/', resource)
 
diff --git a/tests/test_redirects.py b/tests/test_redirects.py
index 0b11dc1..54ca735 100644
--- a/tests/test_redirects.py
+++ b/tests/test_redirects.py
@@ -6,7 +6,7 @@ import falcon.testing as testing
 
 @pytest.fixture
 def client():
-    app = falcon.API()
+    app = falcon.App()
 
     resource = RedirectingResource()
     app.add_route('/', resource)
@@ -16,7 +16,7 @@ def client():
 
 @pytest.fixture
 def client_exercising_headers():
-    app = falcon.API()
+    app = falcon.App()
 
     resource = RedirectingResourceWithHeaders()
     app.add_route('/', resource)
diff --git a/tests/test_request_body.py b/tests/test_request_body.py
index 1cfb231..a728346 100644
--- a/tests/test_request_body.py
+++ b/tests/test_request_body.py
@@ -18,7 +18,7 @@ def resource():
 
 @pytest.fixture
 def client():
-    app = falcon.API()
+    app = falcon.App()
     return testing.TestClient(app)
 
 
diff --git a/tests/test_request_media.py b/tests/test_request_media.py
index be277bc..97c7d43 100644
--- a/tests/test_request_media.py
+++ b/tests/test_request_media.py
@@ -7,7 +7,7 @@ from falcon import errors, media, testing
 def create_client(handlers=None):
     res = testing.SimpleTestResource()
 
-    app = falcon.API()
+    app = falcon.App()
     app.add_route('/', res)
 
     if handlers:
diff --git a/tests/test_response_media.py b/tests/test_response_media.py
index 39023b8..359e0b1 100644
--- a/tests/test_response_media.py
+++ b/tests/test_response_media.py
@@ -9,7 +9,7 @@ from falcon import errors, media, testing
 def create_client(handlers=None):
     res = testing.SimpleTestResource()
 
-    app = falcon.API()
+    app = falcon.App()
     app.add_route('/', res)
 
     if handlers:
@@ -67,7 +67,7 @@ def test_json(media_type):
     },
 ])
 def test_non_ascii_json_serialization(document):
-    app = falcon.API()
+    app = falcon.App()
     app.add_route('/', SimpleMediaResource(document))
     client = testing.TestClient(app)
 
diff --git a/tests/test_sinks.py b/tests/test_sinks.py
index 4c14aab..31ff4da 100644
--- a/tests/test_sinks.py
+++ b/tests/test_sinks.py
@@ -41,7 +41,7 @@ def sink():
 
 @pytest.fixture
 def client():
-    app = falcon.API()
+    app = falcon.App()
     return testing.TestClient(app)
 
 
diff --git a/tests/test_static.py b/tests/test_static.py
index 9cb65cf..8141553 100644
--- a/tests/test_static.py
+++ b/tests/test_static.py
@@ -14,7 +14,7 @@ import falcon.testing as testing
 
 @pytest.fixture
 def client():
-    app = falcon.API()
+    app = falcon.App()
     return testing.TestClient(app)
 
 
diff --git a/tests/test_uri_templates.py b/tests/test_uri_templates.py
index 054d52c..78ec17f 100644
--- a/tests/test_uri_templates.py
+++ b/tests/test_uri_templates.py
@@ -121,7 +121,7 @@ def resource():
 
 @pytest.fixture
 def client():
-    return testing.TestClient(falcon.API())
+    return testing.TestClient(falcon.App())
 
 
 def test_root_path(client, resource):
diff --git a/tests/test_uri_templates_legacy.py b/tests/test_uri_templates_legacy.py
index dadf130..b6aefc3 100644
--- a/tests/test_uri_templates_legacy.py
+++ b/tests/test_uri_templates_legacy.py
@@ -6,7 +6,7 @@ from falcon import routing
 
 class TestUriTemplates:
 
-    @pytest.mark.parametrize('value', (42, falcon.API))
+    @pytest.mark.parametrize('value', (42, falcon.App))
     def test_string_type_required(self, value):
         with pytest.raises(TypeError):
             routing.compile_uri_template(value)
diff --git a/tests/test_utils.py b/tests/test_utils.py
index cbecda2..893f82a 100644
--- a/tests/test_utils.py
+++ b/tests/test_utils.py
@@ -389,7 +389,7 @@ def test_simulate_request_protocol(protocol, method):
         sink_called[0] = True
         assert req.protocol == protocol
 
-    app = falcon.API()
+    app = falcon.App()
     app.add_sink(sink, '/test')
 
     client = testing.TestClient(app)
@@ -418,7 +418,7 @@ def test_simulate_free_functions(simulate):
     def sink(req, resp):
         sink_called[0] = True
 
-    app = falcon.API()
+    app = falcon.App()
     app.add_sink(sink, '/test')
 
     simulate(app, '/test')
@@ -445,7 +445,7 @@ class TestFalconTestingUtils:
         assert env['HTTP_X_FOO'] == ''
 
     def test_decode_empty_result(self):
-        app = falcon.API()
+        app = falcon.App()
         client = testing.TestClient(app)
         response = client.simulate_request(path='/')
         assert response.text == ''
@@ -454,7 +454,7 @@ class TestFalconTestingUtils:
         assert testing.httpnow is util.http_now
 
     def test_default_headers(self):
-        app = falcon.API()
+        app = falcon.App()
         resource = testing.SimpleTestResource()
         app.add_route('/', resource)
 
@@ -471,7 +471,7 @@ class TestFalconTestingUtils:
         assert resource.captured_req.auth == headers['Authorization']
 
     def test_default_headers_with_override(self):
-        app = falcon.API()
+        app = falcon.App()
         resource = testing.SimpleTestResource()
         app.add_route('/', resource)
 
@@ -492,7 +492,7 @@ class TestFalconTestingUtils:
         assert resource.captured_req.get_header('X-Override-Me') == override_after
 
     def test_status(self):
-        app = falcon.API()
+        app = falcon.App()
         resource = testing.SimpleTestResource(status=falcon.HTTP_702)
         app.add_route('/', resource)
         client = testing.TestClient(app)
@@ -506,14 +506,14 @@ class TestFalconTestingUtils:
         assert result.json is None
 
     def test_path_must_start_with_slash(self):
-        app = falcon.API()
+        app = falcon.App()
         app.add_route('/', testing.SimpleTestResource())
         client = testing.TestClient(app)
         with pytest.raises(ValueError):
             client.simulate_get('foo')
 
     def test_cached_text_in_result(self):
-        app = falcon.API()
+        app = falcon.App()
         app.add_route('/', testing.SimpleTestResource(body='test'))
         client = testing.TestClient(app)
 
@@ -536,7 +536,7 @@ class TestFalconTestingUtils:
 
                 resp.body = json.dumps(doc)
 
-        app = falcon.API()
+        app = falcon.App()
         app.req_options.auto_parse_qs_csv = True
         app.add_route('/', SomeResource())
         client = testing.TestClient(app)
@@ -568,14 +568,14 @@ class TestFalconTestingUtils:
         assert result.json['query_string'] == expected_qs
 
     def test_query_string_no_question(self):
-        app = falcon.API()
+        app = falcon.App()
         app.add_route('/', testing.SimpleTestResource())
         client = testing.TestClient(app)
         with pytest.raises(ValueError):
             client.simulate_get(query_string='?x=1')
 
     def test_query_string_in_path(self):
-        app = falcon.API()
+        app = falcon.App()
         resource = testing.SimpleTestResource()
         app.add_route('/thing', resource)
         client = testing.TestClient(app)
@@ -614,7 +614,7 @@ class TestFalconTestingUtils:
         },
     ])
     def test_simulate_json_body(self, document):
-        app = falcon.API()
+        app = falcon.App()
         resource = testing.SimpleTestResource()
         app.add_route('/', resource)
 
@@ -648,7 +648,7 @@ class TestFalconTestingUtils:
                 resp.body = req.remote_addr
                 resp.content_type = falcon.MEDIA_TEXT
 
-        app = falcon.API()
+        app = falcon.App()
         app.add_route('/', ShowMyIPResource())
 
         client = testing.TestClient(app)
@@ -661,7 +661,7 @@ class TestFalconTestingUtils:
             assert resp.text == remote_addr
 
     def test_simulate_hostname(self):
-        app = falcon.API()
+        app = falcon.App()
         resource = testing.SimpleTestResource()
         app.add_route('/', resource)
 
@@ -681,7 +681,7 @@ class TestFalconTestingUtils:
         ),
     ])
     def test_simulate_with_environ_extras(self, extras, expected_headers):
-        app = falcon.API()
+        app = falcon.App()
         resource = testing.SimpleTestResource()
         app.add_route('/', resource)
 
@@ -692,7 +692,7 @@ class TestFalconTestingUtils:
             assert resource.captured_req.get_header(header) == value
 
     def test_override_method_with_extras(self):
-        app = falcon.API()
+        app = falcon.App()
         app.add_route('/', testing.SimpleTestResource(body='test'))
         client = testing.TestClient(app)
 
@@ -706,16 +706,16 @@ class TestFalconTestingUtils:
 
 class TestNoApiClass(testing.TestCase):
     def test_something(self):
-        self.assertTrue(isinstance(self.app, falcon.API))
+        self.assertTrue(isinstance(self.app, falcon.App))
 
 
 class TestSetupApi(testing.TestCase):
     def setUp(self):
         super(TestSetupApi, self).setUp()
-        self.api = falcon.API()
+        self.api = falcon.App()
 
     def test_something(self):
-        self.assertTrue(isinstance(self.api, falcon.API))
+        self.assertTrue(isinstance(self.api, falcon.App))
 
 
 def test_get_argnames():
diff --git a/tests/test_validators.py b/tests/test_validators.py
index 50de192f..0d3c130 100644
--- a/tests/test_validators.py
+++ b/tests/test_validators.py
@@ -95,7 +95,7 @@ def test_both_schemas_validation_success():
     assert result[0] is req_data
     assert result[1] is resp_data
 
-    client = testing.TestClient(falcon.API())
+    client = testing.TestClient(falcon.App())
     client.app.add_route('/test', Resource())
     result = client.simulate_put('/test', json=GoodData.media)
     assert result.json == resp_data.media
@@ -113,7 +113,7 @@ def test_both_schemas_validation_failure():
 
     assert excinfo.value.title == 'Request data failed validation'
 
-    client = testing.TestClient(falcon.API())
+    client = testing.TestClient(falcon.App())
     client.app.add_route('/test', Resource())
     result = client.simulate_put('/test', json=BadData.media)
     assert result.status_code == 400
diff --git a/tests/test_wsgi.py b/tests/test_wsgi.py
index 470b986..2360020 100644
--- a/tests/test_wsgi.py
+++ b/tests/test_wsgi.py
@@ -89,7 +89,7 @@ def _run_server(stop_event, host, port):
             # req.stream, since we already asserted they are the same
             # objects.
 
-    api = application = falcon.API()
+    api = application = falcon.App()
     api.add_route('/', Things())
     api.add_route('/bucket', Bucket())
 
diff --git a/tests/test_wsgi_errors.py b/tests/test_wsgi_errors.py
index f5c01a5..b00b477 100644
--- a/tests/test_wsgi_errors.py
+++ b/tests/test_wsgi_errors.py
@@ -10,7 +10,7 @@ unicode_message = 'Unicode: \x80'
 
 @pytest.fixture
 def client():
-    app = falcon.API()
+    app = falcon.App()
 
     tehlogger = LoggerResource()
     app.add_route('/logger', tehlogger)
diff --git a/tests/test_wsgi_interface.py b/tests/test_wsgi_interface.py
index cba0d31..492440c 100644
--- a/tests/test_wsgi_interface.py
+++ b/tests/test_wsgi_interface.py
@@ -21,7 +21,7 @@ class TestWSGIInterface:
         assert mock.exc_info == exc_info
 
     def test_pep3333(self):
-        api = falcon.API()
+        api = falcon.App()
         mock = testing.StartResponseMock()
 
         # Simulate a web request (normally done though a WSGI server)
diff --git a/tests/test_wsgiref_inputwrapper_with_size.py b/tests/test_wsgiref_inputwrapper_with_size.py
index 965b196..31485e6 100644
--- a/tests/test_wsgiref_inputwrapper_with_size.py
+++ b/tests/test_wsgiref_inputwrapper_with_size.py
@@ -21,7 +21,7 @@ class TestWsgiRefInputWrapper:
         Originally, testing would fail after performing a request because no
         size was specified when calling `wsgiref.validate.InputWrapper.read()`
         via `req.stream.read()`"""
-        app = falcon.API()
+        app = falcon.App()
         type_route = '/type'
         app.add_route(type_route, TypeResource())
         client = testing.TestClient(app)