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
/v1/auth/providersNo authenticationWhich 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{
"password": true,
"signup_enabled": true,
"google": true,
"github": true,
"turnstile_site_key": "0x4AAAAAAA…",
"email_verification": true
}#Create an account
/v1/auth/signupNo authenticationCreate 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
8 to 256 characters.
Display name.
Defaults to {name}'s workspace.
Required when the server enforces Turnstile.
Returns
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 returnedcurl 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"}'{
"status": "pending_verification",
"email": "[email protected]",
"message": "Check your email for a verification link."
}{
"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
/v1/auth/loginNo authenticationExchange email and password for a session token. 401 invalid_credentials on a wrong password, 401 email_unverified when verification is pending.
Body parameters
Returns
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": "..."}'{
"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
/v1/auth/meAPI key or sessionThe 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"{
"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
/v1/auth/meSession token onlyChange the signed-in user's name, avatar URL or password. Changing the password of a password account requires current_password.
Body parameters
8 to 256 characters.
Required with password.
Returns
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"}'{
"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
/v1/auth/me/avatarSession token onlyPOST 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
Base64 image data.
Ignored; the type is sniffed from the bytes.
Returns
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"{
"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
/v1/auth/verify-emailNo authenticationConfirm 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
From the verification email.
Returns
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{
"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
/v1/auth/oauth/{provider}/startNo authenticationBegin 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
google or github. 400 provider_disabled when not configured.Query parameters
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"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
/v1/auth/logoutAPI key or sessionSessions 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
client.auth.logout()curl -X POST https://api.kaimei.ai/v1/auth/logout \
-H "Authorization: Bearer $SESSION_TOKEN" # 204