Overview
A Shipstar mailing list is the audience for your release-notes emails. You can fill one by hand in the dashboard, but for a real product the list should mirror your own users: someone signs up and they start getting release notes; they close their account and the emails stop; they change their address and the next issue reaches the new one. The public API gives you three idempotent calls for that, and the dashboard covers the one-off import and export:
All calls take an API token scoped to the project. List ids come from
GET /email/lists, or create one with POST /email/lists. Management calls are free; only content generation spends credits.
The four things to know
Key byexternal_id. Send your own user id as external_id on every upsert. Shipstar then matches on it first, so when a user changes their email address the same recipient is updated in place instead of a second one appearing. Without it, matching falls back to the email address, which still works for simple lists.
Three statuses. A recipient is active (gets emails), removed (you took them off; an upsert puts them back), or unsubscribed (they clicked the link in an email). Unsubscribed is terminal: no API call ever changes those rows, they just come back in the response as skipped_unsubscribed. Your sync does not need to track opt-outs itself.
Upsert never deletes. PUT only adds and updates. Departed users have to be removed explicitly — either one at a time from your account-deletion path, or by diffing in a reconcile job (below).
Retries are safe. Every call is idempotent per entry. A re-sent batch reports the repeats as unchanged / already_removed. Lists hold at most 500 active recipients; an upsert that would cross that line is rejected as a whole with a 400 so you can split it.
Recipe 1 — Signup and account-deletion hooks
The simplest integration: call the API from the code paths where a user is created, updated or deleted.Recipe 2 — Nightly reconcile from your database
Hooks can miss events (a bulk import into your own database, a migration). A scheduled job that pushes the current truth and removes what is no longer there catches everything:Python
external_id (added by hand or by an email-only import) are left alone by step 2, so a human-curated list and a synced list can coexist.
Write calls are limited to 30 per minute per IP, which is 30,000 recipients a minute in 1000-entry batches — more than a list can hold. Read the RateLimit-Remaining header if you run several syncs from one host.
Recipe 3 — Zapier, n8n or Make
Use the generic HTTP / Webhook action; there is no dedicated Shipstar app and none is needed.- Trigger: new row in your CRM, new customer in Stripe, new signup in your auth provider — whatever marks someone as a user.
- Action: HTTP request
- Method
PUT - URL
https://api.shipstar.ai/api/v1/email/lists/<list id>/recipients - Headers
Authorization: Bearer <api token>,Content-Type: application/json - Body (JSON):
- Method
- For the churn side, a second Zap on your “customer deleted / subscription cancelled” trigger sends
DELETE https://api.shipstar.ai/api/v1/email/lists/<list id>/recipients/{{customer_id}}with the same header.
external_id so a later email change updates the same recipient.
Recipe 4 — One-off CSV import or export
For an initial load from a spreadsheet, open the list in the dashboard (Destinations → Email) and use Import CSV. The importer looks for these headers, case-insensitively:
A file with no header row and email addresses in the first column also works. You get a preview with the detected columns and counts before anything is sent, and the import runs through the same upsert as the API, so re-importing an updated file updates rather than duplicates.
Export CSV on the same page (or
GET .../recipients/export.csv with a token) downloads every recipient with their status — a backup you can re-import later, or feed into another tool.
Checking your work
GET /email/lists/{id}showsactive_count,removed_countandunsubscribed_count; after a sync,active_countshould match the number of users you pushed.GET /email/lists/{id}/recipients?q=<email>finds one person and shows their status and the fields you wrote.- In the dashboard, the list shows the same counts, and the Sync via API button prints ready-to-paste
curlcommands with the list id filled in.
Related
- Upsert Recipients — full matching rules and response fields
- Remove Recipients — single and batch forms
- Authentication — creating and using API tokens
- Error Handling — rate-limit headers and retry guidance