Webhooks
Events
Every event Pactbase sends, and what each one carries.
| Event | When | data |
|---|---|---|
consent.updated | A known person (email) gives, changes or refuses consent: a website form, Manage my data, a re-consent campaign link, or your own API call | The consent event below. From a campaign it also carries campaign: { id, name, external_id }, where external_id is your id for the person from the imported list |
consent.withdrawn | Also sent when such a decision refuses a purpose the person had granted | The consent event. summary.withdrawn lists those purposes |
cookie_consent.updated | An anonymous visitor decides in the cookie banner. There are many of these, so tick it only if you need them | The consent event. data_principal.type is anonymous |
data_request.created | A verified person opens a rights request (access, correction, erasure, nomination) | id, ref_no, sla_due_at, type, requester_email, details |
data_request.status_changed | A rights request moves to in progress or resolved | id, ref_no, type, requester_email, from_status, status. For a resolved erasure, erasure.deletion_run_id, and the email is then null because it was erased |
grievance.created | A verified person raises a grievance | id, ref_no, sla_due_at, category, requester_email, details |
grievance.status_changed | A grievance moves to in progress or resolved | id, ref_no, requester_email, from_status, status |
retention.deletion_due | A retention schedule's deletion is due (checked daily, once per due date) | schedule_id, name, data_category, system, rule, period, action, due_at, owner, log_deletion (how to log it back with Log a deletion) |
webhook.test | You click Send test event | message, endpoint_id |
Parental consent decisions and consent expiry are not sent yet.
The consent event
{
"consent_id": "0b6c2f9e-...",
"recorded_at": "2026-10-12T09:30:12.498Z",
"data_principal": { "id": "asha@example.in", "type": "identified" },
"source": "form",
"collection_point": { "id": "be88e61c-...", "slug": "consultation-form", "name": "Consultation form" },
"website": "shop.example.in",
"notice_version": "3",
"purposes": [
{
"id": "36ff83e5-...",
"name": "Book consultation",
"type": "data",
"category": null,
"lawful_basis": "consent",
"status": "withdrawn",
"previous_status": "granted",
"changed": true
}
],
"summary": {
"granted": [],
"withdrawn": [{ "id": "36ff83e5-...", "name": "Book consultation" }],
"denied": []
}
}| Field | Meaning |
|---|---|
consent_id | The Consent ID on the person's receipt and in the ledger. Shared by every purpose row of this decision |
data_principal | id (the email, or anon_... for the cookie banner) and type (identified or anonymous). Hashed endpoints get the SHA-256 and id_format: "sha256" |
source | banner, preference_center, form, api, gpc or email_link |
collection_point | The form, for form consent. null otherwise |
purposes[].status | granted. withdrawn (was granted, now refused: stop using the data for it). denied (refused, and was not granted before). notice_shown (legitimate use: informed, nothing agreed) |
purposes[].previous_status | The choice before this decision: granted, not_granted, or null if never asked before |
purposes[].changed | Whether this decision moved the purpose |
summary | The purposes by status, with names, for receivers that only need "who granted or withdrew what" |
Every id comes with its name. The guide on Settings, then Webhooks, also lists every purpose and form with its id and a Copy button.