> ## Documentation Index
> Fetch the complete documentation index at: https://docs.baanx.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Compliance & Best Practices

> Regulatory requirements, audit strategies, and best practices for consent management

## Regulatory Compliance Overview

The Baanx Consent Management API is designed to help you meet data privacy regulations including GDPR, CCPA, and other regional requirements. This guide covers compliance considerations and best practices.

<Warning>
  This guide provides technical implementation guidance. Consult with legal counsel to ensure your specific implementation meets all applicable regulatory requirements.
</Warning>

## GDPR Compliance

The General Data Protection Regulation (GDPR) applies to organizations processing personal data of EU residents.

### Key GDPR Requirements

<CardGroup cols={2}>
  <Card title="Lawful Basis" icon="scale-balanced">
    Establish legal basis for data processing (consent, contract, legitimate interest)
  </Card>

  <Card title="Explicit Consent" icon="check-circle">
    Consent must be freely given, specific, informed, and unambiguous
  </Card>

  <Card title="Right to Withdraw" icon="arrow-rotate-left">
    Users can withdraw consent as easily as they gave it
  </Card>

  <Card title="Records of Consent" icon="file-lines">
    Maintain proof of when and how consent was obtained
  </Card>
</CardGroup>

### GDPR-Compliant Consent Collection

<Steps>
  <Step title="Clear Communication">
    Inform users **before** data collection about:

    * What data you're collecting
    * Why you're collecting it
    * How long you'll retain it
    * Who you'll share it with
    * Their rights (access, rectification, erasure, portability)
  </Step>

  <Step title="Granular Consent">
    Separate consent for different purposes:

    ```typescript theme={null}
    const consents = [
      { type: 'termsAndPrivacy', status: 'granted' },      // Required
      { type: 'marketingNotifications', status: 'denied' }, // Optional
      { type: 'smsNotifications', status: 'denied' },       // Optional
      { type: 'emailNotifications', status: 'granted' }     // Optional
    ];
    ```

    Users must be able to opt-in to marketing separately from service requirements.
  </Step>

  <Step title="Affirmative Action">
    Require explicit opt-in (no pre-checked boxes):

    ```typescript theme={null}
    // ✅ Good: User must actively check
    <Checkbox checked={marketingConsent} onChange={setMarketingConsent}>
      I agree to receive marketing communications
    </Checkbox>

    // ❌ Bad: Pre-checked by default
    <Checkbox checked={true} onChange={setMarketingConsent}>
      I agree to receive marketing communications
    </Checkbox>
    ```
  </Step>

  <Step title="Record Keeping">
    Capture comprehensive metadata:

    ```typescript theme={null}
    metadata: {
      ipAddress: req.ip,
      userAgent: req.headers['user-agent'],
      timestamp: new Date().toISOString(),
      consentMethod: 'registration_form',
      privacyPolicyVersion: 'v2.1',
      termsVersion: 'v3.0'
    }
    ```
  </Step>

  <Step title="Easy Withdrawal">
    Implement straightforward revocation:

    ```typescript theme={null}
    async function revokeMarketingConsent(userId: string) {
      const { consentSets } = await consentManager.getUserConsentStatus(
        userId,
        true
      );

      const marketingConsent = consentSets[0].consents.find(
        c => c.consentType === 'marketingNotifications' && c.consentStatus === 'granted'
      );

      if (marketingConsent) {
        await consentManager.revokeConsent(
          consentSets[0].consentSetId,
          marketingConsent.consentId
        );
      }
    }
    ```
  </Step>
</Steps>

### Right to Be Forgotten (GDPR Article 17)

When users request data deletion:

1. **Revoke all consents**:
   ```typescript theme={null}
   const { consentSets } = await consentManager.getUserConsentStatus(userId, true);

   for (const consentSet of consentSets) {
     for (const consent of consentSet.consents) {
       if (consent.consentStatus === 'granted') {
         await consentManager.revokeConsent(
           consentSet.consentSetId,
           consent.consentId
         );
       }
     }
   }
   ```

2. **Export audit trail** (for your records):
   ```typescript theme={null}
   const auditTrail = await consentManager.getAuditTrail(userId, 1000, 0);
   await saveAuditForLegalHold(userId, auditTrail);
   ```

3. **Process deletion** in your systems (user data, accounts, etc.)

<Note>
  The Baanx API maintains consent records even after revocation for regulatory compliance. This is permissible under GDPR as legitimate interest for legal defense.
