Erase a contact's personal data

View as Markdown
> **DESTRUCTIVE AND IRREVERSIBLE.** This permanently destroys a person's data across the workspace > and at Jelliu's voice sub-processor. There is no undo, no soft-delete you can reverse and no > restore path short of a database backup. Double-check `contactId` before calling it. Carries out a data subject's right to erasure (GDPR Art. 17, and the equivalent rights under Ley 1581, LGPD, LFPDPPP and similar laws). In **one database transaction** it: 1. Redacts PII (phone numbers, emails and similar) in the transcript and summary of every call that is not deleted and belongs to the contact. It sets the call's `phone_number` to `[ERASED]` and removes the link to the recording, so `GET /api/calls/{callId}/audio` can no longer replay it. The call rows themselves stay for analytics. 2. Anonymizes reservations and appointments whose phone (matched on the last 7 to 10 digits) or email matches the contact: name and phone become `[ERASED]`, and email and notes are cleared. 3. Marks every consent record of the contact `erased`. 4. Anonymizes the contact (name and phone `[ERASED]`, email, WhatsApp number and metadata cleared) and soft-deletes it. 5. Replaces the body of every message in the contact's conversations with `[ERASED]`. 6. Erases the request bodies in audit-log entries for the contact and its calls, and the tool arguments in agent-action entries for those calls. Each rewritten row is stamped with a signed redaction mark, so `GET /api/audit/verify-chain` still verifies. 7. Deletes fraud flags raised on the contact's calls. After the transaction commits, it deletes each call's conversation (audio and full transcript) in the voice engine, five at a time with a 10-second timeout each. A vendor failure does **not** roll back the local erasure and does **not** change the response. It is logged for manual follow-up. **What it does not touch.** The number stays on the suppression list, so the erased person is still never called. Call rows the retention sweep had already soft-deleted are skipped. The response is identical whether or not the contact exists. **Side effects.** Irreversible writes across calls, contacts, consent, messages, bookings, audit logs and agent actions. Deletion requests to the voice engine. Evicts consent caches. Writes an audit entry (`gdpr_erasure`, resource `contact`) with no personal data in it. **Idempotency.** Safe to retry. Everything it writes is already anonymized on a second run, and it returns the same `200`. **Access** - **Required scope:** `full`. Signed-in users need the `owner` role; admins are refused. - **Rate limit:** General API — 120 (Starter), 200 (Growth), 300 (Business) or 600 (Enterprise) requests/min per workspace. See [Rate limits](/rate-limits). - **Plan:** Available on every plan.

Authentication

AuthorizationBearer
Workspace API key: `jl_` followed by 64 lowercase hex characters, created by the workspace owner in the dashboard (**Settings → API Keys**) and sent as `Authorization: Bearer jl_...`. The plaintext is shown once, at creation; Jelliu stores only a SHA-256 hash. A workspace can hold up to 25 active keys. | Scope | GET / HEAD | POST / PUT / PATCH / DELETE | Admin-only routes | | --- | --- | --- | --- | | `read` | Yes | No | No | | `write` | Yes | Yes | No | | `full` | Yes | Yes | Yes | Operations restricted to admins or owners reject keys without the `full` scope with `403`, and say so in their description. No key, whatever its scope, can mint or revoke API keys or rotate a webhook secret — that requires a signed-in owner session. A revoked key stops authenticating within about 10 seconds. See [Authentication](/authentication).

Path parameters

contactIdstringRequiredformat: "uuid"
The contact to erase. A value that is not a UUID returns 400. An unknown id still returns 200.

Response

Erasure completed in the database. Sub-processor deletion is best-effort.

dataobject

Errors

400
Bad Request Error
401
Unauthorized Error
403
Forbidden Error
429
Too Many Requests Error
500
Internal Server Error