Skip to main content

Consent API Reference

This document provides a complete technical reference for TrueVault's Consent API, which powers cross-platform consent management.

Base URLs​

EnvironmentURL
Productionhttps://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:

ParameterTypeRequiredDescription
providerstringYesProvider type: shopify or email
shopstringYesShop domain or identifier (e.g., example.myshopify.com)
privacy_center_idstringYesYour TrueVault privacy center ID
logged_in_customer_idstringShopify onlyShopify customer ID (added by Shopify App Proxy)
customer_emailstringEmail onlyCustomer email address (required for email provider)
signaturestringShopify onlyHMAC-SHA256 signature (added by Shopify App Proxy)
client_idstring (UUID v4)NoOptional 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:

FieldTypeDescription
jwtstringJWT token representing this consumer (required for POST requests)
consentAnalyticsboolean | nullAnalytics consent preference
consentAdvertisingboolean | nullAdvertising consent preference
consentPersonalizationboolean | nullPersonalization consent preference
consentTargetedAdvertisingboolean | nullTargeted advertising consent
optedOutboolean | nullGlobal opt-out preference
implicitboolean | nulltrue if consumer hasn't explicitly set preferences yet
isExistingbooleantrue 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 CodeError MessageCause
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:

FieldTypeRequiredDescription
jwtstringYesJWT token from GET response
consentAnalyticsbooleanNoAnalytics consent (true/false)
consentAdvertisingbooleanNoAdvertising consent (true/false)
consentPersonalizationbooleanNoPersonalization consent (true/false)
consentTargetedAdvertisingbooleanNoTargeted advertising consent (true/false)
optedOutbooleanNoGlobal opt-out (true/false)

Validation Rules:

  • jwt must 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 CodeError MessageCause
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:

FieldTypeDescription
consumerIdentifierstringCustomer ID (Shopify) or email (email provider)
consumerPartitionstringShop domain for data isolation
iatnumberIssued 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 exp claim 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