Data Subject Rights
Handle access, deletion, and portability requests
Lawful Bases
Understand the six legal grounds for processing
Consent Records
Maintain audit trails and proof of consent
Compliance Tools
Built-in APIs for GDPR requirements
GDPR Overview
The General Data Protection Regulation (GDPR) is a comprehensive data protection law that applies to organizations processing personal data of EU residents. Understanding GDPR is essential for any application handling user data.
Who does GDPR apply to?
Key Principles
- Lawfulness, fairness, and transparency
- Purpose limitation
- Data minimization
- Accuracy
- Storage limitation
- Integrity and confidentiality
Penalties
Tier 1 Violations
Up to 10M EUR or 2% of annual global turnover
Tier 2 Violations
Up to 20M EUR or 4% of annual global turnover
Six Lawful Bases for Processing
GDPR requires a lawful basis for any processing of personal data. You must identify and document your lawful basis before processing begins.
Consent
User has given clear, affirmative consent for specific purposes
Example: Email marketing, analytics tracking, personalized ads
Contract
Processing is necessary to fulfill a contract with the user
Example: Processing orders, delivering services, account management
Legal Obligation
Processing is required to comply with the law
Example: Tax records, fraud prevention, regulatory reporting
Vital Interests
Processing is necessary to protect someone's life
Example: Emergency medical situations, disaster response
Public Task
Processing is necessary for official functions or public interest
Example: Government services, public health monitoring
Legitimate Interests
Processing is necessary for your legitimate business interests
Example: Security logging, fraud detection, direct marketing to existing customers
Choosing the right basis
Consent Requirements
When consent is your lawful basis, it must meet specific GDPR requirements to be valid.
Freely Given
Users must have a genuine choice. No pre-ticked boxes, bundled consent, or coercion.
Specific
Consent must be specific to each purpose. Separate consent for analytics vs marketing.
Informed
Users must know what they are consenting to, who is processing, and why.
Unambiguous
Clear affirmative action required. Silence or inactivity is not consent.
Withdrawable
Users must be able to withdraw consent as easily as they gave it.
'use client'
import { useConsent } from '@sylphx/sdk/react'
export function ConsentForm() {
const { setConsents, consentTypes } = useConsent()
return (
<form>
<h3>We'd like to use cookies for:</h3>
{/* Each purpose has separate consent */}
{consentTypes
.filter(type => !type.required)
.map(type => (
<label key={type.id} className="flex items-start gap-3 p-4 border rounded-lg">
<input
type="checkbox"
defaultChecked={false} // No pre-ticked boxes
onChange={(e) => setConsents({ [type.id]: e.target.checked })}
/>
<div>
<span className="font-medium">{type.name}</span>
<p className="text-sm text-muted-foreground">{type.description}</p>
</div>
</label>
))}
{/* Clear information about data processing */}
<p className="text-sm text-muted-foreground mt-4">
Your data will be processed by Acme Inc. You can withdraw consent
at any time in Settings → Privacy.
</p>
</form>
)
}Data Subject Rights
GDPR grants individuals specific rights over their personal data. You must have processes in place to handle these requests within the required timeframes.
Right of Access
Users can request a copy of their personal data
Right to Rectification
Users can request correction of inaccurate data
Right to Erasure
Users can request deletion of their data ("right to be forgotten")
Right to Portability
Users can request their data in a machine-readable format
Right to Object
Users can object to certain types of processing
Right to Restrict
Users can request limitation of processing
Handling Data Subject Requests
Use the Sylphx Consent API to handle data subject requests programmatically:
import { platform } from '@/lib/platform'
// Handle data access request
export async function handleAccessRequest(userId: string) {
// Gather all user data
const userData = await platform.consent.exportUserData(userId)
// Returns:
// {
// profile: { name, email, ... },
// consents: [{ type, granted, timestamp, ... }],
// activity: [...],
// analytics: [...],
// // All data associated with the user
// }
// Send data to user via secure download link
const downloadUrl = await platform.storage.createSecureDownload({
content: JSON.stringify(userData, null, 2),
filename: 'my-data-export.json',
expiresIn: '7d',
})
await platform.email.send({
to: userData.profile.email,
template: 'data-export-ready',
data: { downloadUrl },
})
}import { platform } from '@/lib/platform'
// Handle deletion request
export async function handleDeletionRequest(userId: string, reason?: string) {
// Verify the request (e.g., re-authenticate user)
// Request deletion - data is queued for removal
const request = await platform.consent.requestDeletion({
userId,
reason: reason || 'User requested account deletion',
// Optional: specify what to delete
scope: ['profile', 'analytics', 'consents', 'activity'],
// Optional: exclude data required for legal compliance
excludeRetained: ['billing', 'audit_logs'],
})
// Returns deletion request details
// {
// requestId: 'del_abc123',
// status: 'pending',
// scheduledAt: '2024-02-15T00:00:00Z',
// estimatedCompletion: '2024-02-20T00:00:00Z',
// }
// Send confirmation email
await platform.email.send({
to: user.email,
template: 'deletion-scheduled',
data: {
requestId: request.requestId,
completionDate: request.estimatedCompletion,
},
})
return request
}import { platform } from '@/lib/platform'
// Export data in machine-readable format
export async function handlePortabilityRequest(userId: string) {
const data = await platform.consent.exportUserData(userId, {
format: 'json', // or 'csv'
// Only include data user provided directly
scope: ['profile', 'preferences', 'content'],
// Exclude derived/inferred data
excludeInferred: true,
})
// Create downloadable file
const downloadUrl = await platform.storage.createSecureDownload({
content: JSON.stringify(data, null, 2),
filename: 'my-data-portable.json',
contentType: 'application/json',
expiresIn: '7d',
})
return downloadUrl
}Data Retention
Recording Consent Proof
GDPR requires you to demonstrate that valid consent was obtained. Maintain detailed records of all consent interactions.
import { platform } from '@/lib/platform'
// When user gives consent, record proof
const consentRecord = await platform.consent.setConsent({
userId: user.id,
consents: {
analytics: true,
marketing: false,
},
// Automatically recorded metadata
metadata: {
timestamp: new Date().toISOString(),
ipAddress: request.ip, // Optional but recommended
userAgent: request.headers['user-agent'],
source: 'cookie_banner',
version: '2024-01-15', // Your consent text version
language: 'en',
},
})
// Retrieve consent history for audits
const history = await platform.consent.getConsentHistory(userId)
// Returns full audit trail:
// [
// {
// id: 'consent_abc123',
// timestamp: '2024-01-15T10:30:00Z',
// action: 'grant',
// categories: ['analytics'],
// source: 'cookie_banner',
// ipAddress: '192.168.1.1',
// userAgent: 'Mozilla/5.0...',
// consentTextVersion: '2024-01-15',
// },
// {
// id: 'consent_def456',
// timestamp: '2024-01-20T15:45:00Z',
// action: 'revoke',
// categories: ['analytics'],
// source: 'settings',
// ...
// },
// ]What to Record
- Who consented (user identifier)
- When consent was given
- What they consented to
- How consent was collected
- Version of consent text shown
- Withdrawal records (if applicable)
Right to Withdraw Consent
Users must be able to withdraw consent as easily as they gave it. Provide clear mechanisms for consent withdrawal.
'use client'
import { useConsent } from '@sylphx/sdk/react'
export function PrivacySettings() {
const { consentTypes, setConsents, resetConsent } = useConsent()
const handleWithdraw = async (categoryId: string) => {
await setConsents({ [categoryId]: false })
// The SDK automatically:
// 1. Updates consent state
// 2. Records the withdrawal in audit trail
// 3. Stops any scripts dependent on this consent
// 4. Triggers any configured webhooks
}
const handleWithdrawAll = async () => {
// Withdraw all non-essential consents
await resetConsent()
}
return (
<div className="space-y-4">
<h2>Privacy Settings</h2>
{consentTypes.map(type => (
<div key={type.id} className="flex items-center justify-between p-4 border rounded-lg">
<div>
<h3 className="font-medium">{type.name}</h3>
<p className="text-sm text-muted-foreground">{type.description}</p>
</div>
<button
onClick={() => handleWithdraw(type.id)}
disabled={type.required}
className="px-4 py-2 text-sm border rounded-lg hover:bg-muted"
>
{type.granted ? 'Withdraw' : 'Grant'}
</button>
</div>
))}
<button
onClick={handleWithdrawAll}
className="w-full py-3 text-destructive border border-destructive rounded-lg"
>
Withdraw All Optional Consents
</button>
</div>
)
}Effect of Withdrawal
Implementation Checklist
Identify Your Lawful Bases
Document the lawful basis for each type of processing you perform. Update your privacy policy to reflect these bases.
Implement Consent Collection
Use the CookieBanner and ConsentPreferences components to collect valid GDPR-compliant consent.
Set Up Audit Trails
Configure consent logging to record all consent interactions with timestamps and metadata.
Build Data Subject Request Handlers
Implement APIs to handle access, deletion, and portability requests within required timeframes.
Test and Document
Test all consent flows and data subject request handlers. Document your compliance procedures.
Also operating in California?
Learn about CCPA/CPRA requirements and how they differ from GDPR.
CCPA Guide