Getting started · 01~15 minutes

Quickstart

In under fifteen minutes, you will spin up a Kimezu sandbox, configure a tenant, integrate a sample application, and verify a session. No card required.

i
Sandbox environment. The sandbox runs against a separate Kimezu cluster — no real user data, no real payments, no audit retention. When you're happy, promote your tenant config to production with one operator-console action.

Prerequisites

You'll need:

  • An operator email — Kimezu signs you in via magic link, no signup form.
  • A domain you control (we'll create a CNAME). Sandbox tenants run under *.sandbox.kimezu.com if you don't want to use your own yet.
  • Any HTTP client. curl is fine; the examples use it.

1. Create the operator and the first tenant

Visit console.kimezu.com/start, enter an email, and click the magic link in the message. You'll land on an empty operator workspace with one button: "Add tenant".

POST   /v1/tenants — create tenant
curl "https://api.kimezu.com/v1/tenants" \
  -H "Authorization: Bearer $OP_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "tenant_id": "your-tenant",
    "display_name": "Your Tenant",
    "domain": "auth.your-tenant.eu",
    "region": "eu-west",
    "brand": {
      "accent": "#7A4A1F",
      "logo_url": "https://cdn.example.com/logo.svg"
    },
    "methods": ["password", "magic-link"]
  }'

# → 201 Created
#   { "tenant_id": "your-tenant",
#     "oidc_issuer": "https://auth.your-tenant.eu",
#     "jwks_uri":    "https://auth.your-tenant.eu/.well-known/jwks.json" }

Kimezu provisions the tenant, creates the OIDC issuer URL, and writes the first audit entry. Total time: roughly three seconds.

2. Register an application

An application is a thing that asks Kimezu to verify users. Each app has its own client credentials and audience claim.

POST   /v1/applications — register app
curl "https://api.kimezu.com/v1/applications" \
  -H "Authorization: Bearer $OP_TOKEN" \
  -H "X-Tenant-Id: your-tenant" \
  -H "Content-Type: application/json" \
  -d '{
    "name":         "Your shop",
    "redirect_uris":["https://your-tenant.eu/auth/callback"],
    "scopes":       ["openid", "profile", "email"]
  }'

# → 201 Created
#   { "client_id":     "app_abc123",
#     "client_secret": "shown once — store it" }
!
Client secrets are shown once. Kimezu hashes them on creation. If you lose the secret, you rotate it — there is no recovery flow.

3. Sign a user in

Send a user to the authorize URL. Kimezu renders the tenant-branded sign-in screen, the user picks a method, and Kimezu redirects back to your callback with an authorization code.

GET   /authorize — start a sign-in
# Browser navigates to:
https://auth.your-tenant.eu/authorize
  ?client_id=app_abc123
  &redirect_uri=https://your-tenant.eu/auth/callback
  &response_type=code
  &scope=openid+profile+email
  &state=<nonce>

# After sign-in, browser is redirected to:
#   https://your-tenant.eu/auth/callback?code=...&state=<nonce>

Exchange the code for tokens server-side:

POST   /token — exchange code
curl "https://auth.your-tenant.eu/token" \
  -u "app_abc123:$CLIENT_SECRET" \
  -d "grant_type=authorization_code" \
  -d "code=$CODE" \
  -d "redirect_uri=https://your-tenant.eu/auth/callback"

# → 200 OK
#   { "access_token":  "<jwt>",
#     "refresh_token": "<opaque>",
#     "id_token":      "<jwt>",
#     "token_type":    "Bearer",
#     "expires_in":    900 }

4. Verify the session

From here, your application verifies tokens locally against the JWKS. No more RPCs to Kimezu on the hot path.

JS   Verify a Kimezu JWT
import { jwtVerify, createRemoteJWKSet } from "jose";

const JWKS = createRemoteJWKSet(
  new URL("https://auth.your-tenant.eu/.well-known/jwks.json")
);

async function verify(token) {
  const { payload } = await jwtVerify(token, JWKS, {
    issuer: "https://auth.your-tenant.eu",
    audience: "app_abc123",
  });
  return payload;
  // payload.actor_type, payload.sub, payload.can, ...
}

That's it. Your application now trusts a Kimezu session. Production cutover is the same flow with a different X-Tenant-Id header — none of the code changes.

What to read next