Why This API Has The Limits It Has

Stage: a position we held and then reversed. In control: us, and now the answer is yes with conditions.

1. What this page used to say

For a long time this page argued that there would be no programmatic access here, and the argument was not decoration. It ran like this: the domains a generator hands out are a limited stock, every domain eventually stops being accepted on signup forms, replacing one costs money and lead time, and a machine draws that stock down at a rate no person can match. A loop does not get bored. One automated consumer pulls a narrow slice of the pool over and over, the receiving side of the internet sees a single domain appear across thousands of signups in a short window, and that is precisely the pattern that gets a domain blocked. The cost of that lands on everyone else using the site.

Every sentence of that is still true. What was wrong was the conclusion drawn from it.

2. What changed

The flaw was treating one pool as the only pool. The reasoning said an interface would spend a shared resource; it did not say the interface has to spend the same resource that visitors do. Once the two are separated, the argument stops forbidding an API and starts describing how to build one.

So the API hands out addresses on domains of its own. In the database a domain carries a role alongside its name, and the role decides who may ever be given an address on it: the site's own domain, the public pool behind the dropdown, the unlisted domains reserved for signed-in visitors, and a fourth set that exists only for the interface. Nothing crosses between them. When integrators burn through the fourth set, and they will, the fire stays inside a pool that was set aside to be burned.

A burnt domain does not vanish, incidentally. It moves to a state where new addresses are no longer issued on it while mail to addresses that already exist keeps arriving, so nobody loses a confirmation code in the middle of a run. Only later does it retire completely.

That single decision resolves most of the old objection. The rest is handled by limits that follow from the same reasoning rather than from a pricing table.

3. Every ceiling, and the reason under it

Three hundred inbox creations an hour on one key, six hundred reads a minute, one hundred live inboxes at a time. Those numbers are not a tier to be upgraded. They are the point where ordinary automated use ends and something else begins.

The two rates differ by a factor of a hundred and twenty because the operations are not comparable. Creating an inbox writes a row and spends a fraction of a domain's remaining life. Reading one costs a query against an index. Charging both at the same rate would either strangle the reads or leave the writes unguarded, so they are counted separately, and a key that trips either gets a 429 with a retry-after telling it exactly how many seconds are left on the window.

The counting is done per key rather than per network address, which is the only arrangement that works here. A build agent picks up a different address on every run, so counting by address would let one pipeline reset itself endlessly. Half a company behind one office connection shares an address, so counting by address would punish colleagues for each other. The key is the thing we actually mean.

An inbox from the API lives twenty four hours from the moment it is created, and reading it does not extend that. This differs from the website on purpose. A visitor who keeps a tab open is telling us the address is in use; a test that polls the same inbox for an hour is telling us nothing except that a loop is running, and rewarding it with a longer life would keep inboxes alive for as long as a pipeline runs. Those inboxes also stay outside the ten that an account may hold in the browser, so a key working through its hundred never locks its owner out of the website.

Sending remains unavailable, in any form, exactly as it is on the site. Receiving is the whole product.

4. The key itself is deliberately unhelpful to a thief

One active key per account, and a new one revokes its predecessor in the same operation. That is the whole of key management, because a second concurrent key solves nothing: rotation is issue-then-revoke, and there are no roles to divide between keys when the interface has exactly one role.

The value is shown once. What the database keeps is a hash of it plus the last six characters, which is enough for you to recognise which key is in which pipeline and not enough for anybody, us included, to reconstruct it. Lose it and you issue another.

It travels in an Authorization header and nowhere else. Keys in a query string are refused on principle: query strings survive in proxy logs, in browser history and in error reports, and the owner of a key leaked that way is invariably the last person to find out. There is also no expiry date, because a key that quietly dies at three in the morning inside somebody's build server is a worse outcome than one that lives until it is revoked.

5. What it does that the browser cannot

Two capabilities exist only through the interface, and both remove work rather than adding a feature.

Messages are pushed. A connection stays open, a comment line goes down it every twenty five seconds so nothing in between decides it has stalled, and the server speaks when mail lands. The polling loop that every integration used to open with does not need to be written. The same mechanism has been serving the website since the first day, and this is a second door onto it.

The confirmation code comes back extracted. Ask for it and the request waits, for thirty seconds by default and up to two minutes if you say so, then returns the digits and the activation link alongside the message itself. The wait is not a loop with a sleep in it: the connection subscribes to the same notification channel the website uses and costs nothing until an email actually exists. Pass a sender fragment and it ignores everything else that lands. Pass a timestamp taken before you triggered the signup and a leftover message from the previous run cannot pass itself off as this one.

The extraction is opinionated because guessing well is the entire value. The subject line is searched first, since it carries the code more often than the body and almost never carries competing numbers, whereas a body is full of order references, totals and years. Four to eight digits count; anything shorter is not a code and anything longer is usually an identifier; a bare year is discarded on sight. In the body the search prefers a number standing next to a word like code, pin or otp, in four languages. For the link, unsubscribe and preference-centre URLs are filtered out before the first plausible confirmation link is chosen. Everyone who has automated a signup flow has written that parser at least once, usually against one vendor's template, and usually again six months later when the template changed.

6. What it is not for

An address from this pool is recognisably disposable. It is meant for systems you own: your test suite, your staging environment, an agent you control, a signup flow of yours that needs checking in five languages without five rounds of clicking.

A key also only ever sees what it created. On the website a guest inbox opens to anyone who knows the address, which is a fair trade for convenience; through the interface that rule is dropped, because addresses in test suites are predictable and one integrator reading another's confirmation codes is not a trade anybody agreed to.

Pointed at somebody else's service to farm accounts or slip past their limits, it stops being a tool and becomes an incident, in their logs first and ours shortly after. Pretending we cannot tell the difference in traffic would be the same wink this page refused to give when it was arguing the opposite case.

7. When your own infrastructure is still the right answer

One thing has not changed since the earlier version of this page. If a pipeline needs a mailbox on every run at high volume, and the mail comes from a system you control, then receiving it in infrastructure you also control is faster, private, and free of anyone else's domain reputation. That path costs an afternoon and then belongs to you.

The interface here is for the case in between: real signup flows on services you do not own, checked occasionally rather than ten thousand times a day, where standing up mail infrastructure to test one form is the wrong shape of effort.

The handover

The reference for every endpoint, along with the key, lives on the API page. If what you needed was one address for one form, the generator on the front page is still faster than reading this. How the address string is put together in the first place is in how an address generator works, what the receiving site does with it starts in what happens the moment you submit, and if the reason you came here was volume rather than convenience, why mass signups do not work covers what actually catches them.

Read next

All guides