</Note>

## CCPA Compliance

The California Consumer Privacy Act (CCPA) applies to businesses collecting personal information of California residents.

### Key CCPA Requirements

| Requirement              | Implementation                                                                           |
| ------------------------ | ---------------------------------------------------------------------------------------- |
| **Notice at Collection** | Inform users at/before data collection what categories of data you're collecting and why |
| **Opt-Out of Sale**      | Provide "Do Not Sell My Personal Information" option                                     |
| **Access & Deletion**    | Enable users to request their data and deletion                                          |
| **Non-Discrimination**   | Don't penalize users who exercise privacy rights                                         |

### CCPA-Compliant Implementation

#### Notice at Collection

Display clear privacy notice:

```typescript theme={null}
<ConsentForm>
  <PrivacyNotice>
    We collect personal information including name, email, phone number, and
    location data to provide financial services. View our full privacy policy
    for details on data categories, purposes, and third-party sharing.
  </PrivacyNotice>

  <ConsentCheckbox type="termsAndPrivacy" required />
  <ConsentCheckbox type="emailNotifications" optional />
</ConsentForm>
```

#### Opt-Out Mechanisms

Implement opt-out for data sales/sharing:

```typescript theme={null}
const consents = [
  { type: 'termsAndPrivacy', status: 'granted' },
  { type: 'marketingNotifications', status: 'denied' }, // Opt-out of marketing
  { type: 'emailNotifications', status: 'denied' }      // Opt-out of emails
];
```

<Info>
  The `denied` status in consent records documents the user's opt-out decision for regulatory compliance.
</Info>

## Audit Trail Management

The API maintains an immutable audit trail for all consent changes. Use this for regulatory compliance and investigations.

### What's Recorded in Audit Trail

Each audit record contains:

```json theme={null}
{
  "auditId": "audit_001",
  "action": "created | updated | revoked",
  "timestamp": "ISO 8601 date-time",
  "consentSetId": "UUID of consent set",
  "changes": {
    "before": {
      "consentType": "marketingNotifications",
      "consentStatus": "granted"
    },
    "after": {
      "consentType": "marketingNotifications",
      "consentStatus": "revoked"
    }
  },
  "metadata": {
    "ipAddress": "192.168.1.1",
    "userAgent": "Mozilla/5.0...",
    "timestamp": "2024-01-15T10:30:00Z"
  }
}
```

### Audit Trail Use Cases

<AccordionGroup>
  <Accordion title="Regulatory Audits">
    Export complete consent history for regulatory examinations:

    ```typescript theme={null}
    async function exportConsentAudit(userId: string) {
      let allRecords = [];
      let offset = 0;
      const limit = 100;

      while (true) {
        const { auditRecords, pagination } = await consentManager.getAuditTrail(
          userId,
          limit,
          offset
        );

        allRecords.push(...auditRecords);

        if (offset + limit >= pagination.total) break;
        offset += limit;
      }

      return generateAuditReport(userId, allRecords);
    }
    ```
  </Accordion>

  <Accordion title="Data Subject Access Requests (DSAR)">
    Users can request their consent history:

    ```typescript theme={null}
    async function handleDSAR(userId: string) {
      const { consentStatus, consentSets } = await consentManager.getUserConsentStatus(
        userId,
        true
      );

      const auditTrail = await consentManager.getAuditTrail(userId, 1000, 0);

      return {
        currentStatus: consentStatus,
        consentSets: consentSets,
        changeHistory: auditTrail.auditRecords
      };
    }
    ```
  </Accordion>

  <Accordion title="Legal Defense">
    Prove consent was obtained correctly in case of disputes:

    ```typescript theme={null}
    async function proveLawfulConsent(userId: string, disputeDate: string) {
      const { auditRecords } = await consentManager.getAuditTrail(userId);

      const relevantRecords = auditRecords.filter(
        record => new Date(record.timestamp) <= new Date(disputeDate)
      );

      return {
        consentObtained: relevantRecords.some(
          r => r.action === 'created' && r.changes.after.consentStatus === 'granted'
        ),
        evidence: relevantRecords
      };
    }
    ```
  </Accordion>

  <Accordion title="Compliance Reporting">
    Generate periodic compliance reports:

    ```typescript theme={null}
    async function generateComplianceReport(startDate: string, endDate: string) {
      // Query all users who completed registration in date range
      const users = await getUsersRegisteredBetween(startDate, endDate);

      const report = {
        totalUsers: users.length,
        completeConsents: 0,
        incompleteConsents: 0,
        revocations: 0
      };

      for (const user of users) {
        const { consentStatus } = await consentManager.getUserConsentStatus(user.id);

        if (consentStatus === 'complete') report.completeConsents++;
        else report.incompleteConsents++;

        const { auditRecords } = await consentManager.getAuditTrail(user.id);
        report.revocations += auditRecords.filter(
          r => r.action === 'revoked'
        ).length;
      }

      return report;
    }
    ```
  </Accordion>
