Digital Anumati
Digital Anumati

Developer Console

End-to-end setup: generate keys, install the SDK, wire up triggers, and handle webhooks — everything needed to take an application from zero to DPDP-compliant consent capture.

Overview

DPDPA compliant

Built around the requirements of India's Digital Personal Data Protection Act.

Real-time webhooks

Consent events reach your server within milliseconds of capture.

Multi-region in India

Run different consent banners per state or region.

Each registered application gets its own site key, a secret key for server calls, and a verified widget script — visible from the application's console page along with when it was last verified.

SDK setup

Client SDKs render the consent banner in the browser; server SDKs verify consent and handle webhook delivery. The web SDK is a single script tag with no build step — it supports React, Vue, Angular, Next.js, Nuxt, and plain HTML out of the box.

HTML
<!-- Digital Anumati Consent SDK -->
<script
async
src="https://demo.digitalanumati.com/anumati-dpdp-consent-v1.js"
data-site-key="APP_your-app-key"
></script>

Load it inside <head> so the widget is ready before any trigger fires.

KeyTypeUsed for
Site key (data-site-key)Public — safe in browserIdentifies the app on every widget call, enforces the origin/domain allowlist, and namespaces its cookies.
Application secret keyServer-onlySigns outgoing webhooks (HMAC-SHA256) and authorizes server-side Consent API calls. Rotating it invalidates the previous value.

Never expose the secret key client-side

Treat it like a password — sign server-to-server requests with it, keep it out of browser bundles, mobile apps, and public repos.

Attribute-based Trigger

HTML attribute

Add one HTML attribute to any element — the widget does the rest. The Digital Anumati widget scans the DOM for elements carrying da-trigger="<trigger-key>", gates clicks on those elements, and opens the notice for that process automatically. Works with dynamic DOM (SPA re-renders, portals, late-mounted content).

A <form> wrapper is compulsory

The trigger element (button, checkbox, link) MUST live inside a <form>. The widget uses that form as the scope to inject the da-transaction-id hidden input after consent is captured — no form, no hidden id, no way for your backend to link the submission to the consent record.

Step-by-step (beginner friendly)

  1. 1

    Load the widget script on your page

    Copy the SDK snippet from the section above and paste it into your <head> once. Without the script the da-trigger attribute is inert.

  2. 2

    Grab the Trigger Key from your notice card

    Open Data Collection Notice (or Cookie Notice) list in the admin. Each card shows a TRIGGER KEY badge — e.g. medicare_plus_for_registration. Copy that human-readable slug exactly as it appears. This is what goes into the da-trigger attribute — no prefix, no extra quotes.

  3. 3

    Wrap your submit UI in a <form> element

    Even if you handle the submit with JavaScript, the trigger MUST live inside a <form> tag — this is the DOM scope the widget uses to append the da-transaction-id hidden input. Example: <form action='/api/register' method='POST'> ...your fields + trigger... </form>

  4. 4

    Add da-trigger="<TRIGGER KEY>" to any element inside the form

    Paste the Trigger Key (e.g. medicare_plus_for_registration) into the da-trigger attribute of your submit button, a checkbox labelled "I agree", or any element you want to gate. Works on <button>, <input type="checkbox">, <a>, <div>, etc. — as long as it sits inside the <form>.

  5. 5

    Optional — add da-trigger-mode="silent" for one-tick agree flows

    With silent mode, ticking the trigger auto-accepts ALL purposes without opening a dialog. Omit this attribute if you want the granular consent dialog to appear.

  6. 6

    User interacts → widget captures consent → hidden input appears

    On the first click / tick the widget POSTs to consent-capture, then appends <input type="hidden" name="da-transaction-id" value="<uuid>" /> inside the same form.

  7. 7

    Send da-transaction-id along with your form submission

    Either let the browser submit the form (the hidden input is included automatically as a normal field) OR read it inside your JS submit handler with document.querySelector('input[name="da-transaction-id"]') and put it in your API body.

Minimal working example

