Identity for your own login page

Your login page.
Your domain.
Never billed
per user.

Every other auth vendor's price goes up when your app starts working. Ours cannot, because auth is not what we sell. Monthly active users are metered and never billed — at every size.

$15/mo or $150 a year — two months free
14-day free trial on your first subscription · card collected at checkout · cancel any time
your monthly auth bill · as your users growthe two shapes
bill users / mo $0 1k 10k 50k 100k 500k priced per monthly active user $15.00 flat
Parsons — $15, flat priced per monthly active user — cheaper until it isn't

Shapes, not quotes — no rival's numbers appear on this chart. Note where the other line starts: below ours. A vendor priced per monthly active user is usually cheaper than us while you are small, and several are free at your first few thousand users. We draw it that way because it is true, and because it is the whole point — nobody leaves an auth vendor while they are small. What we can promise is the other line: any bill computed from your monthly active users rises when your product works, and ours cannot, because monthly active users are metered and never billed, full stop. Check theirs yourself — clerk.com/pricing · supabase.com/pricing · auth0.com/pricing.

What you are actually afraid of

Success is when the bill detonates.

Nobody churns off an auth vendor while they are small. They churn later, once the invoice has quietly grown a second page — and by then leaving means asking every user you have to reset a password nobody can export. That is not a pricing accident. It is what happens when a vendor's revenue is computed from your user count. Ours is not.

a metered identity vendormonthly
Base planfixed
B2B organizationsadd-on
Admin tooling, user impersonationadd-on
Enterprise SSOper connection
Extra sign-in domainadd-on
Retained users above the included tierper user
Totalmoves with you

No vendor named and no figure invented — these are line-item shapes, not quotes. Read any per-user identity vendor's own pricing page and you will find some arrangement of them. The point is not how large the number is. The point is that it is a number which grows when your product does.

parsonsmonthly
Base — every product, every project$15.00
Total$15.00

And then it stops. There is no organizations line, no impersonation line, no per-connection line and no retained-user line, because monthly active users are metered and never billed. The next row on this invoice is blank at 500 users and blank at 500,000.

The price can change under a shipped product
A vendor whose revenue is computed from your user count always has a reason to re-price you once you have launched and cannot easily leave. We do not have that reason, because we never bill your user count.
The migration costs more than the increase
Password hashes do not port between vendors, so leaving means asking every user you have to reset one. Teams do the arithmetic and conclude it is cheaper to keep paying.
Your users see a domain that isn't yours
A vendor-owned sign-in host in the address bar at the exact moment you are asking someone for their password — with a "secured by" line under it carrying somebody else's name.
The turn

We don't sell auth.

Auth cannot be our growth lever, because it is not our product. Parsons is a platform of twenty-two services on one subscription, and identity is the part that has to exist before any of the others make sense. So we built it, we meter it, and we stopped there.

Parsons — Base$15.00
authai gatewayassistantsbillingcloudcrmdatabasedeploydomainsemailfitnessjournalmcp hubmoneymusicnotificationsphoneradarschedulersocialstoragetracker

Auth is not highlighted in that list, and that is the point. It is one chip among twenty-two, at the same weight as the rest — not a line item, because it is not a product here. It is plumbing that comes with the account.

The mechanism

The redirect that never happens.

Most auth products move your user to a host they control, take the credentials there, and bounce them back. Ours never enters the address bar. Your login form posts to your backend; your backend calls /v2/authenticate with its secret key and gets tokens straight back in the response body.

There is no hosted sign-in page of ours to brand, because we removed ours on 2026-08-02. There is nothing to charge you for taking our name off. The door is yours.

Which also means you build the login form. It is four POSTs, and we would rather say so here than have you discover it in the docs.

no redirectServer-to-server. Your user's browser never talks to us, so it never learns our name.
your emailsVerify a link base by DNS TXT and reset, verification and magic-link mail all land on your host.
your consentGoogle and Apple run on your own OAuth client, so the consent screen carries your name.
yourapp.com/pricing
the hosted-page path
User clicks Sign in and leaves your product.
secured by ▸ someone else
yourapp.comaccounts.vendor.comback, eventually
yourapp.com/login
the Parsons path
The address bar does not change. It never did.
your backend → POST auth.parsons.ai/v2/authenticate server-to-server · sk_live_
The whole integration

