Skip to main content
Create new user accounts with email, password, and custom fields.

Endpoint

POST /api/auth/sign-up/email

Request parameters

email
string
required
User’s email address (must be unique)
password
string
required
User’s password (minimum 8 characters recommended)
name
string
required
User’s full name
type
string
required
User type: employee or organization
profession
string
required
User’s professional designation or field (e.g., “Biotechnology Engineer”)
avatar
string
URL to user’s profile avatar image
organizationId
string
Associated organization ID (for employee users)

Request example

Employee registration

{
  "email": "john@example.com",
  "password": "securePassword123",
  "name": "John Doe",
  "type": "employee",
  "profession": "Biochemistry Specialist",
  "avatar": "https://example.com/avatars/john.jpg"
}

Organization registration

{
  "email": "contact@biotech-company.com",
  "password": "securePassword123",
  "name": "BioTech Company",
  "type": "organization",
  "profession": "Biotechnology Research"
}

Response

Success response

user
object
Created user object
id
string
Unique user identifier (UUID)
email
string
User’s email address
name
string
User’s full name
type
string
User type: employee or organization
profession
string
User’s professional designation
avatar
string
Profile avatar URL
isActive
boolean
default:"false"
Account activation status (default: false)
organizationId
string
Associated organization ID (for employees)
isEmailVerified
boolean
default:"false"
Email verification status (default: false)
createdAt
string
Account creation timestamp (ISO 8601)
updatedAt
string
Last update timestamp (ISO 8601)
session
object
Session information (user is automatically logged in)
token
string
Session token
expiresAt
string
Session expiration timestamp (ISO 8601)

Success example

{
  "user": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "email": "john@example.com",
    "name": "John Doe",
    "type": "employee",
    "profession": "Biochemistry Specialist",
    "avatar": "https://example.com/avatars/john.jpg",
    "isActive": false,
    "organizationId": null,
    "isEmailVerified": false,
    "createdAt": "2026-02-28T14:22:00.000Z",
    "updatedAt": "2026-02-28T14:22:00.000Z"
  },
  "session": {
    "token": "session_abc123def456",
    "expiresAt": "2026-03-07T14:22:00.000Z"
  }
}

Error response

error
string
Error message describing the failure
code
string
Error code identifier

Error example

{
  "error": "Email already exists",
  "code": "EMAIL_EXISTS"
}

Client usage

React hook

Use the signUp method from the auth client:
import { signUp } from "@/lib/auth-client"

const handleRegister = async () => {
  const { data, error } = await signUp.email({
    email: "john@example.com",
    password: "securePassword123",
    name: "John Doe",
    type: "employee",
    profession: "Biochemistry Specialist",
    avatar: "https://example.com/avatars/john.jpg",
  })

  if (error) {
    console.error("Registration failed:", error)
    return
  }

  console.log("Registered:", data.user)
}

Full component example

import { useState } from "react"
import { signUp } from "@/lib/auth-client"

export const RegisterForm = () => {
  const [formData, setFormData] = useState({
    email: "",
    password: "",
    name: "",
    type: "employee" as "employee" | "organization",
    profession: "",
    avatar: "",
  })
  const [loading, setLoading] = useState(false)
  const [error, setError] = useState<string | null>(null)

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault()
    setLoading(true)
    setError(null)

    const { data, error: authError } = await signUp.email(formData)

    if (authError) {
      setError(authError.message)
      setLoading(false)
      return
    }

    // Redirect based on user type
    if (data.user.type === "employee") {
      window.location.href = "/dashboard/employee"
    } else {
      window.location.href = "/dashboard/admin"
    }
  }

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="email"
        value={formData.email}
        onChange={(e) => setFormData({ ...formData, email: e.target.value })}
        placeholder="Email"
        required
      />
      <input
        type="password"
        value={formData.password}
        onChange={(e) => setFormData({ ...formData, password: e.target.value })}
        placeholder="Password"
        required
      />
      <input
        type="text"
        value={formData.name}
        onChange={(e) => setFormData({ ...formData, name: e.target.value })}
        placeholder="Full name"
        required
      />
      <select
        value={formData.type}
        onChange={(e) =>
          setFormData({
            ...formData,
            type: e.target.value as "employee" | "organization",
          })
        }
      >
        <option value="employee">Employee</option>
        <option value="organization">Organization</option>
      </select>
      <input
        type="text"
        value={formData.profession}
        onChange={(e) => setFormData({ ...formData, profession: e.target.value })}
        placeholder="Profession"
        required
      />
      {error && <p>{error}</p>}
      <button type="submit" disabled={loading}>
        {loading ? "Registering..." : "Register"}
      </button>
    </form>
  )
}

Rate limiting

Registration attempts are rate-limited to 10 requests per minute per IP address. Exceeding this limit returns a 429 Too Many Requests response:
{
  "error": "Too many requests",
  "code": "RATE_LIMIT_EXCEEDED"
}

Auto-login

Successful registration automatically creates a session and logs the user in:
  • Expiration: 7 days from registration
  • Auto-refresh: Sessions refresh after 1 day of activity
  • Cookie cache: 5-minute cookie cache for performance
  • Tracking: IP address and user agent stored for security

ID generation

User IDs are automatically generated using crypto.randomUUID() and follow UUID v4 format:
advanced: {
  database: {
    generateId: () => crypto.randomUUID(),
  },
}

Error codes

CodeDescription
EMAIL_EXISTSEmail address is already registered
INVALID_EMAILEmail format is invalid
WEAK_PASSWORDPassword does not meet requirements
RATE_LIMIT_EXCEEDEDToo many registration attempts
MISSING_REQUIRED_FIELDRequired field is missing
INVALID_USER_TYPEUser type must be employee or organization