Authentication
How a request carries a publishable or a secret key, which endpoints each key may call, the scopes a secret key holds and what a refused key returns.
A request to https://console.dpconsent.com/consent/sdk/v1 carries a publishable key or a secret key. To decide which one a call needs, read Keys and where to use them.
Keys#
| Key | Looks like | How it is sent | Where it works |
|---|---|---|---|
| Publishable | pk_ and 32 letters and digits |
X-Piedap-Key header, or key in the query |
Browsers and apps, from the origins and app ids listed on the key |
| Secret | sk_ and 40 letters and digits |
Authorization: Bearer header |
Your servers only |
curl "https://console.dpconsent.com/consent/sdk/v1/form?country=IN" \
-H "X-Piedap-Key: $PIEDAP_PUBLISHABLE_KEY"curl "https://console.dpconsent.com/consent/sdk/v1/form?country=IN" \
-H "Authorization: Bearer $PIEDAP_SECRET_KEY"In the examples, PIEDAP_PUBLISHABLE_KEY holds your pk_… key and PIEDAP_SECRET_KEY holds your sk_… key.
- A request with an
Authorization: Bearerheader is always treated as a secret-key request. - The identity secret,
idv_…, is never sent. Your server uses it to compute proofs; see Signed-in visitors. - To create a key, see Create a key.
Endpoints by key and scope#
| Endpoint | Publishable key | Scope a secret key needs |
|---|---|---|
GET /form |
Yes | None |
POST /consent |
Yes. An email address, phone number or user id needs an identity proof | consent:write |
GET /consent/{consentId} |
Yes, without metadata |
consent:read |
PATCH /consent/{consentId} |
Yes | consent:write |
POST /consent/{consentId}/withdraw |
Yes | consent:write |
GET /consent/{consentId}/verify |
Yes | consent:read |
POST /email-consent |
No: 403 EMAIL_CONSENT_SERVER_ONLY |
consent:write |
POST /activity |
No: 401 |
consent:write |
POST /pages/consent-portal-links |
No: 401 |
consent:write |
POST /pages/unsubscribe-links |
No: 401 |
None |
POST /subjects/find |
No: 403 SCOPE_REQUIRED |
subjects:read |
POST /subjects/export |
No: 403 SCOPE_REQUIRED |
subjects:export |
POST /subjects/withdraw |
No: 403 SCOPE_REQUIRED |
subjects:withdraw |
POST /subjects/erase |
No: 403 SCOPE_REQUIRED |
subjects:erase |
POST /subjects/link |
No: 403 SCOPE_REQUIRED |
subjects:link |
POST /requests/link |
No: 403 SCOPE_REQUIRED |
requests:write |
POST /consent/check |
No: 403 SCOPE_REQUIRED |
consent:check |
GET /campaigns/{campaignId}/batches/{batchId}/links |
No: 403 SCOPE_REQUIRED |
campaigns:links |
GET /processor-tasks |
No: 403 SCOPE_REQUIRED |
processors:read |
POST /processor-tasks/acknowledge |
No: 403 SCOPE_REQUIRED |
processors:write |
GET /audit-log |
No: 403 SCOPE_REQUIRED |
audit:read, with a live key |
These need no key: GET /keys, POST /receipts/verify, GET and POST /email-consent/verify, the notice page at /n/{token}, and the runtime files.
Scopes#
| Scope | Held by | Allows |
|---|---|---|
consent:read |
Every secret key | Read one consent record and its receipt |
consent:write |
Every secret key | Record, change and withdraw a record; start an email opt-in; report activity; create consent portal links |
subjects:read |
Keys you grant it to | Find a person's records by your identifier |
subjects:export |
Keys you grant it to | Export a person's records for an access request |
subjects:withdraw |
Keys you grant it to | Withdraw everything a person agreed to |
subjects:erase |
Keys you grant it to | Erase a person |
subjects:link |
Keys you grant it to | Link further identifiers to a person's records |
requests:write |
Keys you grant it to | Link a rights request to your identifier |
consent:check |
Keys you grant it to | Check whether a person allows a purpose |
campaigns:links |
Keys you grant it to | Read notice campaign links, for your sender. Anyone holding a link can answer for that person. |
processors:read |
Keys you grant it to | Read processor tasks |
processors:write |
Keys you grant it to | Record what processors reported |
audit:read |
Keys you grant it to | Read the project's audit log, for your SIEM |
Grant a scope under Scopes on the key in the console. No key holds any of these unless you grant it. A publishable key never holds the subjects:, requests:, consent:check, campaigns:, processors: or audit: scopes.
Every secret key also holds consent:read and consent:write. A key you give only to a consent check or a SIEM can therefore still read and write records. Keep such keys on the servers that need them, and revoke any key you suspect was copied.
Publishable keys and origins#
A publishable key is checked against the Origin header the browser sends.
| Key | Answers |
|---|---|
| Live | Only the origins and app ids on its list. With no entries, it cannot be used from a browser or an app. |
| Test | The entries on its list, plus localhost, 127.0.0.1 and [::1] on any port, apps, and clients that send no Origin, such as cURL. |
| List entry | Matches |
|---|---|
https://www.example.in |
That exact scheme, host and port |
https://*.example.in |
Every subdomain, but not https://example.in itself |
app:in.example.shop |
A mobile app that sends the header X-Piedap-App: in.example.shop |
No key answers every origin: an entry of * is ignored.
A key tied to one property serves only that property's forms and records.
Test and live keys#
Every new key is a test key. It becomes live when the platform team approves it, and the key string stays the same. See Request to go live.
| Behaviour | Test key | Live key |
|---|---|---|
| Records written | Marked "test": true and deleted 30 days after their last change |
Marked "test": false |
| Records reached by updates, withdrawals and the calls on a person | Test records only | Live records only |
| Default request budget | 600 a minute | 6,000 a minute |
Refused requests#
| Status | Code | When |
|---|---|---|
401 |
None. The message is Unauthorized |
The key is missing, wrong, revoked or turned off. A publishable key was used from an origin or app that is not on its list. A publishable key called an endpoint that takes only a secret key. |
403 |
SECRET_KEY_IN_BROWSER |
A secret key arrived with an Origin or Sec-Fetch-Site header. |
403 |
SCOPE_REQUIRED |
The secret key lacks the scope, or a publishable key made a call on a person. |
403 |
PROPERTY_NOT_FOR_KEY |
The key is tied to one property and the request named another, or the key's property is no longer active. |
A 401 does not say which of its causes applied.
Secret keys stay on your server
A secret key seen with a browser header is refused and marked Exposed in the console. The mark does not stop the key. Revoke it and create a new one.
The refusal, with the message shortened:
{
"statusCode": 403,
"code": "SECRET_KEY_IN_BROWSER",
"message": [
"Secret keys work only from your server. This key has been flagged…"
],
"error": "FORBIDDEN",
"timestamp": "2026-09-28T06:41:12.345Z",
"path": "/sdk/v1/consent",
"requestId": "3662a1fd-5721-42cb-b7c7-994fa655ab37"
}The cross-origin policy of /sdk does not allow the Authorization header, so a browser cannot complete such a call. The full list of codes is in Errors.