Korely

Users & agents

Erase a user

Permanently erase every memory and fact scoped to one end user in the key's project, in a single call. It leaves an audit receipt as proof.

DELETE /v1/users/{end_user}/memories

SDK: korely.delete_all(user_id=end_user). Use it when one of your customers asks you to erase their data.

This is a physical delete. The rows are removed from the live database, and the content cannot be read back through the API by any parameter, include_invalidated included. On the Cloud, encrypted nightly backups keep a copy for up to 35 days, and a restore from one replays the erasure.

What survives carries no erased content and never the id itself, only a keyed pseudonym of it, so you can evidence the erasure to your own regulator (Article 5(2) accountability). It is the erasure receipt, whose id is the audit_id of the response, and an erase event in the audit log. The access trail rows that named this end user (kept for the audit retention period), any earlier forget receipts, and the records of webhooks already delivered stay too, relabelled with the same pseudonym. GET /v1/audit?user_id=<the same id> computes the pseudonym and finds them. On an install without SECRET_KEY the id is dropped and nothing replaces it, so the proof is the audit_id.

Looking for a non-destructive drop-from-reads on a single item instead (kept as history, with no undo endpoint)? Use DELETE /v1/memories/{memory_id}, which forgets one memory (it drops out of every read and its row stays) and, with erase=true, erases that one memory for good (REST only; the SDKs' delete() does not send it).

Authentication

HTTP header, required: Authorization: Bearer kor_live_.... The key must carry the memories:write scope.

Path parameter

ParameterTypeDescription
end_userstringThe end-user namespace to erase, the user_id exactly as written. Every memory and fact scoped to this value in the key's project is deleted. Percent-encode it as one path segment (acme/42 is acme%2F42); any stored id is accepted. An unknown end_user is not an error: it returns 200 with zero counts. An empty one, one longer than 255 characters, or one that is an erased pseudonym (erased: and 32 hex characters), is refused with 422 invalid_request.

This endpoint takes no query parameters and no request body.

Example request

Terminal window
curl -X DELETE https://api.korely.ai/v1/users/customer-giulia-4812/memories \
-H "Authorization: Bearer kor_live_..."

Response

200 OK. The end-user namespace that was erased, the counts of what was deleted, and the id of the erasure receipt.

{
"user_id": "customer-giulia-4812",
"memories_deleted": 14,
"facts_deleted": 31,
"erasure": "permanent",
"audit_id": "aud_5f0c2d9e8b7a4c1d9e3f6a2b1c0d4e8f"
}
FieldTypeDescription
user_idstringThe end-user namespace that was forgotten (echoes the path param).
memories_deletedintegerCount of memories physically deleted.
facts_deletedintegerCount of facts physically deleted, superseded ones included.
erasurestringAlways permanent: nothing erased here can be read back through the API.
audit_idstringId of the erasure receipt Korely keeps (counts and a keyed pseudonym of your end-user id, never content): aud_ and 32 hex characters. Store it with your own erasure record.

Up to version 0.1.42 the response also carried memories_forgotten and facts_invalidated, the same two numbers under older names. From 0.2.0 they are gone: read memories_deleted and facts_deleted.

Errors

StatusCodeCause
401invalid_keyMissing or invalid kor_live_ key, Invalid or missing API key: ..., then what is wrong.
403forbiddenThe key lacks the memories:write scope, API key missing required scope(s): memories:write; or the key is confined to some end users and names another one.
422invalid_requestend_user is empty, longer than 255 characters, holds a NUL byte, or names an end user already erased.
429rate_limit_exceededRate limit exceeded. The response carries a Retry-After header.

Notes

  • Write scope required. The key must carry memories:write.
  • Physical delete, audited. Memories and facts are removed from the database, not flagged; only pseudonymised audit and delivery records remain. This is distinct from DELETE /v1/memories/{id}, which forgets one memory (it drops out of every read and its row stays) and, with erase=true, erases that one memory for good (REST only; the SDKs' delete() does not send it).
  • Scoped to the key's project. If the same end user lives in several projects, call it once per project, with that project's key.
  • Names declared elsewhere. If the person has no memory or fact left in any other project of your account, the names declared for them there (Declare a name) are removed too. A namesake, the same id in another project with memories of its own, keeps everything and is not counted as erased.
  • No 404. Forgetting an unknown end_user returns 200 with zero counts, and still writes a receipt.
  • Two audit records. Each call writes the receipt (audit_id) and an erase event in GET /v1/audit, with the counts in meta. The event's user_id is the keyed pseudonym (erased:...), not the id; ask GET /v1/audit?user_id=<the id> and it is found. The event does not carry the audit_id.

Related