Reference
Account and usage
Three reads: what this credential is and what it may do, what you have sent this month, and whether the delivery record itself is still intact.
Who am I
/v1/meaccount:readThe first call worth making with a new key: it confirms the key works, tells you which account it belongs to, and lists exactly the scopes it carries — which is faster than discovering a missing scope from a 403 on your first send.
curl https://api.posthastemail.dev/v1/me \
-H "authorization: Bearer $POSTHASTE_KEY"
# 200
# {
# "id": "acct_Qp4Ns8Vd1Lr6Ta0YhJ3mWc",
# "name": "Acme Ltd",
# "slug": "acme-ltd",
# "status": "active",
# "environment": "live",
# "scopes": ["account:read", "emails:send", "messages:read"],
# "plan": {
# "id": "starter",
# "name": "Starter",
# "monthlyEmails": 100000,
# "maxDomains": null,
# "retentionDays": 90,
# "dedicatedIp": false
# },
# "subscription": {
# "status": "active",
# "graceEndsAt": null,
# "cancelAtPeriodEnd": false
# },
# "sending": {
# "dailyLimit": 2500,
# "sentToday": 418,
# "remainingToday": 2082,
# "warmupTier": 3,
# "sentThisMonth": 21044,
# "remainingThisMonth": 78956
# }
# }| Field | Notes |
|---|---|
| id / name / slug | The account. slug is stable and is not changed when the account is renamed, so it is safe to store. |
| status | active, suspended or closed. A non-active account cannot authenticate at all, so in practice this reads active. |
| environment | live or test, from the key. A label only — both send real mail. |
| scopes | Exactly what this credential may do. Worth asserting against at start-up rather than at 3am. |
| plan | { id, name, monthlyEmails, maxDomains, retentionDays, dedicatedIp }. maxDomains is null when unlimited. |
| subscription | { status, graceEndsAt, cancelAtPeriodEnd }, or null when there is nothing to say — a banner that appears for every account with no subscription is noise that trains people to ignore the one that matters. |
| sending | dailyLimit, sentToday, remainingToday, warmupTier, sentThisMonth, remainingThisMonth. Everything needed to avoid a 429 rather than react to one. |
| Status | When |
|---|---|
| 200 | The account. |
| 403 forbidden | The key lacks account:read. |
| 404 not_found | The account no longer exists. |
Usage for the current month
/v1/usageaccount:readTotals for the current UTC calendar month, with the daily series behind them. The series ships alongside the total deliberately: a customer questioning a number should be able to see which days produced it without asking us.
curl https://api.posthastemail.dev/v1/usage \
-H "authorization: Bearer $POSTHASTE_KEY"
# 200
# {
# "periodStart": "2026-08-01",
# "periodEnd": "2026-08-31",
# "sent": 21044,
# "delivered": 20781,
# "bounced": 212,
# "complained": 4,
# "deliveryRate": 0.98750,
# "complaintRate": 0.00019,
# "bounceRate": 0.01007,
# "days": [
# { "day": "2026-08-01", "sent": 702, "delivered": 694,
# "bounced": 7, "complained": 0 },
# …
# ]
# }| Field | Notes |
|---|---|
| periodStart / periodEnd | First and last day of the current UTC month, as YYYY-MM-DD. |
| sent | Accepted messages. This is the billable figure. A message we refused was never attempted, so it is never counted. |
| delivered / bounced / complained | Outcomes so far. Mail sent late in the month may still be in flight. |
| deliveryRate | delivered / sent. |
| complaintRate | complained / delivered — measured against delivered mail, which is what a receiving provider measures. |
| bounceRate | bounced / sent — measured against what we attempted. |
| days[] | One row per day that had activity, oldest first. Days with nothing on them are absent here — unlike /v1/stats/messages, which fills them in with zeroes for charting. |
The rates here are fractions, not percentages. A complaint rate of 0.00019 is 0.019%. The rates on /v1/stats/messages are percentages — 0.02 there means the same thing. Multiplying the wrong one by 100 is how a healthy account ends up on an alerting dashboard in red.
The counters are written by a trigger on the event log rather than tallied separately, so usage is a projection of the append-only record. Every unit counted has an event behind it, which is what makes the number defensible when somebody queries a bill.
Verify the whole record
/v1/account/verifyaccount:readReplays your account’s entire event chain, in order, and reports the first break. This is the strong version of the tamper-evidence claim: not “these two rows still hash correctly” but “nothing in your whole delivery history has been altered or removed”.
curl https://api.posthastemail.dev/v1/account/verify \
-H "authorization: Bearer $POSTHASTE_KEY"
# 200 — the record is intact
# {
# "intact": true,
# "brokenAt": null,
# "problem": null,
# "checked": "every event on this account, in order"
# }
# 200 — it is not. This is evidence, not an outage.
# {
# "intact": false,
# "brokenAt": 40912,
# "problem": "hash mismatch",
# "checked": "every event on this account, in order"
# }| Field | Notes |
|---|---|
| intact | Whether the chain verifies end to end. |
| brokenAt | The sequence number at which the record stops being trustworthy, or null. It is a position, not an identifier. |
| problem | What went wrong — a hash mismatch, a sequence gap — or null. |
| checked | A plain statement of what was verified, so the answer cannot be over-read. |
This is the account-wide check. The per-message equivalent is recordIntact on GET /v1/messages/:id, which proves those events’ contents are unaltered but cannot prove nothing was deleted — the events either side of a message’s own belong to other messages.
The work happens in the database rather than by shipping every event to a process, because “every event” is the point and an account can have millions of them. Expect it to take longer than the other reads on a large account.
Keys
GET /v1/api-keys lists this account’s credentials, including revoked ones. It is documented with the rest of authentication.
NextBilling →Subscription state, the commercial history, and downloadable invoices.