Documentation

Everything you need to install and configure Korvus.

Right to erasure (GDPR Art. 17)

Technical procedure to delete a visitor's data collected by the Korvus snippet, at the visitor's request, through your DPO team.

Context

Korvus acts as a processor within the meaning of Article 28 of the GDPR; you, as the site publisher, are the controller. When a visitor asks you to delete their data (GDPR Art. 17), you must be able to respond within one month at most (Art. 12).

This page describes the technical helper Korvus provides so you can carry out that deletion on the data collected through our snippet: raw_events, pageviews, sessions.

What is deleted

  • The visitor's sessions for the website concerned
  • The pageviews linked to those sessions
  • The raw events (raw_events) linked to those sessions

What is not deleted

The products and product_history tables only hold aggregated product metadata (SKU, observed price, availability), with no personal data and no visitor identifier. They are therefore not affected by an erasure request.

Alerts (alert_events) and baselines (baselines) are aggregated at site level, never at visitor level. The one exception: a video proof, when one exists, is attached to the session in which the incident occurred. It can only be accessed from that incident's case file, never by searching for a visitor, and it is purged along with the rest of the data.

Technical endpoint

POST https://app.korvus.fr/api/internal/data-subject-request

Authentication

Header Authorization: Bearer <INTERNAL_API_SECRET>. Your Korvus contact shares the secret with you out of band. Use it from a backend or a secure terminal, never in a browser.

Request body

Two mutually exclusive modes (one or the other, not both):

{
  "website_id": "uuid-de-votre-site",
  "session_id": "uuid-de-la-session-du-visiteur"
}

or:

{
  "website_id": "uuid-de-votre-site",
  "created_after": "2026-04-01T00:00:00Z"
}
FieldTypeRequiredDescription
website_idUUIDYesIdentifier of the site concerned
session_idUUIDOptionalIdentifier of the visitor session to delete. It can be retrieved from your session export if the visitor provides it
created_afterISO 8601OptionalDate/time from which all of the website's sessions will be deleted (GDPR request window)

Exactly one of the two fields session_id or created_after must be provided.

Response

{
  "deleted": {
    "sessions": 1,
    "pageviews": 12,
    "events": 84,
    "dup_archive": 0,
    "proofs": 2
  },
  "clickhouse": { "status": "ok" }
}

dup_archive covers session duplicates archived during deduplication, proofs covers video proofs (storage objects and metadata).

Check clickhouse.status. It is ok, skipped or failed. A failed comes back with an HTTP 200 code: the deletion did happen in the main database, but not in the analytics index. In that case, send the same request again: it is idempotent.

Error codes

CodeMeaning
401Missing or invalid secret
400Invalid body (malformed UUID, neither session_id nor created_after provided)
400created_after more than 30 days in the past (see the limit below)
404Unknown website_id
429Too many requests for this website_id. Respect the Retry-After header
503Service temporarily unavailable. Try again; no data was touched
500Server error. The deletion is cancelled (transactional ROLLBACK); contact support

30-day limit on created_after

A single call cannot reach back more than 30 days: this limit protects the collection tables from an extended lock that would interrupt measurement for all of our customers.

To erase older history, chain several calls in 30-day windows, from the most recent to the oldest:

# Effacer 90 jours d'historique = 3 appels successifs
for OFFSET in 0 30 60; do
  SINCE=$(date -u -d "$((OFFSET + 30)) days ago" +%Y-%m-%dT%H:%M:%SZ)
  curl -X POST https://app.korvus.fr/api/internal/data-subject-request \
    -H "Authorization: Bearer $KORVUS_INTERNAL_SECRET" \
    -H "Content-Type: application/json" \
    -d "{\"website_id\": \"$WEBSITE_ID\", \"created_after\": \"$SINCE\"}"
done

A single call over a window that is too wide returns a 400 without erasing anything: do not mistake it for a partial success.

curl example

curl -X POST https://app.korvus.fr/api/internal/data-subject-request \
  -H "Authorization: Bearer $INTERNAL_API_SECRET" \
  -H "Content-Type: application/json" \
  -d '{
    "website_id": "00000000-0000-0000-0000-000000000000",
    "session_id": "11111111-1111-1111-1111-111111111111"
  }'

Guarantees

  • Transactional: deleting raw_events + pageviews + sessions + the deduplication archive runs in a single SQL transaction. If any step fails, everything is rolled back, leaving no partial state.
  • Scoped to the website: a DELETE can never touch another site's data, even through a configuration mistake. The website_id filter is present on every query.
  • Immediate on live systems: the data disappears without delay from our production databases (PostgreSQL and ClickHouse) and from video proof storage.

Backups

The data remains in our backups until they rotate out. Every backup system has this constraint. Here is exactly what it covers:

CopyMaximum retention
PostgreSQL full backups15 days
PostgreSQL hourly archives15 days
ClickHouse backups14 days
Native snapshots of the managed database7 days

During this period, these backups are used for no purpose other than restoring the service after an incident. They are not consulted, analyzed or exploited.

Above all, every erasure is permanently logged. If we ever had to restore a backup taken before your request, our restore procedure requires a step that replays every recorded erasure before the service goes back online: erased data cannot reappear this way.

Once the rotation period above has passed, no copy remains.

Legal response time

The GDPR (Art. 12) requires you to respond to an erasure request within one month, extendable by two months for complex requests. The endpoint above lets you respond in a few seconds.