django-api-utility
Reusable Django app for calling external/partner APIs from a config-driven registry, with automatic OAuth token management and user session tracking.
Features
- Endpoint registry — services and endpoints defined as DB models (
ExternalServiceConfig,ExternalServiceEndpoint), resolved at call time by adefinition_key. - Definition-key aliasing — callers use a stable alias (e.g.
"users_get") mapped via JSON config to the underlyingdefinition_key, decoupling call sites from registry changes. - Machine-token delegation — fetches and caches per-service access tokens from an internal auth proxy (resolved through the same definition-key registry as any other endpoint); this package no longer performs the OAuth exchange or holds client secrets/signing keys itself.
- Payload key remapping & content-type control — per-endpoint
payload_key_mapandcontent_typeonExternalServiceEndpoint. - Request/response schema validation — optional JSON Schema validation per endpoint via
ExternalEndpointSchema. - Resilient HTTP execution — connection-level retries (urllib3) plus status-based retries with exponential backoff/jitter (tenacity) for idempotent methods, transparent 401 → token-refresh → retry-once, and upstream error-message extraction (including non-standard batch/207 responses).
- Structured exception hierarchy — typed errors carrying
http_status,is_retryable, anderror_idfor observability/middleware mapping.
Install
pip install -e .
Django setup
INSTALLED_APPS = [
# ...
"django_api_utility",
]
Run migrations to create the registry, token config, schema, and session tables.
Definition key mapping
Provide a JSON mapping file via EXTERNAL_DEFINITION_KEYS_FILE, or use the packaged default at config/external_definition_keys.json.
{
"users_get": "service_users_get"
}
Usage
Calling an endpoint
from django_api_utility import get_by_key, post_by_key
response = get_by_key("users_get", params={"page": 1})
create_response = post_by_key("users_create", payload={"name": "Alice"})
request_by_key (and its get/post/put/patch/delete_by_key shortcuts) resolves the endpoint, attaches a valid bearer token when the service requires auth, validates payload/response against any configured schema, retries on transient failures, and refreshes+retries once on a 401.
Configuration (Django settings)
| Setting | Purpose | Default |
|---|---|---|
EXTERNAL_DEFINITION_KEYS_FILE |
Path to definition-key JSON mapping | packaged config/external_definition_keys.json |
API_UTILITY_FERNET_KEY |
Encryption key for stored secrets/tokens | derived from SECRET_KEY |
API_UTILITY_VALIDATE_SCHEMAS |
Enable request/response schema validation | True |
API_UTILITY_MACHINE_TOKEN_DEFINITION_KEY |
Definition key for the auth proxy's machine-token endpoint | AUTH_PROXY_MACHINE_TOKEN |
API_UTILITY_TOKEN_EXPIRY_BUFFER_SECONDS |
Refresh-ahead buffer before expiry | 60 |
API_UTILITY_DEFAULT_TOKEN_EXPIRES_IN |
Fallback token TTL if the proxy omits expires_in |
3600 |
Internal layout
django_api_utility/models.py: service/endpoint registry, token config, and schema modelsdjango_api_utility/transport/: sharedrequestssession (connection-level retries), retry policy, outbound execution primitivedjango_api_utility/domain/: definition-key resolution, endpoint resolution, token lifecycle, schema validationdjango_api_utility/orchestration/:request_by_keyand friends — retries, auth refresh, schema hooks, error normalization
Tests
pip install -e ".[test]"
pytest -q
Changelog
0.2.0
- Token issuance moved behind an auth proxy. The package no longer performs the OAuth exchange (
client_credentials, IDPjwt_bearer/RS256) or stores client secrets/signing keys itself — it now fetches a ready-to-use, cached machine token from an internal auth proxy endpoint, resolved through the normal definition-key registry. - Session tracking removed. The
Sessionmodel andsession_service(SSO login-session tracking, revoke-on-logout/new-login) were dropped; that responsibility now lives in the auth proxy. - Structured exceptions.
HttpClientError,TokenRequestError, andEndpointRequestErrornow carryhttp_status,is_retryable, anderror_id, so callers can map failures to typed responses without parsing message strings. - Resilient HTTP execution.
transport/http_client.pynow reuses a pooledrequests.Sessionwith urllib3 connection-level retries (DNS/reset/429), andorchestration/api_service.pyadds status-based retries with exponential backoff/jitter viatenacityfor idempotent methods, plus better non-JSON/error-body handling. form_datasupport end-to-end throughrequest_by_key/_send_request, alongside existing JSON payloads.- Per-endpoint payload key remapping and
content_typeonExternalServiceEndpoint. - Raised floors: Python 3.11+, Django 5.2+, requests 2.32+, cryptography 43+, jsonschema 4.23+; added
tenacityandPyJWTas dependencies.
0.1.0
- Initial release: config-driven endpoint registry (
ExternalServiceConfig/ExternalServiceEndpoint), definition-key aliasing,client_credentials/IDPjwt_bearerOAuth token lifecycle with Fernet-encrypted secret storage,Sessionmodel +session_servicefor SSO login tracking, JSON Schema validation, basic retry/backoff on outbound calls.
Metadata
Release files for django-api-utility 2.0.0
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_utility-2.0.0.tar.gz | 26.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| django_api_utility-2.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 61.1 kB
Release files / django_api_utility-2.0.0.tar.gz
| Download URL | django_api_utility-2.0.0.tar.gz |
|---|---|
| Size | 26.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
7e89ac7647249f5072da85e7866efcd9368b9f5810b5f22516277c2d61ca3565
|
|
BLAKE2b-256 checksum How to use checksums |
10dde7c49859de24ffe40ca80781724c70dc85431de15f42f8f5949f5e982a1f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.15
|
Release files / django_api_utility-2.0.0-py3-none-any.whl
| Download URL | django_api_utility-2.0.0-py3-none-any.whl |
|---|---|
| Size | 35.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
396948b6f9018b8a75d1df7da0ff06f1622e70addc0465058df98a9347b858a9
|
|
BLAKE2b-256 checksum How to use checksums |
166344725b851678ee13b5a9728324c48c8d59afa3aaeddc628d1ccf543e6aa7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.15
|