Skip to main content

Email Logs Guide

The Email Logs API provides access to detailed delivery status and activity information for all emails sent through EDITH.


Overview

Email logs allow you to:

  • Track email delivery status
  • View open and click activity
  • Debug delivery issues
  • Generate reports and analytics
  • Monitor campaign performance

Get Email Logs

Endpoint

GET /v1/email/logs

Authentication

Requires Bearer token authentication.

Query Parameters

All parameters are optional and can be combined for precise filtering. Every query is automatically scoped to your account — you never pass a tenant or account ID. Note the date defaults and limits below the table.

ParameterTypeDescription
emailstringFilter by recipient email address (exact match)
recipientDomainstringFilter by recipient's email domain (exact match)
refIdstringFilter by email reference ID (returned when sending)
statusstringFilter by delivery status
fromAddressstringFilter by sender email address (exact match)
subjectstringFilter by email subject (exact match)
campaignIdstringFilter by campaign ID
recipientTypestringFilter by recipient type: "to", "cc", "bcc"
failedReasonstringFilter by failure reason
startCreatedAtstringStart date for creation date filter (RFC3339 format)
endCreatedAtstringEnd date for creation date filter (RFC3339 format)
startDeliveredDatestringStart date for delivery date filter (RFC3339 format)
endDeliveredDatestringEnd date for delivery date filter (RFC3339 format)
pageSizeintegerNumber of results per page (default: 20, max: 50)
pageTokenstringOpaque cursor for the next page (see Pagination)

Defaults & Limits

These rules are enforced by the API — read them before building queries:

  • Default window is the last 7 days. If you send neither startCreatedAt nor endCreatedAt, the API returns the most recent 7 days.
  • A date window cannot exceed 7 days. A wider range returns 400 "date range cannot exceed 7 days". To cover a longer period, page through it in ≤ 7-day windows.
  • Send startCreatedAt and endCreatedAt together. Providing only one returns 400 ("endCreatedAt is required" / "startCreatedAt is required"), and startCreatedAt must not be after endCreatedAt.
  • pageSize must be 1–50 (default 20). Values outside that range are rejected with 400 "pageSize must be between 1 and 50" — they are not silently clamped.
  • The same 7-day defaults and limits apply to the delivery-date window (startDeliveredDate / endDeliveredDate).

Email Status Values

StatusDescription
queuedEmail is queued for sending
sentEmail sent to the mail server
deliveredEmail successfully delivered to recipient's inbox
openedRecipient opened the email (if tracking enabled)
clickedRecipient clicked a link (if tracking enabled)
bouncedEmail bounced (soft or hard)
failedEmail failed to send
spamEmail marked as spam
unsubscribedRecipient unsubscribed

Example Requests

Get All Logs (Paginated)

curl -X GET "https://api.sparrowmailer.com/v1/email/logs?pageSize=20" \
-H "Authorization: Bearer YOUR_TOKEN"

Filter by Recipient Email

curl -X GET "https://api.sparrowmailer.com/v1/email/logs?email=customer@example.com" \
-H "Authorization: Bearer YOUR_TOKEN"

Filter by Status

curl -X GET "https://api.sparrowmailer.com/v1/email/logs?status=bounced" \
-H "Authorization: Bearer YOUR_TOKEN"

Filter by Campaign

curl -X GET "https://api.sparrowmailer.com/v1/email/logs?campaignId=welcome-series-2024" \
-H "Authorization: Bearer YOUR_TOKEN"

Filter by Date Range

Send startCreatedAt and endCreatedAt together, within a 7-day window:

curl -X GET "https://api.sparrowmailer.com/v1/email/logs?startCreatedAt=2024-01-15T00:00:00Z&endCreatedAt=2024-01-21T23:59:59Z" \
-H "Authorization: Bearer YOUR_TOKEN"

Filter by Reference ID

curl -X GET "https://api.sparrowmailer.com/v1/email/logs?refId=01JC3BBW8S9YGX2VNKG5MD7BTA" \
-H "Authorization: Bearer YOUR_TOKEN"

Combine Multiple Filters

curl -X GET "https://api.sparrowmailer.com/v1/email/logs?campaignId=promo-jan&status=delivered" \
-H "Authorization: Bearer YOUR_TOKEN"

Response Format

