Email Auth API
Ship Auth in
20 Minutes
Email verification → signed JWT → done. No user database. No vendor lock-in. Just the one primitive you actually need.
Free up to 50 MAU
What This Isn't
We do exactly one thing: verify an email and sign a JWT. Your public key, your RLS policies, your data. Outgrow us? Swap in any JWT issuer. Your Postgres policies don't change.
Zero Passwords
Users authenticate with their email. No passwords to store, hash, or breach.
Instant Setup
Generate keys, register your tenant, and start authenticating users immediately.
Postgres RLS Ready
Public key JWT verification directly in Postgres. Email-based row-level security.
Who This Is For
Vibe Coders
Ship your side project this weekend. Auth shouldn't be the hard part.
Startups
Stop paying for features you'll never use. Start with this, migrate if you need more.
Enterprises
POC in a day. Your security team can audit two endpoints.
Eliminate Password Headaches Forever
Passwords are the #1 attack vector in security breaches. Every password you store is a liability waiting to happen. With Effortless Magic Links, you never store a password again.
Nothing to hash, nothing to leak. Users prove identity through email verification.
Eliminate "forgot password" flows and the support tickets that come with them.
Attackers can't reuse leaked passwords from other sites against your app.
Cryptographically secure tokens that can be verified anywhere without shared secrets.
Up and Running in Minutes
No complex OAuth flows. No third-party dependencies. Just a simple, secure authentication system you can integrate in an afternoon.
They enter their email address. A 6-digit code is instantly sent to their inbox.
They type the 6-digit code from their inbox. No clicking email links, no redirects.
A signed JWT with the verified email. Use it in your backend or Postgres RLS policies.
That's all you need to integrate:
Your Database Enforces Access. Not Your App.
Public key lives in Postgres. auth.email() in your RLS policies. Defense in depth without middleware.
Even if your app has bugs, the database won't leak.
Predictable Pricing. Stupid Margins.
No per-auth fees. No overages. MAU = unique emails per month.
Each tenant gets its own RSA key pair for signing JWTs. Your users will authenticate via email, and you'll receive cryptographically signed tokens to verify in your backend or database.
| # | namevarchar | emailvarchar | phonevarchar | rolevarchar | registered_attimestamp | order_countint4 |
|---|
This script creates the auth schema with all necessary tables and functions
for JWT verification and session management.
Run the script using psql:
-- auth schema setup CREATE SCHEMA auth; -- store trusted public keys CREATE TABLE auth.trusted_tenants ( tenant_id TEXT PRIMARY KEY, public_key_pem TEXT NOT NULL, ... ); -- JWT verification function CREATE FUNCTION auth.set_jwt(token TEXT) RETURNS BOOLEAN AS $$ -- decode & verify JWT signature -- extract claims (email, role, etc) -- store in session variables ... $$ LANGUAGE plpython3u; -- helper functions for RLS CREATE FUNCTION auth.email() RETURNS TEXT; CREATE FUNCTION auth.role() RETURNS TEXT; CREATE FUNCTION auth.tenant_id() RETURNS TEXT; CREATE FUNCTION auth.claim(key) RETURNS TEXT;
The auth schema uses Python for JWT verification. Your Postgres server needs:
- plpython3u extension — Run
CREATE EXTENSION IF NOT EXISTS plpython3u;as superuser - PyJWT package — Run
pip install pyjwton the Postgres server - Cryptography package — Run
pip install cryptographyon the Postgres server
The auth.trusted_tenants table stores public keys for tenants whose JWTs should be trusted.
Run these scripts in your Postgres database to register your tenant.
At the start of each request, call auth.set_jwt() with the user's JWT.
This makes the authenticated user's info available to RLS policies.
Create RLS policies that use the auth.* functions
to filter data based on the authenticated user.
{
"email": "user@example.com"
}
{
"success": true,
"message": "Verification code sent"
}
{
"email": "user@example.com",
"code": "123456"
}
{
"success": true,
"jwt": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"user": {
"email": "user@example.com",
"name": "John Doe",
"phone": "+1234567890",
"role": "customer"
}
}