Skip to content

Registration

The account registration and onboarding flow spans account creation, handle validation, and profile completion. This page documents the live custom registration route in apps/api and the currently mounted Better Auth email sign-up route.

The registration and immediate onboarding workstream maps to KUB-112, KUB-114, and KUB-115.

Create Account

http
POST /api/v1/auth/register

Body

json
{
	"name": "Jane Doe",
	"email": "[email protected]",
	"password": "your-password",
	"passwordConfirmation": "your-password"
}

Response

json
{
	"data": {
		"token": "<bearer-token>",
		"expiresAt": "<iso8601-expires-at>",
		"user": {
			"id": "usr_123",
			"email": "[email protected]",
			"name": "Jane Doe",
			"type": "user"
		}
	}
}

The API stores the account in the Better Auth and Prisma-backed app_users table, then returns the existing /api/v1/* JWT response contract for client use. Admin users are not created through this surface and continue to authenticate through the Laravel/Filament admin app.

Error Responses

  • 400 invalid_body when the request body is malformed JSON or a JSON value other than an object
  • 409 email_taken when the email address is already registered
  • 422 validation_error when one or more fields are invalid
  • 429 rate_limited after too many registration attempts from the same resolved client key; if trusted proxy IP headers are disabled or unavailable, registration throttling falls back to a shared bucket instead of trusting forwarded IP headers

Validation Rules

  • name is required and should be a human-readable display name.
  • email is required and must be unique.
  • password is required and must meet the production password policy.
  • passwordConfirmation must match password.

Better Auth Email Sign-Up

The Better Auth handler also exposes:

http
POST /api/auth/sign-up/email

That route is live and follows Better Auth request and response conventions. Use it when integrating a Better Auth client directly. Use POST /api/v1/auth/register when you need the Kubuli-specific JWT response envelope documented on this page.


Check Handle Availability

http
GET /api/v1/users/handle/check?handle=jane_doe

Use this endpoint during onboarding before persisting the final profile.

Response

json
{
	"data": {
		"handle": "jane_doe",
		"available": true
	}
}

Errors

  • 422 validation_error when the handle format is invalid

Create or Update the Onboarding Profile

http
POST /api/v1/users/profile
Authorization: Bearer <token>

This route accepts either a valid user bearer token or a Better Auth session cookie. Guest identities cannot create a profile.

Body

json
{
	"handle": "jane_doe",
	"name": "Jane Doe"
}

Response

json
{
	"data": {
		"user": {
			"id": "usr_123",
			"email": "[email protected]",
			"name": "Jane Doe",
			"handle": "jane_doe",
			"type": "user",
			"createdAt": "<iso8601-created-at>"
		}
	}
}

Errors

  • 400 invalid_body when the request body is malformed JSON or a JSON value other than an object
  • 401 auth_required when no valid bearer token or session cookie is present, or the authenticated user no longer exists
  • 403 forbidden when the caller is a guest identity
  • 409 handle_taken when the handle already belongs to another user
  • 422 validation_error when handle or name fails validation

Current Flow

The current onboarding flow is:

  1. Create the account with POST /api/v1/auth/register.
  2. Check candidate handles with GET /api/v1/users/handle/check.
  3. Persist the chosen profile with POST /api/v1/users/profile.
  4. Read the resulting identity with GET /api/v1/me.
  5. Update the saved profile later with PATCH /api/v1/me.

Email verification and additional provider onboarding flows remain separate follow-up work. Current-user profile read and patch semantics are documented in Authentication.

Built with VitePress