Minor mode for your servers
Ask whether a person is a minor before you target them or share their lead, tell DPDP Guard an age you know, and stay in sync through webhooks.
The DPDP Act, s.9(3), bars tracking, behavioural monitoring and targeted advertising directed at children (anyone under 18). Parental consent does not lift the bar. It applies from 13 May 2027.
Minor mode makes DPDP Guard decide, for each person, whether they are a minor and which of your purposes are barred for them. The consent banner, the consent APIs and the script blocker enforce that answer for you. What DPDP Guard cannot reach is tracking and lead sharing that run on your own servers: an ad server choosing whom to target, or a CRM sending a student’s profile to a college. These three APIs let those systems apply the same answer.
All three use your organization’s service API key, sent as
Authorization: Bearer dpdpg_live_…, from your backend only.
Ask before you target or share a lead
GET /api/v1/principals/minor-status takes exactly one of externalId
(your own user id), email, or anonymousId (the banner’s
dpdp_anonymous_consent_id):
curl "https://<deployment>.convex.site/api/v1/principals/minor-status?externalId=crm-12345" \
-H "Authorization: Bearer $DPDP_API_KEY"
{
"principalRef": "up:k17a2…",
"principalRefKind": "up",
"minorStatus": {
"status": "minor",
"restricted": true,
"parentalConsent": "none",
"restrictedPurposeKeys": ["personalised_recommendations", "share_my_profile_with_colleges"]
},
"evaluatedAt": 1793606400000
}
statusisminor,adultorunknown. A minor signal always beats an adult one.restricted: truemeans: do not track, target or share for any purpose inrestrictedPurposeKeys. Anunknownperson is restricted when your organization runs minor mode as “assume minor”.parentalConsentsays whether a guardian is verified. It never liftsrestricted.- A
404means your organization holds no consent, age signal or mapping for that identifier. If your organization assumes minors, treat it as restricted.
The same minorStatus object, plus a restrictedForMinor flag on each
purpose, is in GET /api/v1/consent-status. A plugin that already gates a
marketing sync on consent status gets minor mode with no second call.
Recipe: ad server and CRM
- Before you target someone: call
minor-statuswith your user id (or the visitor’sanonymousId). Ifrestrictedistrueand the campaign’s purpose is inrestrictedPurposeKeys, serve an untargeted ad, or none, and do not record the impression against a profile. - Before you share a lead: call
minor-statuswith the lead’s email or your id for them. Ifrestrictedistrueand lead sharing is inrestrictedPurposeKeys, do not send the lead. - Cache the answer, and keep it fresh with webhooks: subscribe an
endpoint to
principal.minor_status_changedand update your cache from each event, keyed onprincipalReforexternalId. You no longer need to callminor-statuson every impression. - Stop on withdrawal too: when a person becomes restricted, their
barred consents are withdrawn and you receive
consent.withdrawnfor each. Treat it like any other withdrawal.
Tell DPDP Guard an age you know
If your signup form asks for a date of birth, or you run a KYC check, send the result so the banner and every consent path see it:
curl -X POST "https://<deployment>.convex.site/api/v1/age/signal" \
-H "Authorization: Bearer $DPDP_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: signup-crm-12345" \
-d '{"externalId": "crm-12345", "band": "16_18", "level": "self_declared", "source": "signup_dob"}'
- Name the person with exactly one of
externalIdoremail. AnexternalIdDPDP Guard has not seen yet is recorded on its own and joins the person when you broker a token for them. bandis one ofunder_8,8_12,12_16,16_18,adultorunknown.levelis how sure you are:self_declared(the default),inferredordocument_asserted.verified_adult_linkedis refused, because only parental verification can record it: today, a checked attestation your DPO records on the Children’s Data page. (/api/v1/age/verify-parentanswers503until an online verification provider is integrated.)- A minor band always wins. An adult band never replaces stronger evidence,
and lifts a minor band only when it is stronger evidence than that band.
For example, a
document_asserteddate of birth corrects a mistaken “No” given in the banner, but a second self-declaration does not. (The correction applies on the server and to every API; the browser that answered “No” keeps its own stored answer until its site data is cleared.) It never lifts a child flag your staff set. - Under “assume minor”, an adult signal counts only at or above your organization’s adult assurance level.
sourceis a short label (up to 64 characters) for where the signal came from. It is audited with your API key, and never changes how the signal is weighed.
The response is the person’s status after the signal. applied: false
means it could not loosen what was already held. Send an Idempotency-Key
so a retried request is not recorded twice. Requests are limited to 60 a
minute per API key.
Withdrawals from the banner
When the banner learns a visitor is restricted, it withdraws their stored
grants for barred purposes with reason: "minor_mode" on
POST /api/v1/consents/anonymous/withdraw. These are recorded like DPDP
Guard’s own minor-mode withdrawals. A custom client can send the same
field.
What this does not cover
Minor mode tells your systems; it cannot enforce what runs outside DPDP Guard, such as server-side tag managers or CRM enrichment. A script that has already run in a visitor’s browser cannot be unloaded; the banner recommends a reload instead.