Hold queue
No email is ever silently dropped. When Frontmail cannot send a message right now – because your organization is out of credits, or because your email service rejected its credentials – the message is accepted, stored safely in the hold queue (Held messages in the dashboard) and sent automatically as soon as the problem is solved.
When messages are held
Section titled “When messages are held”| Reason | Status | Triggered by |
|---|---|---|
| No credits | held | No grant with remaining credits (quota, packs and overdraft all used up) and the organization uses hold mode |
| Service error | held_service_error | The provider rejected the credentials (authentication error) and the template has no working fallback service |
For credit holds, the API answers right away:
HTTP/1.1 202 Accepted
{ "message_id": "msg_01J9Z3K7Q2", "status": "held", "status_token": "…" }The SDKs resolve with status: 'held' – it is a success, not an error. Show your visitor a normal
confirmation; the email will go out once credits are available.
Service holds happen later, in the sender: the message was accepted as queued, the provider
refused the credentials, the credit was refunded and the message moved to held_service_error.
How long messages are held
Section titled “How long messages are held”| Plan | Hold duration |
|---|---|
| Free | 3 days |
| Starter, Pro, Business | 14 days |
The duration is counted from the moment the message was held, using the plan you are on at that
time. When held messages will expire within the next 24 hours, the owner, admins and billing
members get a “held emails expire soon” email (at most once a day). Messages that reach the
end of the hold duration are discarded (status discarded), and the same people get an email
listing them, with a link to download the full list as CSV. A held message is never discarded
without anyone being told.
Hold queue limit
Section titled “Hold queue limit”One organization can have at most 10 % of its plan’s monthly quota on hold – at least 1,000 and
at most 10,000 messages (Free, Starter, Pro: 1,000; Business 50k: 5,000; Business 100k and
200k: 10,000). When the queue is full, new requests without credit are rejected with 402
insufficient_credits and
details.reason: "hold_queue_full" instead of being held. Someone who copied your public key
therefore can’t fill the queue with junk that – released oldest first – would use up every new
credit before your real messages. Release or discard held messages, or buy credits, to make room.
Automatic release
Section titled “Automatic release”Frontmail releases the queue automatically whenever credits appear:
- a credit pack is purchased,
- an auto top-up succeeds,
- you upgrade your plan,
- a new billing period starts (subscription renewal; Free: new calendar month),
- Frontmail support adds bonus credits.
…and, for held_service_error messages, when the service becomes healthy again (credentials
updated, OAuth reconnected, or a successful health check).
Release processes held messages oldest first. For each message it reserves a credit, moves it
back to queued and hands it to the sender. It stops at the first message for which there is no
credit – the rest stay held, still in order. Release is safe to run concurrently; a message is
never sent twice.
Messages sent with the public key are released automatically only from credits other than the overdraft, unless you allow public-key traffic to use it in Billing → Buy credits → Spending by public-key traffic. If only overdraft is left, such messages stay held while other messages are released. A manual Release in the dashboard may use the overdraft for them.
Held messages are rendered with the template version that was current when they were accepted.
Manual release and discard
Section titled “Manual release and discard”Held messages in the dashboard lists every held message, oldest first, with the columns Held since, template (with the subject), recipient, Reason and Expires. Rows that expire within 24 hours are highlighted. Filter by reason with All / No credits / Service error. Owners, admins and developers can:
- Release N – release the selected messages. Useful after fixing a service, or to send the most important messages first when you only have a few credits. Messages are released oldest first while there are credits; the rest stay held and the dashboard tells you so.
- Release all – release every held message, oldest first, as far as credits allow.
- Discard N – discard the selected messages after a confirmation. They are never sent and don’t use credits. This can’t be undone.
Owners and billing members also see a Buy credits button on the page. If your organization
uses reject mode, the page shows a note that new requests are rejected instead of held.
The top bar of the dashboard always shows how many credits are left (N requests left). Click it for the breakdown by source (subscription, credit packs, bonus, overdraft) and the nearest expiry. When messages are held, a red badge with their number appears next to it and links to Held messages.
hold vs reject mode
Section titled “hold vs reject mode”Each organization chooses what happens when there are no credits, in Security → When you run out of credits (owners and admins):
| Mode | Response | Use when |
|---|---|---|
Hold emails (hold, default, recommended) |
202 with status: "held", message stored and sent later |
You’d rather deliver late than never – contact forms, orders, bookings |
Reject requests (reject) |
402 insufficient_credits, nothing stored |
Late delivery is worse than none (one-time codes, time-sensitive alerts) and your code handles the error |
In reject mode the SDKs throw an InsufficientCreditsError. Service holds (held_service_error)
happen in both modes, because the request was already accepted.
Notifications
Section titled “Notifications”| When | Sent to | |
|---|---|---|
| Emails are waiting – you’re out of credits | The first time a message is held in a calendar month | owner, admins, billing |
| Held emails expire soon | At most once a day while held messages will expire within 24 hours | owner, admins, billing |
| Held emails discarded | After expiry, with the list of discarded messages and a CSV link | owner, admins, billing |
| Service not working / working again | When a service fails authentication / recovers | owner, admins |
See Notifications for all emails.
Checking status from code
Section titled “Checking status from code”const res = await send('svc_01J9…', 'tpl_order', params);if (res.status === 'held') { // Accepted and safe – it will be sent automatically.}
// Later (public-key clients need the status token from the send result):const status = await getStatus(res.messageId, { token: res.statusToken });console.log(status.status); // "held" → "queued" → "sent" …