Four calls, no SDK.

There is nothing to learn and nothing to install. It is one JSON API on your project's sk_live_ key: sign up, authenticate, refresh, revoke. Password, Google, Apple and magic link are endpoints on that same plane, each togglable per project — a disabled method answers method_disabled rather than quietly working.

0 requests to Parsons per verified request. Access tokens are ES256 and verify offline against /.well-known/jwks.json — we are not in your request path, and we cannot be your outage.
access token 1 hour · refresh token, 30-day absolute session
user_metadata / app_metadata4 KiB each, merged server-side
/v1/users is still live and is not deprecated
Read the API reference →
POST /v2/signup
Authorization: Bearer sk_live_…
{ "email": "ada@yourapp.com", "password": "…" }
200 { "user": { "id": "usr_4f1c", "email_verified": false } }
// no session returned. email verification gates first sign-in by default
the access token, decoded
alg "ES256"  ·  typ "JWT"
iss "https://auth.parsons.ai"
aud "proj_9f4c2ab1e8d3"
sub "usr_4f1c"  ·  exp iat + 3600
That aud claim is the tenancy boundary. Pin iss and aud when you verify and a token minted for another project is not merely rejected — it is unusable.
Isolation by construction

Another tenant's valid id is a 404, not a disclosure.

One worker serves every tenant, so isolation cannot be a WHERE clause somebody remembers to write. It is a uniqueness constraint that has been in the schema since line one, and a data-access layer that binds project_id into every query it builds.

UNIQUE (project_id, email)
project_idemailidcreated
proj_9f4c2ab1e8d3ada@yourapp.comusr_4f1c2026-08-04
proj_1b77e0d5c9a2ada@yourapp.comusr_a0e82026-08-11
proj_9f4c2ab1e8d3grace@yourapp.comusr_77b22026-08-14
proj_1b77e0d5c9a2hopper@other.devusr_c31d2026-08-19
GET /v2/users/usr_a0e8  ·  Authorization: Bearer sk_live_… (project proj_9f4c2ab1e8d3) 404 not_found

The row is still on screen. It exists, it is valid, and you are holding a valid key — for a different project. The record does not disappear from the database; it disappears from your reachable universe. Same email, two tenants, no collision, no leak.

sk_live_
30 base62 chars + a CRC32 checksum
About 178 bits of entropy, stored hashed. A typo is caught by the checksum before it becomes a support ticket.
rotation
24-hour overlap, settable 0–720h
Old key and new key both work while you redeploy. Set the window to zero if you want the old one dead on the spot.
metadata
role, permissions, plan are refused at the write
Tokens verify offline with no row-level-security backstop, so a tenant trusting user_metadata.role === 'admin' would be a privilege escalation. We refuse the key rather than let you build it.
Specificity is the trust mechanism

The rung, and the parameters.

"Securely hashed" is worth nothing — everyone says it. Here are the actual numbers, the actual timings, and the one place we deliberately chose availability over strictness and will tell you why.

01 · work factor
Supabase reference
N=2^14, r=16 · 32 MiB
Parsons · OWASP rung 2
N=2^16, r=8, p=2 · 64 MiB
scrypt N=2^16, r=8, p=2 — 64 MiB per hash, PHC-string encoded. Four times the Supabase reference, and rehashed on your next successful login when the parameters move. Not PBKDF2: workerd caps WebCrypto PBKDF2 below the OWASP floor.
02 · timing
known user0.43 s
unknown user0.43 s
t = 0same tick ▲
Both bars land on the same tick, and that is the feature. The miss path does the same work against a DUMMY_HASH, so response time cannot tell an attacker whether an address is registered. Passwords are NFKC-normalised first, so a smart quote is not a different password.
03 · failure posture
HIBP reachable breach-checked
HIBP times out (2 s) let them in
New passwords are checked against known breaches by k-anonymity — the full password never leaves us. The check has a 2-second timeout and fails open: a third party's outage will never lock your users out of your product. We chose availability here on purpose, and we would rather print it than bury it.
Bot protection

