Skip to content
🚨 DPDP Rules 2025: Compliance Deadline 27 weeks awayRead handbook →

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
}
  • status is minor, adult or unknown. A minor signal always beats an adult one.
  • restricted: true means: do not track, target or share for any purpose in restrictedPurposeKeys. An unknown person is restricted when your organization runs minor mode as “assume minor”.
  • parentalConsent says whether a guardian is verified. It never lifts restricted.
  • A 404 means 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

  1. Before you target someone: call minor-status with your user id (or the visitor’s anonymousId). If restricted is true and the campaign’s purpose is in restrictedPurposeKeys, serve an untargeted ad, or none, and do not record the impression against a profile.
  2. Before you share a lead: call minor-status with the lead’s email or your id for them. If restricted is true and lead sharing is in restrictedPurposeKeys, do not send the lead.
  3. Cache the answer, and keep it fresh with webhooks: subscribe an endpoint to principal.minor_status_changed and update your cache from each event, keyed on principalRef or externalId. You no longer need to call minor-status on every impression.
  4. Stop on withdrawal too: when a person becomes restricted, their barred consents are withdrawn and you receive consent.withdrawn for 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 externalId or email. An externalId DPDP Guard has not seen yet is recorded on its own and joins the person when you broker a token for them.
  • band is one of under_8, 8_12, 12_16, 16_18, adult or unknown.
  • level is how sure you are: self_declared (the default), inferred or document_asserted. verified_adult_linked is 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-parent answers 503 until 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_asserted date 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.
  • source is 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.