List Recipients
curl --request GET \
--url https://api.example.com/email/lists/{list_id}/recipientsimport requests
url = "https://api.example.com/email/lists/{list_id}/recipients"
response = requests.get(url)
print(response.text)const options = {method: 'GET'};
fetch('https://api.example.com/email/lists/{list_id}/recipients', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.example.com/email/lists/{list_id}/recipients",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.example.com/email/lists/{list_id}/recipients"
req, _ := http.NewRequest("GET", url, nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.example.com/email/lists/{list_id}/recipients")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/email/lists/{list_id}/recipients")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
response = http.request(request)
puts response.read_body{
"items": [
{
"id": "<string>",
"email": "<string>",
"name": "<string>",
"external_id": "<string>",
"attributes": {},
"status": "<string>",
"status_changed_at": "<string>",
"is_active": true,
"created_at": "<string>",
"updated_at": "<string>"
}
],
"next_cursor": "<string>"
}Mailing Lists
List Recipients
Page through a mailing list’s recipients, with status filter and search
GET
/
email
/
lists
/
{list_id}
/
recipients
List Recipients
curl --request GET \
--url https://api.example.com/email/lists/{list_id}/recipientsimport requests
url = "https://api.example.com/email/lists/{list_id}/recipients"
response = requests.get(url)
print(response.text)const options = {method: 'GET'};
fetch('https://api.example.com/email/lists/{list_id}/recipients', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.example.com/email/lists/{list_id}/recipients",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.example.com/email/lists/{list_id}/recipients"
req, _ := http.NewRequest("GET", url, nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.example.com/email/lists/{list_id}/recipients")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/email/lists/{list_id}/recipients")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
response = http.request(request)
puts response.read_body{
"items": [
{
"id": "<string>",
"email": "<string>",
"name": "<string>",
"external_id": "<string>",
"attributes": {},
"status": "<string>",
"status_changed_at": "<string>",
"is_active": true,
"created_at": "<string>",
"updated_at": "<string>"
}
],
"next_cursor": "<string>"
}Returns a mailing list’s recipients oldest first, 100 per page by default. Each recipient carries the fields your sync wrote (
name, external_id, attributes) plus its lifecycle status.
Recipient statuses:
| Status | Meaning | Reactivated by upsert? |
|---|---|---|
active | Receives release emails | — |
removed | You removed them (API or dashboard) | Yes |
unsubscribed | They clicked unsubscribe in an email | Never |
Authentication
This endpoint requires an API token passed as a Bearer token in theAuthorization header.
Authorization: Bearer YOUR_API_TOKEN
Path Parameters
string
required
The mailing list’s unique identifier (UUID).
Query Parameters
string
Only recipients in this status:
active, removed or unsubscribed.string
Case-insensitive search across email, name and external_id.
integer
default:"100"
Page size, 1–500.
string
The
next_cursor from the previous page. Omit for the first page.Request
curl "https://api.shipstar.ai/api/v1/email/lists/a1b2c3d4-e5f6-7890-abcd-ef1234567890/recipients?status=active&limit=200" \
-H "Authorization: Bearer YOUR_API_TOKEN"
const listId = 'a1b2c3d4-e5f6-7890-abcd-ef1234567890';
const all = [];
let cursor = null;
do {
const url = new URL(`https://api.shipstar.ai/api/v1/email/lists/${listId}/recipients`);
url.searchParams.set('limit', '500');
if (cursor) url.searchParams.set('cursor', cursor);
const page = await (await fetch(url, {
headers: { Authorization: 'Bearer YOUR_API_TOKEN' }
})).json();
all.push(...page.items);
cursor = page.next_cursor;
} while (cursor);
import requests
list_id = 'a1b2c3d4-e5f6-7890-abcd-ef1234567890'
url = f'https://api.shipstar.ai/api/v1/email/lists/{list_id}/recipients'
headers = {'Authorization': 'Bearer YOUR_API_TOKEN'}
recipients, cursor = [], None
while True:
params = {'limit': 500, **({'cursor': cursor} if cursor else {})}
page = requests.get(url, headers=headers, params=params).json()
recipients += page['items']
cursor = page['next_cursor']
if not cursor:
break
Response
object[]
required
Recipients in this page.
Show Recipient
Show Recipient
string
required
Recipient id (UUID)
string
required
Lowercased email address
string
Display name, if set
string
Your identifier for this person, if set
object
required
Free-form key/value map (strings, numbers, booleans)
string
required
active, removed or unsubscribedstring
When the status last changed; null while never changed
boolean
required
Shorthand for
status == "active"string
required
ISO 8601 timestamp
string
required
ISO 8601 timestamp
string
Opaque cursor for the next page;
null on the last page.200
{
"items": [
{
"id": "5e0b1c1e-6d2b-4a1f-9a3d-1c2b3a4d5e6f",
"email": "[email protected]",
"name": "Sam Lee",
"external_id": "usr_42",
"attributes": {"plan": "pro"},
"status": "active",
"status_changed_at": null,
"is_active": true,
"created_at": "2026-09-01T08:00:00Z",
"updated_at": "2026-09-20T08:00:00Z"
}
],
"next_cursor": "MjAyNi0wOS0wMVQwODowMDowMCswMDowMHw1ZTBiMWMxZS0..."
}
Errors
| Status | Description |
|---|---|
| 400 | Unknown status value or malformed cursor |
| 401 | Invalid or expired API token |
| 404 | Mailing list not found in the token’s project |
Rate Limits
This endpoint is limited to 100 requests per minute per IP.Was this page helpful?