Search Documentation

Search for a documentation page...

Subscribers API

REST API endpoints for newsletter subscriber management.

List Subscribers

GET /api/v1/subscribers

Returns a paginated subscriber list with per-subscriber purchase stats (orderCount, totalSpent, lastOrderAt) for audience segmentation. The sensitive unsubscribe token is never returned.

Query Parameters

ParameterTypeDefaultDescription
limitnumber50Subscribers per page (1-100)
offsetnumber0Subscribers to skip
statusstringallFilter by status: all, active, unsubscribed, or bounced. active leaves out both unsubscribed and paused addresses
querystring–Search by email or name
groupstring–Only subscribers in this subscriber group (group UUID)
curl \
-H "Authorization: Bearer your_api_key" \
"https://your-store.yns.store/api/v1/subscribers?status=active&limit=20"

Response

{
"data": [
{
"id": "0191abc0-1234-7def-8000-000000000001",
"email": "jane@example.com",
"name": "Jane Doe",
"location": "New York, US",
"source": "checkout",
"placement": "footer",
"locale": "en-US",
"unsubscribed": false,
"unsubscribedAt": null,
"pending": false,
"confirmedAt": "2024-05-01T09:01:00.000Z",
"suppressedAt": null,
"suppressedReason": null,
"suppressedDetail": null,
"groups": [
{ "id": "0191abc0-1234-7def-8000-0000000000a1", "name": "VIP" }
],
"orderCount": 3,
"totalSpent": 12500,
"lastOrderAt": "2024-06-10T14:22:00.000Z",
"createdAt": "2024-05-01T09:00:00.000Z"
}
],
"meta": {
"count": 1,
"offset": 0,
"limit": 50
}
}

Each subscriber also carries groups: the subscriber groups it belongs to, as { id, name } objects (an empty array when it is in none).

Paused Addresses

An address is paused when mail can no longer reach it: it hard-bounced, or the person reported a campaign as spam. Campaigns and back-in-stock notifications skip a paused address until a merchant reactivates it from the dashboard. This is separate from unsubscribed, which is the person's own choice.

FieldTypeDescription
suppressedAtstring | nullWhen the address was paused (ISO 8601), or null if mail can still reach it
suppressedReasonstring | nullWhy it was paused: bounce or complaint
suppressedDetailstring | nullThe receiving mail server's own words, when available (e.g. "550 5.1.1 user unknown")

Pass status=bounced to list only paused addresses:

curl \
-H "Authorization: Bearer your_api_key" \
"https://your-store.yns.store/api/v1/subscribers?status=bounced"

Create Subscriber

POST /api/v1/subscribers

Adds an email address to the store's subscriber list. If the email is already subscribed, returns a 200 with { status: "already_subscribed" } instead of creating a duplicate.

When double opt-in is enabled in your store's newsletter settings (settings.newsletter.doubleOptIn), new subscribers are created with pending: true and receive a confirmation email. The welcome offer is only triggered after the subscriber confirms. If the email already exists and is still pending, the confirmation email is re-sent (at most once per day).

Request Body

FieldTypeRequiredDescription
emailstringYesSubscriber email address
namestringNoSubscriber display name
placementstringNoStorefront form or page that drove the signup, max 120 chars (e.g. "footer", "hero-banner")
localestringNoThe storefront language the form was in, e.g. pl-PL. Must be the store's default or an enabled language (400 otherwise). The confirmation, welcome and reminder emails and the confirm/unsubscribe pages render in it; signing up again in another language updates it
groupIdsstring[]NoSubscriber groups to add the signup to (max 20). An address that is already subscribed is added to them too; this call never takes anyone out of a group. An id that is not a group of this store returns 400 with unknownGroupIds
curl -X POST \
-H "Authorization: Bearer your_api_key" \
-H "Content-Type: application/json" \
-d '{"email": "jane@example.com", "name": "Jane Doe", "placement": "footer", "locale": "en-US"}' \
https://your-store.yns.store/api/v1/subscribers

Response (201)

{
"id": "0191abc0-1234-7def-8000-000000000001",
"email": "jane@example.com",
"name": "Jane Doe",
"placement": "footer",
"locale": "en-US",
"pending": false,
"createdAt": "2024-06-15T10:30:00.000Z",
"groups": [],
"welcomeOffer": { "status": "queued" }
}

The welcomeOffer.status field indicates whether a welcome email was triggered for this subscriber:

StatusDescription
"queued"A welcome offer is configured and the welcome email (with a discount code, or without one in mode "none") has been queued for delivery
"pending_confirmation"Double opt-in is enabled; the welcome offer will fire after the subscriber confirms
"off"No welcome offer is configured for this store

Already Subscribed (200)

{
"status": "already_subscribed"
}

Import Subscribers

POST /api/v1/subscribers/import

Bulk-adds subscribers – the programmatic equivalent of the dashboard CSV import. Up to 1000 subscribers per request. The mode field controls handling of emails that already exist.

Request Body

FieldTypeRequiredDescription
subscribersarrayYesSubscribers to import (1-1000)
subscribers[].emailstringYesSubscriber email address
subscribers[].namestringNoSubscriber display name
subscribers[].locationstringNoFree-text location
subscribers[].groupsstring[]NoGroup names to put this subscriber in (max 20), matched ignoring case. A name that doesn't exist yet creates the group
modestringNoHow to handle existing emails: skip (default) or update (refresh name/location)
groupIdsstring[]NoExisting group ids to add every subscriber in the request to (max 20). An id that is not a group of this store returns 400 with unknownGroupIds

Group memberships are added for newly imported subscribers and, in update mode, for ones that already existed. In skip mode an existing subscriber's groups are left alone. Import never removes anyone from a group.

