Billing & Credits
Sending is prepaid: you buy credits in the customer portal at https://emails.routeon.io, and every message draws on that balance. This page explains what costs a credit, how to read the balance and the per-class headroom, how protected minimums and credit lines work, and what happens when credits run out. Buying credits and configuring credit protection are portal actions; the API reads balance, activity, statements and invoices.
What costs a credit
Every message costs one credit, whatever its class or size: a transactional email, an OTP code, one campaign recipient, one automation send step, and one address of a template test send.
- Reserve. The credit is reserved before the message is created — per request for transactional and OTP sends, per
sendstep for automations, and per batch of recipients for campaigns. Template test sends are charged when each message is dispatched. - Spend. When the message is handed to the mail provider, the reserved credit is spent. Whatever happens afterwards — delivery, bounce, complaint — it is not returned.
- Refund. When a message fails before hand-off (
suppressed,canceled, orfailedfor a reason such asdefer_cap_exceededor an unusable domain), its credit is returned automatically. See Messages.
A request refused before any message exists costs nothing.
Balance
GET /billing/balance returns:
| Field | Description |
|---|---|
credits |
The balance. It can be negative when a credit line is in use; a negative balance is a debt, not an error. |
credit_protection_enabled |
Whether your protected minimums apply. It affects only the two minimums below, not the credit lines. |
min_credits_otp / min_credits_transactional |
Protected minimums reserved for OTP and for transactional mail, in credits; null means none. Configured by the account owner in the portal. |
credit_line_otp / credit_line_transactional |
Credit lines granted to your account by the platform, as positive numbers; null means none. Read-only. The transactional line never exceeds the OTP line. |
available_to_otp |
What an OTP send could spend right now. |
available_to_transactional |
What a transactional send could spend right now. |
available_to_marketing |
What a campaign or automation could spend right now. |
auto_recharge |
There is no automatic top-up: the balance only grows through purchases and platform adjustments. |
Credit protection and credit lines
The balance is shared by all classes, but it is spent along a priority ladder so that marketing can never use up the credits your login codes and receipts depend on.
- Protected minimums (
min_credits_otp,min_credits_transactional) keep part of the balance back for higher-priority mail. They apply only whilecredit_protection_enabledistrue; otherwise they count as zero. - Credit lines (
credit_line_otp,credit_line_transactional) let OTP and transactional mail continue below zero, up to the granted amount. They apply whether or not protection is enabled. A credit line replaces the protected minimum of its class. Marketing never uses a credit line.
Each class may spend down to its own floor:
| Class | Floor the balance may reach |
|---|---|
OTP (critical) |
minus the OTP line (0 without a line) |
| Transactional | the OTP minimum, minus the transactional line |
| Marketing | the OTP minimum plus the transactional minimum |
Here "the OTP minimum" is 0 when an OTP line exists and min_credits_otp otherwise, and "the transactional minimum" is 0 when a transactional line exists and min_credits_transactional otherwise. The available_to_* fields are the balance minus that floor, never below 0. For example, with credits: 1000, protection enabled, min_credits_otp: 100, min_credits_transactional: 200 and no lines: available_to_otp is 1000, available_to_transactional is 900 and available_to_marketing is 700.
Template test sends are not held back by the protected minimums, so frequent test sends can take the balance below them.
When credits run out
A send the balance cannot cover is refused with 402, for one of two reasons in meta.reason:
INSUFFICIENT_CREDITS— the balance (including any credit line of the class) cannot cover it;CREDIT_PROTECTION— the raw balance would cover it, but it would cross a protected minimum you configured.
meta.details carries code (insufficient_credits or credit_protection), needed, balance and available, so you can show the shortfall. What happens next depends on the send path:
- Transactional and OTP — the request fails with
402; nothing is sent or charged. Retry once the balance allows it. - Campaigns — a launch can be refused with
402. During sending, a batch that cannot be funded pauses the campaign withpause_reason: insufficient_creditsorcredit_protection(see Campaigns); resume it after topping up or lowering the minimum. - Automations — the enrollment whose
sendstep cannot be funded exits withexit_reason: insufficient_creditsorcredit_protection(see Automations).
Activity and statements
GET /billing/activity— a cursor-paginated feed for a period (frominclusive,toexclusive). Rows ofkind: sendgroup debits — campaigns and automations over the whole period, transactional and OTP per day — withmessages,refunded_messagesand netcredits; rows ofkind: accrualare top-ups and adjustments. The first page of a period also returnsmeta.totals:opening_balance,closing_balance,credits_spent(gross; refunds do not reduce it),credits_received(gross; includes refunds) andmessages.GET /billing/activity/messages— the messages behind one activity group, selected bysource_type,source_idand, for every group except campaigns and automations,day;to_emailnarrows by a case-insensitive part of the recipient address. Each row says whether the message wasrefunded.GET /billing/statement— a CSV file for a date range (both ends inclusive).kind=summary(default) has one row per activity group and covers up to 92 days;kind=messageshas one row per message and covers up to 31 days and 200 000 rows. For days outside your message-log retention period, message rows remain but their recipient, status and send time are empty.
Invoices
GET /billing/invoices lists the invoices of your credit purchases, cursor-paginated.
| Field | Description |
|---|---|
number |
The invoice number. |
amount / currency |
The total in minor currency units (cents) and its currency. |
status |
open — issued and not yet paid; paid — paid; void — canceled, nothing is owed. |
created_at |
When the invoice was issued. |
Related API
- Billing tag —
GET /billing/balance,GET /billing/activity,GET /billing/activity/messages,GET /billing/statement,GET /billing/invoices.
See the API Reference for full schemas. Buying credits and setting protected minimums are done in the customer portal.