lemma.id

When you ban someone,
they stay banned.

One account per verified human, keyed to an ID that's private to your site. Passkey sign-in is free and passwordless; require a human proof only on the actions where abuse actually hurts.

Account rotation is the attack every signal misses. The banned user comes back with a fresh email. The trial abuser rotates accounts. The presale farmer turns 500 inboxes into 500 buyers. Devices, IPs, and email verification are cheap to rotate. The only durable handle is the human.

What enforcement looks like

A visitor signs in with a passkey and your backend verifies a signed proof carrying a stable account ID that only your site ever sees. On the actions that matter — a ban appeal, a presale claim, a payout — you require a human proof on that same ID. Now the account is backed by one verified person, and coming back after a ban means passing identity verification again, not opening a new inbox.

The assurance ladder

Passkey for continuity. Human proof for consequences.

One integration, three strengths of claim. Start free, then turn up assurance per action — same account ID, no migration, nothing about your login changes.

Passkey sign-in · free

Passwordless login with a stable, site-private account ID. The same person returns as the same ID every time. This is the default, and it's all most sites need. It doesn't stop someone from making another account, since anyone can create another lemma.id.

Presence proof

A fresh passkey at presentation signing shows the holder is at the device right now. Use it on sensitive actions like payouts or deletions, without adding OTP codes.

Human proof

One account per verified human, same account ID. When you ban someone, coming back means passing identity verification again. Add it per action when abuse shows up; nothing about your login changes.

Verifiable audit stamps

Prove a verified human did it, later

Stamp a checkout, post, or moderation call with an offline-verifiable proof. Evidence stays in your systems, re-check years later without calling lemma.id. As agents write more of the internet, "a human did this" becomes the claim worth keeping.

Stamp at the action

The SDK's stamp() helper attaches a signed credential to any event your backend records.

Verify offline

Same local verifier you use at signup. No network call on audit review day.

Your data, your systems

lemma.id doesn't store your logs. Useful for chargebacks, regulators, and “human or agent?” questions.

See stamp integration →

The on-ramp is free sign-in

Passwordless login. No user data to store.

Sign in with lemma.id replaces the password and the signup form for free, and it's the same integration you later step up. It also changes what your servers have to hold and who sits in your login path.

Nothing to breach

Your user table is one opaque ID per account. No emails, no phone numbers, no password hashes. A database leak exposes identifiers that mean nothing anywhere else.

Private by structure

Every site gets a different ID for the same person, so users can't be correlated across sites. lemma.id can't profile your users or sell ads against them, because it never learns who they are.

Not in your login path

Your backend verifies proofs locally with an open verifier library. No API key to provision, no per-login call to lemma.id, and your account records stay yours.

How it works

Drop in, approve, verify

One script tag on the front end, one verifier library on your backend. lemma.id is not in the request path after that.

1

Drop in the button

Add the <lemma-signin> element with your hostname as the site ID. No registration, no API key, no dashboard step.

2

User approves a passkey

First-time visitors get a lemma.id in the popup; returning users just confirm. Either way your page receives a signed presentation.

3

Verify on your backend

The open verifier library checks the proof locally and hands you a stable, site-private ID. Use it as your account key and issue your own session.

Your login stack today

Signup form → verification email → password database → reset flows → OTP codes for anything risky → a breach target you maintain forever

With Sign in with lemma.id

Passkey approval → site-private account ID → local verification → step up to presence or human proofs where it matters → nothing sensitive to store

Verification flow, recovery, and data model →

Why teams choose lemma.id

Compare it to the sign-in you'd build instead

Every login option makes you custodian of something: passwords, emails, or a big provider's shared user ID. And none of them makes a ban survive a fresh account. Sign in with lemma.id is the option where there's nothing to hold and the consequence sticks.

Sign in with lemma.id Google / social SSO Email + password
Ban survives rotation
requires human proofs
Step up to one account per verified human Attacker rotates email or OAuth account Attacker rotates emails
Your servers store One site-private ID per user Email, name, shared sub Emails, password hashes, reset tokens
Who sees your users' logins No one. Verification runs on your servers The identity provider, on every login Only you, but you hold the secrets
Cross-site tracking Different ID per site, nothing to correlate Same identity across every app Email reused everywhere
Signup friction One passkey approval, no form OAuth redirect + consent screen Form, verification email, password rules

Full trust & data comparison →

For your users

One lemma.id works everywhere. No account per site.

Users create a lemma.id once, secured by their device passkeys, and sign in to every lemma.id-enabled site with it. Each site sees a different ID, so there's no profile following them across the web, and no company that can sell ads against their logins.

Developer integration

Sign-in in one element

The drop-in button handles the popup, the passkey, and the proof. Your backend verifies the presentation locally and uses the site-private ID as the account key. Need finer control? The SDK exposes the same flow with requiredAssurance: 'passkey', and stepping up an action is the same call with requiredAssurance: 'ishuman'.

Passwordless sign-in, no registration or API key required
<script src="https://lemma.id/sdk/proof-verifier.js"></script>
<script src="https://lemma.id/sdk/lemma-signin.js"></script>

<lemma-signin site-id="app.example.com"></lemma-signin>

<script>
  document.querySelector('lemma-signin')
    .addEventListener('lemma-signin-success', async ({ detail }) => {
      // detail.presentation → verify server-side, then issue your session
      await fetch('/api/login', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ presentation: detail.presentation }),
      });
    });
</script>
View integration docs See the demo

Product boundaries

What lemma.id is not

Honest edges. It replaces the password and the signup form, not your whole account system.

Not a global identity

Every site gets its own ID for the same person. Pairwise PPIDs are designed so relying sites cannot correlate users across the web.

Not a contact channel

You get an account key, not an email address. If your product needs to reach users, ask for contact info separately, and only when you actually need it.

Not bot detection

Finding suspicious behavior is still your fraud stack's job. lemma.id makes the consequence stick once you've decided, if you step up to human proofs.

Make the next ban stick

One verified human per account on the actions that matter, and free passwordless sign-in everywhere else. A script tag and a backend check.

Add to Your Site Watch Demo