Batchrouter
All posts
Product
#accounts
#onboarding
#email-verification
#billing

Sign in before you verify — and a verify link that always works

Batchrouter now lets you sign in before confirming your email, fixes a verification link that could read 'invalid or expired' on the first click, and gates credit purchases on a verified address.

The Batchrouter Team

Engineering

June 10, 2026 4 min read

The first five minutes with a new tool decide whether you ever reach the tenth. For Batchrouter, those minutes start with email verification — and until this week that step had more friction than it should. You couldn't sign in until you'd verified, and the verification link itself sometimes greeted you with "invalid or expired" on your very first click. We fixed both, and tightened one thing on purpose.

These changes shipped to production on June 9, 2026 and are live now. Here's what's different.

Sign in before you verify

Signing up no longer locks you out of your own workspace. Previously, logging in before confirming your email returned a hard 403 email_unverified — you had to go find the verification message before you could see anything. Now POST /v1/auth/login issues a normal session for unverified accounts, so you land in the app right away and can look around while you get to verification in your own time.

A quiet in-app banner reminds you that your address isn't confirmed yet, with a one-click Resend verification email action so you never have to dig through your inbox for the original.

One door stays locked on purpose: admin sign-in still requires a verified email. The operator entry point keeps its stricter check as defense in depth.

The more interesting fix is the one you'll never see again. Some people clicked a fresh verification link and got "invalid or expired" on the first click — a confusing dead end for a link that had only just been generated.

The cause was a subtle collision between one-time tokens and modern email security. Verification tokens were single-use: the first request to load the confirmation page consumed the token. But mail providers like Gmail and Microsoft Safe Links prefetch links — they quietly open and render a page to scan it for malware before you ever click. That automated render spent the one-time token first, so by the time you clicked, it was already used and the page reported it as expired.

We fixed it from both sides. The verification endpoint (POST /v1/auth/verify-email/confirm) is now idempotent — a token stays valid until it genuinely expires, so a scanner opening it ahead of you is harmless and your click always succeeds. And the verify page no longer auto-submits on load: it waits for an explicit Verify my email click, so a bare prefetch never touches the token in the first place.

Buying credits stays behind a verified email

One thing got stricter, deliberately. Buying credits now requires a verified email. The check is enforced server-side at POST /v1/billing/checkout-sessions — the authoritative gate — and mirrored in the app, where the buy-credits action is clearly disabled, with an explanation and a resend link, until you've confirmed your address.

It's a one-time step, and it keeps billing tied to an address we know reaches you. Everything else — exploring your workspace, wiring up the API, reading your usage — is open the moment you sign up. (API keys are issued credentials in their own right, so they're treated as verified and programmatic access is unaffected.)

When both reminders could apply, verification comes first: the app shows a single nudge at a time, and an unverified email always takes precedence over the low-balance "top up credits" prompt — so the next step is never ambiguous.

It's a small surface — sign-in, one banner, one link — but it's the part of the product everyone touches first, so it should just work. A plain-language summary is on our changelog.

Share X LinkedIn HN RSS

The Batchrouter Team

Engineering

We build the routing engine, dispatch lanes, and settlement pipeline behind every batch.

Keep reading

All posts