</AccordionGroup>

## Best Practices

### 1. Version Your Policies

Track policy versions in metadata to prove which version users consented to:

```typescript theme={null}
metadata: {
  privacyPolicyVersion: 'v2.1',
  termsOfServiceVersion: 'v3.0',
  policyUrl: 'https://example.com/privacy-v2.1',
  timestamp: new Date().toISOString()
}
```

When policies change significantly, require re-consent:

```typescript theme={null}
async function checkPolicyVersions(userId: string) {
  const { consentSets } = await consentManager.getUserConsentStatus(userId, true);
  const latestConsent = consentSets[0];

  const consentedVersion = latestConsent.consents[0].metadata?.privacyPolicyVersion;
  const currentVersion = 'v3.0';

  if (consentedVersion !== currentVersion) {
    return { requiresReconsent: true, reason: 'policy_update' };
  }

  return { requiresReconsent: false };
}
```

### 2. Implement Consent Expiry

Consider re-confirming consent periodically:

```typescript theme={null}
async function checkConsentAge(userId: string, maxAgeMonths: number = 24) {
  const { consentSets } = await consentManager.getUserConsentStatus(userId, true);
  const latestConsent = consentSets[0];

  const consentDate = new Date(latestConsent.createdAt);
  const now = new Date();
  const monthsSinceConsent = (now.getTime() - consentDate.getTime()) / (1000 * 60 * 60 * 24 * 30);

  if (monthsSinceConsent > maxAgeMonths) {
    return { requiresReconsent: true, reason: 'consent_expired' };
  }

  return { requiresReconsent: false };
}
```

### 3. Separate Required vs Optional Consents

Make it clear which consents are necessary for service:

```typescript theme={null}
const consentConfig = {
  required: ['termsAndPrivacy', 'eSignAct'],
  optional: ['marketingNotifications', 'smsNotifications', 'emailNotifications']
};

function validateConsents(consents: ConsentItem[]) {
  const requiredGranted = consentConfig.required.every(type =>
    consents.some(c => c.consentType === type && c.consentStatus === 'granted')
  );

  if (!requiredGranted) {
    throw new Error('Required consents must be granted');
  }

  return true;
}
```

UI Example:

```tsx theme={null}
<ConsentForm>
  <RequiredSection>
    <h3>Required for Service</h3>
    <Checkbox required>Terms of Service & Privacy Policy</Checkbox>
    <Checkbox required>Electronic Signature Agreement</Checkbox>
  </RequiredSection>

  <OptionalSection>
    <h3>Optional</h3>
    <Checkbox>Marketing Communications (you can opt out anytime)</Checkbox>
    <Checkbox>SMS Notifications</Checkbox>
    <Checkbox>Email Notifications</Checkbox>
  </OptionalSection>
</ConsentForm>
```

### 4. Provide Consent Management UI

Build user-facing consent preferences:

```typescript theme={null}
function ConsentPreferences({ userId }: { userId: string }) {
  const [consents, setConsents] = useState<ConsentSetDetail[]>([]);

  useEffect(() => {
    const fetchConsents = async () => {
      const { consentSets } = await consentManager.getUserConsentStatus(
        userId,
        true
      );
      setConsents(consentSets);
    };

    fetchConsents();
  }, [userId]);

  const handleToggle = async (consentSetId: string, consentId: string, currentStatus: string) => {
    if (currentStatus === 'granted') {
      await consentManager.revokeConsent(consentSetId, consentId);
    } else {
      // Create new consent record with 'granted' status
      // (requires new endpoint or re-consent flow)
    }

    // Refresh consents
  };

  return (
    <Card>
      <h2>Privacy Preferences</h2>
      {consents[0]?.consents.map(consent => (
        <ConsentToggle
          key={consent.consentId}
          consent={consent}
          onToggle={() => handleToggle(
            consents[0].consentSetId,
            consent.consentId,
            consent.consentStatus
          )}
        />
      ))}
    </Card>
  );
}
```

