diff --git a/docs/img/tutorial/body-nested-models/image01.png b/docs/img/tutorial/body-nested-models/image01.png
new file mode 100644
index 000000000..f3644ce79
Binary files /dev/null and b/docs/img/tutorial/body-nested-models/image01.png differ
diff --git a/docs/tutorial/body-nested-models.md b/docs/tutorial/body-nested-models.md
new file mode 100644
index 000000000..2d57dd78c
--- /dev/null
+++ b/docs/tutorial/body-nested-models.md
@@ -0,0 +1,213 @@
+With **FastAPI**, you can define, validate, document, and use arbitrarily deeply nested models (thanks to Pydantic).
+
+## List fields
+
+You can define an attribute to be a subtype. For example, a Python `list`:
+
+```Python hl_lines="12"
+{!./tutorial/src/body-nested-models/tutorial001.py!}
+```
+
+This will make `tags` be a list of items. Although it doesn't declare the type of each of the items.
+
+## List fields with subtype
+
+But Python has a specific way to declare lists with subtypes:
+
+### Import typing's `List`
+
+First, import `List` from standard Python's `typing` module:
+
+```Python hl_lines="1"
+{!./tutorial/src/body-nested-models/tutorial002.py!}
+```
+
+### Declare a `List` with a subtype
+
+To declare types that have subtypes, like `list`, `dict`, `tuple`:
+
+* Import them from the `typing` module
+* Pass the subtype(s) as "type arguments" using square brackets: `[` and `]`
+
+```Python
+from typing import List
+
+my_list: List[str]
+```
+
+That's all standard Python syntax for type declarations.
+
+Use that same standard syntax for model attributes with subtypes.
+
+So, in our example, we can make `tags` be specifically a "list of strings":
+
+```Python hl_lines="14"
+{!./tutorial/src/body-nested-models/tutorial002.py!}
+```
+
+## Set types
+
+But then we think about it, and realize that tags shouldn't repeat, they would probably be unique strings.
+
+And Python has a special data type for sets of unique items, the `set`.
+
+Then we can import `Set` and declare `tags` as a `set` of `str`:
+
+```Python hl_lines="1 14"
+{!./tutorial/src/body-nested-models/tutorial003.py!}
+```
+
+With this, even if you receive a request with duplicate data, it will be converted to a set of unique items.
+
+And whenever you output that data, even if the source had duplicates, it will be output as a set of unique items.
+
+And it will be annotated / documented accordingly too.
+
+## Nested Models
+
+Each attribute of a Pydantic model has a type.
+
+But that type can itself be another Pydantic model.
+
+So, you can declare deeply nested JSON `object`s with specific attribute names, types and validations.
+
+All that, arbitrarily nested.
+
+### Define a submodel
+
+For example, we can define an `Image` model:
+
+```Python hl_lines="9 10 11"
+{!./tutorial/src/body-nested-models/tutorial004.py!}
+```
+
+### Use the submodel as a type
+
+And then we can use it as the type of an attribute:
+
+```Python hl_lines="20"
+{!./tutorial/src/body-nested-models/tutorial004.py!}
+```
+
+This would mean that **FastAPI** would expect a body similar to:
+
+```JSON
+{
+ "name": "Foo",
+ "description": "The pretender",
+ "price": 42.0,
+ "tax": 3.2,
+ "tags": ["rock", "metal", "bar"],
+ "image": {
+ "url": "http://example.com/baz.jpg",
+ "name": "The Foo live"
+ }
+}
+```
+
+Again, doing just that declaration, with **FastAPI** you get:
+
+* Editor support (completion, etc), even for nested models
+* Data conversion
+* Data validation
+* Automatic documentation
+
+## Special types and validation
+
+Apart from normal singular types like `str`, `int`, `float`, etc. You can use more complex singular types that inherit from `str`.
+
+To see all the options you have, checkout the docs for Pydantic's exotic types.
+
+For example, as in the `Image` model we have a `url` field, we can declare it to be instead of a `str`, a Pydantic's `UrlStr`:
+
+```Python hl_lines="5 11"
+{!./tutorial/src/body-nested-models/tutorial005.py!}
+```
+
+The string will be checked to be a valid URL, and documented in JSON Schema / OpenAPI as such.
+
+## Attributes with lists of submodels
+
+You can also use Pydantic models as subtypes of `list`, `set`, etc:
+
+```Python hl_lines="21"
+{!./tutorial/src/body-nested-models/tutorial006.py!}
+```
+
+This will expect (convert, validate, document, etc) a JSON body like:
+
+```JSON hl_lines="11"
+{
+ "name": "Foo",
+ "description": "The pretender",
+ "price": 42.0,
+ "tax": 3.2,
+ "tags": [
+ "rock",
+ "metal",
+ "bar"
+ ],
+ "images": [
+ {
+ "url": "http://example.com/baz.jpg",
+ "name": "The Foo live"
+ },
+ {
+ "url": "http://example.com/dave.jpg",
+ "name": "The Baz"
+ }
+ ]
+}
+```
+
+!!! info
+ Notice how the `images` key now has a list of image objects.
+
+## Deeply nested models
+
+You can define arbitrarily deeply nested models:
+
+```Python hl_lines="10 15 21 24 28"
+{!./tutorial/src/body-nested-models/tutorial007.py!}
+```
+
+!!! info
+ Notice how `Offer` as a list of `Item`s, which in turn have an optional list of `Image`s
+
+## Bodies of pure lists
+
+If the top level value of the JSON body you expect is a JSON `array` (a Python `list`), you can declare the type in the parameter of the function, the same as in Pydantic models:
+
+```Python
+images: List[Image]
+```
+
+as in:
+
+```Python hl_lines="16"
+{!./tutorial/src/body-nested-models/tutorial008.py!}
+```
+
+## Editor support everywhere
+
+And you get editor support everywhere.
+
+Even for items inside of lists:
+
+
+
+You couldn't get this kind of editor support if you where working directly with `dict` instead of Pydantic models.
+
+But you don't have to worry about them either, incoming dicts are converted automatically and your output is converted automatically to JSON too.
+
+## Recap
+
+With **FastAPI** you have the maximum flexibility provided by Pydantic models, while keeping your code simple, short and elegant.
+
+But with all the benefits:
+
+* Editor support (completion everywhere!)
+* Data conversion (a.k.a. parsing / serialization)
+* Data validation
+* Schema documentation
+* Automatic docs
diff --git a/docs/tutorial/src/body-nested-models/tutorial001.py b/docs/tutorial/src/body-nested-models/tutorial001.py
new file mode 100644
index 000000000..9e0fa4494
--- /dev/null
+++ b/docs/tutorial/src/body-nested-models/tutorial001.py
@@ -0,0 +1,18 @@
+from fastapi import FastAPI
+from pydantic import BaseModel
+
+app = FastAPI()
+
+
+class Item(BaseModel):
+ name: str
+ description: str = None
+ price: float
+ tax: float = None
+ tags: list = []
+
+
+@app.put("/items/{item_id}")
+async def update_item(*, item_id: int, item: Item):
+ results = {"item_id": item_id, "item": item}
+ return results
diff --git a/docs/tutorial/src/body-nested-models/tutorial002.py b/docs/tutorial/src/body-nested-models/tutorial002.py
new file mode 100644
index 000000000..8f769279b
--- /dev/null
+++ b/docs/tutorial/src/body-nested-models/tutorial002.py
@@ -0,0 +1,20 @@
+from typing import List
+
+from fastapi import FastAPI
+from pydantic import BaseModel
+
+app = FastAPI()
+
+
+class Item(BaseModel):
+ name: str
+ description: str = None
+ price: float
+ tax: float = None
+ tags: List[str] = []
+
+
+@app.put("/items/{item_id}")
+async def update_item(*, item_id: int, item: Item):
+ results = {"item_id": item_id, "item": item}
+ return results
diff --git a/docs/tutorial/src/body-nested-models/tutorial003.py b/docs/tutorial/src/body-nested-models/tutorial003.py
new file mode 100644
index 000000000..bb539b127
--- /dev/null
+++ b/docs/tutorial/src/body-nested-models/tutorial003.py
@@ -0,0 +1,20 @@
+from typing import Set
+
+from fastapi import FastAPI
+from pydantic import BaseModel
+
+app = FastAPI()
+
+
+class Item(BaseModel):
+ name: str
+ description: str = None
+ price: float
+ tax: float = None
+ tags: Set[str] = set()
+
+
+@app.put("/items/{item_id}")
+async def update_item(*, item_id: int, item: Item):
+ results = {"item_id": item_id, "item": item}
+ return results
diff --git a/docs/tutorial/src/body-nested-models/tutorial004.py b/docs/tutorial/src/body-nested-models/tutorial004.py
new file mode 100644
index 000000000..257928ef3
--- /dev/null
+++ b/docs/tutorial/src/body-nested-models/tutorial004.py
@@ -0,0 +1,26 @@
+from typing import Set
+
+from fastapi import FastAPI
+from pydantic import BaseModel
+
+app = FastAPI()
+
+
+class Image(BaseModel):
+ url: str
+ name: str
+
+
+class Item(BaseModel):
+ name: str
+ description: str = None
+ price: float
+ tax: float = None
+ tags: Set[str] = []
+ image: Image = None
+
+
+@app.put("/items/{item_id}")
+async def update_item(*, item_id: int, item: Item):
+ results = {"item_id": item_id, "item": item}
+ return results
diff --git a/docs/tutorial/src/body-nested-models/tutorial005.py b/docs/tutorial/src/body-nested-models/tutorial005.py
new file mode 100644
index 000000000..f5f19b390
--- /dev/null
+++ b/docs/tutorial/src/body-nested-models/tutorial005.py
@@ -0,0 +1,27 @@
+from typing import Set
+
+from fastapi import FastAPI
+from pydantic import BaseModel
+from pydantic.types import UrlStr
+
+app = FastAPI()
+
+
+class Image(BaseModel):
+ url: UrlStr
+ name: str
+
+
+class Item(BaseModel):
+ name: str
+ description: str = None
+ price: float
+ tax: float = None
+ tags: Set[str] = []
+ image: Image = None
+
+
+@app.put("/items/{item_id}")
+async def update_item(*, item_id: int, item: Item):
+ results = {"item_id": item_id, "item": item}
+ return results
diff --git a/docs/tutorial/src/body-nested-models/tutorial006.py b/docs/tutorial/src/body-nested-models/tutorial006.py
new file mode 100644
index 000000000..09d8be768
--- /dev/null
+++ b/docs/tutorial/src/body-nested-models/tutorial006.py
@@ -0,0 +1,27 @@
+from typing import List, Set
+
+from fastapi import FastAPI
+from pydantic import BaseModel
+from pydantic.types import UrlStr
+
+app = FastAPI()
+
+
+class Image(BaseModel):
+ url: UrlStr
+ name: str
+
+
+class Item(BaseModel):
+ name: str
+ description: str = None
+ price: float
+ tax: float = None
+ tags: Set[str] = []
+ image: List[Image] = None
+
+
+@app.put("/items/{item_id}")
+async def update_item(*, item_id: int, item: Item):
+ results = {"item_id": item_id, "item": item}
+ return results
diff --git a/docs/tutorial/src/body-nested-models/tutorial007.py b/docs/tutorial/src/body-nested-models/tutorial007.py
new file mode 100644
index 000000000..cda802d3e
--- /dev/null
+++ b/docs/tutorial/src/body-nested-models/tutorial007.py
@@ -0,0 +1,33 @@
+from typing import List, Set
+
+from fastapi import FastAPI
+from pydantic import BaseModel
+from pydantic.types import UrlStr
+
+app = FastAPI()
+
+
+class Image(BaseModel):
+ url: UrlStr
+ name: str
+
+
+class Item(BaseModel):
+ name: str
+ description: str = None
+ price: float
+ tax: float = None
+ tags: Set[str] = []
+ image: List[Image] = None
+
+
+class Offer(BaseModel):
+ name: str
+ description: str = None
+ price: float
+ items: List[Item]
+
+
+@app.post("/offers/")
+async def create_offer(*, offer: Offer):
+ return offer
diff --git a/docs/tutorial/src/body-nested-models/tutorial008.py b/docs/tutorial/src/body-nested-models/tutorial008.py
new file mode 100644
index 000000000..34b868563
--- /dev/null
+++ b/docs/tutorial/src/body-nested-models/tutorial008.py
@@ -0,0 +1,17 @@
+from typing import List
+
+from fastapi import FastAPI
+from pydantic import BaseModel
+from pydantic.types import UrlStr
+
+app = FastAPI()
+
+
+class Image(BaseModel):
+ url: UrlStr
+ name: str
+
+
+@app.post("/images/multiple/")
+async def create_multiple_images(*, images: List[Image]):
+ return images
diff --git a/mkdocs.yml b/mkdocs.yml
index 30f803ef2..84107b828 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -26,6 +26,7 @@ nav:
- Path Parameters - Numeric Validations: 'tutorial/path-params-numeric-validations.md'
- Body - Multiple Parameters: 'tutorial/body-multiple-params.md'
- Body - Schema: 'tutorial/body-schema.md'
+ - Body - Nested Models: 'tutorial/body-nested-models.md'
- Concurrency and async / await: 'async.md'
- Deployment: 'deployment.md'