{
"success": true,
"emailLogs": [
{
"refId": "01JC3BBW8S9YGX2VNKG5MD7BTA",
"accountId": 12345,
"tenantId": 67890,
"fromAddress": "notifications@mail.yourcompany.com",
"recipientAddress": "customer@example.com",
"recipientDomain": "example.com",
"recipientType": "to",
"subject": "Your Order Confirmation",
"status": "delivered",
"priority": "normal",
"campaignId": "order-confirmation",
"opened": true,
"clicked": true,
"failedReason": null,
"createdAt": "2024-01-15T10:30:00Z",
"deliveredDate": "2024-01-15T10:30:05Z",
"updatedAt": "2024-01-15T11:45:00Z",
"track": {
"opens": [
{
"timestamp": "2024-01-15T11:00:00Z",
"userAgent": "Mozilla/5.0...",
"ip": "192.168.1.1"
}
],
"clicks": [
{
"timestamp": "2024-01-15T11:05:00Z",
"url": "https://yourcompany.com/orders/12345",
"userAgent": "Mozilla/5.0...",
"ip": "192.168.1.1"
}
]
}
}
],
"nextPageToken": "eyJJZCI6IjAxSkM0...",
"totalCount": 1
}

Response Fields Explained

Response Envelope

FieldTypeDescription
successbooleantrue when the request succeeded
emailLogsarrayThe matching log entries for this page
nextPageTokenstringCursor for the next page. Omitted when there are no more results — see Pagination
totalCountintegerNumber of records returned in this response — not a global total across all pages

Email Log Entry

FieldTypeDescription
refIdstringUnique reference ID for this email (returned when sending)
accountIdintegerYour account identifier
tenantIdintegerTenant/organization identifier
fromAddressstringSender email address
recipientAddressstringRecipient email address
recipientDomainstringDomain portion of recipient email
recipientTypestringHow recipient was addressed: "to", "cc", "bcc"
subjectstringEmail subject line
statusstringCurrent delivery status
prioritystringEmail priority: "normal" or "high"
campaignIdstringCampaign identifier (if provided when sending)
openedbooleanWhether email has been opened (if tracking enabled)
clickedbooleanWhether any links were clicked (if tracking enabled)
failedReasonstringReason for failure (if status is failed/bounced)
createdAtstringWhen the email was created (RFC3339)
deliveredDatestringWhen the email was delivered (RFC3339)
updatedAtstringLast update timestamp (RFC3339)
trackobjectDetailed tracking events (opens, clicks)

Track Object

FieldTypeDescription
opensarrayList of open events with timestamp, userAgent, and IP
clicksarrayList of click events with timestamp, URL, userAgent, and IP

Pagination

The API uses cursor-based pagination. Each response returns a nextPageToken while more results exist; pass it back as pageToken to fetch the next page.

When to use it: a single page returns at most 50 records, so any query that matches more than pageSize rows — exporting a busy 7-day window, pulling every bounce for a campaign — needs paging to read the full set.

Initial Request

curl -X GET "https://api.sparrowmailer.com/v1/email/logs?status=bounced&pageSize=50" \
-H "Authorization: Bearer YOUR_TOKEN"

Next Page

Use the nextPageToken from the previous response as pageToken, keeping every other filter identical:

curl -X GET "https://api.sparrowmailer.com/v1/email/logs?status=bounced&pageSize=50&pageToken=eyJJZCI6IjAxSkM0..." \
-H "Authorization: Bearer YOUR_TOKEN"

Pagination Tips

  • pageSize must be 1–50 (default 20); out-of-range values are rejected, not clamped.
  • nextPageToken is omitted from the response when there are no more results — stop paging when it's absent.
  • Treat the token as opaque: pass it back exactly as received. Don't parse, build, or modify it.
  • Keep your filters identical across pages — changing a filter mid-pagination invalidates the cursor.
  • totalCount is the size of the current page, not a count of all matching records. To get a full total, page to the end and sum the pages.
  • Remember the 7-day window cap: to page across a longer period, repeat the loop for each ≤ 7-day window.

Use Cases

1. Track Specific Email Delivery

# Using the ref_id from send response
curl -X GET "https://api.sparrowmailer.com/v1/email/logs?refId=01JC3BBW8S9YGX2VNKG5MD7BTA" \
-H "Authorization: Bearer YOUR_TOKEN"

2. Find Bounced Emails

curl -X GET "https://api.sparrowmailer.com/v1/email/logs?status=bounced&pageSize=50" \
-H "Authorization: Bearer YOUR_TOKEN"

3. Emails from a Sender

Find everything sent from a given fromAddress, then narrow with common combinations:

# All emails from a sender
curl -X GET "https://api.sparrowmailer.com/v1/email/logs?fromAddress=notifications@mail.yourcompany.com" \
-H "Authorization: Bearer YOUR_TOKEN"

