Skip to content

Authentication

The REST API takes a workspace API key, an OAuth access token, or a session token from logging a user in. Whichever you send, the request acts with that user’s permissions — anything they can see in Klaarin, the credential can read.

Choosing a credential

Server-to-server integration → API key. A third-party app acting on your users’ behalf → OAuth. Your own app, signing its own users in → login. One caveat worth knowing: a session token cannot be revoked before it expires, while a key can be killed instantly from Connected Apps — so anything running on a server you control should use a key.

Workspace keys are pinned at creation

A workspace-scope API key is bound to the workspace you were in when you created it, for its whole lifetime. To reach a different workspace, create a new key from that workspace. Signed in with a session token instead? You can list and switch workspaces directly — see Workspaces.

Create a key

  1. Open your Klaarin profile and go to Connected Apps.
  2. Click Create API key, and name it after the system that will use it.
  3. Copy the key once — it is shown a single time, then stored hashed.

Use it

Send the key in the Authorization header of every request. Keys start with kl_live_.

Revoke

Revoke any key from the same Connected Apps list. Revocation is immediate; in-flight requests fail with 401 unauthorized.

Keys will be plan-gated

API keys will require a Medium or Pro workspace plan. That gate isn’t wired up yet — there’s no enforcement today.

View example
Request
curl https://api.klaarin.com/v1/me \
  -H "Authorization: Bearer kl_live_9f2ac…"
401 without a valid key
{
  "error": {
    "code": "unauthorized",
    "message": "Missing or invalid Authorization header."
  }
}

Log in from your own app

Building a first-party client that signs a user in directly — a mobile app, say? Use POST /v1/auth/login instead of a static key. It takes an email and password and returns a token scoped to that one user, so you never have to ship a shared key inside your app.

This endpoint is the one place on /v1 that needs no credential — it is how you get one. It is rate-limited to 10 attempts per 15 minutes per IP, and a wrong password and an unknown email return the same 401 unauthorized, so it can’t be used to discover who has an account. Every other REST endpoint carries its own, higher limit — see the full error and rate-limit reference on the REST Overview.

View example
Log in
curl -X POST https://api.klaarin.com/v1/auth/login \
  -H "Content-Type: application/json" \
  -d '{"email":"bayu@floothink.com","password":"••••••••"}'
Response
{
  "token": "eyJhbGciOi…",
  "expiresAt": "2026-08-25T10:00:00.000Z",
  "user": {
    "id": "clx1a2b3c",
    "email": "bayu@floothink.com",
    "name": "Bayu Pratama",
    "image": null,
    "role": "admin",
    "workspace": { "id": "clw...", "name": "Floothink", "plan": "pro" }
  }
}

Send the returned token as Authorization: Bearer … on any REST endpoint, exactly like a key. It expires after 7 days — call POST /v1/auth/refresh with the current token as the Bearer to trade it for a fresh one before then. There is no grace period: once a token has expired, the user logs in again.

Register a new user

No existing account yet? POST /v1/auth/register creates one — also with no credential required, same as login. It does not return a token directly: the new account has to verify its email first (a welcome email with a verify link is sent immediately), so the flow is register, verify, then log in. A duplicate email comes back as 400 invalid_request, not a dedicated conflict code — the error codes on this API are a closed list, see the REST Overview.

View example
Register
curl -X POST https://api.klaarin.com/v1/auth/register \
  -H "Content-Type: application/json" \
  -d '{"email":"new-user@floothink.com","password":"••••••••","name":"New User"}'
Response
{
  "success": true,
  "requiresVerification": true,
  "email": "new-user@floothink.com",
  "message": "Account created. Check your inbox to verify your email before logging in."
}