2025, Dec 17 23:00
How to List SendGrid Single Send Campaigns with Names: Use the /v3/marketing/singlesends Endpoint, Not Stats
List SendGrid Single Send campaigns with names via /v3/marketing/singlesends and pagination. Avoid stats endpoints; export a clean campaign catalog fast.
When you need a clean list of all SendGrid Single Send campaigns with their human-readable names, it’s easy to end up at the wrong API surface. The stats endpoints return detailed message-level data, but they stop short of telling you which Single Send those messages belong to by name. Here’s how to get exactly the dataset you’re after without guesswork.
Reproducing the mismatch
Pulling message data via the SendGrid API is straightforward, but it doesn’t surface Single Send names. A minimal example illustrates the gap.
import sendgrid
import json
import os
sg_client = sendgrid.SendGridAPIClient(os.environ.get('SENDGRID_API_KEY'))
msg_resp = sg_client.client.messages.get()
data_obj = json.loads(msg_resp.body)
print(json.dumps(data_obj, indent=4))The response contains message-level fields only, such as recipient and status, but no Single Send campaign names.
{
"messages": [
{
"from_email": "email@example.com",
"msg_id": "some-message-id-here1",
"subject": "Message subject here",
"to_email": "madeline@example.com",
"status": "processing",
"opens_count": 0,
"clicks_count": 0,
"last_event_time": "2025-05-14T12:00:10Z"
},
{
"from_email": "email@example.com",
"msg_id": "some-message-id-here2",
"subject": "Message subject here",
"to_email": "theo@example.com",
"status": "delivered",
"opens_count": 1,
"clicks_count": 0,
"last_event_time": "2025-05-14T12:00:08Z"
}
]
}Why you don’t see the names
The stats endpoint at /v3/marketing/stats/singlesends focuses on engagement and delivery metrics. It’s designed for performance analysis and aggregates at the message level. As a result, Single Send names are not part of that payload. There is also an endpoint for Single Send stats by ID, but it only helps if you already possess the relevant Single Send ID and wish to query it specifically by that identifier.
The correct endpoint for listing Single Sends and names
To enumerate campaigns with their names, use the marketing resource that lists Single Sends. The endpoint is /v3/marketing/singlesends. The server returns up to 100 results per page and, when there are more results, provides a next page link in _metadata.next.
{
"result": [
{
"id": "some_long_id_1",
"name": "Name of Single Send 1",
"status": "draft",
"categories": [],
"send_at": null,
"created_at": "2025-05-14T11:00:00Z",
"updated_at": "2025-05-14T11:30:00Z",
"is_abtest": false,
"abtest": null
},
{
"id": "some_long_id_2",
"name": "Name of Single Send 2",
"status": "triggered",
"categories": [],
"send_at": "2025-05-10T12:00:00Z",
"created_at": "2025-05-05T12:00:00Z",
"updated_at": "2025-05-07T12:00:00Z",
"is_abtest": false,
"abtest": null
}
],
"_metadata": {
"self": "https://api.sendgrid.com/v3/marketing/singlesends?page_token=SOME_TOKEN_HERE_1",
"next": "https://api.sendgrid.com/v3/marketing/singlesends?page_token=SOME_TOKEN_HERE_2",
"count": 159
}
}Solution: fetch all Single Sends with pagination
To collect the complete set of Single Send campaigns and their names, request /v3/marketing/singlesends and follow _metadata.next until it is no longer present. The following Python snippet retrieves all pages and prints the consolidated list.
import requests
import os
import json
auth_hdrs = {"Authorization": f"Bearer {os.environ.get('SENDGRID_API_KEY')}"}
singlesend_catalog = []
page_url = 'https://api.sendgrid.com/v3/marketing/singlesends'
while True:
http_res = requests.get(page_url, headers=auth_hdrs)
payload = http_res.json()
singlesend_catalog.extend(payload.get('result', []))
next_url = payload.get("_metadata").get("next")
if next_url:
page_url = next_url
else:
break
print(json.dumps(singlesend_catalog, indent=2))Why this matters
Choosing the right endpoint saves hours of wrangling. If your objective is inventory and naming—auditing campaigns, mapping IDs to labels, or presenting operators with understandable lists—the stats resources will not deliver the fields you need. The marketing list endpoint does, with a consistent pagination model via _metadata.next and a per-page limit of 100 results. That makes it reliable for full exports and synchronization jobs.
Takeaways
If you want Single Send names, call /v3/marketing/singlesends and traverse _metadata.next to the end. Use the stats endpoints only when you actually need engagement data by ID or message. Keeping these roles separate keeps your integration simple and your data model clean.