Billing
Plans, the prepaid token wallet, and how each verification check is priced, including refunds for checks that end without an answer.
PricklyMails bills from a token wallet, not per request. Every plan grants a monthly token allowance, and each verification check costs a fixed number of tokens, deducted as you use them.
The wallet model
A verification request reserves its estimated cost from your wallet at submit time. When the job finishes, the worker settles the reservation:
- A fresh result debits the checks that ran.
- A definitive answer reached without the mailbox probe debits the full reservation: an address at Google, Microsoft, or Yahoo, which accept every recipient so a probe would prove nothing, or a domain that provably cannot receive mail. You pay for the answer, not for a probe that could not change it.
- An
unknownresult debits only the checks that answered and refunds the mailbox and catch-all probes; when nothing answered, the whole reservation is refunded. - A result served from the verification cache is free: the whole reservation is refunded. A recent result of the same address is reused when it ran every check you asked for, or when it is one of the definitive answers above, which no mailbox probe could change.
Plan and pricing config
GET /api/config is public and unauthenticated: it returns the plan grid (monthly token grant, prices, rate limit, max keys, max batch size), the top-up pricing, and the per-check token cost, so you can build pricing UI directly from the backend instead of hardcoding it.
curl https://api.pricklymails.com/api/config
Wallet balance
GET /api/wallet returns your current balance: available, reserved (held by in-flight jobs), total, and avg_daily_spend (a 30-day mean, useful to estimate remaining runway).
Transaction history
GET /api/wallet/transactions lists your ledger entries, newest first by default, paginated (limit default 20, cap 96; offset).
Sort with sort (occurred_at, amount, or transaction_type) and order (desc or asc).
Each entry carries job_uuid, the linked verification job, null for a credit or top-up.
GET /api/wallet/transactions/grouped returns the same ledger grouped by verification: one entry per job_uuid (a standalone credit or top-up is its own entry) carrying the latest lifecycle status, the net token effect, and the ordered reserve, commit, and cancel history.
Same sort, order, and pagination as /api/wallet/transactions.
GET /api/wallet/balance-history returns a zero-filled, oldest-first series of your available balance, for charting.
Accepts granularity (hour, day, week, or month) and days: the series holds the whole buckets that fit in those days, ending with the current one, so day over 8 days returns 8 points and month over 364 days returns 12.
Subscription
GET /api/subscription returns your active plan, status, billing cycle, current period, and monthly credit grant.
It returns a synthetic Free plan with HTTP 200 when you have never subscribed, so the endpoint never 404s.
Checkout and the billing portal
POST /api/billing/checkout creates a Stripe hosted checkout session for a plan subscription or a one-time token top-up, and returns the redirect URL.
The hosted page, shown in the optional locale you pass (en by default, or fr), asks the buyer to accept the terms of sale before paying.
POST /api/billing/portal creates a session for the Stripe customer portal (manage payment methods, view invoices).
Both return 503 Service Unavailable until Stripe billing is configured on the account.