The consent layer your product plugs into.
Capture, version, prove and revoke consent and preferences — cookies included — through one API. An append-only vault, signed offline-verifiable receipts, and every event kept in the EU.
| Subject | Purpose | State | Version | Collected | Receipt |
|---|---|---|---|---|---|
| email:a.rivera@… | marketing_email | granted | v3 | 14:02:11 | rcpt_9f2… |
| external_id:u_4821 | analytics | denied | v1 | 14:02:07 | rcpt_1c8… |
| email:m.chen@… | marketing_email | withdrawn | v3 | 13:58:44 | rcpt_a41… |
| cookie_id:ck_77b | personalization | granted | v2 | 13:58:40 | rcpt_2d0… |
| email:s.k@… | data_sharing | expired | v2 | 13:51:19 | rcpt_e77… |
Consent is a data problem that never stops moving.
Proof, not just a boolean
A regulator asks what exactly did the user see, and when? That means an immutable record with the statement version, IP, timestamp — and a signature anyone can verify offline.
The framework keeps changing
GDPR, ePrivacy, LOPDGDD, CCPA, TCF revisions. Hard-coding any of it means a migration every time. Rules belong in data, evaluated at request time.
Cookies are their own project
Scanning a site, classifying every tracker, keeping it current. Cookiebot spent a decade on the classification database alone.
Append-only, with a signed receipt for every decision.
ConsentRecord rows are never updated — a change is a new row that supersedes the last. A materialized projection serves the hot read; the log is the truth.
- Ed25519 detached signatures, public JWKS, verify offline
- IP encrypted at rest, statement-hash in the proof
- Full timeline + one-click subject export
Versioned statements and a configurable preference center.
Publish a purpose version as DISPLAY_ONLY (notify) or RECONSENT_REQUIRED (treat prior consent as stale). Channels × topics, typed fields, JSON-logic dependency rules.
- Multi-locale legal text, frozen per version
- Your banner renders from
GET /v1/purposes - Expiry windows & bulk reconsent campaigns
Cascade classification: reference DB → heuristics → AI.
The first confident tier wins. Unknowns go to a per-site review queue; a confirmed classification promoted across tenants becomes a tier-1 hit for everyone.
- Human override is authoritative for that site
- Shared definition set grows with every review
GET /v1/cookiesfor the banner table
TCF v2.2 and Consent Mode v2 — derived, not implemented.
Ask for a TC string or a gtag('consent','update', …) object built from the subject's current state. The SDK's tag gate loads your scripts on grant and re-evaluates on change.
GET /v1/consent/tcstringGET /v1/consent/google-consent-mode- Signed webhooks on every change, with retry + replay
OneTrust's power, an API's simplicity.
| OneTrust · Cookiebot | Tripticonsent | |
|---|---|---|
| Model | A suite your team runs | An API you plug into |
| Proof of consent | A record in their system | Append-only vault + Ed25519 signed receipt |
| Regulatory framework | Template configuration | RuleSet in data (JSON-logic), no migrations |
| Cookies | Scanner + proprietary DB | Cascade DB → heuristics → AI + shared DB |
| TCF / Consent Mode | A separate module | Derived from the subject's state, one endpoint |
| Residency | Plan-dependent | Always EU (Vercel fra1 · Neon eu-central) |
| Integration | Tags + portal | npm i @tripticonsent/sdk |
Indicative comparison. Not affiliated with OneTrust or Cookiebot.
Ten lines, then it's just an API.
- Browser + Node SDK, or plain REST
- In-memory cache with ETag revalidation
- Idempotency-Key on every mutation
- Offline receipt verification built in
import { TripticonsentClient } from '@tripticonsent/sdk';
const tc = new TripticonsentClient({ baseUrl: API_URL, apiKey: 'pk_live_…' });
await tc.recordConsent(
{ subject: 'email:user@example.com', purpose: 'marketing_email', state: 'GRANTED' },
{ idempotencyKey: crypto.randomUUID() },
);
// load analytics only after consent
await tc.gate('email:user@example.com', ['analytics'], () => loadAnalytics());Plug in the consent layer.
One vault, one source of truth, in the EU. Wire up your banner in an afternoon.