The setup you didn't have to do.

The alternative to a platform-supplied captcha credential is not "the tenant configures one". It is "the tenant ships an unprotected signup form", because the setup starts with creating an account at a third party and a step like that does not get done.

So new projects start at captcha: "platform". Signup, password recovery and magic link are bot-protected for any app on *.parsonsapps.com with no Cloudflare account of your own — and the platform credential is hostname-pinned to that project's verified link base, so one tenant's solved token cannot be spent against another tenant's project. Your own credential always wins if you bring one.

01 create a Cloudflare account
02 create a Turnstile widget
03 copy the sitekey
04 copy the secret
05 set two environment variables
06 redeploy and hope
becomes captcha: "platform"the default on every new project
stateoutcome
Unconfigured — no credential anywherepass
Configured, request carries no tokenfail
Configured, verifier unreachablefail

Three states, printed because the third one is the interesting one. When the captcha verifier cannot be reached, the request is refused — the opposite of the breach check, which fails open. A breach check failing open costs you nothing; a captcha failing open costs you a bot flood. Different failure, different posture, both decided on purpose.

coverssignup · password recovery · magic-link request
pinned tothe project's verified link base — issuance is not authorization, the same reason the JWT pins aud
introspectGET /v2/captcha-settings returns the sitekey and exactly which endpoints will refuse without a token
Published, because nobody else does

The actual rate limits.

"Rate-limited" is a phrase, not a number, and a phrase cannot be checked against your traffic. Here are ours, unrounded, so you can decide whether they fit before you integrate — rather than afterwards, from a 429 in production.

bucketwhat it protectslimit
/v2 per keyyour server-to-server plane300 / 60 min
/v2/authenticate/refresh per keytoken refresh, which is chattier by nature3,000 / 60 min
/v2 per origin IPone misbehaving host600 / 60 min
/v2 per accountcredential stuffing against one user10 / 2 min
console sign-in per IPour own console door20 / 10 min
console sign-in per emailone targeted account10 / 2 min
OAuth startsocial sign-in initiation30 / 15 min
password resetreset-mail flooding10 / 3 min
password changean authenticated abuse path5 / 1 min
/v1/usersthe older admin plane, still live120 / 120 min
every counter key is shapedrl:{projectId}:…

That prefix is not cosmetic. One worker serves every tenant, so an unscoped bucket would be cross-tenant denial-of-service by construction: a noisy neighbour would spend your budget. Counters live in Durable Objects, and the project id leads every key.

after you verify a link base
PacStow <no-reply@pacstow.com>
Confirm your email address
before — ours catches it
Parsons <no-reply@parsons.ai>
Confirm your email address
the record you add, once
typeTXT
name_parsons.pacstow.com
valueparsons-link-base=proj_9f4c2ab1e8d3
// one project, two products, two From lines
appBranding: {
  "pacstow.com": { appName: "PacStow" },
  "otherapp.com": { appName: "OtherApp" }
}
Mail that comes from you

The From line is yours from day one.

Verify a link base with one DNS TXT record and every auth email — verification, password reset, magic link — lands on your host with your sender name. Until you do, ours catches it, so nothing is broken while you are still setting up.

automaticApps you deploy on Parsons get a verified link base on their next deploy. You do not touch DNS at all.
re-checkedA daily cron re-verifies the TXT record. If it vanishes we clear the base and log it loudly — you would otherwise find out from a customer noticing the branding changed.
per hostnameOne project can serve several products. appBranding is keyed by hostname, so each product's customers get mail from that product's name.
introspectableget_project reports the link base, the From line and whether it is yours or ours — resolved the same way the send path resolves it, so it can never report an address the mail would not carry.

Honest gate: magic link is unavailable until a link base is verified — the request answers link_base_required. A magic link's whole effect is a session, and only a page of yours should be able to create one. Do not plan on it for day one.