React · Next.js "use client"
TS
"use client";
export default function RegisterForm() {
return (
<form action="/api/register" method="POST">
<input name="email" type="email" required />
<label>
<input
type="checkbox"
name="agreement"
da-trigger="medicare_plus_for_registration"
/>
I agree to the privacy notice
</label>
<button type="submit">Create account</button>
</form>
);
}

How resolution works

Attribute scan on load

Widget calls document.querySelectorAll("[da-trigger]") after script init and binds a click gate on each match. Value is the Trigger Key from the notice card.

MutationObserver for SPAs

New nodes and attribute changes on da-trigger are observed on document.body — no manual re-bind needed after route changes or React re-renders.

Synthetic trigger built at runtime

Each match produces a synthetic trigger with id da-attr-<processId> — no server-side triggersConfig record required. Consent-config is fetched by processId.

Consent-aware pass-through

After the visitor accepts/rejects, the widget stops intercepting clicks on that trigger for the consent validity window. Re-fires only if consent expires or is revoked.

Attribute name is exact

Use da-trigger (not data-da-trigger). The value must be the Trigger Key from your notice card (e.g. medicare_plus_for_registration) — no prefix, no extra quotes.

Silent Mode — direct accept without dialog

New

Add da-trigger-mode="silent" next to da-trigger to auto-accept ALL purposes when the element is clicked / ticked. No dialog opens. The widget captures consent server-side and injects a hidden input carrying the returned consentId.

1. Mark the trigger as silent

HTML
<input
type="checkbox"
name="agreement"
da-trigger="medicare_plus_for_registration"
da-trigger-mode="silent"
/>

Works on any element (checkbox, button, link, div). On the first user interaction the widget POSTs consent-capture with ALL purposes = granted. Once the capture succeeds, the widget automatically appends a hidden input <input type="hidden" name="da-transaction-id" value="<uuid>" /> inside element.closest("form") ?? element.parentElement. If the trigger sits inside a form the id auto-submits with the form body as a normal field — otherwise read it directly from the DOM.

2. Read da-transaction-id in your submit handler

When the user submits your form, grab the injected hidden input from the DOM and forward its value as consentId to your backend. This is the audit-safe reference issued by the consent-capture API and can be replayed later to prove the user's decision. Read it inside your submit handler (not at render time) — the input only exists after the trigger has fired and the API has returned.

TS
const consentId = (
document.querySelector(
'input[name="da-transaction-id"]',
) as HTMLInputElement | null
)?.value;

Prefer a reactive flow? Subscribe to the da:consent:captured custom event — event.detail.consentId fires the moment the API returns, so you can stash the id in a ref or state without touching the DOM.

When to use silent mode

Ideal for single-checkbox "I agree" experiences where the purpose set is short and the user's tick counts as full acceptance. For notices that require granular purpose choice (Cookie Preferences, multi-level DC notices), omit da-trigger-mode so the dialog opens as usual.

Framework examples

Full <form> samples for Vanilla JS / HTML, React, Next.js, Vue, Angular, and WordPress — each with the trigger checkbox + submit handler wired to read da-transaction-id.

Vanilla JS / HTML

Plain <form> + addEventListener("submit") reading the hidden input from the DOM before fetch().

React

Controlled form with onSubmit handler pulling da-transaction-id off the event target before calling the API.

Next.js (App Router)

"use client" form component; server action receives da-transaction-id as a normal form field.

Vue 3

@submit.prevent handler using $refs.form to look up the injected hidden input.

Angular

Template-driven form + ngSubmit; read the hidden input via ViewChild or direct querySelector.

WordPress

Drop the trigger into a Gutenberg HTML block; the hidden input rides along with any classic PHP form POST.

Webhooks & postbacks

A consent event fires webhook events to your registered server URL; for the events that matter, your server calls back a postback API to confirm what it did. That round trip is what closes the DPDP audit trail.

EventPostback requiredSLAIf missed
consent.createdNo——
consent.withdrawnYes1 hourat_risk → breach
consent.expiry.reminderNo——
consent.expiredYes72 hoursat_risk → breach
consent.grantedNo——
data.deletedYes24 hoursat_risk → unconfirmed_erasure

