dpdpguard-python-sdk
DPDP Guard Server SDK (Python) — typed API client, consent gate, token broker
helper, audit-hash verifier, and webhook signature verifier over DPDP Guard's
public /api/v1.
PyPI distribution: dpdpguard-sdk · Import as: dpdpguard
This SDK mirrors @dpdpguard/server
(the Node/TypeScript reference implementation) method for method, so behavior —
auth modes, idempotency headers, error codes, audit-hash canonicalization — stays
identical across ecosystems.
Install
pip install dpdpguard-sdk
Or with uv:
uv add dpdpguard-sdk
Quickstart
import os
from dpdpguard import DpdpGuardClient, has_consent, verify_webhook_signature
client = DpdpGuardClient(
"https://<your-deployment>.example.com",
api_key=os.environ["DPDP_SERVICE_API_KEY"], # required for broker_token() only
)
# Mint a brokered principal access token for a known user.
client.broker_token(external_id)
# Now authenticated calls use that token automatically.
result = client.list_dsr_requests()
client.create_dsr_request(organization_id=org_id, type="erasure")
# Public reads need no auth at all.
org = client.get_organization("acme")
notices = client.get_notices(org["orgId"])
# Verify an inbound webhook.
ok = verify_webhook_signature(webhook_secret, raw_body, request.headers.get("x-dpdp-signature"))
Use it as a context manager to close the underlying httpx.Client automatically:
with DpdpGuardClient(base_url) as client:
org = client.get_organization("acme")
DpdpGuardClient
DpdpGuardClient(
base_url: str,
*,
api_key: str | None = None,
access_token: str | None = None,
http_client: httpx.Client | None = None,
)
base_url— your DPDP Guard deployment's base URL.api_key— service API key; required forbroker_token().access_token— a brokered principal access token, if you already minted one.http_client— override for testing/transport customization; defaults to a newhttpx.Client. The client owns and closes it unless one was passed in.
Every non-2xx response raises a DpdpGuardApiError with a code from the
error catalog (err.code, e.g. "NOT_FOUND") and the HTTP status.
Every request also sends X-DPDP-SDK: python/<version> for SDK-version
identification.
Public reads (no auth)
| Method | Description |
|---|---|
get_organization(slug) |
Fetch an organization's public summary by slug. |
get_notices(org_id) |
List published consent notices for an organization. |
get_notice(notice_id) |
Fetch a single notice. |
get_banner_config(org_id, *, domain=None, app_id=None) |
Fetch consent-banner config, optionally scoped to a domain or app. |
Auth
| Method | Description |
|---|---|
broker_token(external_id) |
Mints a brokered principal access token using the service API key, and stores it on the client for subsequent calls. |
set_access_token(token) |
Replace the stored access token (e.g. after re-brokering on expiry). |
link_anonymous_consent(anonymous_id) |
Link consent given anonymously to an authenticated principal. |
DSR (Data Subject Requests)
| Method | Description |
|---|---|
list_dsr_requests() |
List the caller's DSR requests. |
create_dsr_request(*, organization_id, type, details=None, idempotency_key=None) |
Create a DSR request (type is one of "summary", "processors", "correction", "erasure"). Pass idempotency_key to set an Idempotency-Key header. |
Grievances
| Method | Description |
|---|---|
list_grievances() |
List the caller's grievances. |
create_grievance(*, organization_id, subject, description) |
File a grievance. |
Nomination
| Method | Description |
|---|---|
get_nomination() |
Fetch the caller's current nomination, or None. |
upsert_nomination(*, nominee_name, nominee_contact) |
Create or replace the caller's nomination. |
revoke_nomination() |
Revoke the caller's nomination. |
Consent gate
from dpdpguard import has_consent
if not has_consent(consents, "Marketing"):
return # don't send the campaign
has_consent(consents, purpose) is a pure helper — it doesn't call the
network. consents is any sequence of objects matching the ConsentRecord
protocol (a purpose: str and a withdrawn_at: int | None); combine it with
list_dsr_requests()-style reads or your own cached consent state.
Audit-hash verification
A holder of the platform's audit-hash HMAC secret can independently verify a
consent audit trail row's auditHash:
from dpdpguard import AuditHashInput, compute_audit_hash
input = AuditHashInput(
organization_id="org_abc123",
notice_id="notice_v1",
notice_version=1,
purpose="Newsletter",
data_types=["email"],
given_at=1700000000000,
source="direct",
)
assert compute_audit_hash(input, secret) == stored_audit_hash
canonicalize_audit_event(input) is also exported if you need the canonical
string form (e.g. for debugging a mismatch) without hashing it.
Webhook signature verification
from dpdpguard import verify_webhook_signature
ok = verify_webhook_signature(secret, raw_body, request.headers.get("x-dpdp-signature"))
raw_body must be the exact bytes/string received on the wire, before any
json.loads — HMACs are sensitive to whitespace/key-order, so re-serializing
a parsed object and hashing that will not match. Comparison is constant-time.
Error handling
from dpdpguard import ApiErrorCode, DpdpGuardApiError, ERROR_CATALOG
try:
client.get_notice("missing")
except DpdpGuardApiError as err:
print(err.code, err.status) # e.g. "NOT_FOUND", 404
ERROR_CATALOG is a list of ErrorCatalogEntry ({"code": ..., "description": ...})
describing every code in ApiErrorCode.
Typed models
dpdpguard.models exposes TypedDicts for every wire shape the client
returns — OrgSummary, Notice, NoticeItemized, DsrRequest, Grievance,
Nomination, BannerConfig, BrokerTokenResult, LinkAnonymousConsentResult,
NeedsReconsentEntry, NoticesResponse, DsrRequestsResponse,
GrievancesResponse, and the DsrType alias. Field names are the exact JSON
keys (camelCase) the API sends/expects — no snake_case remapping — so what
you see is what's on the wire.
Development
pip install -e ".[dev]"
ruff check .
mypy src
pytest --cov=src --cov-report=term-missing
Metadata
Release files for dpdpguard-sdk 1.1.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 | |
|---|---|---|---|
| dpdpguard_sdk-1.1.0.tar.gz | 18.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| dpdpguard_sdk-1.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 34.4 kB
Release files / dpdpguard_sdk-1.1.0.tar.gz
| Download URL | dpdpguard_sdk-1.1.0.tar.gz |
|---|---|
| Size | 18.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c2832ce115a1c384cb2954674f90f8066497f00658b7e3f6b0888c425b3c0aa0
|
|
BLAKE2b-256 checksum How to use checksums |
8d6562aed7e59477aef32c1133bee0327df17afe6b2c766d5ec520379c406cff
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 12, 2026.
Transparency logRelease files / dpdpguard_sdk-1.1.0-py3-none-any.whl
| Download URL | dpdpguard_sdk-1.1.0-py3-none-any.whl |
|---|---|
| Size | 15.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
15dc2d00a867391ed3a6f722c28829cb96e05a1342f833c5fb13f8f53d9f1f40
|
|
BLAKE2b-256 checksum How to use checksums |
f36e81daa59a4b21918ab06d627dea7d22907c27b404e1eed64efa9f2f3937c7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 12, 2026.
Transparency log