Webhooks
Subscribe to DPDP Guard events from your own backend.
DPDP Guard can POST an event to your backend whenever something your own systems must act on happens: a consent given or withdrawn, a rights request raised or closed, a breach recorded, a grievance resolved, or a person’s minor status changing. Add an endpoint under Integrations → Webhooks, pick the events, and keep the signing secret it shows you once.
Every delivery
Each delivery is a POST with a JSON body:
{
"eventType": "consent.withdrawn",
"organizationId": "<your organization id>",
"payload": { "...": "event-specific, see below" },
"timestamp": 1793606400000
}
timestamp is when the delivery was sent, in epoch milliseconds. The
X-DPDP-Signature header is the hex HMAC-SHA256 of the raw request body,
keyed with your endpoint’s signing secret. Verify it against the raw bytes
before parsing; re-serialising the JSON can change them. The setup wizard
shows a copy-pasteable Node.js verifier.
Answer with any 2xx status. Every attempt, with its HTTP status, is
listed in the endpoint’s delivery log.
Events
| Event | When | payload |
|---|---|---|
consent.given |
A person records a consent. | consentId, purpose, dataTypes |
consent.withdrawn |
A consent is withdrawn — by the person, the banner, your API call, or minor mode’s automatic withdrawal. | consentId, purpose |
dsr.created |
A rights request is raised. | requestId, type |
dsr.completed |
A rights request is completed. | requestId, type, principal (email, name) when known |
dsr.rejected |
A rights request is rejected. | requestId, type |
breach.recorded |
A breach is logged in the breach register. | breachId, discoveredAt |
grievance.resolved |
A grievance is resolved. | grievanceId |
principal.minor_status_changed |
A person’s minor status changes. | See below. |
principal.minor_status_changed
Sent when a person becomes, or stops being, a minor or restricted under minor mode (DPDP Act s.9(3): no tracking, behavioural monitoring or targeted advertising directed at children). Use it to keep your ad server’s and CRM’s view of who may be targeted, or whose lead may be shared, up to date without polling.
{
"eventType": "principal.minor_status_changed",
"organizationId": "<your organization id>",
"payload": {
"principalRef": "up:k17a2…",
"externalId": "crm-12345",
"status": "minor",
"restricted": true,
"restrictedPurposeKeys": ["personalised_recommendations", "share_my_profile_with_colleges"],
"effectiveAt": 1793606400000
},
"timestamp": 1793606400125
}
| Field | Meaning |
|---|---|
principalRef |
Who changed. Opaque, and the same value GET /api/v1/principals/minor-status returns, so you can correlate the two. A banner visitor linked to a known person is reported as that person. |
externalId |
Your own user id for the person, when you have brokered a token for them or sent an age/signal with it. Omitted otherwise. |
status |
minor, adult or unknown. |
restricted |
true when purposes barred for minors are refused for this person. |
restrictedPurposeKeys |
The purpose keys that are refused. Empty when restricted is false. |
effectiveAt |
When the change took effect, in epoch milliseconds. |
It is sent only when status or restricted actually changes: a repeated
signal sends nothing. Every source of change sends it — a staff child
flag, an answer in the banner, your POST /api/v1/age/signal, parental
verification, linking a banner visitor to a signed-in person, and a change
to your organization’s minor-mode setting. A setting change re-checks every
person you hold a consent or an age signal for, in batches, and sends one
event per person whose status changed.
When a person becomes restricted, their consents for barred purposes are
also withdrawn, and each withdrawal sends its own consent.withdrawn.
See Minor mode for your servers for how to use this event with the minor-status lookup.