Auth

Auth

Sign-up, sign-in and profile endpoints for dashboard users and for front ends built on the API.

Sign-up, sign-in and profile endpoints for dashboard users. Most integrations never call these: create an API key in the dashboard and use it. They matter when you script account creation, build on the API with your own front end, or need a session to manage keys and settings.

Production sign-up may require a Cloudflare Turnstile token and email verification; GET /v1/auth/providers says what the server enforces. Sign-in and sign-up are rate limited per IP (20 and 5 per hour).

#Sign-in methods

GET/v1/auth/providersNo authentication

Which sign-in methods this server enables, whether self-serve sign-up is open, the Turnstile site key when bot protection is on, and whether email verification is required.

Returns

{password, signup_enabled, google, github, turnstile_site_key, email_verification}.
print(client.auth.providers())
curl https://api.kaimei.ai/v1/auth/providers
200 OKResponse
{
  "password": true,
  "signup_enabled": true,
  "google": true,
  "github": true,
  "turnstile_site_key": "0x4AAAAAAA…",
  "email_verification": true
}

#Create an account

POST/v1/auth/signupNo authentication

Create a user and a new organization for them (the user becomes its owner). When email verification is required the response is {"status": "pending_verification", …} and a link is emailed; otherwise a session is returned straight away. 409 email_taken if the address exists.

Body parameters

emailstringrequired

passwordstringrequired

8 to 256 characters.

namestringoptional

Display name.

organization_namestringoptional

Defaults to {name}'s workspace.

turnstile_tokenstringoptional

Required when the server enforces Turnstile.

Returns

A session (access_token, expires_in, user, organization) or a pending-verification notice. 201.
session = client.auth.signup(email="[email protected]", password="correct horse battery staple",
                             name="You", organization_name="Acme Risk")
# the client now sends the session token when one was returned
curl https://api.kaimei.ai/v1/auth/signup \
  -H "Content-Type: application/json" \
  -d '{"email": "[email protected]", "password": "correct horse battery staple", "name": "You", "organization_name": "Acme Risk"}'
201 CreatedResponse
{
  "status": "pending_verification",
  "email": "[email protected]",
  "message": "Check your email for a verification link."
}
201 Createdwhen verification is not required
{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.…",
  "token_type": "bearer",
  "expires_in": 604800,
  "user": {
    "object": "user",
    "id": "usr_99d45281ca85b8a7cc92",
    "email": "[email protected]",
    "name": "Kaimei Demo",
    "avatar_url": null,
    "auth_provider": "password",
    "role": "owner",
    "email_verified": true,
    "organization_id": "org_c72a301b93331f42b7b9",
    "created_at": "2026-10-31T22:37:25.378782Z",
    "last_login_at": "2026-10-31T22:40:22.603319Z"
  },
  "organization": {
    "object": "organization",
    "id": "org_c72a301b93331f42b7b9",
    "name": "Kaimei Demo",
    "slug": "kaimei-demo",
    "plan": "free",
    "settings": {},
    "quotas": null,
    "created_at": "2026-10-31T22:37:25.334655Z"
  }
}

#Sign in

POST/v1/auth/loginNo authentication

Exchange email and password for a session token. 401 invalid_credentials on a wrong password, 401 email_unverified when verification is pending.

Body parameters

emailstringrequired

passwordstringrequired

Returns

A session. The Python client installs the token on the client automatically.
session = client.auth.login(email="[email protected]", password="...")
print(session.expires_in, session.user.role, session.organization.plan)
curl https://api.kaimei.ai/v1/auth/login \
  -H "Content-Type: application/json" \
  -d '{"email": "[email protected]", "password": "..."}'
200 OKResponse
{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.…",
  "token_type": "bearer",
  "expires_in": 604800,
  "user": {
    "object": "user",
    "id": "usr_99d45281ca85b8a7cc92",
    "email": "[email protected]",
    "name": "Kaimei Demo",
    "avatar_url": null,
    "auth_provider": "password",
    "role": "owner",
    "email_verified": true,
    "organization_id": "org_c72a301b93331f42b7b9",
    "created_at": "2026-10-31T22:37:25.378782Z",
    "last_login_at": "2026-10-31T22:40:22.603319Z"
  },
  "organization": {
    "object": "organization",
    "id": "org_c72a301b93331f42b7b9",
    "name": "Kaimei Demo",
    "slug": "kaimei-demo",
    "plan": "free",
    "settings": {},
    "quotas": null,
    "created_at": "2026-10-31T22:37:25.334655Z"
  }
}

#Who am I

GET/v1/auth/meAPI key or session

The principal behind the token: user for a session, api_key for a key, with the organization either way.

Returns

{principal, user, organization, api_key}.
who = client.auth.me()
curl https://api.kaimei.ai/v1/auth/me \
  -H "Authorization: Bearer $KAIMEI_API_KEY"
200 OKResponse
{
  "principal": "user",
  "user": {
    "object": "user",
    "id": "usr_99d45281ca85b8a7cc92",
    "email": "[email protected]",
    "name": "Kaimei Demo",
    "avatar_url": null,
    "auth_provider": "password",
    "role": "owner",
    "email_verified": true,
    "organization_id": "org_c72a301b93331f42b7b9",
    "created_at": "2026-10-31T22:37:25.378782Z",
    "last_login_at": "2026-10-31T22:40:22.603319Z"
  },
  "organization": {
    "object": "organization",
    "id": "org_c72a301b93331f42b7b9",
    "name": "Kaimei Demo",
    "slug": "kaimei-demo",
    "plan": "free",
    "settings": {},
    "quotas": null,
    "created_at": "2026-10-31T22:37:25.334655Z"
  },
  "api_key": null
}

