01
Create one compatible consent scope
A scope contains one policy version, its purposes, and approved deployment bindings. Use another scope for an unrelated brand or materially different notice.
json
{
"id": "customer-account",
"tenantId": "acme",
"name": "Customer account properties",
"policyVersion": "policy-2026-08",
"purposes": ["essential", "analytics", "marketing"],
"bindings": [
{ "platform": "web", "identifier": "app.example.com" },
{ "platform": "ios", "identifier": "com.example.ios" },
{ "platform": "android", "identifier": "com.example.android" }
]
}02
Mint the link credential on your backend
After customer authentication, derive a tenant-scoped opaque subject and call Pact with the tenant's server-only link key. Never place that key or a raw identity in browser or app code.
typescript
const opaqueSubject = createHmac('sha256', customerIdentitySecret)
.update(authenticatedUser.internalId)
.digest('base64url')
const response = await fetch('https://consent.example.com/v1/consent/link-credentials', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${process.env.PACT_LINK_KEY}`,
},
body: JSON.stringify({ consentScopeId: 'customer-account', opaqueSubject }),
})
return response.json() // credential expires after five minutes03
Exchange from an approved deployment
The device exchanges the short-lived credential for a 24-hour consent session. On the first merge, denial wins and GPC remains restrictive.
typescript
import { createPactLinkedConsentClient } from '@pact/web/linked'
const linked = createPactLinkedConsentClient({
tenantId: 'acme',
consentScopeId: 'customer-account',
policyVersion: 'policy-2026-08',
purposes: ['essential', 'analytics', 'marketing'],
})
await linked.link(linkCredentialFromYourAuthenticatedBackend)
await linked.refresh()04
Know the boundary
- Anonymous decisions never leave the device before linking
- Only deployment bindings approved on the scope can exchange or use a session
- A policy-version mismatch fails closed instead of silently applying incompatible choices
- Native and web changes append to the same SHA-256 evidence chain