Consent Docs

Audit log

The endpoint that pulls the project's audit log with a cursor, and every field of an audit entry, for SIEM collectors.

Reference4 min readFor developers calling the REST API

This endpoint hands the project's audit log to a collector, oldest entry first, one page at a time. Paths are relative to https://console.dpconsent.com/consent/sdk/v1. How to set up a collector is in Send the audit log to your SIEM.

Endpoints#

GET /audit-log#

Returns the next page of audit entries after a cursor.

Key Scope Idempotency-Key Webhook sent
Secret, live audit:read Ignored None

Parameters

Name Type Required Description
after string, up to 200 No The nextCursor of the previous page.
since string No Where to start when there is no cursor: a UTC day, 2026-10-02, or a time with Z or an offset, 2026-10-02T05:00:00Z. Ignored when after is sent.
limit integer, 1 to 1,000 No Entries in the page. Default 500.

Without after or since, the feed starts from the project's first entry.

Request

cURLShell
curl "https://console.dpconsent.com/consent/sdk/v1/audit-log?since=2026-10-01&limit=500" \
  -H "Authorization: Bearer $PIEDAP_AUDIT_KEY"
Node.jsJavaScript
const query = new URLSearchParams({ after: cursor, limit: '1000' });
const response = await fetch(
  `https://console.dpconsent.com/consent/sdk/v1/audit-log?${query}`,
  { headers: { Authorization: `Bearer ${process.env.PIEDAP_AUDIT_KEY}` } },
);
const page = await response.json();

Response

200, with Cache-Control: no-store:

JSON
{
  "items": [
    {
      "id": "3f6c1d2e-8b0a-4c5e-9d71-2a4b6c8e0f13",
      "createdOn": "2026-10-03T05:08:09.189304Z",
      "action": "lookup",
      "resource": "consent-record",
      "resourceId": null,
      "userId": "6f0c2a54-…",
      "userEmail": "ananya.iyer@example.in",
      "organizationId": "…",
      "accountId": "…",
      "projectId": "…",
      "ipAddress": "203.0.113.24",
      "userAgent": "Mozilla/5.0 …",
      "details": {
        "method": "POST",
        "path": "/api/v1/api/consent-record/customer-user/lookup-subject",
        "statusCode": 200,
        "subjects": ["9c41e07a2b5d"],
        "subjectType": "EMAIL",
        "environment": "all",
        "records": 1
      }
    }
  ],
  "nextCursor": "MjAyNi0xMC0wM1QwNTowODowOS4xODkzMDRafDNmNmMxZDJl…",
  "hasMore": false,
  "lagSeconds": 60
}
Field Type Description
items array Entries, oldest first. See Fields of an entry.
nextCursor string or null Send it as after for the next page. On an empty page it repeats your cursor.
hasMore boolean true when another page is ready now.
lagSeconds integer Entries younger than this are held back.

Errors

Status Code When
400 INVALID_CURSOR after is not a cursor this endpoint returned.
400 None. The message is a list since or limit is not valid.
403 SCOPE_REQUIRED A publishable key, or a secret key without audit:read.
403 LIVE_KEY_REQUIRED A test key. Audit entries belong to the project, not to an environment.
429 None The key read the feed 60 times this minute. Wait for Retry-After.

Also the errors every call can return.

Cursor rules#

  • Entries come oldest first, ordered by createdOn to the microsecond, then id.
  • Entries younger than lagSeconds, 60 unless the operator changes AUDIT_FEED_LAG_SECONDS, are held back. An entry whose write commits within that time is not skipped.
  • An entry whose write commits later than that reaches the feed late or not at all. The download and standard output still have it.
  • An empty page returns your cursor unchanged. Call again later with it.
  • Delivery is at least once. Remove duplicates by id.
  • A key may read the feed 60 times a minute, set by AUDIT_FEED_CALLS_PER_MINUTE, on top of its own budget.

Fields of an entry#

Field Type Description
id string The entry's id.
createdOn string When it was written, in UTC to the microsecond.
action string What was done. See Actions.
resource string The area: consent-record, subject-request, audit-log, consent-import, notice-campaign, processor, processor-task, sdk_key, subject and others.
resourceId string or null The target, such as a record or key id.
userId, userEmail string or null Who did it. null for a secret key or a job.
organizationId, accountId, projectId string The tenant.
ipAddress string or null The address the request came from, in clear. These are your team's and your servers' addresses.
userAgent string or null The browser or client.
details object or null See Keys inside details.

Actions#

Action Written when
create, update, delete, publish, archive, rotate, import, resolve A console change
withdraw, erase A withdrawal or an erasure from the console
export A property export, a receipt, an audit log download, or a notice-campaign export
view Someone opened a record or a rights request
lookup A person search in Records, or Find a person in a notice campaign
close, issue A notice campaign was closed, or links were issued
replay Failed webhook events were replayed
acknowledge A processor report was recorded in the console
revoke, reveal, request_live, cancel_live_request, approve, decline Key actions
purge Records were deleted under Keep evidence for
FIND, EXPORT, WITHDRAW, ERASE, LINK_IDENTIFIERS, LINK_REQUEST A secret key acted on a person, resource subject
CHECK_BUDGET_EXCEEDED A key ran out of its consent check budget, once a minute
CAMPAIGN_LINKS_READ A key read a page of notice links
ISSUE The job finished minting a batch of notice links
ACKNOWLEDGE_PROCESSOR_TASKS A key recorded processor reports

Keys inside details#

Key Present on
method, path, statusCode, error Console entries. path never holds a query string.
subjects, subjectType, environment, records lookup. subjects holds the first 12 characters of each hash, never the identifier.
via, keyId, keyName Every entry a secret key wrote. via is secret key, or job for the link minting job.
subject, environment, records Secret-key calls on a person. subject is the first 12 characters of the hash.
query, searched, rows, complete Downloads. A search is recorded as searched: true, never its text.
batchId, count CAMPAIGN_LINKS_READ
batchId, sequence, linkCount ISSUE
limit, environment CHECK_BUDGET_EXCEEDED
environment, recorded, unchanged, refused ACKNOWLEDGE_PROCESSOR_TASKS
purgedRecords, retentionDays, cutoff, consentIds purge

Standard output#

Each entry is also written as one JSON line on the API's standard output, unless AUDIT_LOG_STDOUT=false. The line holds the fields above, flat, plus:

Field Value
context AUDIT
level log
message audit <action> <resource>
timestamp When the line was written
stored false when the database did not store the entry
JSON
{"level":"log","message":"audit view consent-record",
 "timestamp":"2026-10-03T05:08:09.402Z","context":"AUDIT","stored":true,
 "id":"…","createdOn":"2026-10-03T05:08:09.189304Z","action":"view",
 "resource":"consent-record","resourceId":"cns_…","userId":"…",
 "userEmail":"ananya.iyer@example.in","organizationId":"…",
 "accountId":"…","projectId":"…","ipAddress":"203.0.113.24",
 "userAgent":"Mozilla/5.0 …","details":{"method":"GET",
 "path":"/api/v1/api/consent-record/customer-user/fetch-one/cns_…",
 "statusCode":200}}

↑↓ to move, Enter to open