Consent Docs

Email consent

The endpoints that start an email double opt-in and confirm it from the link, with parameters, examples, responses and errors.

Reference3 min readFor developers calling the REST API

These endpoints start a double opt-in for an email address and confirm it. Paths are relative to https://console.dpconsent.com/consent/sdk/v1. The whole flow is in Email double opt-in.

Endpoints#

POST /email-consent#

Creates a PENDING record for an email address and returns the confirmation link that your server emails to the person.

Key Scope Idempotency-Key Webhook sent
Secret consent:write Accepted consent.granted with the status PENDING for a new record, consent.updated for one still waiting

Parameters

Name Type Required Description
email email address, up to 255 Yes The address to confirm.
formKey string, up to 60 Yes The form the person answered.
decisions array, 1 or more Yes The answers to hold until the link is followed. Answer every purpose that is not always on.
locale string, up to 10 No The language the form was shown in.
returnUrl string, up to 500 No An absolute http or https address to send the person to after they confirm.

Request

cURLShell
curl -X POST https://console.dpconsent.com/consent/sdk/v1/email-consent \
  -H "Authorization: Bearer $PIEDAP_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: optin-7c41" \
  -d '{
    "email": "rohan.das@example.in",
    "formKey": "newsletter",
    "decisions": [{ "purposeKey": "newsletter", "granted": true }],
    "locale": "en",
    "returnUrl": "https://www.example.in/subscribed"
  }'
Node.jsJavaScript
const pending = await client.startEmailConsent({
  email: 'rohan.das@example.in',
  formKey: 'newsletter',
  decisions: [{ purposeKey: 'newsletter', granted: true }],
  locale: 'en',
  returnUrl: 'https://www.example.in/subscribed',
  idempotencyKey: 'optin-7c41',
});
Python
from piedap_consent import Decision

pending = client.start_email_consent(
    "rohan.das@example.in",
    "newsletter",
    [Decision("newsletter", True)],
    locale="en",
    return_url="https://www.example.in/subscribed",
    idempotency_key="optin-7c41",
)

Response

202:

JSON
{
  "consentId": "cns_91b7d0c4a2e64f0f8d3c5a7b9e1f2c60",
  "status": "PENDING",
  "verificationUrl":
    "https://console.dpconsent.com/consent/sdk/v1/email-consent/verify?token=…",
  "expiresOn": "2026-09-26T10:12:03.000Z"
}
Field Type Description
consentId string The record that waits for confirmation.
status string Always PENDING.
verificationUrl string The link to email to the person. The API sends no email.
expiresOn time When the link stops working, 48 hours after it was made.

Errors

Status Code When
403 EMAIL_CONSENT_SERVER_ONLY The call was made with a publishable key.
403 PROPERTY_NOT_FOR_KEY The key is tied to a property that is no longer active.
404 CONSENT_FORM_NOT_FOUND No form has this formKey.
400 AMBIGUOUS_FORM_KEY The formKey exists on more than one property. Use a key tied to one property.
400 INVALID_PURPOSE_DECISIONS A purpose was left unanswered, or an answer names a purpose the form does not offer.
400 INVALID_PARTNER_DECISIONS A partners answer names a partner the version does not list, or the version offers no choices per partner.
400 CONSENT_FORM_NOT_PUBLISHED The form has no published version.

Also the errors every call can return.

Shows the person a page with a Confirm button. Nothing changes yet, so a mail scanner that follows the link confirms nothing.

Key Scope Idempotency-Key Webhook sent
None. The token in the link is the credential None Ignored None

Parameters

Name Type Required Description
token string Yes The single-use token. It is already in verificationUrl.
returnUrl string No Present in verificationUrl when you sent returnUrl.
sig string No The signature that goes with returnUrl. Present in verificationUrl.

Request

The person opens verificationUrl in a browser:

https://console.dpconsent.com/consent/sdk/v1/email-consent/verify?token=…

Response

200 with an HTML page, in English.

Errors

None. A token that is not valid is refused when the person presses Confirm.

POST /email-consent/verify#

Confirms the consent. The Confirm button sends this request.

Key Scope Idempotency-Key Webhook sent
None. The token in the link is the credential None Ignored consent.updated

Parameters

Name Type Required Description
token string Yes Query parameter. The single-use token from the link.
returnUrl string No Query parameter. Where to send the person afterwards.
sig string No Query parameter. The signature issued with returnUrl. Without a valid one, returnUrl is not followed.

Request

Shell
curl -X POST \
  "https://console.dpconsent.com/consent/sdk/v1/email-consent/verify?token=$TOKEN" \
  -H "Accept: application/json"

Response

Case Answer
A signed returnUrl is present 303 redirect to it, with consent=confirmed or consent=failed added to the query
The request sends Accept: application/json 200 with the consent record. A link that was already used answers 200 with consentId and "alreadyConfirmed": true.
Otherwise 200 with a short thank you page, also when the link was already used

Errors

Status Code When
400 EMAIL_CONSENT_TOKEN_EXPIRED The link is older than 48 hours.
404 VERIFICATION_TOKEN_NOT_FOUND The token is not known.

Every code is explained in Errors.

↑↓ to move, Enter to open