COPPA §312.6 and §312.5 give parents explicit statutory rights to review personal information collected from their child and to revoke consent — which triggers deletion of all data collected under that consent. These are not optional customer-service courtesies; they are legal obligations enforceable by the FTC. If a parent contacts your support team and there is no defined process, no identity verification step, and no mechanism to actually produce or delete the data, you are in violation of §312.6 regardless of whether you obtained consent correctly in the first place. GDPR Article 17 extends the deletion obligation to EU child data as well.
Medium because the violation is procedural rather than immediate data exposure, but the FTC treats absence of a functional parental access mechanism as non-compliance with §312.6 independent of other COPPA gaps.
Implement a self-serve parental review flow: the parent submits their email, receives a time-limited review link, and can revoke consent and delete the child's account through authenticated API endpoints. Document the process and SLA in your privacy policy.
// app/api/parent/revoke/[childId]/route.ts
export async function DELETE(req: Request, { params }: { params: { childId: string } }) {
const token = req.headers.get('x-parent-review-token')
const reviewToken = await db.parentReviewToken.findUnique({
where: { token, expiresAt: { gt: new Date() } }
})
if (!reviewToken) return Response.json({ error: 'Invalid or expired token.' }, { status: 403 })
await db.parentalConsent.updateMany({
where: { childUserId: params.childId, parentEmail: reviewToken.parentEmail },
data: { revokedAt: new Date() }
})
await db.user.delete({ where: { id: params.childId } })
return Response.json({ status: 'revoked' })
}
In your privacy policy, add: 'Parents may review, correct, or request deletion of their child's data at any time by [process]. We respond within [N] business days and verify parent identity before releasing any information.'
ID: coppa-compliance.parental-consent.parent-review-revoke
Severity: medium
What to look for: Count all relevant instances and enumerate each. COPPA grants parents the right to review their child's data and to revoke consent at any time. Look for a parental portal, a contact mechanism specifically for parents, or a parent-authenticated view. Check for API routes or settings pages that allow a verified parent to view data held about their child, request a data export, or delete the child's account and all associated data. Look for how parent identity is verified before granting access to a child's data — the verification should be equivalent to the original consent method (e.g., email the parent a review link that they must click). Check the privacy policy for disclosure of these rights. Look for a dedicated privacy contact email or form for parental inquiries.
Pass criteria: A mechanism exists for parents to review their child's data, request corrections, and revoke consent (triggering account deletion). The mechanism verifies parent identity before granting access. The process is documented in the privacy policy with a contact method.
Fail criteria: No mechanism for parents to review or delete their child's data exists. The only path is emailing general support, with no described process or timeline. Revocation requires contacting legal, not a self-serve or standardized flow.
Skip (N/A) when: The application hard-blocks all users under 13 and no parental consent workflow exists.
Detail on fail: Example: "No parental portal or review mechanism found. Privacy policy does not describe how parents can access or delete their child's data. No contact method specifically for parental data requests." or "Privacy policy says 'contact us to review your child's data' but no SLA, no verification process, and no dedicated contact channel are described.".
Remediation: Implement a parental access flow and document it clearly:
// app/api/parent/request-review/route.ts
// Parent submits their email to receive a review link
export async function POST(req: Request) {
const { parentEmail } = await req.json()
// Find child accounts linked to this parent's consent record
const consents = await db.parentalConsent.findMany({
where: { parentEmail, revokedAt: null },
include: { childUser: { select: { id: true, email: true } } }
})
if (consents.length === 0) {
// Don't reveal whether accounts exist — just say the email will arrive if accounts found
return Response.json({ status: 'check_your_email' })
}
// Send a time-limited review link to the parent
const token = crypto.randomUUID()
await db.parentReviewToken.create({
data: { token, parentEmail, expiresAt: new Date(Date.now() + 24 * 60 * 60 * 1000) }
})
await sendParentReviewEmail({ parentEmail, token })
return Response.json({ status: 'check_your_email' })
}
// app/api/parent/revoke/[childId]/route.ts
// Authenticated (via review token) parent revokes consent and deletes child account
export async function DELETE(req: Request, { params }: { params: { childId: string } }) {
const token = req.headers.get('x-parent-review-token')
const reviewToken = await db.parentReviewToken.findUnique({
where: { token, expiresAt: { gt: new Date() } }
})
if (!reviewToken) return Response.json({ error: 'Invalid or expired token.' }, { status: 403 })
await db.parentalConsent.updateMany({
where: { childUserId: params.childId, parentEmail: reviewToken.parentEmail },
data: { revokedAt: new Date() }
})
await db.user.delete({ where: { id: params.childId } })
return Response.json({ status: 'revoked' })
}
In your privacy policy, add a dedicated section: "Parents' Rights — Parents may review, correct, or request deletion of their child's data at any time by [process]. We will respond within [N] business days."