Recording & reading consent
POST /v1/consent, batch, idempotency, and reading state & history.
Record
POST /v1/consent
Authorization: Bearer sk_live_…
Idempotency-Key: 4b0f…
{
"subject": "email:user@example.com",
"purpose": "marketing_email",
"state": "GRANTED",
"channel": "banner",
"locale": "en",
"pageUrl": "https://acme.com/signup"
}The subject can be an internal id, <type>:<value>, or an object { "identifiers": [{ "type", "value" }] } to create the subject if it does not exist. state can only be GRANTED, DENIED or WITHDRAWN.
201 response: { id, subjectId, subjectCreated, purpose, state, purposeVersion, collectedAt, receiptId }.
Batch
POST /v1/consent/batch with { "records": [ … ] } (max 100). Issues one receipt per subject covering all of that subject’s records in the batch.
Read the state
GET /v1/subjects/email:user@example.com/consent?purpose=marketing_email
→ { "subjectId": "…", "purposes": {
"marketing_email": { "state": "GRANTED", "purposeVersion": 3,
"needsReconsent": false, "latestPurposeVersion": 3 } } }Published purposes with no record for the subject appear with their defaultState. needsReconsent is true if the stored version lags a later version published as RECONSENT_REQUIRED, or if the record has expired.
History
GET /v1/subjects/{ref}/consent/history (sk_ only) returns up to 500 append-only rows, each with its proof and the supersedesId chain.