How our tech choices trickle down to capabilities #
We just shipped Wagtail 8.1 ahead of Wagtail Space, and the list of v3 API improvements is a good occasion for us to unpack why we selected Django Ninja as the foundation for this new API.
What shipped in Wagtail 8.1 #
We explained the design goals of the API back in August with CMS with AI, not AI CMS: Wagtail 8.0’s new API. The latest release essentially fills the gaps, with better support for complex variations within Wagtail’s content model. We introduced support for more 'write' CMS operations:
- [TypedTableBlock](https://docs.wagtail.org/en/latest/advanced_topics/api/v3/streamfield.html#api-v3-streamfield) (a particularly complex block type)
- [Nested inline relations](https://docs.wagtail.org/en/latest/advanced_topics/api/v3/streamfield.html#api-v3-child-relations) - bit of an oversight, this is very common.
- [Workflow operations](https://docs.wagtail.org/en/latest/advanced_topics/api/v3/workflows.html#api-v3-workflows) - non-essential for the API to work but certainly highly desirable.
And for both 'read' and 'write', spent a lot of time making sure the API schema is as good as it can be:
- StreamField block schemas
- More API schema details for ForeignKey, ManyToManyField, GenericRelation, and Redirects
- Better multi-level relations, multi-table inheritance, and self-references
- Better performance / scaling for larger projects with more models and blocks.
As an illustration, here’s what it would look like to inspect the schema of a specific content block, to check supported values for its fields. Here with an alert block’s alert type:
This doesn’t replicate exactly what information is available in the CMS, but it’s very close. It takes a lot of work to generate schemas that have 'information parity' with the Django forms we have within the CMS, so there is likely more to do here.
Try it out #
We’ll demo the API extensively at Wagtail Space 2026 next week, but if you want to see for yourself, here are the options:
-
Run our official demo site locally. It has lots of API features turned on so you can try both 'read' and 'write' use cases.
-
Run the new headless demo site . It’s a good demo of how the v3 API works as a replacement for v2.
-
Explore the Wagtail user guide contents via its pages API . It’s a public production endpoint you can access anonymously.
-
Or watch the video recording in Wagtail API in action: Content ops with DeepSeek Harness . Here’s an excerpt of what the user guide API offers, depending on authentication and permissions:
Give it a go, it doesn’t take much time at all!
How it’s built and why Ninja #
We considered a lot of factors before going ahead with Ninja. You can review our thinking in RFC 115, here are the highlights.
Schema generation derived from type hints
Having better support for OpenAPI schemas was one of the big draws in going ahead with Django Ninja. Picking API frameworks in 2026, it feels anachronistic to consider options where schema generation isn’t a first-party goal. This functionality is deprecated in DRF, with drf-spectacular being the go-to implementation.
We also wanted to do it based on type annotations. This is a response to three intertwined trends:
- The overall popularity of type annotations and type checking in the overall Python community, as a developer experience benefit.
- Interest in adoption of typing in Wagtail itself , from our users and contributors.
- Fatigue with the verboseness of DRF’s serializers.
Ninja’s function views and Pydantic schemas are much more terse. In practice, in Wagtail, we have a lot of code to dynamic schema generation that is far from idiomatic or ideal. That’s the cost to pay if you place a higher value on feature parity / compatibility between the API and the forms, rather than pure API beauty.
For Wagtail users, they get to enjoy the terseness of the new framework for their new endpoints, and have built-in endpoints that already respond to their need for client / SDK generation based on server-side code.
What DRF does better
While functional Ninja views make the business logic very terse to write, we struggled to adapt some of the things at the periphery of each endpoint’s functionality, like:
- Authentication and authorization (permissions). DRF's class-based model (IsAuthenticated, DjangoModelPermissions, and OPTIONS introspection) maps naturally onto Wagtail's PermissionPolicy. Ninja has no native permission classes.
- Filtering, pagination, versioning. django-filter and DRF's URL/namespace/header versioning options are more mature.
With DRF, there is a whole ecosystem of add-on packages that also bring extra opinions. The best example of this is authentication, where we chose to roll our own authentication and API tokens management. This is a very difficult choice as it greatly increases the maintenance surface of this code. But it seemed necessary to provide a simple 'out of the box' setup for most projects. Auth needs to be pluggable, but the one and only default auth option should already aim for a good balance between convenience and security.
Sustainability factors
We also considered the health / maintenance / sustainability of both projects. Both DRF and Ninja get a lot of usage (downloads at 50% and 5% of Django’s respectively). Both have maintenance challenges, with DRF needing a new home for its maintainers to collaborate, while Ninja is at the stage of a solo author considering onboarding new maintainers. Although DRF is well-maintained for its current feature set and will probably be maintained in perpetuity, it’s clearly not going to evolve in any way to respond to changes in technology, unless you consider it in addition to its surrounding ecosystem.
We looked at both projects’ dependency chains carefully. DRF has none, but we would also need to bring in drf-spectacular and possibly one or two auth packages to get our desired features. While Ninja is mostly just a layer on top of Pydantic. The validation library, not the AI / observability ones.
Ninja’s README, is a good reminder about how those ecosystem governance considerations are impacted by wider societal challenges, with a prominent banner to make package users aware of how the maintainer (and therefore the project) is impacted by Russia’s invasion of Ukraine:
There’s not necessarily any 'right' or 'wrong' answer here. Even with the best-run projects, it’s hard to make open source sustainable in 2026. But for us, it’s important to understand exactly how we can contribute to the sustainability of those projects, and plan contingencies if needed.
What’s next for the API #
First - [Wagtail Space](https://wagtail.org/wagtail-space-2026/), next week, with two API-focused talks!
- In the [State of Wagtail](https://wagtail.org/wagtail-space-2026/state-of-wagtail/) , we’ll get an overview of what the API enables with and without AI agents.
- In How can a 🥷 ninja help 🧑 humans and 🤖 agents talk to 🐦 birds , we’ll get a more in-depth look at how the API’s flagship functionality works
As part of this event, we’ll be looking for feedback on our plans for Wagtail’s next release in RFC 118. Let us know what you think!