Skip to content

2026-09-10

Invoices, ninety days of uptime, and a key you can use before you sign up

A published sandbox key, so the first request in the docs is one that runs. Proper invoices with a tax number and a billing address, and a portal button a pack-only customer can actually see. Ninety days of measured availability with an honest account of what it cannot see, plus an incident log and a feed. And a conversion footer that copies a command that works.

  • The first request in the documentation now runs. Every generated sample printed sk_live_…, so evaluating this API meant creating an account, confirming an email and minting a key before you could see a single real response. There is a published sandbox key now. It answers a handful of read-only lookups for the sample values the documentation prints — the test addresses, the fiction-block numbers, the sample IP and postal address — and refuses everything else with a typed error that names what it would have answered for.
  • It is a credential everybody has, so its limits are the point: no account behind it, no credits spent, nothing written that lasts, no arbitrary value looked up, and its own small budget counted per source address. Anything that would cost something — a callback URL, a forced refresh, the live carrier check, the deliverability check — is refused rather than ignored. meta.sandbox is true and credits_remaining is null, because there is no balance it could be about.
  • Businesses can get an invoice. Checkout collected no tax number and no billing address, and a credit pack produced a receipt rather than an invoice — so an EU or UK company could not get the reverse-charge document its accountant needs. Both now ask for a tax number (optional: a private buyer has none) and a billing address, and a pack raises a real invoice. Past invoices are listed on the billing page with the number, the date and the total each one states.
  • A customer who only ever bought credit packs could not reach the billing portal at all. The "Card and invoices" button sat inside a branch that only rendered for subscribers, so a pack customer had no way to update their card and no way to read past invoices. It is reachable by anyone with a card on file now.
  • Ninety days of measured availability, and a straight account of what it cannot see. /status had no memory: no uptime figure, no incidents, no feed, and the raw data was deleted after a week before anything could roll it up. There is a daily rollup now, a ninety-day strip on the status page and the same figures on the status endpoint.
  • Read it as a floor on the bad days, never as proof of a good one — and the page says exactly that, at some length. It only counts requests that reached this server and were recorded. A whole day of outage is blank, and blank is never counted as good; but an hour of outage leaves the other twenty-three, and the day can read as a clean 100%. A partial outage is the common case and this figure is close to blind to it. A fault that also stops the recording write — a database incident, the likeliest cause of a real burst of 5xx — takes those failures out of the number along with everything else. There is an incident log because that is where an outage is actually described, by a person, and a feed at /status.rss to follow it.
  • The widgets ask for something now. All four ended at the verdict with the nearest sign-up button a page-height away. There is a footer under each: "Copy as cURL" writing the real request for the value just typed, a link to the full response fields, and the way to get a key. A test replays every command the footer offers against the real API, and another pins each widget's own default to the command being replayed — so a widget cannot quietly start copying something that fails.
  • The landing page and the product pages read as one site again. They had drifted into two design languages, one with uppercase section eyebrows and one without; the rule already said which wins, and the eyebrow text is folded into the headings rather than dropped.
  • Three things found while checking the above, all in work from this same day. A value that was not a string — {"email": ["a"]} — made the sandbox throw rather than refuse, so a credential printed in our own documentation could force a 500 on the most-read endpoint on the site. Sandbox calls were being kept out of the request timings entirely, which was right for the latency percentiles and quietly took sandbox failures out of the availability figure that exists to catch them; they are recorded and flagged now, so each number sees what it should. And the availability strip's own caveat was wrong in the direction that flatters us — it described a whole-day outage and left the reader to assume it covered a partial one.
  • Smaller corrections: the invoice list said every row carries a tax number and a billing address, which is not true of anything bought before today; the billing page was making an outbound call to Stripe on every tab focus, which also made the local credit balance wait on it; the consistency product page still said "four signals" in six more places; and the rate-limit reference page did not know about the sandbox budget, so a reader meeting it had nowhere to look it up.

markdown version: /changelog/2026-09-10-invoices-uptime-a-sandbox-key-and-a-way-in.md · atom feed: /changelog.atom

All releases