Consent Docs

Campaign events

The webhook events a notice campaign sends when a batch of links is ready, when a person withdraws on a link and when a day of answers is anchored.

Reference2 min readFor developers calling the REST API

Three webhook events report what happens in a notice campaign. Each arrives in the envelope described in Webhook format. None of them carries a link or an identifier in clear.

Events#

campaign.batch_issued#

Sent when

A batch of links is ready, once for each batch. Fetch its links with the links endpoint within 7 days.

Payload

Field in data Type Description
campaignId, campaignName string The campaign.
batchId UUID The batch.
sequence integer The batch's number in the campaign.
kind string FIRST_ISSUE, or REISSUE for new links.
reissueFilter string or null For a re-issue: EXPIRED, NO_RESPONSE or FAILED_DELIVERY.
linkCount integer Links in the batch.
issuedOn time When the batch was finished.
expiresOn time When its links stop working.
availableUntil time Until when its links can be read.
merkleRoot string The root over the batch's links. See How notice campaigns are proven.
download object method, path and scope of the call that reads the links.
test boolean true for a test campaign.

Example

JSON
{
  "id": "6a0e3f2b-9c71-4d58-b2e4-0f8d1a7c5e39",
  "type": "campaign.batch_issued",
  "createdOn": "2026-10-03T06:30:41.208Z",
  "projectId": "c2a6f0de-51b3-4f0a-9d7e-8b1f3a6c4e90",
  "test": false,
  "data": {
    "campaignId": "9d1f2a6e-4b3c-4e8f-a1d2-7c5b0e9f3a41",
    "campaignName": "Notice to existing savings customers, 2027",
    "batchId": "c2e8b4d0-1f7a-4a39-9e65-3b0d8c2f6a17",
    "sequence": 2,
    "kind": "REISSUE",
    "reissueFilter": "EXPIRED",
    "linkCount": 48211,
    "issuedOn": "2026-10-03T06:30:40.977Z",
    "expiresOn": "2027-01-01T06:30:12.004Z",
    "availableUntil": "2026-10-10T06:30:40.977Z",
    "merkleRoot": "4be1c09a…",
    "download": {
      "method": "GET",
      "path": "/sdk/v1/campaigns/9d1f…/batches/c2e8…/links",
      "scope": "campaigns:links"
    },
    "test": false
  }
}

campaign.withdrawn#

Sent when

A person withdrew on a notice link and the withdrawal was applied to their records, once for each withdrawal. Stop processing their data. Each record withdrawn also sends its own consent.withdrawn.

Payload

Field in data Type Description
campaignId, campaignName string The campaign.
recipientId UUID The person in the campaign.
linkId UUID The link they used.
subject.type string The type of their first identifier.
subject.fingerprint string or null Their subject fingerprint under your project's key.
subject.reference string or null The reference you gave their row.
basis string PRE_COMMENCEMENT or NO_CONSENT_ON_RECORD, as you stated it.
withdrawnOn time When the person chose Withdraw my consent.
withdrawnConsentIds array The records withdrawn. Empty when no record was held under their first identifier.
test boolean true for a test campaign.

Example

JSON
{
  "id": "e5b0c7d2-3a19-4f86-8d4e-1c7a9b2f0e63",
  "type": "campaign.withdrawn",
  "createdOn": "2027-02-14T09:12:45.031Z",
  "projectId": "c2a6f0de-51b3-4f0a-9d7e-8b1f3a6c4e90",
  "test": false,
  "data": {
    "campaignId": "9d1f2a6e-4b3c-4e8f-a1d2-7c5b0e9f3a41",
    "campaignName": "Notice to existing savings customers, 2027",
    "recipientId": "1f4c8e2a-7b3d-4a96-b0e5-9d2c6a8f1b74",
    "linkId": "5b7e9c21-0d4a-4f6b-8e3c-2a1f9d7b6c50",
    "subject": {
      "type": "USER_ID",
      "fingerprint": "a71c…",
      "reference": "CRM-104233"
    },
    "basis": "PRE_COMMENCEMENT",
    "withdrawnOn": "2027-02-14T09:12:44.512Z",
    "withdrawnConsentIds": ["cns_3f1c9a7e2b8d4c6fa0e5d1b7c9f2a4e8"],
    "test": false
  }
}

campaign.anchored#

Sent when

A UTC day with notice answers or issued batches is anchored, once for each such day, after 00:30 UTC the next day. Keep each one: it is your copy of the day's signed root.

Payload

Field in data Type Description
statement.specification string piedap-campaign-anchor/1.0.
statement.projectId UUID The project.
statement.periodStart, statement.periodEnd time The UTC day covered.
statement.leafCount integer Answers and batches in the day.
statement.merkleRoot string The root over them.
statement.previousAnchorHash string The hash of the project's previous campaign anchor, so the days form a chain.
anchorHash string The SHA-256 of the statement as canonical JSON.
signature string The signature over the statement.
algorithm string Ed25519.
signingKeyId string The key, matched against kid in GET /keys.

Example

JSON
{
  "id": "7c2d9e40-5f1b-4a83-9e6c-2b8d0f4a1c95",
  "type": "campaign.anchored",
  "createdOn": "2027-02-15T00:30:02.114Z",
  "projectId": "c2a6f0de-51b3-4f0a-9d7e-8b1f3a6c4e90",
  "test": false,
  "data": {
    "statement": {
      "specification": "piedap-campaign-anchor/1.0",
      "projectId": "c2a6f0de-51b3-4f0a-9d7e-8b1f3a6c4e90",
      "periodStart": "2027-02-14T00:00:00.000Z",
      "periodEnd": "2027-02-15T00:00:00.000Z",
      "leafCount": 612,
      "merkleRoot": "d93a6f1e…",
      "previousAnchorHash": "0b7e24c5…"
    },
    "anchorHash": "8f2c41ad…",
    "signature": "kq3n…",
    "algorithm": "Ed25519",
    "signingKeyId": "…"
  }
}

↑↓ to move, Enter to open