Browse docs

Email & password

The default sign-in method. Argon2id-hashed passwords, constant-time verification, rate limiting, and a configurable password policy per instance.

Copy this quickstart guide as a prompt for LLMs to implement KolayLogin in your application.

Endpoints

  • POST /v1/auth/sign-up/email-password  — create user + session
  • POST /v1/auth/sign-in/email-password  — verify + session
  • POST /v1/auth/sign-out  — end this client
  • POST /v1/auth/sign-out/all  — end every session for the user

Request shape

POST /v1/auth/sign-up/email-password
{
  "email": "ada@example.com",
  "password": "correct-horse-battery-staple"
}

Both sign-up and sign-in respond with the created session shape and set __client + __session cookies:

{ "userId": "...", "sessionId": "..." }

Client example

async function signIn(email: string, password: string) {
  const res = await fetch(base + '/v1/auth/sign-in/email-password', {
    method: 'POST',
    credentials: 'include',
    headers: { 'content-type': 'application/json' },
    body: JSON.stringify({ email, password }),
  });
  if (!res.ok) throw new Error('invalid_credentials');
  return res.json();
}

Password policy

Per-instance policy configured from the dashboard. Hobby plans get the default; Pro+ can require uppercase / lowercase / digit / special.

instance sessionConfig.passwordPolicy
{
  "minLength": 10,
  "requireUppercase": true,
  "requireLowercase": true,
  "requireNumber": true,
  "requireSpecial": false
}

Errors

  • 400 password_too_short — fails the configured policy.
  • 400 email_already_exists — on sign-up when the email is taken.
  • 401 invalid_credentials — on sign-in with wrong email/password (constant-time).
  • 429 signup_rate_limited / signin_rate_limited — sliding-window limit.
No user enumeration
Sign-in always runs argon2.verifyagainst either the real hash or a dummy hash, so response time is identical whether the email exists. Your UI should not distinguish "wrong email" from "wrong password".