# Sender + only failures
curl -X GET "https://api.sparrowmailer.com/v1/email/logs?fromAddress=notifications@mail.yourcompany.com&status=failed" \
-H "Authorization: Bearer YOUR_TOKEN"

Any of these can also be scoped to a date window — see Filter by Date Range.

4. Emails to a Recipient

Pull a recipient's full history, or focus on a specific outcome:

# Every email to a recipient
curl -X GET "https://api.sparrowmailer.com/v1/email/logs?email=customer@example.com" \
-H "Authorization: Bearer YOUR_TOKEN"

# Only what landed as a primary (To) recipient and was delivered
curl -X GET "https://api.sparrowmailer.com/v1/email/logs?email=customer@example.com&recipientType=to&status=delivered" \
-H "Authorization: Bearer YOUR_TOKEN"

5. Campaign Performance

# All sends for a campaign
curl -X GET "https://api.sparrowmailer.com/v1/email/logs?campaignId=black-friday-2024" \
-H "Authorization: Bearer YOUR_TOKEN"

# Delivered vs. bounced for a campaign
curl -X GET "https://api.sparrowmailer.com/v1/email/logs?campaignId=black-friday-2024&status=bounced" \
-H "Authorization: Bearer YOUR_TOKEN"

6. Domain-Wide Issues

# Check if emails to a specific domain are failing
curl -X GET "https://api.sparrowmailer.com/v1/email/logs?recipientDomain=problematic-domain.com&status=failed" \
-H "Authorization: Bearer YOUR_TOKEN"

7. Recent Failures

# Recent failures (defaults to the last 7 days)
curl -X GET "https://api.sparrowmailer.com/v1/email/logs?status=failed&pageSize=50" \
-H "Authorization: Bearer YOUR_TOKEN"

Best Practices

1. Use Specific Filters

Narrow down results to improve performance:

# Good: specific filters
?campaignId=promo-jan&status=delivered

# If you add a date bound, add both — a lone startCreatedAt returns 400
?campaignId=promo-jan&startCreatedAt=2024-01-15T00:00:00Z # 400: endCreatedAt is required

2. Store Reference IDs

When sending emails, store the ref_id for easy lookup:

const response = await sendEmail(payload);
await database.saveEmailRecord({
orderId: order.id,
emailRefId: response.ref_id,
sentAt: new Date()
});

3. Use Campaign IDs Consistently

Tag emails with meaningful campaign IDs:

const payload = {
// ... email content
campaign_id: `${emailType}-${year}-${quarter}`
// e.g., "welcome-2024-q1", "invoice-2024-q1"
};

4. Handle Pagination Properly

async function getAllBouncedEmails() {
const allLogs = [];
let pageToken = null;

do {
const params = new URLSearchParams({
status: 'bounced',
pageSize: '50'
});
if (pageToken) params.set('pageToken', pageToken);

const response = await fetch(
`https://api.sparrowmailer.com/v1/email/logs?${params}`,
{ headers: { 'Authorization': `Bearer ${token}` } }
);
const data = await response.json();

allLogs.push(...data.emailLogs);
pageToken = data.nextPageToken;
} while (pageToken);

return allLogs;
}

5. Monitor Failed Emails

Set up regular checks for failures:

// Daily bounce report — pass both bounds (within 7 days)
const now = new Date();
const yesterday = new Date(now.getTime() - 86400000);
const bouncedEmails = await getEmailLogs({
status: 'bounced',
startCreatedAt: yesterday.toISOString(),
endCreatedAt: now.toISOString()
});

if (bouncedEmails.length > threshold) {
alertOps('High bounce rate detected');
}

Common Errors

ErrorCauseSolution
Invalid query parameter: <name>An unrecognized query parameter was sentUse only the parameters listed above
date range cannot exceed 7 daysstartCreatedAtendCreatedAt spans more than 7 daysSplit into ≤ 7-day windows and page through them
endCreatedAt is required / startCreatedAt is requiredOnly one date bound was sentSend both bounds together, or neither (defaults to last 7 days)
startCreatedAt cannot be after endCreatedAtDate bounds are reversedEnsure start ≤ end
pageSize must be between 1 and 50pageSize outside the allowed rangeUse a value from 1 to 50
Wrong date formatDate not RFC3339Use RFC3339 (e.g., 2024-01-15T10:30:00Z)
invalid page tokenpageToken was altered or malformedPass the nextPageToken exactly as returned; don't modify it
UnauthorizedInvalid or expired bearer tokenRefresh authentication token