Skip to content

Handle a privacy request

Documented Checked against the CLI's current help and source. Not run end to end. CLI 0.3.1, checked 2026-11-04.

A customer has asked what we hold on them, then to be forgotten.

Answer a subject access request with one file, honour a do-not-call request at once, and erase a person with a certificate you can check.

What you get: the everyday data protection jobs done from the terminal, each one checked by ContactsQ itself rather than by memory. You need: a signed-in profile and an organisation admin for the access request, the erasure and lifting a block (we ran every step as the owner). About 8 minutes.

The contact here is the made-up Priya Shah from Keep your contacts tidy, with two email addresses and a phone number.

best channel
quox contacts best-channel ct_mw2qlxb8_2233421bc6bd --purpose marketingchannel: none allowedvoice: deny (no_marketing_consent)email: deny (no_marketing_consent)sms: deny (no_marketing_consent)Ⓠ CONTACTSQ │ contacts best-channel │ none allowedquox contacts best-channel ct_mw2qlxb8_2233421bc6bd --purpose servicechannel: voiceemail: allow (assumed_legitimate_interest)sms: allow (assumed_legitimate_interest)Ⓠ CONTACTSQ │ contacts best-channel │ voice
From a real run on the demo profile.

With no marketing consent on record, nothing may be used for marketing. For service, every channel is open on legitimate interest, and voice comes first. The answer never shows the number or address itself. The purposes are service, transactional, marketing and research.

suppress
quox contacts suppress +442079460958 --reason dncⓆ CONTACTSQ │ contacts suppress │ phone dncquox contacts suppressed +442079460958suppressed: dncⓆ CONTACTSQ │ contacts suppressed │ dncquox contacts best-channel ct_mw2qlxb8_2233421bc6bd --purpose servicechannel: emailvoice: deny (dnc)sms: deny (dnc)Ⓠ CONTACTSQ │ contacts best-channel │ email
From a real run on the demo profile.

The moment the number is suppressed, voice and text are refused for her and email becomes the channel to use. The reasons are dnc, do_not_market and bounced. The suppression list keeps only a blind index of the number, not the number itself.

dsar
quox contacts dsar ct_mw2qlxb8_2233421bc6bd --out priya-dsar.jsonⓆ CONTACTSQ │ contacts dsar │ priya-dsar.json (facts=0 identifiers=3 …jq .counts priya-dsar.json{"facts": 0,"identifiers": 3,"consents": 0,"touchpoints": 0,"edges": 1,"policy_decisions": 3,"leases": 0,"lease_uses": 0,"provenance": 2}
From a real run on the demo profile.

The bundle is one JSON file: the record, where each detail came from, consents, interactions, links to other contacts, every policy decision made about her, and every time an agent was lent her details. The three policy decisions are the three channel checks from steps 1 and 2, one for marketing and two for service, each with its decision and reasons.

compliance
quox contacts complianceBand                      Count    IDsnotice_overdue            0candidates_expiring_7d    0no_lawful_basis           1        ct_mw2qlxcj_258cbc6e3fceconsents_expiring_30d     0special_category          0Ⓠ CONTACTSQ │ contacts compliance │ notice_overdue=0 candidates_expiring_7d…quox contacts retention statusenabled                noscheduler_armed        yesrun_time_utc           03:15last_run_at            -last_status            -last_countsconsecutive_failures   0backoff_until          -next_tick_at           -pending                {"expired":0,"legal_hold":0,"retired_failed":0}Ⓠ CONTACTSQ │ contacts retention status │ disabled next never
From a real run on the demo profile.

compliance lists the contacts that need attention, band by band. Here the one contact with no lawful basis recorded is the Harbour Dental organisation record, created when Priya was added. retention status shows the retention reaper; on this workspace it is switched off, so nothing is erased on a timer. quox contacts processing-record prints the organisation’s record of processing as JSON.

erase
quox contacts erase ct_mw2qlxb8_2233421bc6bd --scope full --reason subject_request --yeserasure       er_mw2qoe5k_e6900ef11574contact       ct_mw2qlxb8_2233421bc6bdscope         fullexecuted_at   2026-11-04T23:19:45.318Zsha256        56737bff942f19461fa7e66944f69003804d6ff6bd6175e333b44d52e... contactsq        shreddedtouchpoints      shredded_with_contactleases           revokedconsents         retained_codes_onlysuppressions     tombstonedphoto            shreddedvoice_call_log   NOT_PROPAGATEDbackups          ages_out_by:2026-12-04Ⓠ CONTACTSQ │ contacts erase │ er_mw2qoe5k_e6900ef11574 full
From a real run on the demo profile.

Erasure cannot be undone. The report says, place by place, what happened to her data. Read it line by line: here the call log was not reached by the erasure (NOT_PROPAGATED), and backups age out by the date shown rather than at once.

certificate
quox contacts certificate er_mw2qoe5k_e6900ef11574{"certificate": {  "certificate_version": 1,  "contact_id": "ct_mw2qlxb8_2233421bc6bd",  "counts": {    "edges_removed": 1,    "identifiers_removed": 3,    "merge_records_shredded": 1,    "merged_shells_shredded": 1,    "name_tokens_removed": 4,    "tombstones_written": 3  },  "erasure_id": "er_mw2qoe5k_e6900ef11574",  "executed_at": "2026-11-04T23:19:45.318Z",  "reason_code": "subject_request",  "scope": "full",  "sha256": "56737bff942f19461fa7e66944f69003804d6ff6bd6175e333b44d52ead9ec8a"},"verified": true}Ⓠ CONTACTSQ │ contacts certificate │ er_mw2qoe5k_e6900ef11574 verified
From a real run on the demo profile. Some fields left out.

The certificate counts what was removed, including the merged duplicate from the earlier guide, and verified: true is ContactsQ’s own check of the certificate. Keep the erasure id: it is all you need to show the erasure later.

unblock
quox contacts add "Priya Shah" --email [email protected] --relationship customer✖ That number or email belongs to an erased person and is blocked from coming back. If they have legitimately returned, an org admin can run `quox contacts unblock <value> --reason <code> --yes` first.quox contacts unblock [email protected] --reason subject_returned --yeschannel   emailremoved   1Ⓠ CONTACTSQ │ contacts unblock │ email tombstone lifted
From a real run on the demo profile.

Erasure leaves a tombstone for each number and address, so the same person cannot slip back in by accident. Lifting one is a deliberate admin step with a reason.

Every step went through ContactsQ’s own rules: the channel checks were recorded as policy decisions on the contact, the access request gathered them up, and the erasure produced a report and a certificate with a hash ContactsQ verifies. Lifting a block is witnessed.

quox contacts certificate <erasureId> re-checks an erasure at any time and prints verified: true when it holds. quox contacts suppressed <number or email> shows whether a suppression is in place.

Erasure is final by design. Its tombstones stay until you lift them with quox contacts unblock, one number or address at a time.