Sends
Query send history with filtering by status, contact, and template.
The Sends API provides access to your email send history. Every email sent through Kraiter — whether transactional, sequence-based, or campaign-driven — is recorded as a send with status tracking.
List sends
GET /api/sendsReturns a paginated list of send records with optional filtering.
Query parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
cursor | string | — | Pagination cursor from a previous response. |
limit | number | 20 | Number of sends to return (max 100). |
status | string | — | Filter by delivery status: sent, delivered, bounced, or complained. |
from | string | — | Only include sends at or after this ISO 8601 datetime. |
to | string | — | Only include sends at or before this ISO 8601 datetime. |
contactId | string | — | Filter by contact ID (uses an optimised query; the contact must exist). |
templateId | string | — | Filter by template ID. |
sequenceId | string | — | Filter by sequence ID. |
Response
The delivery status is on the deliveryStatus field. Sends record fromAddress/toAddress (not email) and reference their origin via sequenceId/stepId when they come from a sequence.
{
"items": [
{
"sendId": "snd_01H9...",
"messageId": "0100018f...",
"contactId": "cnt_01H8MZXK...",
"templateId": "welcome-email",
"sequenceId": "onboarding",
"stepId": "welcome",
"fromAddress": "hello@notifications.example.com",
"toAddress": "alice@example.com",
"subject": "Welcome, Alice!",
"deliveryStatus": "delivered",
"sentAt": "2025-09-15T11:00:00.000Z",
"deliveredAt": "2025-09-15T11:00:02.000Z",
"openedAt": "2025-09-15T12:30:00.000Z",
"openCount": 1,
"clickedAt": "2025-09-15T12:31:00.000Z",
"clickCount": 1
}
],
"nextCursor": "eyJpZCI6InNuZF8wMUg5Li4uIn0="
}Delivery statuses
The send's deliveryStatus field can be:
| Status | Description |
|---|---|
sent | The email has been accepted by SES. |
delivered | SES confirmed delivery to the recipient's mail server. |
bounced | The email bounced. A bounceType of hard or soft is included. |
complained | The recipient marked the email as spam. |
rejected | SES rejected the email before sending. |
The status query parameter filters on sent, delivered, bounced, and complained. A send originates from a sequence when sequenceId is present; otherwise it is transactional.
Errors
| Code | Description |
|---|---|
VALIDATION_ERROR | Invalid filter parameter, or from is after to. |
CONTACT_NOT_FOUND | The contactId filter references a contact that does not exist. |
Examples
# List all sends
curl "https://api.kraiter.com/api/sends?limit=20" \
-H "Authorization: Bearer YOUR_API_KEY"
# Filter by status
curl "https://api.kraiter.com/api/sends?status=bounced&limit=50" \
-H "Authorization: Bearer YOUR_API_KEY"
# Filter by contact
curl "https://api.kraiter.com/api/sends?contactId=cnt_01H8MZXK..." \
-H "Authorization: Bearer YOUR_API_KEY"
# Filter by template
curl "https://api.kraiter.com/api/sends?templateId=welcome-email" \
-H "Authorization: Bearer YOUR_API_KEY"// List recent sends
const sends = await kraiter.sends.list({ limit: 20 });
// Filter by status
const bounced = await kraiter.sends.list({
status: "bounced",
limit: 50,
});
// Filter by contact
const contactSends = await kraiter.sends.list({
contactId: "cnt_01H8MZXK...",
});
// Combine filters
const filtered = await kraiter.sends.list({
status: "delivered",
templateId: "welcome-email",
limit: 100,
});Get send
GET /api/sends/:sendIdReturns a single send record by its ID.
Path parameters
| Parameter | Type | Description |
|---|---|---|
sendId | string | The send ID. |
Errors
| Code | Description |
|---|---|
SEND_NOT_FOUND | No send with this ID exists. |
Examples
curl https://api.kraiter.com/api/sends/snd_01H9... \
-H "Authorization: Bearer YOUR_API_KEY"const send = await kraiter.sends.get("snd_01H9...");Paginating through results
Use cursor-based pagination to iterate through large result sets:
let cursor: string | undefined;
const allBounced: Send[] = [];
do {
const page = await kraiter.sends.list({
status: "bounced",
limit: 100,
cursor,
});
allBounced.push(...page.items);
cursor = page.nextCursor ?? undefined;
} while (cursor);
console.log(`Total bounced sends: ${allBounced.length}`);# First page
curl "https://api.kraiter.com/api/sends?status=bounced&limit=100" \
-H "Authorization: Bearer YOUR_API_KEY"
# Subsequent pages (use nextCursor from previous response)
curl "https://api.kraiter.com/api/sends?status=bounced&limit=100&cursor=eyJpZCI6InNuZF8wMUg5Li4uIn0=" \
-H "Authorization: Bearer YOUR_API_KEY"Engagement timestamps
Each send includes optional engagement timestamps that are populated as events occur:
| Field | Description |
|---|---|
sentAt | When the email was handed off to SES. |
deliveredAt | When SES confirmed delivery. |
openedAt | When the recipient first opened the email (tracked via pixel). |
clickedAt | When the recipient first clicked a tracked link. |
bouncedAt | When the bounce notification was received. |
complainedAt | When the spam complaint was received. |
These fields are null until the corresponding event occurs.