Skip to main content

GDPR Data Retention Policy

This guide explains how the Push Notification System (Hober) stores, retains, and deletes personal data in compliance with GDPR. It covers retention periods per data category, deletion cascade behaviour, audit logging, bulk deletion constraints, the API endpoints for triggering deletion, and an operator runbook for handling manual data removal requests.

Retention periods

Data categoryTable(s)Retention periodNotes
Subscriber PIIsubscribersUntil deletion requestedexternal_id, email, attributes
Device tokensdevicesUntil deletion requestedCascade-deleted with subscriber
List membershipssubscriber_list_membershipsUntil deletion requestedCascade-deleted with subscriber
Delivery logsnotification_delivery_logs90 daysAnonymised on subscriber delete; row retained for analytics
Audit logssubscriber_deletion_audit7 yearsRequired for compliance evidence; never deleted

Hober does not proactively expire subscriber PII. Deletion is always initiated by an operator or by the subscriber via your product's account-deletion flow (which should call the Hober deletion API described below).

Deletion cascade behaviour

When a subscriber is deleted, Hober applies the following cascade rules atomically within a single database transaction:

Hard deletes

The following rows are permanently removed:

  • subscribers — the subscriber record itself
  • devices — all devices belonging to the subscriber (ON DELETE CASCADE)
  • subscriber_list_memberships — all list memberships for the subscriber (ON DELETE CASCADE)

Once hard-deleted, these records cannot be recovered. Ensure any downstream systems (CRM, analytics warehouse) are notified before triggering deletion.

Anonymisation (delivery logs)

notification_delivery_logs rows are not deleted. Instead, the foreign keys are nullified to preserve aggregate delivery metrics while removing the link to the individual:

subscriber_id = NULL -- anonymised
device_id = NULL -- anonymised

The log row (timestamp, status, provider response) is retained for 90 days from delivery date to support throughput analytics and SLA reporting. After 90 days the row is removed by a scheduled purge job.

Audit log — subscriber_deletion_audit

Every deletion operation (single or bulk) writes one row to subscriber_deletion_audit. This table is append-only and is never purged.

ColumnTypeDescription
iduuidPrimary key
tenant_iduuidThe tenant that owns the deleted subscriber
subscriber_iduuidUUID of the deleted subscriber
deleted_byuuidUser ID of the operator or service account that triggered the deletion
subscriber_countinteger1 for single-subscriber deletions; N for bulk deletions
deleted_attimestamptzWall-clock time of the deletion (UTC)

Use this table to produce GDPR erasure evidence. For bulk deletions, one audit row is written per subscriber in the batch, all sharing the same deleted_at timestamp.

Bulk deletion limits and rate limiting

The bulk deletion endpoint accepts a maximum of 1,000 subscriber IDs per request. Requests exceeding this limit are rejected with HTTP 422 Unprocessable Entity.

IDs included in the request but not found in the tenant's subscriber set are returned in the not_found array of the response body and are not treated as errors — the overall request succeeds for the IDs that were found and deleted.

Rate limiting applies at the tenant level:

PlanBulk deletion rate limit
Starter10 requests / minute
Growth50 requests / minute
Premium200 requests / minute

For large-scale erasure operations (for example, a data-subject access request requiring deletion of tens of thousands of subscribers), batch requests in chunks of 1,000 and respect the rate limit for your plan. See the operator runbook below for a scripted approach.

Triggering deletion via the API

See the Subscribers API reference for full request/response schemas.

Single subscriber deletion

DELETE /api/v1/subscribers/{id}
Authorization: Bearer <api_key>

{id} is the Hober subscriber UUID (the id field returned by POST /api/v1/subscribers/upsert).

Success response — 204 No Content.

Error responses:

StatusMeaning
401Missing or invalid bearer token
404Subscriber not found

Operator runbook

Use this runbook when a data subject submits a GDPR erasure request and you need to delete one or more subscribers manually.

Step 1 — Identify the subscriber UUID

If you have the subscriber's external_id (your internal user ID), look up the Hober UUID:

curl -s -X GET \
"https://api.hober.io/api/v1/subscribers?external_id=<your_user_id>" \
-H "Authorization: Bearer $Hober_API_KEY" \
| jq '.id'

Record the returned UUID as $SUBSCRIBER_ID.

Step 2 — Trigger deletion

curl -s -X DELETE \
"https://api.hober.io/api/v1/subscribers/$SUBSCRIBER_ID" \
-H "Authorization: Bearer $Hober_API_KEY"

A 204 No Content response confirms deletion. If you receive 404, the subscriber has already been deleted or the UUID is incorrect.

Step 3 — Verify the deletion

Repeat the lookup from Step 1: a 404 (or an empty result for the external_id query) confirms the subscriber is gone. Every deletion is also recorded in Hober's internal deletion audit trail — including when and by whom — which is retained for compliance evidence.

Step 4 — Bulk erasure (scripted)

For erasure requests covering many subscribers, loop over the single-delete endpoint. Replace ids.txt with a file containing one Hober subscriber UUID per line.

#!/usr/bin/env bash
set -euo pipefail

TOKEN="${HOBER_ACCESS_TOKEN:?HOBER_ACCESS_TOKEN is required}"
BASE_URL="https://api.hober.io"
IDS_FILE="${1:?Usage: $0 ids.txt}"

DELETED=0
while IFS= read -r ID; do
[[ -z "$ID" ]] && continue
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" -X DELETE "$BASE_URL/api/v1/subscribers/$ID" -H "Authorization: Bearer $TOKEN")
case "$HTTP_CODE" in
204) DELETED=$((DELETED + 1)) ;;
404) echo "already gone: $ID" ;;
*) echo "ERROR: $ID returned HTTP $HTTP_CODE" >&2; exit 1 ;;
esac
# Respect rate limits — adjust for your plan
sleep 0.3
done < "$IDS_FILE"

echo "Done. Total deleted: $DELETED"

Step 5 — Document the erasure

Record the following in your erasure request ticket:

  • Date and time of deletion (UTC)
  • Subscriber UUID(s) deleted
  • deleted_by user ID used
  • Confirmation of the verification lookup (Step 3)

Retain this evidence for the 7-year audit log period required by GDPR Article 5(2).

Irreversible operation

Subscriber deletion is permanent. Hard-deleted rows cannot be recovered from the database. Ensure you have confirmed the correct subscriber UUID before proceeding.

Delivery log retention

Delivery log rows are anonymised (subscriber and device foreign keys set to NULL), not deleted, when a subscriber is removed. The anonymised rows are purged automatically after 90 days. This means aggregate delivery metrics are unaffected by erasure operations.