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.
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
{
"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
{
"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
{
"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": "…"
}
}