MATIH Platform is in active MVP development. Documentation reflects current implementation status.
7. Tenant Lifecycle
Privacy & Compliance
Consent Management

Consent Management

The ConsentController at /api/v1/privacy/consent provides a full consent lifecycle: recording, verification, withdrawal, renewal, and audit. Consent records support GDPR requirements including lawful basis tracking, double opt-in, cross-border transfer documentation, and granular communication preferences.


Consent Lifecycle

RECORD --> ACTIVE (or PENDING_DOUBLE_OPT_IN) --> WITHDRAWN
              |                                      ^
              v                                      |
           EXPIRED ---------> RENEWED ---------------+

Recording Consent

public record RecordConsentRequestDTO(
        @NotNull UUID subjectId,
        String subjectEmail,
        String subjectType,
        @NotBlank String purpose,
        String purposeDescription,
        @NotNull ConsentType consentType,    // EXPLICIT, IMPLICIT, OPT_IN, OPT_OUT
        boolean isGranted,
        List<String> dataCategories,
        List<String> processingActivities,
        List<ThirdPartyRequestDTO> thirdParties,
        boolean crossBorderTransfer,
        List<String> transferCountries,
        LegalBasis legalBasis,               // CONSENT, CONTRACT, LEGAL_OBLIGATION, ...
        String legalBasisDescription,
        String collectionPoint,
        String collectionMethod,
        String privacyPolicyVersion,
        String privacyPolicyUrl,
        String termsVersion,
        String optInText,
        Instant expiresAt,
        boolean doubleOptIn,
        String sourceIp,
        String userAgent,
        String deviceId,
        String sessionId,
        Map<String, Object> geoLocation,
        Map<String, Boolean> preferences,
        Boolean emailMarketing,
        Boolean smsMarketing,
        Boolean pushNotifications,
        Boolean analyticsTracking,
        Boolean personalization,
        Map<String, String> labels
) {}
curl -X POST http://localhost:8082/api/v1/privacy/consent \
  -H "X-Tenant-ID: {tenantId}" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "subjectId": "a1b2c3d4-...",
    "subjectEmail": "user@example.com",
    "purpose": "marketing_emails",
    "purposeDescription": "Send promotional emails about new features",
    "consentType": "EXPLICIT",
    "isGranted": true,
    "dataCategories": ["email", "name", "preferences"],
    "processingActivities": ["email_marketing", "personalization"],
    "legalBasis": "CONSENT",
    "collectionPoint": "signup_form",
    "collectionMethod": "web_form",
    "privacyPolicyVersion": "2.1",
    "expiresAt": "2027-02-12T00:00:00Z",
    "doubleOptIn": true,
    "emailMarketing": true,
    "analyticsTracking": true,
    "personalization": true
  }'

Response (201 Created): Returns a ConsentResponse with the full consent record including generated consentId.


Retrieving Consent Records

List All Consents

# All consents for the tenant
curl http://localhost:8082/api/v1/privacy/consent \
  -H "X-Tenant-ID: {tenantId}"
 
# Filter by purpose
curl "http://localhost:8082/api/v1/privacy/consent?purpose=marketing_emails" \
  -H "X-Tenant-ID: {tenantId}"

Get by Subject

# All consents for a subject
curl http://localhost:8082/api/v1/privacy/consent/subject/{subjectId} \
  -H "X-Tenant-ID: {tenantId}"
 
# Active consents only
curl http://localhost:8082/api/v1/privacy/consent/subject/{subjectId}/active \
  -H "X-Tenant-ID: {tenantId}"
 
# By email
curl http://localhost:8082/api/v1/privacy/consent/subject/email/user@example.com \
  -H "X-Tenant-ID: {tenantId}"

Consent Verification

Check Consent

Quick check if a subject has valid consent for a purpose:

curl "http://localhost:8082/api/v1/privacy/consent/check?subjectId={id}&purpose=marketing_emails" \
  -H "X-Tenant-ID: {tenantId}"

