Consent Docs

Answer an access request

Export one package with a signed receipt for every record a person has, link a rights request to your own id, and check the receipts.

How-to2 min readFor web, backend and mobile developers

When a person asks what you hold about them, export one package from your server. It holds a signed receipt for each consent record, a summary of the processing and whom to contact.

Before you start#

  • A secret key with the scope subjects:export. To link requests from the hosted form, it also needs requests:write.
  • The client from Record consent from your server.

Export the person's records#

  1. If the request came from the hosted request form, email the verificationUrl from the subject_request.received webhook to replyTo. The request waits until the person follows it.

  2. If you keep records under your own id, link the request to that id. The webhook carries the request's reference and the subjectId the person typed.

    Node.jsJavaScript
    const linked = await client.linkRequest(
      'DSR-2026-4F2A91',
      'usr_8f2K1xQz',
      'USER_ID',
    );
    // { reference: 'DSR-2026-4F2A91', linkedRecordCount: 2 }
    Python
    linked = client.link_request(
        "DSR-2026-4F2A91", "usr_8f2K1xQz", "USER_ID"
    )
    # {"reference": "DSR-2026-4F2A91", "linkedRecordCount": 2}
    cURLShell
    curl -X POST https://console.dpconsent.com/consent/sdk/v1/requests/link \
      -H "Authorization: Bearer $PIEDAP_SECRET_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "reference": "DSR-2026-4F2A91",
        "subjectId": "usr_8f2K1xQz",
        "subjectType": "USER_ID"
      }'
  3. Export the package with exportSubject.

    Node.jsJavaScript
    import { writeFile } from 'node:fs/promises';
    
    const pack = await client.exportSubject('usr_8f2K1xQz', 'USER_ID');
    await writeFile(
      'access-usr_8f2K1xQz.json',
      JSON.stringify(pack, null, 2),
    );
    Python
    import json
    
    pack = client.export_subject("usr_8f2K1xQz", "USER_ID")
    with open("access-usr_8f2K1xQz.json", "w", encoding="utf-8") as file:
        json.dump(pack, file, indent=2)
    cURLShell
    curl -X POST https://console.dpconsent.com/consent/sdk/v1/subjects/export \
      -H "Authorization: Bearer $PIEDAP_SECRET_KEY" \
      -H "Content-Type: application/json" \
      -d '{ "subjectId": "usr_8f2K1xQz", "subjectType": "USER_ID" }' \
      -o access-usr_8f2K1xQz.json
  4. Add your own account data. The package names the person only by hashes.

  5. Send the package to the person, with the contact details from it in your reply.

The package holds these parts:

Part What it holds
summary.purposes Each purpose the person was asked about: its key and name, whether it is allowed now, any partner answers, and the data it uses
summary.sharedWith Each partner the data could be shared with, including under consent since withdrawn
contact organisation, email and dataProtectionOfficer, from the console's settings
receipts One signed receipt per record: the notice version, every decision, the times and the proof chain
generatedOn When the package was made

Each export is noted in the history of every record it covers. A linked request shows how many consent records it matched. When your team carries out the request in the console, it acts on those records.

Check the receipts#

Every receipt is signed with the deployment's Ed25519 key, so anyone can check it without an account.

Node.jsJavaScript
import { verifyReceipt } from '@piedap/consent/server';

const keys = await client.publicKeys();

for (const signed of pack.receipts) {
  const ok = verifyReceipt(signed, keys);
  console.log(signed.receipt.consentId, ok ? 'verified' : 'NOT verified');
}
cURLShell
curl -X POST https://console.dpconsent.com/consent/sdk/v1/receipts/verify \
  -H "Content-Type: application/json" \
  -d @receipt.json

verifyReceipt makes no network call once you hold the keys. The cURL call needs no key. It takes one receipt, saved as receipt.json with its receipt, signature and algorithm. The Python package has no offline check, so post each receipt to the same endpoint.

If a call is refused#

  • 403 SCOPE_REQUIRED: the key lacks the scope for the call.
  • 404 REQUEST_NOT_FOUND: no request has that reference.

↑↓ to move, Enter to open