Your webhook handler must return HTTP 200 within 10 seconds and do the actual work afterward — a slow response is treated as a failed delivery and gets retried.

TS
app.post('/webhook', async (req, res) => {
res.status(200).json({ received: true }); // ack first
const event = req.body;
const dispatchId = req.headers['x-da-dispatch-id'];
// process asynchronously, then call the postback endpoint
});

Postback call

Confirm processing by posting back to the consent action endpoint with the dispatch ID, what you did, and a risk rating.

HTTP
POST https://uat-apis.digitalanumati.com/api/v1/server/consent/action
x-secret-key: da_sk_<your-app-secret-key>
{
"dispatchId": "<from X-DA-Dispatch-ID header>",
"referenceId": "DA-REF-XXXXXXXX",
"status": "processed",
"completedAt": "2026-06-24T10:45:00.000Z",
"risk": "none",
"tags": ["email_stopped", "crm_updated"],
"actions": [
{ "type": "email_unsubscribed", "result": "success" }
],
"remark": "All processing stopped within SLA"
}
complianceFlagMeaningTriggered by
okConfirmed doneprocessed/deleted + risk none/low
at_riskNeeds attentionfailed/partial, or risk medium
breachSerious violationrisk high, or past SLA
criticalImmediate action requiredrisk critical
unconfirmed_erasureDPDP violation30+ days with no data.deleted confirmation

Never skip a postback

Even on failure, send status: "failed" with a remark explaining why — silence reads as a compliance breach.

Consent Management API

A public REST API for managing consent transactions and records on a user's behalf. Calls from a whitelisted browser origin are authenticated by CORS; server-to-server calls use the secret key via an x-secret-key header.

HTTP
Base URL: https://api.digitalanumati.com/api/public/consents
MethodPathPurpose
GET/my-transactionsList transactions
GET/my-transactions/:transactionIdGet one transaction
POST/my-transactions/:transactionId/grantGrant a transaction
POST/my-transactions/:transactionId/revokeRevoke a transaction
POST/my-transactions/:transactionId/eraseErase a transaction
POST/my-transactions/records/:recordId/grantGrant a single record
POST/my-transactions/records/:recordId/revokeRevoke a single record
POST/my-transactions/records/:recordId/eraseErase a single record
POST/my-transactions/bulk/revokeBulk revoke consents
POST/my-transactions/bulk/eraseBulk erase consents
POST/my-transactions/bulk/grantBulk grant consents

Embed a full consent history and self-service management portal on your own site with one div — the widget script already on the page detects it and mounts the portal automatically.

TS
// app/consent/dashboard/page.tsx
"use client";
import { useAuth } from "@/contexts/AuthContext";
export default function ConsentDashboardPage() {
const { user } = useAuth();
return (
<div id="consent-detail-root" data-reference-id={user?.referenceId ?? ""} />
);
}

referenceId (format DA-REF-XXXXXXXX) comes back in the webhook payload the first time a user grants consent — store it against your user record.

User Consent Portal

Consent notification emails — grant requests, expiry reminders, erasure acknowledgements — include a "Manage consent" link. Point it at the hosted Digital Anumati portal, or a custom URL on your own domain using the {referenceId} template variable.

URL
https://yourapp.com/manage/{referenceId}/consent
→ resolves to: https://yourapp.com/manage/DA-REF-647660FC/consent

DPDP compliance checklist

Every application tracks a compliance checklist across seven areas, each item marked critical, important, or recommended before the app can go live:

Consent Collection & Notice

Notice wording, purposes, and capture flow.

Webhook Security & Delivery

Signature verification and reliable delivery.

Postback Compliance (SLA)

Meeting the 1h / 24h / 72h response windows.

Data Processing Controls

Stopping and resuming processing on consent state.

Principal Rights

Access, correction, deletion, grievance handling.

Security & Key Management

Key rotation and secret handling.

Monitoring & Audit Trail

Logging every webhook and postback for evidence.

Not legal advice

This checklist is a technical integration guide. DPDP compliance also needs a published privacy notice, a nominated grievance officer, processor agreements, and board-level accountability — consult your legal team before going live with personal data from Indian residents.
Was this page helpful?