Response:

{
  "subjectId": "a1b2c3d4-...",
  "purpose": "marketing_emails",
  "hasValidConsent": true
}

Verify for Processing

Detailed verification for data processing operations:

curl -X POST http://localhost:8082/api/v1/privacy/consent/verify \
  -H "X-Tenant-ID: {tenantId}" \
  -H "Content-Type: application/json" \
  -d '{
    "subjectId": "a1b2c3d4-...",
    "purpose": "marketing_emails",
    "dataCategories": ["email", "name"],
    "processingActivity": "email_marketing"
  }'

Returns a ConsentVerificationResult with detailed information about consent coverage for each data category and processing activity.


Double Opt-In Confirmation

When consent is recorded with doubleOptIn: true, a verification token is generated. The subject must confirm:

curl -X POST http://localhost:8082/api/v1/privacy/consent/confirm-double-opt-in \
  -H "X-Tenant-ID: {tenantId}" \
  -H "Content-Type: application/json" \
  -d '{
    "consentId": "consent-abc123",
    "verificationToken": "token-xyz789"
  }'

Withdrawing Consent

Withdraw Specific Consent

curl -X POST http://localhost:8082/api/v1/privacy/consent/{consentId}/withdraw \
  -H "X-Tenant-ID: {tenantId}" \
  -H "Content-Type: application/json" \
  -d '{
    "reason": "Subject requested withdrawal via support ticket"
  }'

Withdraw by Purpose

curl -X POST http://localhost:8082/api/v1/privacy/consent/subject/{subjectId}/withdraw \
  -H "X-Tenant-ID: {tenantId}" \
  -H "Content-Type: application/json" \
  -d '{
    "purpose": "marketing_emails",
    "reason": "Unsubscribed from marketing"
  }'

Withdraw All (for DSR Erasure)

curl -X POST http://localhost:8082/api/v1/privacy/consent/subject/{subjectId}/withdraw-all \
  -H "X-Tenant-ID: {tenantId}" \
  -H "Content-Type: application/json" \
  -d '{
    "reason": "Data erasure request DSR-2026-001"
  }'

Returns a BulkWithdrawResponse with the count of withdrawn consent records.


Renewing Consent

curl -X POST http://localhost:8082/api/v1/privacy/consent/{consentId}/renew \
  -H "X-Tenant-ID: {tenantId}" \
  -H "Content-Type: application/json" \
  -d '{
    "newExpiryDate": "2028-02-12T00:00:00Z"
  }'

Communication Preferences

Update granular communication preferences for a consent record:

curl -X PUT http://localhost:8082/api/v1/privacy/consent/{consentId}/communication-preferences \
  -H "X-Tenant-ID: {tenantId}" \
  -H "Content-Type: application/json" \
  -d '{
    "emailMarketing": true,
    "smsMarketing": false,
    "pushNotifications": true,
    "analyticsTracking": true,
    "personalization": false
  }'

Expiring Consents

Monitor consents approaching expiration:

curl "http://localhost:8082/api/v1/privacy/consent/expiring?daysThreshold=30" \
  -H "X-Tenant-ID: {tenantId}"

Consent Statistics

curl "http://localhost:8082/api/v1/privacy/consent/statistics?daysPeriod=90" \
  -H "X-Tenant-ID: {tenantId}"

Returns a ConsentStatistics object with total counts, granted/withdrawn ratios, consent by purpose, and trend data.


Error Codes

CodeHTTP StatusDescription
CONSENT_NOT_FOUND404Consent record does not exist
INVALID_CONSENT_STATE400Operation not valid for current consent state

Source Files

FilePath
Controllercontrol-plane/tenant-service/src/main/java/com/matih/tenant/privacy/controller/ConsentController.java
Servicecontrol-plane/tenant-service/src/main/java/com/matih/tenant/privacy/service/ConsentService.java
Entitycontrol-plane/tenant-service/src/main/java/com/matih/tenant/privacy/ConsentRecord.java