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