Appearance
Statistics
Retrieve aggregated email sending statistics for your team. There are two endpoints with different response shapes — GET /mail/stats returns rolled-up totals for a fixed period, while GET /mail/stats/daily returns one row per day.
Base URL: https://app.krafter.dev/api/v1
Email Stats
Returns aggregate email counts grouped by status for a given time period.
GET /mail/statsRequired scope: mail:read
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
period | string | "7d" | Time period. One of: "1d", "7d", "30d", "90d". Other values fall back to "7d". |
Example Request
bash
curl "https://app.krafter.dev/api/v1/mail/stats?period=30d" \
-H "Authorization: Bearer kr_live_abc123def456"Example Response
json
// 200 OK
{
"data": {
"period": "30d",
"since": "2026-01-16T12:00:00Z",
"total": 1250,
"by_status": {
"queued": 5,
"sent": 20,
"delivered": 1180,
"bounced": 30,
"complained": 2,
"failed": 13
}
}
}The by_status object contains counts keyed by status string. Only statuses with non-zero counts are included. total is the sum across all statuses.
Daily Stats
Returns daily email counts broken down by status for the requested number of days. Each item in the array represents a single day.
GET /mail/stats/dailyRequired scope: mail:read
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
days | integer | 30 | Number of days to look back. Capped server-side at 365. |
This endpoint accepts only days. It does not accept from_date or to_date query parameters.
Example Request
bash
curl "https://app.krafter.dev/api/v1/mail/stats/daily?days=7" \
-H "Authorization: Bearer kr_live_abc123def456"Example Response
json
// 200 OK
{
"data": [
{
"date": "2026-02-09",
"queued": 0,
"sent": 3,
"delivered": 42,
"bounced": 1,
"complained": 0,
"failed": 0
},
{
"date": "2026-02-10",
"queued": 0,
"sent": 5,
"delivered": 38,
"bounced": 0,
"complained": 0,
"failed": 1
}
]
}Response Fields (per day)
| Field | Type | Description |
|---|---|---|
date | string | The date in YYYY-MM-DD format (UTC). |
queued | integer | Emails created on this date still queued. |
sent | integer | Emails handed off to the upstream provider. |
delivered | integer | Emails confirmed delivered. |
bounced | integer | Emails that bounced. |
complained | integer | Spam complaints recorded. |
failed | integer | Sends that failed (post-retry). |
INFO
Daily stats are returned in ascending date order. Past days are served from a pre-aggregated email_daily_stats table updated by a daily cron job. Today's row is computed live from the emails table — counts may shift slightly until the next aggregation run.
INFO
The daily-stats response does not currently include opened or clicked columns. Use GET /emails/:id/events to inspect open and click activity per email, or watch the email.opened / email.clicked webhooks for real-time tracking.
Computing Rates Client-Side
Both endpoints return raw counts. Compute rates in your client code:
typescript
type DailyRow = {
date: string;
queued: number;
sent: number;
delivered: number;
bounced: number;
complained: number;
failed: number;
};
function rates(row: DailyRow) {
const total = row.sent + row.delivered + row.bounced + row.failed;
return {
delivery_rate: total > 0 ? ((row.delivered / total) * 100).toFixed(2) : "0.00",
bounce_rate: total > 0 ? ((row.bounced / total) * 100).toFixed(2) : "0.00",
complaint_rate: row.delivered > 0 ? ((row.complained / row.delivered) * 100).toFixed(2) : "0.00",
};
}