What the API can do
Piano ESP exposes a third-party HTTPS API that lets external systems interact with the ESP platform without going through the dashboard. The API covers:
-
Subscriber management - add, remove, and check the subscription status of an email on a given mailing list.
-
Mailing list and campaign management - create, update, and list mailing lists and campaigns and their relationships.
-
Email campaign customization - update email templates, RSS feeds, mailing-list associations, and sending schedules for an existing campaign.
-
Analytics - query campaign-level and mailing-list-level statistics (deliverability, open/click, by device, by client, by location).
-
Custom user merge fields - set and delete custom data values per subscriber.
-
Webhooks - receive real-time notifications when subscribers are added or removed.
-
Server-side tracking - submit page visits and link visitor IDs to subscriber email addresses.
The API also has companion client-side SDK methods for embedding ESP behavior inside a webpage (visitor impersonation, programmatic subscription, viewport-based widget tracking).
What the API cannot do
Two limitations come up frequently and are worth knowing before you scope an integration:
-
No on-demand campaign sending. The API does not let you compose an email externally and trigger an immediate send to a chosen audience. Campaigns dispatch based on their configured triggers (scheduled sends, RSS triggers, etc.). Use the API to manage content, lists, and templates - then let Piano ESP send according to the campaign's own schedule.
-
No full mailing-list export endpoint. There is no public endpoint that returns every subscriber for a mailing list. Use the "Download mailing list" button in the ESP dashboard for full exports. The campaign/mailing-list listing endpoints return list metadata (IDs, names, status, associations), not per-user rows.
Environments and base URLs
ESP runs two environments, each with regional production hosts:
|
Environment |
Base URL |
|---|---|
|
Production (Americas) |
|
|
Production (Europe) |
|
|
Production (Asia-Pacific) |
|
|
Sandbox |
|
Use the base URL that matches your dashboard region. Examples throughout the reference docs use the Americas host - if your account lives in another region, substitute the matching host.
Sandbox is available to existing clients and is meant for integration testing. It does not run scheduled background jobs: subscription renewals and status updates do not occur automatically, subscriptions remain active past their expiration date, and webhooks tied to expiration events (such as access_revoked.subscription_expired) do not fire. Anything that depends on time-based status transitions must be tested in production.
API keys
Every request authenticates with an ESP-specific API key, which is different from the general Piano API Token used by Composer, Management + Billing, or Identity Management APIs. Using a general Piano API Token against ESP endpoints results in errors like CPAKM: Bad Request (0).
To find your ESP API key:
-
In the ESP dashboard, open Setup > Integrations.
-
The API key is shown at the top right of the page. In some UIs, click the (i) information button to reveal it.
-
In sandbox, navigate to
https://sandbox-esp.piano.io/#/setup/integrations?siteId=.
If no key is visible under Setup > Integrations, contact Piano Support to have one created.
Treat the key like a password. Do not embed it in client-side code or commit it to public repositories.
ESP ID and other identifiers
Calls that operate on a publisher require an ESP ID (also called publisher_id or site_id). You can find it in the ESP management interface next to the site name. The same value appears in the integration code snippet emitted by the dashboard.
Mailing lists are identified by mailing list IDs (mlids or sqIds, depending on the endpoint). Campaigns are identified by campaign IDs. Both are listed in the dashboard and returned by the campaign/mailing-list listing endpoints.
Subscriber management endpoints (quick reference)
These are the most common endpoints you will call. See the ESP Technical Integration reference for the full schema, headers, and error codes.
|
Operation |
HTTP method |
Endpoint |
|---|---|---|
|
Subscribe an email |
POST |
|
|
Unsubscribe an email |
DELETE |
|
|
Check subscription status |
GET |
|
|
List active subscribers for mailing lists |
POST |
|
|
List campaigns for a site |
GET |
|
|
List mailing lists for a site |
GET |
|
|
Mine Users export (create) |
POST |
|
|
Mine Users export (status / download) |
GET |
|
Subscribe / unsubscribe requests
POST and DELETE against /tracker/securesub accept either form-encoded or JSON bodies:
# Form-encoded (Content-Type: application/x-www-form-urlencoded)
curl -X POST 'https://api-esp.piano.io/tracker/securesub?api_key=<key>' \
-d 'email=user@example.com' \
-d 'mlids=5628,5629'
# JSON (Content-Type: application/json)
curl -X POST 'https://api-esp.piano.io/tracker/securesub?api_key=<key>' \
-H 'Content-Type: application/json' \
-d '{"email":"user@example.com","mlids":[5628,5629]}'
mlids must be a comma-separated string for form-encoded requests, and a JSON array for JSON requests. The email must be in the body, not the URL. Sending mailing list IDs in the wrong format (for example, an HTTP-encoded PHP array from a Guzzle client) results in a bad-request error.
Listing active subscribers
curl -X POST --header 'content-type: application/json' \
'https://api-esp-eu.piano.io/publisher/pub/{ESP_ID}/sq/subscribers?api_key=<api_key>' \
-d '{"sqIds":[<list_id_1>,<list_id_2>]}'
If you get a 401 here, the most common cause is a missing sqIds parameter in the body or an invalid API key. A 403 usually means an incorrect API URL or insufficient account permissions.
Integration patterns
There are two fundamental ways to drive ESP subscriptions programmatically. Most real-world integrations combine them; pick the variant that matches where the subscription event originates.
Variant 1 - Direct API integration (universal)
Your back-office system, server-side opt-in form, CRM, or any process you control calls the ESP API directly to subscribe or unsubscribe users. This pattern is universal - it works server-side or client-side, with custom opt-in forms or fully automated flows. It is the right choice when you want a private subscription pipeline that does not depend on the ESP opt-in widget rendered on your site.
Use the POST /tracker/securesub and DELETE /tracker/securesub endpoints from the quick reference above. Combine with GET /tracker/securesub/email//ml/ to verify status afterward.
Variant 2 - Client-side notification from a webpage
You want to notify ESP about new subscribers from a webpage without using the ESP opt-in form. This pattern is appropriate when the subscription event happens on-page and you already have the user's email in JavaScript. The Piano ESP SDK provides window.PianoESP.handleUserDataPromise({ email, squads: [...] }) for exactly this purpose:
window.PianoESP &&
"function" == typeof window.PianoESP.handleUserDataPromise &&
window.PianoESP.handleUserDataPromise({
email: "user@example.com",
squads: [mailing_list_ID0, mailing_list_ID1]
});
This is also the pattern to use when running subscription logic from a JavaScript snippet inside a Composer experience.
ESP + Identity Management integration
Identity Management can manage the subscriber list on your behalf so subscriptions stay in sync with registrations. ESP subscriptions and Identity Management registrations are separate by default - you enable the link explicitly by hooking ESP API calls into your Identity Management registration / login / preferences handlers, or by exposing a "Manage Newsletters" tab inside the user's account.
Mine Users export
Use Users > Mine Users in the dashboard to define user-property-based criteria and export the matching subscriber set. The exports flow through the /publisher/export/* endpoints listed above.
Webhooks
ESP can notify your endpoints when subscribers are added (user_added) or removed (user_removed). Webhook endpoints are HTTPS URLs you register with Piano (contact your Account Manager or support@piano.io).
Some operational guidance for webhook integrations:
-
Confirm the ESP fires the events you expect for both add and remove. If a webhook only triggers on one side, that is usually a configuration issue worth raising with support.
-
Update any custom fields you sync downstream on every webhook event (for example, set a "subscribed" custom field to
truewhenuser_addedfires). -
If the ESP imposes API rate limits, exceeding them can prevent webhook delivery; coordinate with support if you need a temporary or permanent ceiling raise.
-
Test with disposable accounts and exercise both subscribe and unsubscribe flows before going live.
-
Periodically run a full sync to reconcile state if you ever suspect drift.
A webhook endpoint that stops returning HTTP 200 for an extended period will be deactivated automatically. See the troubleshooting article on newsletter deactivation for the exact safeguard thresholds and how to recover.
Where to go next
-
Custom preferences page - the FAQ "How to create a custom page to manage ESP newsletter preferences?" shows how to build a self-service preferences UI on top of the listing and subscribe/unsubscribe endpoints.
-
ESP Technical Integration reference - the canonical reference, with full schemas for every endpoint, including custom user merge fields, GDPR data deletion, campaign and push statistics, and the client-side SDK API.
-
Public API documentation portal -
https://docs.piano.io/api/andhttps://docs.piano.io/track/esp/host the live reference. -
Rate limits and troubleshooting - see the API troubleshooting article for HTTP 429 handling,
CPAKMerrors, Cloudflare blocks, and other common issues.