How Transactional Emails Are Counted
Transactional emails are the messages you send through the Email API. This page explains exactly what counts toward your plan, what does not, and how the billing window is calculated.
Overview
Every email you send with POST /api/v1/emails is a transactional email. Usage is metered per recipient — not per API request — and only the recipients inside your to list are counted. Usage is always measured against the current billing window, which rolls monthly from the day your API subscription started.
The counting unit: recipients
A single API call can address up to 1,000 recipients in its to list. Each address in that list is counted as one transactional email. So one request to 50 recipients consumes 50 from your plan — not 1.
Internally, the count is the cardinality (length) of the stored recipients array:
-- per send, the contribution to usage is:
cardinality(recipients) -- = number of "to" addressesWhat counts
- Each address in the
tolist of a successfulPOST /api/v1/emailssend. - The send is counted at enqueue time (when the email row is persisted), not at delivery time. A recipient still counts even if the message later bounces.
- Hard bounces are counted again, separately, to compute your bounce rate — they do not reduce your usage total.
What does not count
ccandbccrecipients. Only the to array is metered.- Replies. Messages sent via the reply endpoints (
/reply) are flaggedis_reply = trueand are excluded from usage. - Deleted rows. Sends that have been soft-deleted (
deleted_at IS NOT NULL) are excluded. - Sends outside the current cycle. Only the active billing window is counted toward your quota.
The exact query
Usage for the current cycle is a single scan that returns both the sent count and the hard-bounced count:
SELECT
COALESCE(SUM(cardinality(recipients)), 0) AS sent,
COALESCE(SUM(
CASE WHEN is_bounced = true
THEN cardinality(recipients)
ELSE 0
END
), 0) AS hard_bounced
FROM email_apis
WHERE organization_id = :orgId
AND created_at >= :cycleStart -- inclusive
AND created_at < :cycleEnd -- exclusive
AND deleted_at IS NULL
AND is_reply = false;The billing window
Usage is not measured against the calendar month. It is measured against a rolling monthly cycle anchored to the day your API subscription started (started_at). The current cycle is the half-open interval [cycleStart, cycleEnd) — start inclusive, end exclusive — and the count resets to 0 at the start of each new cycle.
- The first cycle begins on the subscription anchor date.
- Each cycle advances one month at a time until the next boundary would fall after today.
- All boundaries are evaluated in UTC at start-of-day.
Example
anchor (started_at) = 2025-11-11
today = 2025-11-29 -> cycle = [2025-11-11, 2025-12-11)
today = 2025-12-20 -> cycle = [2025-12-11, 2026-01-11)
today = 2026-01-11 -> cycle = [2026-01-11, 2026-02-11) // resetsNote: if your organization has no active API subscription, usage is reported as 0 and the plan cap is shown as-is.
Quota & remaining
Your plan defines a monthly send cap (sends_cap). Remaining capacity is simply:
remaining = monthlyCap - sentInCurrentCycleThe remaining value can go negative if a single batch send pushes you past the cap; the cap is checked per request rather than per recipient, so a large to list can overshoot.
Bounce rate & account state
Alongside the sent count, SendTrim tracks how many of those recipients hard-bounced in the same cycle and derives a bounce rate:
bounceRate = hardBouncedInCycle / sentInCycleThat rate drives an account state used to protect deliverability:
GOOD
Bounce rate ≤ 2%. Normal sending.
WARNING
Bounce rate > 2%. Sending continues; clean your lists.
SUSPENDED
Bounce rate > 5% (after ≥ 100 sends). New API sends are rejected with 400.
Below 100 sends in a cycle, the account can only be GOOD or WARNING — suspension only applies once there is a statistically meaningful volume (≥ 100 sends).
Worked examples
1 request, 3 recipients
to: ["a@x.com", "b@x.com", "c@x.com"]
cc: ["mgr@x.com"]
bcc: ["audit@x.com"]
counted = 3 // only "to"; cc and bcc are ignoredA reply does not count
POST /api/v1/emails/{referenceId}/reply
to: ["customer@x.com"]
counted = 0 // is_reply = true -> excluded from usageCycle total
Cycle [2025-11-11, 2025-12-11):
send #1 to: 200 recipients -> +200
send #2 to: 50 recipients -> +50
reply to: 1 recipient -> +0
send #3 to: 300 (later deleted) -> +0 (deleted_at set)
sentInCycle = 250FAQ
Does sending to the same address twice count twice?
Yes. Counting is per recipient per send, with no deduplication across requests.
Do bounced emails refund my usage?
No. A recipient is counted when the send is enqueued. Bounces are tracked separately only to compute your bounce rate.
When does my counter reset?
At the start of each monthly cycle, anchored to your subscription start date — not on the 1st of the calendar month.
Where can I see my current usage?
The API usage summary returns sent, remaining, hardBounces, bounceRate, and state for the current cycle.