This release has been yanked by its maintainers, and will be ignored by installers, except when explicitly specified.
Consider using release 0.1.10 instead.
Reason given by maintainers: Superseded by 0.1.8: the account assignment was redesigned, and 0.1.7 never reached production.
django-api-usage
Lightweight, privacy-first usage metering for Django APIs, with an optional deprecation lifecycle layer on top.
It answers two questions that decide whether an endpoint can be changed or removed:
- How much is this endpoint (or this whole Django app) used?
- Who is calling it, so they can be contacted before it changes?
The package is deliberately generic: the core is plain Django middleware (works with or without Django REST Framework), it never breaks a request because metering failed, and it stores no raw personal data by default.
Why not just drf-api-tracking?
drf-api-tracking stores one database row per request (including bodies), which
is heavy and privacy-sensitive. django-api-usage accumulates counters and
keeps consumer attribution hashed and opt-in. That makes it suitable both for
continuous usage analytics and for the concrete decision of deprecating an
endpoint.
Install
pip install django-api-usage
INSTALLED_APPS = [
# ...
"django_api_usage",
]
MIDDLEWARE = [
# ...
"django_api_usage.middleware.ApiUsageMiddleware",
]
Metering starts immediately. Counters are buffered in the cache and written to the database in batches:
python manage.py api_usage_flush # from cron, or a Celery beat task
python manage.py api_usage_report --days 30
python manage.py api_usage_report --days 90 --sunset-candidates
With Celery (and the celery extra) two tasks are provided:
django_api_usage.tasks.flush_api_usage and
django_api_usage.tasks.prune_api_usage.
Configuration
API_USAGE = {
"ENABLED": True,
"FAIL_OPEN": True,
"BUFFER_BACKEND": "cache", # "cache" (batched) or "db" (write per request)
"RETENTION_DAYS": 90,
"TRACK_CONSUMERS": False, # opt-in; stores hashed callers only
"CONSUMER_SALT": "a-rotatable-secret",
}
All resolvers are overridable, so no project-specific knowledge leaks into the package:
API_USAGE = {
"APP_LABEL_RESOLVER": "myproject.api.resolvers.app_label",
"SITE_RESOLVER": "myproject.api.resolvers.site_id",
"ROLE_SCOPES_RESOLVER": "myproject.api.resolvers.role_scopes",
}
Admin
The package ships a read-only admin for the three models, built with plain
Django — no dependency beyond Django itself (no django-object-actions or
similar):
- Endpoint stats changelist: a search box (by endpoint path, route name, app,
method or replacement), filters by date, client type, status class, and
Application / Method, plus the sum of the
countcolumn for the rows matching the current filters. The Method filter lists the riskiest verbs first (DELETE,POST, ...), so write and destructive calls stand out. - Endpoint changelist: the same Application / Method filters, plus deprecation state, the site and the CSV export.
- Flush now: moves counters buffered in the cache into the database, so they
appear immediately when you run with
BUFFER_BACKEND = "cache". - Clear statistics: empties the aggregated counters behind a confirmation page (endpoints and their deprecation metadata are kept).
- Export selected rows to CSV on all three admins. Relations are flattened into one analysis-friendly table (a stat row carries its endpoint's path, app and method), so the file can be fed straight to pandas or a spreadsheet. Use the "select all" link to export every row matching the current filters.
Client applications
Not every caller is a person: ERPs, partners, your own web front end and the
native mobile apps also hit the API. ClientApp is an editable table, so a
new consumer is recognised from the admin, without a deploy:
| Rule | Matched against | Use it for |
|---|---|---|
accounts |
the authenticated user (and therefore its DRF token) | one dedicated token per integration (ERP, partner...) |
domains |
the Origin/Referer host, subdomains included |
your own web front end |
ip_networks |
the client address, against a CIDR (one per line) | internal networks and servers |
user_agent_patterns |
a case-insensitive substring of User-Agent |
native mobile apps |
Rules are checked in that order, and priority decides between applications
(lower wins). A caller matching nothing stays unattributed, so the dimension
cannot grow out of control: EndpointStat.client_app only ever holds a
ClientApp.slug.
Counters, the CSV export and the admin filters all carry the application, so "which application calls this endpoint?" is one filter away. The Endpoint stats changelist also offers Not attributed: the callers still to classify.
Deprecation lifecycle
Endpoint carries deprecated, sunset_date, replacement and owner, so the
same data that measures usage also drives a deprecation plan. See the consuming
project's migration guide for the full workflow (measure → notify → enforce).
DRF shadow mode
django_api_usage.drf.HasAPIScope enforces scopes declared on a view:
class AllUserViewSet(viewsets.ReadOnlyModelViewSet):
permission_classes = [HasAPIScope]
required_scopes = ["user:read_all"]
With API_ENFORCEMENT = "report" (the default) nothing is blocked yet: a
X-Api-Would-Deny header is returned instead, so you can deploy a permission and
measure what it would have denied before enforcing it.
Status
Alpha. The core is implemented: metering middleware, models and migrations, management commands, the deprecation layer and a DRF shadow-mode permission. Tested on Python 3.10-3.12 and Django 4.2/5.2. MIT licensed.
Development
python -m django test tests --settings=tests.settings
ruff check .
black --check .
Metadata
Release files for django-api-usage 0.1.7
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| django_api_usage-0.1.7.tar.gz | 35.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| django_api_usage-0.1.7-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 70.4 kB
Release files / django_api_usage-0.1.7.tar.gz
| Download URL | django_api_usage-0.1.7.tar.gz |
|---|---|
| Size | 35.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
e61ae0b4bd34274afc9c7dfd3ac0a85eddd0c4b90b873e0e579ac2979c775511
|
|
BLAKE2b-256 checksum How to use checksums |
3349f2af0722b7417ce0bfc8736df260689dcf5c1a484f9b4c9e918da7c9d020
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.9.25
|
Release files / django_api_usage-0.1.7-py3-none-any.whl
| Download URL | django_api_usage-0.1.7-py3-none-any.whl |
|---|---|
| Size | 34.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
75028f511856203065beed8c98446ffd8abddc748d498a85944510f247afd7be
|
|
BLAKE2b-256 checksum How to use checksums |
e287968b7e1eac3c69ffe64e4d5102c02f220057c0153dc1299af6170b5f0a4d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.9.25
|