Mobile & server SDKs
Install a published DPDP Guard SDK for web, React Native, Flutter, Android, iOS, Node or the JVM, and integrate without a native Convex client.
DPDP Guard publishes seven SDKs plus one shared contract package. Each SDK is a
typed client over DPDP Guardβs /api/v1 HTTP surface, so your app or backend
never talks to Convex directly and never depends on this repository.
For a benefit-led overview with use cases for each SDK, see the public SDKs page.
Availability
Versions below were verified against each public registry on 26 July 2026. Registries are the source of truth β a few SDK repository READMEs are still stale and describe themselves as unreleased even though their artefact is live.
| Platform | Package | Version | Install from |
|---|---|---|---|
| Web / JavaScript | @dpdpguard/js |
1.0.1 | npm |
| React Native | @dpdpguard/react-native |
0.1.0 | npm |
| Flutter | dpdpguard_flutter |
0.1.0 | pub.dev |
| Android (Kotlin) | ai.dpdpguard:consent-sdk |
0.1.1 | Maven Central |
| iOS / macOS (Swift) | DPDPGuardConsent |
0.1.0 | Swift Package Manager |
| Node (server) | @dpdpguard/server |
1.0.0 | npm |
| JVM β Kotlin/Java (server) | ai.dpdpguard:server-sdk |
0.1.0 | Maven Central |
| Shared contract | @dpdpguard/contract |
0.2.0 | npm |
The /api/v1 surface is enabled per organisation. The packages are
installable today, but the HTTP API they call is still being switched on
workspace by workspace during rollout β while it is off, its endpoints respond
as though they do not exist. Build against an SDK now, and ask support to enable
the API for your organisation before you ship.
Install
# Web / any fetch-capable JavaScript runtime
npm install @dpdpguard/js
# React Native
npm install @dpdpguard/react-native
# Node backend
npm install @dpdpguard/server
# Flutter
flutter pub add dpdpguard_flutter
// Android β app/build.gradle.kts
dependencies {
implementation("ai.dpdpguard:consent-sdk:0.1.1")
}
// JVM backend β build.gradle.kts
dependencies {
implementation("ai.dpdpguard:server-sdk:0.1.0")
}
// iOS / macOS β Package.swift
.package(
url: "https://github.com/dpdp-guard-ai/dpdpguard-ios-sdk.git",
from: "0.1.0"
)
Client vs. server: where the API key lives
The split between the client and server SDKs is a security boundary, not a packaging convenience.
- Server SDKs (
@dpdpguard/server,ai.dpdpguard:server-sdk) hold your service API key. They mint short-lived data-principal access tokens withbrokerToken(), check consent before your own processing runs, and verify theX-DPDP-Signatureheader on inbound webhooks. - Client SDKs (web, React Native, Flutter, Android, iOS) deliberately have
no token broker. A service API key is extractable from any app binary, so
brokering stays server-side: your backend mints the token and hands it to the
app, which passes it to the client via
setAccessToken()or the constructor. Audit-hash and webhook-signature helpers are likewise absent from the hybrid client SDKs β both need a server-held HMAC secret.
A typical mobile integration therefore uses two SDKs: a server SDK in your backend to broker the token, and a client SDK in the app to use it.
Typical client usage
import { DpdpGuardClient } from "@dpdpguard/react-native";
const client = new DpdpGuardClient({
baseUrl: "https://<your-deployment>.convex.site",
});
// Token brokered by your own backend, never by the app.
client.setAccessToken(tokenFromMyBackend);
const org = await client.getOrganization("acme");
const { notices } = await client.getNotices(org.orgId);
const { requests } = await client.listDsrRequests();
await client.createDsrRequest({ organizationId: org.orgId, type: "erasure" });
The Flutter SDK exposes the same surface in Dart, and @dpdpguard/js covers the
public, unauthenticated subset only (org lookup, notices, banner config,
anonymous consent).
Typical server usage
import {
DpdpGuardClient,
hasConsent,
verifyWebhookSignature,
} from "@dpdpguard/server";
const client = new DpdpGuardClient({
baseUrl: "https://<your-deployment>.convex.site",
apiKey: process.env.DPDP_SERVICE_API_KEY,
});
// Mint a short-lived token for a known user, then hand it to your app.
await client.brokerToken(externalId);
// Gate your own processing on a consent decision. `hasConsent` is a pure
// helper over consent records you already hold β it makes no network call.
if (hasConsent(consents, "Marketing")) {
await addToExport(user);
}
// Verify an inbound webhook before acting on it.
const ok = verifyWebhookSignature(
webhookSecret,
rawBody,
req.headers["x-dpdp-signature"],
);
Errors
Every non-2xx response raises a DpdpGuardApiError β the same name across the
TypeScript, Dart and Kotlin SDKs β carrying the HTTP status and a stable code
from the error catalog in @dpdpguard/contract. Branch on the code, not on the
free-text message: codes are part of the versioned contract, messages are not.
Versioning
Three axes move independently:
- Wire API β the major version is in the URL path (
/api/v1). - Contract package β
@dpdpguard/contractfollows semantic versioning and carries the OpenAPI description, the error catalog, and the audit-hash canonicalisation spec with its golden vectors. - Each SDK β versioned independently on its own registry.
A breaking contract change (a newly required field, a removal, an error-code change, or any change to audit-hash canonicalisation) forces a major bump in the SDKs that consume it. An audit-hash change additionally requires human sign-off before anything downstream is published, because it affects whether existing consent evidence still reconciles.
Every SDK that computes an audit hash runs the same golden vectors as a required test, so a hash produced on a phone must match one produced on your server β which is what makes a cross-platform consent audit trail defensible.
Licensing
The JavaScript, Node, React Native and Flutter SDK repositories carry an MIT
licence, and @dpdpguard/contract is Apache-2.0. The Android, iOS and JVM
repositories do not yet declare a licence file; treat their terms as unspecified
until they do.