Skip to navigation

Right To Be Forgotten (RTBF)

Implement GDPR-compliant data deletion for your typeforms

The Right to Be Forgotten (RTBF), also known as the Right to Erasure, is a key component of GDPR and other privacy regulations. It gives individuals the right to request deletion of their personal data. The Typeform Responses API provides endpoints to help you comply with these requirements.

What is the Right to Be Forgotten?

Under GDPR (General Data Protection Regulation) and similar privacy laws, individuals have the right to:

  • Request deletion of their personal data
  • Have their data removed from systems without undue delay
  • Be informed when their data has been deleted

As a data controller using Typeform, you’re responsible for honoring these requests for responses collected through your forms.

When to delete responses

You should delete responses when:

  • A respondent explicitly requests deletion of their data
  • The data is no longer necessary for the purpose it was collected
  • The respondent withdraws consent for data processing
  • The data was unlawfully processed
  • Required by law or regulation

Before deleting data, ensure you understand your legal obligations. In some cases, you may be required to retain data for legal, accounting, or regulatory purposes even when a deletion request is made.

Deleting responses via API

Delete specific responses

To delete one or more responses, send a DELETE request with the response tokens:

DELETE https://api.typeform.com/forms/{form_id}/responses?included_tokens={token1},{token2},{token3}

Example:

DELETE https://api.typeform.com/forms/abc123/responses?included_tokens=xyz789,def456,ghi012

This permanently removes the specified responses from Typeform’s systems.

This action is irreversible. Once deleted, responses cannot be recovered. Always verify response tokens before deletion.

Response deletion confirmation

Successful deletion returns a 204 No Content status code:

HTTP/1.1 204 No Content

If any tokens are invalid or don’t exist, you’ll receive an error:

{
"code": "RESPONSE_NOT_FOUND",
"description": "The response does not exist or you don't have access to it"
}

Implementing an RTBF workflow

Step 1: Identify the response to delete

First, locate the response(s) associated with the deletion request. You’ll typically need to:

  1. Match the user’s email or identifier to form responses
  2. Retrieve the response token(s) for that user
# Find responses by email
GET https://api.typeform.com/forms/{form_id}/responses

Then filter responses in your application to find matching email addresses or identifiers.

Step 2: Verify the request

Before deletion:

  1. Authenticate the requester (confirm they own the data)
  2. Check if you have legal grounds to retain the data
  3. Document the request for compliance purposes

Step 3: Delete the response

DELETE https://api.typeform.com/forms/{form_id}/responses?included_tokens={token}

Step 4: Delete from your systems

Remember: Typeform only stores response data on its platform. If you’ve exported or synced responses to your own databases, you must also delete them from:

  • Your database
  • Analytics platforms
  • CRM systems
  • Email marketing tools
  • Any other integrated systems

Step 5: Confirm deletion

Notify the requester that their data has been deleted, including:

  • What data was deleted
  • From which systems
  • Date of deletion
  • Retention of any data (with justification)

Automation example

/**
* Handle Right to Be Forgotten request
*/
async function handleRTBFRequest(formId, userEmail) {
try {
// 1. Find all responses from this email
const responses = await fetchAllResponses(formId);
const userResponses = responses.filter((r) => {
const emailAnswer = r.answers.find(
(a) => a.type === 'email' && a.email === userEmail
);
return emailAnswer !== null;
});
if (userResponses.length === 0) {
return {
success: false,
message: 'No responses found for this email',
};
}
// 2. Extract tokens
const tokens = userResponses.map((r) => r.token);
// 3. Log the deletion request (for compliance)
await logDeletionRequest({
email: userEmail,
formId: formId,
tokens: tokens,
timestamp: new Date(),
reason: 'RTBF request',
});
// 4. Delete from Typeform
await deleteFromTypeform(formId, tokens);
// 5. Delete from your database
await deleteFromDatabase(tokens);
// 6. Delete from integrated systems
await deleteFromCRM(userEmail);
await deleteFromAnalytics(userEmail);
// 7. Send confirmation email
await sendDeletionConfirmation(userEmail);
return {
success: true,
deletedCount: tokens.length,
timestamp: new Date(),
};
} catch (error) {
console.error('RTBF process failed:', error);
throw error;
}
}
async function deleteFromTypeform(formId, tokens) {
const tokenString = tokens.join(',');
const url = `https://api.typeform.com/forms/${formId}/responses?included_tokens=${tokenString}`;
const response = await fetch(url, {
method: 'DELETE',
headers: {
Authorization: `Bearer ${accessToken}`,
},
});
if (response.status !== 204) {
throw new Error('Failed to delete from Typeform');
}
return true;
}

