The endpoint
GET http(s)://api-esp.piano.io/tracker/securesub/email/<email>/ml/<mailing_list_id>?api_key=<api_key>
|
Parameter |
Required |
Description |
|---|---|---|
|
|
Yes |
The reader's email address (URL-encoded if it contains special characters). |
|
|
Yes |
The ID of the mailing list to query. |
|
|
Yes |
Publisher API key. Available in the ESP dashboard under Setup > Integrations. Separate keys exist for sandbox and production — contact Piano Support to provision a key for a new environment if you don't already have one. |
The base URL changes by region:
-
US production:
https://api-esp.piano.io -
EU production:
https://api-esp-eu.piano.io -
Asia-Pacific production:
https://api-esp-ap.piano.io -
Sandbox:
https://sandbox-api-esp.piano.io
Use the regional base URL that matches the dashboard your account lives in.
What the HTTP status code means
The endpoint returns its answer through the HTTP status code:
|
Code |
Meaning |
|---|---|
|
|
The user is currently subscribed to the mailing list. |
|
|
The user is not currently subscribed. The response body provides a more specific reason (see below). |
|
|
Server error. Check your HTTP logs and contact Piano Support if it persists. |
A 404 is always one of the following sub-states. Read the response body to distinguish them:
|
Body suffix |
Meaning |
|---|---|
|
(no |
The user was never subscribed. |
|
|
The user was deactivated via the API, the dashboard, or by clicking unsubscribe in an email. |
|
|
A hard bounce occurred (the email address is invalid). |
|
|
The user marked an email from this campaign as spam. |
|
|
The email address has been blacklisted by ESP (manually or by a system rule). |
Listing every mailing list a user is on
There is no single public API that returns all the mailing lists a given user belongs to. The workaround is to iterate:
-
Fetch the publisher's mailing lists with
GET http(s)://api-esp.piano.io/publisher/pub//sq?api_key=. -
For each mailing list ID, call the subscription status endpoint above with the user's email.
-
Treat each
200response as "subscribed" and each404as "not subscribed" (optionally inspecting the body for the reason).
This pattern is the supported way to build a "user's subscriptions" view today.
Avoiding the opt-in pop-up for already-subscribed users
A common use of the status query is to suppress a newsletter sign-up dialog for users who are already on the list. The pattern:
-
When the page loads (or before the pop-up would fire), call the status endpoint for the user's email and the relevant
mailing_list_id. -
If the response is
200, do not show the dialog. -
If the response is
404, show the dialog.
If you're using Composer, you can also configure a sign-up experience to show only once per session through the Composer settings. That handles the common case without requiring an API call on every page view.
Synchronizing subscription status with your own database
When the ESP list and your own user database diverge, the most frequent cause is one of the 404-with-reason states above. Plan for them when designing a sync:
-
Status
0(deactivated). The user opted out somewhere — your sync should treat this as unsubscribed and stop attempting to re-add them automatically. Resubscribing a deactivated user is allowed (they're not blacklisted), but should be triggered by an explicit user action, not by reconciliation logic. -
Status
-2(hard bounce). The email address is invalid. Re-adding it will fail or immediately bounce again. Surface this to the user so they can correct the address. -
Status
-3(spam complaint). ESP will not send to this address again. Don't re-add programmatically. -
Status
-9(blacklisted). The address is blocked at the ESP level. Contact Piano Support if you believe this is in error.
When designing your registration flow, consider returning detailed status and rejection reasons via your own API when a registration attempt is refused so you can diagnose discrepancies — for example, distinguishing "user is on the list but inactive" from "user was never added."
Reconciliation is best done in batches: iterate through your user database, query each user against the relevant mailing lists, and reconcile the result. Run this on a schedule (for example, nightly) and log discrepancies for review.
Other reasons ESP state and database state can drift
Beyond the 404 reason codes, three operational factors cause counts to disagree:
-
Manual unsubscribes and spam reports. These deactivate the user (status
0or-3) but leave them on the list. The list count includes them; the active-subscriber count does not. -
Re-subscription not handled. If a user unsubscribes and later resubscribes through a different path (a form, an import), the resubscribe may not have been wired into your downstream sync.
-
Legacy users. Users who joined before your sync was in place may exist in one system but not the other. A one-off reconciliation closes the gap.
Removing a user from all lists at once
When you need to unsubscribe a user from every mailing list — for example, in response to a "delete my data" request or a global opt-out — use the unsubscribe endpoint:
DELETE http(s)://api-esp.piano.io/tracker/securesub?api_key=<api_key>
Content-Type: application/json
{ "email": "<reader_email>", "mlids": [ idX, idY, ... ] }
Pass every mailing list ID you want the user removed from. For complete removal of personal data in line with GDPR, use the dedicated GDPR deletion endpoint described in the ESP Technical Integration reference.
API key reminders
-
Sandbox and production each have their own API key. Confirm you're using the right key for the environment you're calling.
-
Keys are visible in the ESP dashboard under Setup → Integrations. If you don't see one, your account may not have a key provisioned for that environment — contact Piano Support.
-
Treat the API key as a secret. Don't expose it in client-side code; all status queries should happen server-side.