Serving Other Systems From a Django Application
Last updated:
Share the logic, not the views
The temptation is to duplicate business rules between web views and API endpoints. That duplication drifts, and the two paths eventually behave differently.
Put the business logic in a service layer that both the web views and the API call. Then a rule change applies everywhere by construction.
Permissions must apply identically
- The same record-level filtering as the web interface
- The same action permissions
- Tested adversarially, with tokens from different users
- Applied to list endpoints, not just detail ones
An API that bypasses your permission model is a hole in it, and it is frequently discovered by someone exploring rather than by a test.
Design for the consumer
- Consistent structure across every endpoint
- Meaningful status codes, not 200 with an error in the body
- Pagination on every collection, from the start
- Filtering and ordering where consumers will need it
- Expose business concepts, not your table structure
Version it from the beginning
Adding versioning after the first consumer means either breaking them or maintaining an unversioned path forever. A path prefix costs nothing at the start.
Then be explicit about what constitutes a breaking change and announce deprecations with real dates.
Rate limit, including internally
| Limit | Applies to |
|---|---|
| Per token | External consumers |
| Per endpoint | Expensive operations |
| Internal services | Yes — loops cause outages |
| Unauthenticated endpoints | Strictly |
Frequently asked questions
Should we use a REST framework?
How do we handle authentication?
Can the API and web app share models?
What about documentation?
Adding an API to an existing application?
The permission and logic sharing decisions matter most. Happy to review a design.
Related services
What we build for problems like this one