Consent API Reference
This document provides a complete technical reference for TrueVault's Consent API, which powers cross-platform consent management.
Base URLs
| Environment | URL |
|---|---|
| Production | https://consent.truevault.com |
Endpoints
GET /api/v1/cmp/consent
Retrieves existing consent preferences for a consumer or creates a new consent record with a JWT.
Request
Method: GET
Query Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
provider | string | Yes | Provider type: shopify or email |
shop | string | Yes | Shop domain or identifier (e.g., example.myshopify.com) |
privacy_center_id | string | Yes | Your TrueVault privacy center ID |
logged_in_customer_id | string | Shopify only | Shopify customer ID (added by Shopify App Proxy) |
customer_email | string | Email only | Customer email address (required for email provider) |
signature | string | Shopify only | HMAC-SHA256 signature (added by Shopify App Proxy) |
client_id | string (UUID v4) | No | Optional client identifier; must be a valid UUID v4 when provided |
Response
Status: 200 OK
Content-Type: application/json
Response Body:
{
jwt: string;
consentAnalytics: boolean | null;
consentAdvertising: boolean | null;
consentPersonalization: boolean | null;
consentTargetedAdvertising: boolean | null;
optedOut: boolean | null;
implicit: boolean | null;
isExisting: boolean;
}
Field Descriptions:
| Field | Type | Description |
|---|---|---|
jwt | string | JWT token representing this consumer (required for POST requests) |
consentAnalytics | boolean | null | Analytics consent preference |
consentAdvertising | boolean | null | Advertising consent preference |
consentPersonalization | boolean | null | Personalization consent preference |
consentTargetedAdvertising | boolean | null | Targeted advertising consent |
optedOut | boolean | null | Global opt-out preference |
implicit | boolean | null | true if consumer hasn't explicitly set preferences yet |
isExisting | boolean | true if record already existed, false if newly created |
Example: Shopify Provider
Request:
GET /api/v1/cmp/consent?provider=shopify&shop=example.myshopify.com&privacy_center_id=EXAMPLE&logged_in_customer_id=6789012345&signature=abc123...&client_id=550e8400-e29b-41d4-a716-446655440000 HTTP/1.1
Host: consent.truevault.com
Response (existing consumer):
{
"jwt": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjb25zdW1lcklkZW50aWZpZXIiOiI2Nzg5MDEyMzQ1IiwiY29uc3VtZXJQYXJ0aXRpb24iOiJleGFtcGxlLm15c2hvcGlmeS5jb20iLCJpYXQiOjE2OTk1NjQ4MDB9.signature",
"consentAnalytics": true,
"consentAdvertising": false,
"consentPersonalization": true,
"consentTargetedAdvertising": false,
"optedOut": false,
"implicit": false,
"isExisting": true
}
Response (new consumer):
{
"jwt": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjb25zdW1lcklkZW50aWZpZXIiOiI2Nzg5MDEyMzQ1IiwiY29uc3VtZXJQYXJ0aXRpb24iOiJleGFtcGxlLm15c2hvcGlmeS5jb20iLCJpYXQiOjE2OTk1NjQ4MDB9.signature",
"consentAnalytics": null,
"consentAdvertising": null,
"consentPersonalization": null,
"consentTargetedAdvertising": null,
"optedOut": null,
"implicit": true,
"isExisting": false
}
Example: Email Provider
Request:
GET /api/v1/cmp/consent?provider=email&shop=yourstore.com&privacy_center_id=EXAMPLE&customer_email=customer@example.com&client_id=6ba7b810-9dad-11d1-80b4-00c04fd430c8 HTTP/1.1
Host: consent.truevault.com
Response:
{
"jwt": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjb25zdW1lcklkZW50aWZpZXIiOiJjdXN0b21lckBleGFtcGxlLmNvbSIsImNvbnN1bWVyUGFydGl0aW9uIjoieW91cnN0b3JlLmNvbSIsImlhdCI6MTY5OTU2NDgwMH0.signature",
"consentAnalytics": null,
"consentAdvertising": null,
"consentPersonalization": null,
"consentTargetedAdvertising": null,
"optedOut": null,
"implicit": true,
"isExisting": false
}
Error Responses
| Status Code | Error Message | Cause |
|---|---|---|
| 400 | "Provider parameter is required (shopify or email)" | Missing provider query parameter |
| 400 | "provider must be at most 100 characters" | provider exceeds 100 character limit |
| 400 | "Provider must be either 'shopify' or 'email'" | Invalid provider value |
| 400 | "Shop domain is required for Shopify provider" | Missing shop for Shopify provider |
| 400 | "Shop parameter is required for email provider" | Missing shop for email provider |
| 400 | "shop must be at most 100 characters" | shop exceeds 100 character limit |
| 400 | "Privacy center ID is required" | Missing privacy_center_id |
| 400 | "privacy_center_id must be at most 100 characters" | privacy_center_id exceeds 100 character limit |
| 400 | "Customer email is required for email provider" | Missing customer_email for email provider |
| 400 | "Customer email must be a valid email address" | customer_email format is invalid |
| 400 | "client_id must be a valid UUID v4" | client_id is present but not a UUID v4 |
| 401 | "Customer must be logged in to access this endpoint" | Missing logged_in_customer_id for Shopify |
| 401 | "Request signature verification failed" | Invalid Shopify signature (production only) |
| 500 | "SHOPIFY_API_SECRET is not configured" | Server misconfiguration |
POST /api/v1/cmp/consent
Updates consent preferences for an existing consumer record.
Request
Method: POST
Headers:
Content-Type: application/json
Request Body:
{
jwt: string; // Required, non-empty
consentAnalytics?: boolean;
consentAdvertising?: boolean;
consentPersonalization?: boolean;
consentTargetedAdvertising?: boolean;
optedOut?: boolean;
}
Field Descriptions:
| Field | Type | Required | Description |
|---|---|---|---|
jwt | string | Yes | JWT token from GET response |
consentAnalytics | boolean | No | Analytics consent (true/false) |
consentAdvertising | boolean | No | Advertising consent (true/false) |
consentPersonalization | boolean | No | Personalization consent (true/false) |
consentTargetedAdvertising | boolean | No | Targeted advertising consent (true/false) |
optedOut | boolean | No | Global opt-out (true/false) |
Validation Rules:
jwtmust be a non-empty string- At least one consent field must be provided
- All consent fields must be
boolean
Response
Status: 200 OK
Content-Type: application/json
Response Body: Same structure as GET response
{
jwt: string;
consentAnalytics: boolean | null;
consentAdvertising: boolean | null;
consentPersonalization: boolean | null;
consentTargetedAdvertising: boolean | null;
optedOut: boolean | null;
implicit: boolean | null; // Automatically set to false after POST
isExisting: boolean; // Always true for POST
}
Example Request
POST /api/v1/cmp/consent HTTP/1.1
Host: consent.truevault.com
Content-Type: application/json
{
"jwt": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"consentAnalytics": true,
"consentAdvertising": false,
"consentPersonalization": true,
"consentTargetedAdvertising": false,
"optedOut": false
}
Example Response
{
"jwt": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"consentAnalytics": true,
"consentAdvertising": false,
"consentPersonalization": true,
"consentTargetedAdvertising": false,
"optedOut": false,
"implicit": false,
"isExisting": true
}
Partial Updates
You can update only specific consent fields:
{
"jwt": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"consentAnalytics": true
}
This updates only consentAnalytics, leaving other fields unchanged.
Error Responses
| Status Code | Error Message | Cause |
|---|---|---|
| 400 | "Request body must be valid JSON" | Malformed JSON in request body |
| 400 | 'Property "jwt" must be a non-empty string' | Missing or empty jwt field |
| 400 | "At least one consent field must be provided" | No consent fields in request body |
| 400 | 'Field "X" must be a boolean or null' | Invalid value for consent field |
| 404 | "No valid consent record exists for the provided JWT" | JWT not found in database (expired or invalid) |
JWT Structure
TrueVault generates JWTs to represent consumers in a privacy-preserving way.
JWT Header
{
"alg": "HS256",
"typ": "JWT"
}
JWT Payload
{
"consumerIdentifier": "6789012345",
"consumerPartition": "example.myshopify.com",
"iat": 1699564800
}
Payload Fields:
| Field | Type | Description |
|---|---|---|
consumerIdentifier | string | Customer ID (Shopify) or email (email provider) |
consumerPartition | string | Shop domain for data isolation |
iat | number | Issued at (Unix timestamp in seconds) |
JWT Properties
- Algorithm: HS256 (HMAC with SHA-256)
- Encoding: Base64URL (RFC 4648)
- Signature: Signed with TrueVault's
JWT_SECRET - Expiration: No
expclaim in JWT; cookie consent records are valid for 180 days, while opt-outs never expire - Opaque: Treat as opaque token; do not decode client-side
Example JWT
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjb25zdW1lcklkZW50aWZpZXIiOiI2Nzg5MDEyMzQ1IiwiY29uc3VtZXJQYXJ0aXRpb24iOiJleGFtcGxlLm15c2hvcGlmeS5jb20iLCJpYXQiOjE2OTk1NjQ4MDB9.zV4v8K1h2_kP-mN5xQ7RtYuIoPlKjHgFeDcBa9wX3Zk
Decodes to:
- Header:
{"alg":"HS256","typ":"JWT"} - Payload:
{"consumerIdentifier":"6789012345","consumerPartition":"example.myshopify.com","iat":1699564800}
Best Practices
- Avoid redundant POST requests (only send when preferences change)
- Implement client-side throttling for preference updates