Run it from your assistant

Twenty-three tools — and the two we took away.

Identity vendors ship MCP servers now, so "an AI can drive it" is not a differentiator any more and we will not pretend otherwise. Ours is narrower and more specific: the secret never enters the model's context in the first place, and the irreversible operations are absent from the schema rather than confirmable within it.

kelly@ is phishing our users — shut her out, but don't delete anything
parsons_auth → disable_user Done. Live sessions revoked. The account is now refused at every door — password, magic link, social, and token refresh. Nothing was deleted; enable_user reverses it.
rotate the production key
parsons_auth → rotate_project_key Here is a session-gated link. I can't rotate it for you — a human has to be present when a production key is replaced. The 24-hour overlap starts when you confirm.
removed from the AI surface · 2026-07-12
purge_project_data delete_account
Not gated. Not behind a confirmation. Gone from the tool list. A confirm: true argument is supplied by the model, which makes it a formality rather than a safeguard, so the two operations that can destroy a business live behind a console page where you type the project's name. The machinery still works — it runs a cross-service purge fan-out — it just is not something an assistant can reach.
projects 5
list_projectscreate_projectget_projectupdate_project_configrotate_project_key
your own account 7
list_sessionsrevoke_sessionrevoke_all_sessionslist_identitiesset_display_namechange_passwordunlink_social
end users 5
list_usersdelete_userdisable_userenable_userauth_stats
the console chat-first
Ask authOverviewUsersAPI keysActivitySettings
webhooks 3
set_webhookget_webhookdelete_webhook
meta 3
whoamidocsaudit_log
the keycreate_project withholds the sk_live_ and returns a URL for your own browser. Not stripped from the response — never put in it. A leak test greps the tool result for the prefix.
the docsThe docs tool serves the same reference as GET /docs, so the assistant integrating your app pulls the real API mid-task instead of inventing an SDK from training data.
the trailaudit_log has two scopes: your project's events, and your own — sign-ins, failed attempts against your address, password changes. It resolves failed attempts against your live email, so changing it cannot hide the attack.
one connection · minted for you at sign-in
Every Parsons service, through one MCP profile.
Auth, database, storage, email, scheduler and the rest arrive on the same connection, with per-profile tool grants and per-member allowlists. You do not assemble it — it is waiting in the console.
Get yours →
The part nobody else can price

Unlimited projects. No extra cost.

A project is a whole isolated world: its own users, its own keys, its own data, its own members and its own spend caps. Run your business in one, your side project in another, a client's app in a third. There is no project cap in auth and no project cap in the plan.

pacstow
usersown directory
sk_live_ keyown
spend capown
membersown
weekend-app
usersown directory
sk_live_ keyown
spend capown
membersown
+ as many as you like$0 each
one subscription
$15 covers every product, not this one
$15/mo — $150 paid yearly — buys the whole platform on one account and one bill — auth, database, storage, deploy, email, scheduler, notifications, CRM and the rest. Auth is not billed on its own and never will be.
unlimited projects
Separate businesses on one bill
Where other platforms gate this behind workspace tiers or dashboard seats, ours are unlimited and cost nothing extra. A client's app, your business and a weekend idea can all live on the same $15, each with its own users, keys, members and spend cap.
members
Invite by signed claim link
Seven-day signed invites to any address, an explicit Accept rather than a GET side effect, and each member carries an allowlist of which MCP profiles they may use. Not per-seat priced, because we do not price per seat.
The credibility purchase

What we don't do.

This section is here so the rest of the page is believable. If one of these is a requirement, buy something else today — we would rather lose the sale than the argument in three months.

Not built — buy elsewhere if you need it
No roadmap dates, because a roadmap date is a promise and we are trying to make fewer of those.
  • TOTP / multi-factor authentication
  • Passkeys
  • Roles, RBAC or a permissions model
  • SAML and enterprise SSO
  • B2B organization primitives
  • Pre-built UI components — no <SignIn/> to drop in
  • Bulk data export — there is GET /v2/users/{id} and list_users to page through, and deletion that genuinely completes, but no CSV and no bulk dump. We will not claim an export we have not built.