#Update the profile

PATCH/v1/auth/meSession token only

Change the signed-in user's name, avatar URL or password. Changing the password of a password account requires current_password.

Body parameters

namestringoptional

avatar_urlstringoptional

passwordstringoptional

8 to 256 characters.

current_passwordstringoptional

Required with password.

Returns

The User.
client.auth.update_me(name="Samson", password="new-password", current_password="old-password")
curl -X PATCH https://api.kaimei.ai/v1/auth/me \
  -H "Authorization: Bearer $SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "Samson"}'
200 OKResponse
{
  "object": "user",
  "id": "usr_99d45281ca85b8a7cc92",
  "email": "[email protected]",
  "name": "Samson",
  "avatar_url": null,
  "auth_provider": "password",
  "role": "owner",
  "email_verified": true,
  "organization_id": "org_c72a301b93331f42b7b9",
  "created_at": "2026-10-31T22:37:25.378782Z",
  "last_login_at": "2026-10-31T22:40:22.603319Z"
}

#Upload or remove a profile photo

POST/v1/auth/me/avatarSession token only

POST a base64 JPEG, PNG, WEBP or GIF under 750 KB (a data: URL prefix is accepted and stripped). The photo is served inline as a data URL in avatar_url. DELETE /v1/auth/me/avatar removes it.

Body parameters

datastringrequired

Base64 image data.

content_typestringoptional

Ignored; the type is sniffed from the bytes.

Returns

The User.
curl https://api.kaimei.ai/v1/auth/me/avatar \
  -H "Authorization: Bearer $SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d "{\"data\": \"$(base64 -w0 me.png)\"}"

curl -X DELETE https://api.kaimei.ai/v1/auth/me/avatar -H "Authorization: Bearer $SESSION_TOKEN"
200 OKResponse
{
  "object": "user",
  "id": "usr_99d45281ca85b8a7cc92",
  "email": "[email protected]",
  "name": "Kaimei Demo",
  "avatar_url": "data:image/png;base64,iVBORw0KGgo…",
  "auth_provider": "password",
  "role": "owner",
  "email_verified": true,
  "organization_id": "org_c72a301b93331f42b7b9",
  "created_at": "2026-10-31T22:37:25.378782Z",
  "last_login_at": "2026-10-31T22:40:22.603319Z"
}

#Verify an email address

POST/v1/auth/verify-emailNo authentication

Confirm a verification token and receive a session. The mailed link uses GET /v1/auth/verify-email?token=…, which redirects to the dashboard with the session in the URL fragment. POST /v1/auth/resend-verification with {"email"} (and a Turnstile token when enforced) sends a new link; it always returns 204.

Body parameters

tokenstringrequired

From the verification email.

Returns

A session.
client.auth.verify_email(token=token_from_email)
client.auth.resend_verification(email="[email protected]")
curl https://api.kaimei.ai/v1/auth/verify-email \
  -H "Content-Type: application/json" \
  -d '{"token": "…"}'

curl https://api.kaimei.ai/v1/auth/resend-verification \
  -H "Content-Type: application/json" \
  -d '{"email": "[email protected]"}'   # 204
200 OKResponse
{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.…",
  "token_type": "bearer",
  "expires_in": 604800,
  "user": {
    "object": "user",
    "id": "usr_99d45281ca85b8a7cc92",
    "email": "[email protected]",
    "name": "Kaimei Demo",
    "avatar_url": null,
    "auth_provider": "password",
    "role": "owner",
    "email_verified": true,
    "organization_id": "org_c72a301b93331f42b7b9",
    "created_at": "2026-10-31T22:37:25.378782Z",
    "last_login_at": "2026-10-31T22:40:22.603319Z"
  },
  "organization": {
    "object": "organization",
    "id": "org_c72a301b93331f42b7b9",
    "name": "Kaimei Demo",
    "slug": "kaimei-demo",
    "plan": "free",
    "settings": {},
    "quotas": null,
    "created_at": "2026-10-31T22:37:25.334655Z"
  }
}

#OAuth sign-in

GET/v1/auth/oauth/{provider}/startNo authentication

Begin a Google or GitHub sign-in. The browser is redirected to the provider and back to /v1/auth/oauth/{provider}/callback, which creates or links the user and redirects to the dashboard's /auth/callback with access_token and redirect_to in the URL fragment. An existing password account with the same email is linked rather than duplicated.

Path parameters

providerstringrequired
google or github. 400 provider_disabled when not configured.

Query parameters

redirect_tostringoptionaldefault "/"

Dashboard path to return to.

Returns

302 to the provider.
# in a browser
open "https://api.kaimei.ai/v1/auth/oauth/github/start?redirect_to=/models"
302 FoundResponse
HTTP/1.1 302 Found
Location: https://github.com/login/oauth/authorize?client_id=…&redirect_uri=https%3A%2F%2Fapi.kaimei.ai%2Fv1%2Fauth%2Foauth%2Fgithub%2Fcallback&scope=read%3Auser+user%3Aemail&state=…

#Sign out

POST/v1/auth/logoutAPI key or session

Sessions are stateless signed tokens, so this endpoint changes nothing server-side; it exists so clients have one place to clear their state. Returns 204.

Returns

Nothing.
client.auth.logout()
curl -X POST https://api.kaimei.ai/v1/auth/logout \
  -H "Authorization: Bearer $SESSION_TOKEN"   # 204
204 No ContentResponse