curl -X POST \
-H "Authorization: Bearer your_api_key" \
-H "Content-Type: application/json" \
-d '{
"subscribers": [
{"email": "jane@example.com", "name": "Jane Doe", "location": "New York, US"},
{"email": "john@example.com", "name": "John Smith", "groups": ["VIP", "Wholesale"]}
],
"mode": "skip"
}' \
https://your-store.yns.store/api/v1/subscribers/import

Response (200)

{
"imported": 2,
"skipped": 0,
"updated": 0,
"groupsCreated": 2
}

groupsCreated is how many groups the request's groups names created.

A 403 is returned with { error, limit, count } when the subscriber limit for your plan is reached.


Update Subscriber

PATCH /api/v1/subscribers/{id}

Edits one subscriber. Send at least one field.

FieldTypeDescription
namestring | nullDisplay name. null or "" clears it
locationstring | nullFree-text location. null or "" clears it
placementstring | nullWhere the signup came from. null or "" clears it
unsubscribedbooleantrue opts the subscriber out, false puts them back on the list. Only set it when the person asked. Not allowed for back-in-stock watchers (409)
groupIdsstring[]The subscriber's groups as the complete list: groups left out are removed, [] removes every group. Omit it to leave groups unchanged. An id that is not a group of this store returns 400 with unknownGroupIds
curl -X PATCH \
-H "Authorization: Bearer your_api_key" \
-H "Content-Type: application/json" \
-d '{"groupIds": ["0191abc0-1234-7def-8000-0000000000a1"]}' \
https://your-store.yns.store/api/v1/subscribers/0191abc0-1234-7def-8000-000000000001

Returns the updated subscriber, including groups. To add or remove one group for many subscribers at once, use the group members endpoints instead.


Delete Subscriber

DELETE /api/v1/subscribers?email=jane@example.com

Unsubscribes an email address.

Query Parameters

ParameterTypeRequiredDescription
emailstringYesEmail to unsubscribe

Response

{
"status": "unsubscribed"
}

Subscriber Groups

Groups are labels a merchant puts on subscribers, such as VIP or Wholesale. A subscriber can be in any number of groups, and a newsletter can send to some groups and leave others out with groupFilter. Group names are unique per store, ignoring case.

A group object:

{
"id": "0191abc0-1234-7def-8000-0000000000a1",
"name": "VIP",
"description": "Spent over $500 last year",
"memberCount": 42,
"activeCount": 38,
"createdAt": "2024-06-01T09:00:00.000Z",
"updatedAt": "2024-06-01T09:00:00.000Z"
}
FieldTypeDescription
memberCountnumberEvery subscriber in the group
activeCountnumberMembers a campaign would reach today: subscribed, confirmed and not paused. Unsubscribed, pending and paused members – and back-in-stock watchers (source: "restock"), which are never mailed campaigns – stay in the group but are not counted here

List Groups

GET /api/v1/subscriber-groups

Returns every group of the store, ordered by name.

curl \
-H "Authorization: Bearer your_api_key" \
https://your-store.yns.store/api/v1/subscriber-groups
{
"data": [
{
"id": "0191abc0-1234-7def-8000-0000000000a1",
"name": "VIP",
"description": "Spent over $500 last year",
"memberCount": 42,
"activeCount": 38,
"createdAt": "2024-06-01T09:00:00.000Z",
"updatedAt": "2024-06-01T09:00:00.000Z"
}
],
"meta": { "count": 1 }
}

Create Group

POST /api/v1/subscriber-groups
FieldTypeRequiredDescription
namestringYesGroup name, 1-80 characters
descriptionstring | nullNoUp to 500 characters
curl -X POST \
-H "Authorization: Bearer your_api_key" \
-H "Content-Type: application/json" \
-d '{"name": "VIP", "description": "Spent over $500 last year"}' \
https://your-store.yns.store/api/v1/subscriber-groups

Returns the new group with 201. A name the store already uses (in any letter case) returns 409.

Get Group

GET /api/v1/subscriber-groups/{id}

Returns one group with its counts, or 404 with { "error": "Subscriber group not found" }.

Update Group

PATCH /api/v1/subscriber-groups/{id}

Renames a group or changes its description. Send at least one of name and description; pass "description": null to clear it. Returns the updated group, 404 for an unknown id, or 409 when the new name is taken.

Delete Group

DELETE /api/v1/subscriber-groups/{id}

Deletes the group and its memberships. The subscribers themselves are not touched. Returns { "ok": true, "deleted": 1 }, or 404.

A newsletter that still names a deleted group in groupFilter never reaches more people because of it: an included group that no longer exists matches nobody, and an excluded one excludes nobody.

Add Members

POST /api/v1/subscriber-groups/{id}/members

Adds subscribers to the group, by id, by email, or both. Up to 1000 subscribers per request. Subscribers already in the group are left as they are.

FieldTypeRequiredDescription
subscriberIdsstring[]One of the twoSubscriber UUIDs. Ids that are not subscribers of this store are ignored
emailsstring[]One of the twoSubscriber email addresses, matched ignoring case. Addresses with no subscriber come back in unknownEmails
curl -X POST \
-H "Authorization: Bearer your_api_key" \
-H "Content-Type: application/json" \
-d '{"emails": ["jane@example.com", "john@example.com"]}' \
https://your-store.yns.store/api/v1/subscriber-groups/0191abc0-1234-7def-8000-0000000000a1/members
{
"groupId": "0191abc0-1234-7def-8000-0000000000a1",
"added": 2,
"unknownEmails": []
}

added counts new memberships only, so it can be lower than the number of subscribers sent.

Remove Members

DELETE /api/v1/subscriber-groups/{id}/members

Takes the same body as Add Members and takes those subscribers out of the group. Responds with { groupId, removed, unknownEmails }.