Best practices

Verification

  1. Authenticate requests: Verify the requester’s identity before deletion
  2. Confirm email ownership: Send confirmation emails to verify the request
  3. Document everything: Keep logs of all deletion requests and actions

Process

  1. Respond promptly: GDPR requires response within 30 days
  2. Search comprehensively: Check all forms and systems for the user’s data
  3. Delete completely: Remove data from all systems, not just Typeform
  4. Verify deletion: Confirm data is removed from all locations

Communication

  1. Acknowledge requests: Respond immediately upon receiving a request
  2. Set expectations: Explain the timeline and process
  3. Confirm completion: Notify the requester when deletion is complete
  4. Document exceptions: If data must be retained, explain why

Handling file uploads

If responses include file uploads, those files should also be deleted:

  1. Download and store file metadata before deletion (if needed for compliance logs)
  2. Delete the response (files are automatically deleted with the response)
  3. Remove any copies you’ve stored elsewhere

Data retention policies

Implement clear data retention policies:

/**
* Automated data retention policy
*/
async function enforceRetentionPolicy(formId, retentionDays = 365) {
const cutoffDate = new Date();
cutoffDate.setDate(cutoffDate.getDate() - retentionDays);
const oldResponses = await fetchResponses(formId, {
until: cutoffDate.toISOString(),
});
// Delete responses older than retention period
if (oldResponses.length > 0) {
const tokens = oldResponses.map((r) => r.token);
await deleteFromTypeform(formId, tokens);
console.log(
`Deleted ${tokens.length} responses older than ${retentionDays} days`
);
}
}
// Run monthly
scheduleJob('0 0 1 * *', () => {
enforceRetentionPolicy('form_id', 365);
});

Audit trail

Maintain an audit trail of all deletions for compliance:

{
"deletion_id": "del_abc123",
"timestamp": "2024-01-15T10:30:00Z",
"requested_by": "user@example.com",
"form_id": "abc123",
"response_tokens": ["token1", "token2"],
"reason": "RTBF request",
"deleted_from": [
"Typeform",
"PostgreSQL database",
"Mailchimp",
"Google Analytics"
],
"performed_by": "admin@company.com",
"verification_method": "email_confirmation"
}

This guide provides technical implementation guidance only. Always consult with legal counsel to ensure your RTBF processes comply with applicable laws and regulations in your jurisdiction.

Key legal points:

  • 30-day response time: GDPR requires response within one month
  • Exceptions exist: Some data may need to be retained for legal reasons
  • Proof required: You may need to demonstrate data deletion
  • Scope matters: Deletion must be comprehensive across all systems
  • Communication required: You must inform the requester of the outcome

Testing your RTBF process

/**
* Test RTBF workflow with test data
*/
async function testRTBFProcess() {
// 1. Create a test response
const testEmail = 'test-rtbf@example.com';
await submitTestResponse(formId, { email: testEmail });
// 2. Wait for processing
await sleep(5000);
// 3. Verify response exists
const responses = await findResponsesByEmail(formId, testEmail);
assert(responses.length > 0, 'Test response not found');
// 4. Execute RTBF
const result = await handleRTBFRequest(formId, testEmail);
assert(result.success, 'RTBF process failed');
// 5. Verify deletion
const remaining = await findResponsesByEmail(formId, testEmail);
assert(remaining.length === 0, 'Response not deleted');
console.log('RTBF process test passed ✓');
}

Custom RTBF script

For more complex scenarios, see the RTBF custom script guide for advanced implementation patterns.

Next steps