Importing users
CSV imports via the dashboard
The simplest way to import users is the mailing-list CSV uploader in the ESP dashboard.
-
Active subscribers are added through the Subscribers tab of the target mailing list.
-
Previously unsubscribed users should first be imported into the subscribers list and then moved to the unsubscribed list using the Unsubscribe tab. This preserves the suppression history correctly.
For large imports, follow this order to minimize processing time:
-
Import the users first.
-
Once the user import finishes, import the merge fields for those users in a second pass.
Doing users + merge fields together in a single import on a very large file is significantly slower and can stall the merge-field indexing step. If the import is unusually slow, double-check the CSV format and that every column maps to a valid field; for very large jobs, schedule them during off-peak hours and avoid running other heavy operations (deletions, manual edits) in parallel.
API-based imports
For ongoing or programmatic imports, use the ESP API directly:
-
Add subscribers via
HTTP POSTto/tracker/securesub?api_key=withemailandmlids(mailing-list IDs). -
Suppress / unsubscribe via
HTTP DELETEto the same endpoint.
Use only POST to add — accidentally sending a DELETE (for example, re-importing the same file with a "remove" option ticked, or re-using the same handler that also has a delete branch) will mark the contact as "unsubscribed via API" the moment they appear, which is a common and confusing failure mode.
Why does my import show users as "unsubscribed via API"?
If contacts appear as unsubscribed via API immediately after being imported, something downstream is sending a DELETE to /tracker/securesub for those addresses. Typical causes:
-
A CRM, automation script, or third-party tool is mirroring the same list and issuing deletions.
-
The same import file is being re-uploaded with a "remove" option selected.
-
A handler is reading the file and unintentionally treating updates as deletions.
To diagnose, export the mailing list CSV and look at the Status column. The value tells you why an address is inactive:
|
Status |
Meaning |
|---|---|
|
|
Active subscriber — will receive campaigns. |
|
|
Unsubscribed manually or via API. |
|
|
Hard bounce (invalid address). |
|
|
Marked the email as spam. |
|
|
Blacklisted by ESP. |
Only 1 status means active. For any other status, the contact will not receive campaigns until you re-activate them (see the resubscribe workflows for details).
To prevent recurrences:
-
Use only
POSTrequests for adds; do not invokeDELETEfrom import code paths. -
Verify Double Opt-In (DOI) mailing-list settings — DOI lists require an explicit confirmation, so a freshly imported contact remains pending until they click through.
-
After every import, spot-check the CSV to confirm contact statuses.
Removing users
ESP exposes three different "removal" operations, and they are not interchangeable. Choose based on what you actually need.
Unsubscribe (suppress) — keeps the record
HTTP DELETE to /tracker/securesub?api_key= with email and mlids unsubscribes the user from the listed mailing lists. The address remains in the list as inactive with status 0. Historical reporting data (delivery, open, click rates for past campaigns) is preserved.
This is the right call for the everyday case of "the user no longer wants emails" and for most API-driven workflows.
Hard delete from a mailing list — dashboard only
If you need to completely remove an email address from a mailing list — including the associated report data such as delivery and open-rate contributions — that operation is only available through the ESP dashboard. There is no API equivalent for fully wiping a single address out of a mailing list while leaving the rest of the list intact.
Be aware: dashboard-driven deletion also strips that user's contribution from aggregated reports, which can shift historical metrics.
GDPR erasure — full data deletion across the user's ESP footprint
For regulated erasure ("right to be forgotten") requests, use:
HTTP DELETE /userdata/gdpr/data/email/<email>/<PUB_ID>?api_key=<API_KEY>
This removes the user's data across all ESP-internal stores (subscriber records, behavioral data, indices) for the given publisher. The response confirms how many records were deleted from each underlying store.
Path / query parameters:
-
— the user's email address (URL-encoded if it contains special characters).
-
— the publisher (Site) ID, as shown in the ESP dashboard.
-
api_key— your ESP API key.
If your account-cancellation flow needs to wipe a user across the whole Piano stack, note that /publisher/gdpr/delete (with scope=ALL) removes the user from the main Piano user database but does not remove them from the ESP audience. You must call the ESP GDPR endpoint above as a separate step for a complete erasure.
For the ESP-side GDPR API to be enabled on a given Site, contact Piano Support. Implementations of "right to be forgotten" automation in the wider Piano stack vary by product (Piano DMP / Insight and Identity Management expose their own delete APIs); coordinate the full deletion across all relevant APIs to satisfy a single user request.
Speeding up large deletion jobs
Deletions in ESP run partly as background jobs that update mailing-list indices and suppression tables across multiple shards. Some inherent propagation time (in the range of a few minutes) cannot be avoided. If you are seeing deletions that are slower than expected, several factors help:
-
Batch via the API, don't loop in the dashboard. A single
DELETEto/tracker/securesubspawns one background job whether you target 1 address or many; deleting addresses one-by-one through the dashboard spawns many jobs and is markedly slower. The API payload pattern:DELETE https://api-esp.piano.io/tracker/securesub?api_key=<API_KEY> Content-Type: application/json { "email": "<email>", "mlids": [12345] }mlidsaccepts one or many list IDs. -
Schedule list maintenance during off-peak hours. Background jobs share compute with campaign sends and other tasks; late evening / early morning typically gives faster turnaround.
-
Avoid overlapping large jobs. Finish a CSV import before starting a manual deletion sweep, and vice versa.
-
Rule out front-end / browser issues. If only the dashboard feels slow, try an up-to-date browser, an incognito window without extensions, and a different network to rule out caching and local latency.
If propagation persists beyond five to seven minutes, contact Piano Support so the engineering team can check for queue-related causes.
Storing Double Opt-In email copies for compliance
Some jurisdictions require keeping a copy of the DOI confirmation email (with metadata such as send / open / click timestamps) for up to two years, particularly for non-registered users where no account record otherwise exists. Piano ESP does not expose a turn-key, public API for retrieving stored DOI message bodies, but the message-rendering and feedback endpoints can be combined to capture the content of confirmed DOI sends as they happen. If you have a regulatory requirement to retain DOI email copies for a defined retention window, contact your Piano account manager to scope the implementation; the data your provider holds, the retention guarantee, and the access pattern need to be agreed up front rather than retrofitted.
Quick decision guide
|
Need |
Use |
|---|---|
|
Add active subscribers in bulk |
Dashboard CSV upload, or |
|
Suppress (unsubscribe) keeping history |
|
|
Fully remove from a single mailing list |
Dashboard deletion (no API equivalent) |
|
GDPR / right-to-be-forgotten erasure |
|
|
Diagnose "unsubscribed via API" surprise |
Inspect Status column in mailing-list CSV ( |
|
Speed up large deletion sweeps |
Batch via API, off-peak, no overlap with imports |