Skip to main content

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 a definition_key.
  • Definition-key aliasing — callers use a stable alias (e.g. "users_get") mapped via JSON config to the underlying definition_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_map and content_type on ExternalServiceEndpoint.
  • 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, and error_id for 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 models
  • django_api_utility/transport/: shared requests session (connection-level retries), retry policy, outbound execution primitive
  • django_api_utility/domain/: definition-key resolution, endpoint resolution, token lifecycle, schema validation
  • django_api_utility/orchestration/: request_by_key and 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, IDP jwt_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 Session model and session_service (SSO login-session tracking, revoke-on-logout/new-login) were dropped; that responsibility now lives in the auth proxy.
  • Structured exceptions. HttpClientError, TokenRequestError, and EndpointRequestError now carry http_status, is_retryable, and error_id, so callers can map failures to typed responses without parsing message strings.
  • Resilient HTTP execution. transport/http_client.py now reuses a pooled requests.Session with urllib3 connection-level retries (DNS/reset/429), and orchestration/api_service.py adds status-based retries with exponential backoff/jitter via tenacity for idempotent methods, plus better non-JSON/error-body handling.
  • form_data support end-to-end through request_by_key/_send_request, alongside existing JSON payloads.
  • Per-endpoint payload key remapping and content_type on ExternalServiceEndpoint.
  • Raised floors: Python 3.11+, Django 5.2+, requests 2.32+, cryptography 43+, jsonschema 4.23+; added tenacity and PyJWT as dependencies.

0.1.0

  • Initial release: config-driven endpoint registry (ExternalServiceConfig/ExternalServiceEndpoint), definition-key aliasing, client_credentials/IDP jwt_bearer OAuth token lifecycle with Fernet-encrypted secret storage, Session model + session_service for 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)

Source distribution for django-api-utility 2.0.0
File Size Uploaded
django_api_utility-2.0.0.tar.gz 26.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for django-api-utility 2.0.0
File Interpreter ABI Platform
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

Release history Release notifications | RSS feed

3.1.0

2 release files

3.0.0

2 release files

This release

2.0.0 This release

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page