Subscriptions and preferences
Record explicit subscription requests, distinguish newsroom and account-wide opt-outs, and handle feedback separately.
A subscription records an email address's preference for newsroom updates. It is separate from a CRM contact, a press-contact card, or a campaign recipient. Adding someone to any of those does not establish a subscription.
For requests to export, correct, or remove contact data, use Handle privacy requests. A subscription preference change does not complete a data request.
There are three meaningful states: explicitly subscribed, explicitly unsubscribed, and no recorded preference. “Not unsubscribed” is not the same as “subscribed.” Keep that distinction when building forms or synchronizing preferences.
Choose the credential and boundary
Load your credential into PREZLY_API_TOKEN. The variable can hold a personal token or integration key; eligibility depends on the endpoint.
| Operation | Personal token access |
|---|---|
| Read newsroom subscribers | sites:read and contacts:read |
| Subscribe an address | sites:write and contacts:write |
| Unsubscribe from one newsroom or update its feedback | sites:write |
| Account-wide unsubscribe or feedback | Integration key required; these endpoints are unavailable to personal tokens. |
The credential's owner must also have access to the newsroom and corresponding data. Keep credentials and subscriber reads on your server. For a public form, use your own narrowly scoped handler: fix the destination newsroom, validate/allowlist fields and locales, require a deliberate visitor action, and control abuse. Forward the intended preference change rather than arbitrary paths or a browser-supplied CRM contact object.
Return only the confirmation your form needs. The API response can contain names and related CRM references; do not forward it wholesale to a public client. The source page url is context, not proof that an address was verified. The API records the IP/user agent seen by Prezly; sending an ip_address value in JSON does not override the controller's captured value.
Record a fresh subscription request
First check the destination and configured locale. Use POST /newsrooms/{newsroom_id}/subscribe for new integrations.
Subscribe reactivates the selected newsroom subscription and clears an account-wide opt-out for that address. Call it only for a fresh, explicit request to receive updates. Do not use it to repair a contact import or silently reverse an earlier preference. Other newsrooms' cancelled subscriptions are not automatically reactivated.
This endpoint applies the preference directly. A 200 response is not proof of email ownership or a completed confirmation-email flow. If your form requires email confirmation, complete that step before making this request.
Save this as subscription-request.json, replacing the illustrative address, locale, and source page with the intended values:
{
"email_address": "reader@example.test",
"locale": "en",
"url": "https://newsroom.example.test/en/subscribe"
}Replace YOUR_NEWSROOM_UUID:
curl --fail-with-body --silent --show-error --request POST 'https://api.prezly.com/v2/newsrooms/YOUR_NEWSROOM_UUID/subscribe' \
--header "Authorization: Bearer $PREZLY_API_TOKEN" \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--data-binary @subscription-request.jsonA successful request returns 200 OK with subscription. Save its UUID id and returned email_address in your server-side workflow. This identity response does not contain active/inactive status flags.
Subscribing can create a CRM contact depending on the newsroom's configuration. Supplying the optional contact payload explicitly creates a contact and requires additional contact-management permission; it is not a general upsert. Keep that separate from a public email-only form.
The deprecated POST /newsrooms/{newsroom_id}/subscriptions behaves differently: it returns 201 with an empty body, including when it catches an already-subscribed conflict. Do not parse that response as JSON or mistake its success semantics for the current endpoint.
Subscribe → · Legacy endpoint →
Inspect the resulting newsroom preference
From your server, list matching newsroom subscriptions:
curl --fail-with-body --silent --show-error --get 'https://api.prezly.com/v2/newsrooms/YOUR_NEWSROOM_UUID/subscriptions' \
--header "Authorization: Bearer $PREZLY_API_TOKEN" \
--header 'Accept: application/json' \
--data-urlencode 'search=reader@example.test' \
--data-urlencode 'limit=5' \
--data-urlencode 'offset=0'The response contains subscriptions, pagination, and sort. Each entry has subscriber, is_active, created_at, and culture; subscriber.id is the subscription UUID. Match the actual returned email address, rather than treating keyword search as an exact identity lookup, and follow pagination when needed.
is_active takes account-wide opt-outs into account. An absent entry does not establish consent or prove that no account-wide opt-out exists. Do not expose the subscriber list to your public website.
Subscriber names may be null; do not require them when reconciling a subscription.
Unsubscribe from one newsroom
When the request is to stop updates from this newsroom only, replace the address and locale below:
curl --fail-with-body --silent --show-error --request POST 'https://api.prezly.com/v2/newsrooms/YOUR_NEWSROOM_UUID/unsubscribe' \
--header "Authorization: Bearer $PREZLY_API_TOKEN" \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--data '{"email_address":"reader@example.test","locale":"en"}'The response is 200 OK with subscription. Store its id if you will collect feedback afterward. This changes the newsroom preference; it does not delete the contact or remove the address from every newsroom in the account.
Existing email unsubscribe flows can identify a recipient through tracking data. For a custom form, use the explicit address associated with the verified request; do not invent or reuse another recipient's tracking identifier.
Collect feedback without changing the preference again
After a successful newsroom unsubscribe, replace YOUR_SUBSCRIPTION_UUID with the returned subscription.id:
curl --fail-with-body --silent --show-error --request PATCH 'https://api.prezly.com/v2/newsrooms/YOUR_NEWSROOM_UUID/unsubscribe/YOUR_SUBSCRIPTION_UUID' \
--header "Authorization: Bearer $PREZLY_API_TOKEN" \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--data '{"reason":"unwanted","comment":"I no longer cover this topic.","locale":"en"}'This updates the existing unsubscribe event's details and returns subscription. It does not resubscribe the address. It requires the address to be unsubscribed from the relevant scope already. The identifier is a subscription UUID, not a CRM contact ID or a campaign recipient ID.
The supported reasons are unknown, unwanted, spam, never_signed_up, and other. Keep the preference action and optional feedback separate so a failed feedback request does not imply the unsubscribe itself failed.
Update Newsroom Unsubscribe Details →
Use account-wide opt-out only when requested
For a request to stop all communications from this Prezly account, use an integration key:
curl --fail-with-body --silent --show-error --request POST 'https://api.prezly.com/v2/unsubscribe' \
--header "Authorization: Bearer $PREZLY_API_TOKEN" \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--data '{"email_address":"reader@example.test","locale":"en"}'This cancels the account's newsroom subscriptions for that address and sets the account-wide opt-out. It does not affect unrelated Prezly accounts. Use this broader action only for that broader choice.
Feedback for that global event uses the global path and the returned subscription UUID:
curl --fail-with-body --silent --show-error --request PATCH 'https://api.prezly.com/v2/unsubscribe/YOUR_SUBSCRIPTION_UUID' \
--header "Authorization: Bearer $PREZLY_API_TOKEN" \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--data '{"reason":"other","comment":"Please stop all account communications.","locale":"en"}'Both return subscription. Global unsubscribe and global feedback are unavailable to personal tokens; adding sites:write does not unlock them.
Global Unsubscribe → · Global Feedback →
Reconcile conflicts and downstream state
The examples represent distinct visitor choices; do not execute them sequentially as a preference-sync routine. Repeated subscribe/unsubscribe requests can return 409 for an already-recorded state. Inspect the reported conflict and current state instead of repeatedly toggling the preference to make a retry succeed.
For a timeout or lost response, reconcile the address, newsroom, and intended action before submitting another change. Permission/validation failures should follow Handling errors. A feedback failure belongs to the feedback step, not an automatic retry of the preference change.
CRM status summaries can update asynchronously. Recheck recipient eligibility and warnings in the campaign before sending; subscription success is neither an email-delivery receipt nor a guarantee that a particular campaign will send. Reversing a prior opt-out and recording a fresh opt-in are different actions—use the appropriate Prezly workflow rather than treating Subscribe as a reset button.