### 5. Log All Consent Operations

Maintain application-level logs for consent operations:

```typescript theme={null}
async function createConsentWithLogging(
  onboardingId: string,
  consents: ConsentItem[],
  metadata: any
) {
  logger.info('Creating consent set', {
    onboardingId,
    consentTypes: consents.map(c => c.consentType),
    timestamp: new Date().toISOString()
  });

  try {
    const result = await consentManager.createOnboardingConsent(
      onboardingId,
      consents,
      metadata
    );

    logger.info('Consent set created successfully', {
      consentSetId: result.consentSetId,
      onboardingId
    });

    return result;
  } catch (error) {
    logger.error('Consent creation failed', {
      onboardingId,
      error: error.message
    });

    throw error;
  }
}
```

### 6. Handle Incomplete Consent Gracefully

Guide users to complete required consents:

```typescript theme={null}
async function checkAndEnforceConsent(userId: string) {
  const { consentStatus, consentSets } = await consentManager.getUserConsentStatus(
    userId,
    true
  );

  if (consentStatus === 'incomplete') {
    const missingConsents = identifyMissingConsents(consentSets[0]);

    return {
      allowed: false,
      reason: 'incomplete_consent',
      action: 'redirect_to_consent_page',
      missingConsents
    };
  }

  return { allowed: true };
}

function identifyMissingConsents(consentSet: ConsentSetDetail) {
  const requiredTypes = consentSet.policyType === 'US'
    ? ['eSignAct', 'termsAndPrivacy', 'marketingNotifications', 'smsNotifications', 'emailNotifications']
    : ['termsAndPrivacy', 'marketingNotifications', 'smsNotifications', 'emailNotifications'];

  const grantedTypes = consentSet.consents
    .filter(c => c.consentStatus === 'granted')
    .map(c => c.consentType);

  return requiredTypes.filter(type => !grantedTypes.includes(type));
}
```

## Data Retention

### Consent Record Retention

* **Active consent records**: Retain indefinitely while user account is active
* **Revoked consents**: Retain for legal defense (typically 7 years minimum)
* **Audit trail**: Retain according to regulatory requirements (GDPR: 6 years, CCPA: varies)

### Deletion After Account Closure

When a user closes their account:

1. Retain consent audit trail for legal hold period
2. Mark records as "account closed" but don't delete
3. After legal hold expires, anonymize consent records (remove PII from metadata)

```typescript theme={null}
async function handleAccountClosure(userId: string) {
  const auditTrail = await consentManager.getAuditTrail(userId, 1000, 0);

  await archiveForLegalHold(userId, auditTrail, {
    retentionYears: 7,
    reason: 'account_closure'
  });

  scheduleAnonymization(userId, addYears(new Date(), 7));
}
```

## Regional Considerations

### US-Specific Requirements

* Use `policyType: "US"` for US-based users
* **Requires `eSignAct` consent** for E-Sign Act compliance
* Consider state-specific laws (CCPA in California, VCDPA in Virginia, etc.)
* All 5 consent types required

### EU-Specific Requirements

* Use `policyType: "global"` for EU users
* 4 consent types (excludes `eSignAct`)
* Implement "Right to Object" for automated processing
* Provide data portability mechanisms

### Multi-Region Deployments

Use the `x-us-env` header to route requests correctly:

```typescript theme={null}
const headers = {
  'x-client-key': clientKey,
  'x-secret-key': secretKey
};

if (userRegion === 'US') {
  headers['x-us-env'] = 'true';
}

await fetch('https://api.baanx.com/v2/consent/onboarding', {
  method: 'POST',
  headers,
  body: JSON.stringify(requestBody)
});
```

## Next Steps

<CardGroup cols={2}>
  <Card title="Implementation Guide" icon="code" href="/guides/consent/implementation">
    Technical integration steps
  </Card>

  <Card title="Troubleshooting" icon="wrench" href="/guides/consent/troubleshooting">
    Common issues and solutions
  </Card>

  <Card title="API Reference" icon="book" href="/api-reference/consent/create-onboarding-consent">
    Complete endpoint documentation
  </Card>

  <Card title="Overview" icon="circle-info" href="/guides/consent/overview">
    Back to consent management overview
  </Card>
</CardGroup>