Missing on purpose — and the reason
Each of these is a decision, and each has a cost we are choosing to pay.
  • No hosted login page — ours was removed 2026-08-02. The door is yours, which also means you build the form.
  • No shared social client — Google and Apple run on your own OAuth client. It is a real onboarding step, and Apple is a one-way door: its sub values and private-relay addresses are team-scoped, so you cannot start on ours and move later. There is no "ours" to start on.
  • role, permissions and plan refused in metadata — offline verification has no row-level-security backstop, so we refuse the write instead of shipping you a privilege escalation.
  • Magic link needs a verified domain first link_base_required until you prove one.
  • Enumeration-safe on your plane, deliberately not on our own console signup — a pinned asymmetry, both halves locked by tests.

We publish every difference from GoTrue in a divergence log, on the principle that we copy the reference implementation and every deviation needs a written justification or it is a bug. Fifteen rows so far, including the ones that make us look worse.

Honest, including where we lose

Eleven rows. We lose four.

A comparison table that only flatters its author reads as a lie, so the rows we lose are at the bottom in full weight rather than quietly omitted. If you scrolled here to find out whether we do SAML, the answer is at the end and it is no.

Parsons AuthClerkAuth0Supabase AuthWorkOS
Monthly active users billedNever, at any sizeMetered above 10,000Metered per MAU
Projects on one accountUnlimited, $0 eachOne instance per project
Tenant isolationUNIQUE (project_id, email), one workerOne instance per project
Login page lives onYour domain — we have no hosted page
Rate-limit numbers publishedAll ten buckets, on this page
Password-hash parameters publishedscrypt N=2^16, r=8, p=2
Irreversible ops on the AI surfaceAbsent from the schema
MFA / TOTPNot builtYesYesYesYes
PasskeysNot builtYesYesYes
SAML / enterprise SSONot builtYesYesYes — this is their product
Organizations & RBACNot builtYesYesYes

We lose four of eleven. MFA, passkeys, SAML and organizations. If you need any of them, WorkOS or Clerk will serve you better than we will, and we would rather you found that out here.

Our column is read off the shipped code, and every figure in it appears elsewhere on this page. Rival columns record only what we could confirm from each vendor's own public documentation; a dash means we could not, and we would rather leave a cell blank than guess on somebody else's behalf. We list no rival prices at all — theirs change, and ours is the only one we are in a position to promise.

Pricing

Fifteen dollars — for the whole platform.

And here is the part that would annoy a salesperson: there is exactly one plan. Unlimited monthly active users on it, and no tier above it holding anything back — if auth is all you need, $15 is the whole bill.

Base
$15 / month
or $150 / year — two months free
auth on this plan
Unlimited monthly active users
Unlimited projects · all four sign-in methods · the whole /v2 API · ES256 tokens · webhooks · 23 MCP tools.
  • Every Parsons product on one account and one bill
  • 1 GB database · 5 GB object storage · 200 emails/day
  • 10,000 tracker tasks · 50,000 CRM contacts · 20,000 scheduler fires
unlimited users is the plan, not the teaser
The obvious question

"Fifteen dollars. Against what?"

Taken one product at a time, this is not the cheapest thing you can buy, and we are not going to pretend it is — a good specialist tool in any one of these categories can cost the same as us or less. The comparison that matters is the bill you actually pay at the end of the month, and there the arithmetic is not close.

One product, or twenty-two
Fifteen dollars is not the price of auth. It is the price of the platform auth sits inside — database, storage, deploy, email, scheduler, notifications, CRM, tracker and the rest, on one account and one bill. Pick the best specialist for four of those and you have four subscriptions, four renewal dates and four onboardings, for considerably more than this.
The lines we never add
No per-seat charge, so inviting your co-founder costs nothing. No per-workspace tier, no per-organization add-on, no per-connection SSO fee and no charge per monthly active user — the line items that turn somebody else's published price into an unpublished one.
Unlimited projects, $0 each
A client's app, your business and a weekend idea are three isolated tenants — own users, own keys, own members, own spend cap — on the same subscription. Where a workspace is the billing unit elsewhere, one subscription there quietly becomes three.
Consumption is prepaid, separately
The things that genuinely cost money — AI spend, voice minutes, phone numbers — are a prepaid wallet with its own caps, and committed items ride your subscription at a stated price. Going past an included allowance simply draws from that wallet at roughly cost × 1.5 — the bill starts when real usage does. The $15 is access, not a loss-leader hiding a metered bill.

14-day free trial on your first subscription · card collected at checkout · cancel any time
Billed monthly at $15, or yearly at $150two months free.
No per-seat pricing, no enterprise tier, no free tier — the trial, then the plan.

The questions you actually typed

Answers, including the unflattering ones.

What happens when I hit 100,000 users?
Nothing. Monthly active users are metered — we record them, and auth_stats will show you the number per project per month — but they are never billed. There is no threshold, no overage line and no tier to be pushed into. Your bill at 100,000 monthly active users is the same $15 it was at ten. Against anything metered per monthly active user, that gap only widens with every user you add — it is the one number on this page that gets better the larger you get. We keep counting because it tells us how real a tenant is; we never charge for it.
Is there a free tier?
No. There is a 14-day free trial on your first subscription, the card is collected at checkout, and you can cancel any time. Cancelling and resubscribing later does not start a second trial. After the trial it is $15/mo, or $150 a year.
Is there an annual plan?
Yes. $150 a year, against $180 if you pay by the month — so a year costs you ten months. Nothing else changes: the same allowances, the same unlimited monthly active users, the same unlimited projects. Pick the interval at checkout.
Can I export my users?
Not in bulk today. There is no CSV and no bulk dump. You can page through with list_users and read individuals with GET /v2/users/{id}, and deletion genuinely completes — a cross-service purge fan-out with a 14-day grace window and a daily cron that fails closed and escalates if it falls three days behind. But an export endpoint does not exist and we are not going to imply one.
Do my users ever see a parsons.ai URL?
Not once you have verified a link base. Sign-in is server-to-server so there is never a redirect, and after DNS verification the emails land on your host too. Before verification, auth links point at ours so nothing is broken while you set up.
What if I need MFA, passkeys or SAML?
We don't have them, and there is no date. Buy Clerk or WorkOS today — that is a genuine recommendation, not a hedge. Coming back later is easy; discovering the gap after you have shipped is not.
Can I use my own Google client?
You must. There is no shared-client fallback: Google resolves ours only far enough to return an actionable provider_not_configured error, and Apple has no fallback ever — Apple's sub values and private-relay addresses are team-scoped, so moving between Apple teams is a one-way door that would strand your users' identities. Registering your own client is self-serve, but it is a real onboarding step. Plan for it.
How do I get my users out if I leave?
The same way you would leave any of our competitors, with the same limitation: password hashes are scrypt with our parameters, and a receiving vendor generally cannot import them, so your users reset their passwords once. Profiles, identities and metadata you can read through the API. This is the industry's worst property and we have not solved it either — we are just not going to let you find out about it from a migration doc.
What happens if I stop paying?
Your subscription lapses at the end of the period and the console tells you what the plan gate does. We are not going to describe enforcement as airtight, because it is still being tightened, and a page that overstates its own paywall is a page that will be wrong.
Do I need one account per app?
No — one account, unlimited projects, no extra charge. Each project is its own isolated tenant with its own users, keys, members and spend caps. A separate project per business, or one for work and one for personal, is the intended shape rather than an upsell.
Which webhooks fire?
Three: user.created, user.deleted and user.email_verified. One endpoint per project, signed X-Parsons-Signature: t=…,v1=… as an HMAC-SHA256 over the timestamp and body, with a whsec_ secret returned once. get_webhook returns the last 20 deliveries with the final HTTP status and attempt count — a zero means we never reached you at all.

Your login page, on your domain,
on a bill that does not move.

Unlimited monthly active users. Unlimited projects. One subscription that covers every Parsons product.

14-day free trial · cancel any time · already have an account? Open the console