> ## Documentation Index
> Fetch the complete documentation index at: https://docs.nullpass.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Register User

> Register a new user account

## Endpoint

```
POST /api/auth/register
```

## Overview

Creates a new user account, generates a JWT token, creates an initial session, and logs audit events. The endpoint is protected by Arcjet with rate limiting (2 requests per token bucket).

## Request

<ParamField body="email" type="string" required>
  User email address. Must be unique and valid email format.
</ParamField>

<ParamField body="password" type="string" required>
  User password. Minimum 8 characters. Will be hashed with bcrypt (10 rounds).
</ParamField>

<ParamField body="displayName" type="string">
  Optional display name for the user (1-100 characters).
</ParamField>

## Response

<ResponseField name="user" type="object">
  Created user object

  <Expandable title="User Object">
    <ResponseField name="id" type="string">
      Unique user ID (CUID)
    </ResponseField>

    <ResponseField name="email" type="string">
      User email address
    </ResponseField>

    <ResponseField name="displayName" type="string">
      User display name (if provided)
    </ResponseField>

    <ResponseField name="createdAt" type="string">
      ISO timestamp of account creation
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="token" type="string">
  JWT token for authentication. Valid for 7 days (configurable via `JWT_EXPIRES_IN`).
</ResponseField>

## Implementation Details

### Process Flow

1. **CORS Check**: Validates CORS headers
2. **Arcjet Protection**: Rate limiting (2 requests per bucket)
3. **Email Validation**: Arcjet email validation
4. **Duplicate Check**: Verifies email doesn't exist
5. **Password Hashing**: bcrypt with 10 rounds
6. **User Creation**: Creates user in database
7. **IP Encryption**: Encrypts IP address using user-specific key
8. **Session Creation**: Creates session with JWT token
9. **Audit Logging**: Logs `USER_REGISTER` and `SESSION_CREATE` events

### Code Reference

```13:93:nullpass_clean/src/app/api/auth/register/route.ts theme={null}
export async function POST(request: NextRequest) {
  const corsResponse = handleCors(request)
  if (corsResponse) return corsResponse

  const blocked = await protectRoute(request, { requested: 2 })
  if (blocked) return blocked

  try {
    const body = await request.json()
    const validated = registerSchema.parse(body)

    logger.ups('Register attempt:', validated.email)

    const emailValidation = await validateEmailWithArcjet(request, validated.email)
    if (emailValidation) return emailValidation

    const existingUser = await prisma.user.findUnique({
      where: { email: validated.email },
    })

    if (existingUser) {
      logger.warn('Register failed: User already exists', validated.email)
      return errorResponse('User already exists', 409, request.headers.get('origin'))
    }

    const passwordHash = await bcrypt.hash(validated.password, 10)

    const user = await prisma.user.create({
      data: {
        email: validated.email,
        passwordHash,
        displayName: validated.displayName,
      },
      select: {
        id: true,
        email: true,
        displayName: true,
        createdAt: true,
      },
    })

    const clientIp = getClientIp(request)
    const encryptedIp = getClientIpForStorage(request, user.id)

    const token = generateToken({ userId: user.id, email: user.email })
    const expiresAt = getSessionExpiresAt()

    await prisma.session.create({
      data: {
        userId: user.id,
        token,
        expiresAt,
        ip: encryptedIp,
      },
    })

    await createAuditLog(user.id, 'USER_REGISTER', {
      email: user.email,
      ip: encryptedIp,
    })
    await createAuditLog(user.id, 'SESSION_CREATE', {
      ip: encryptedIp,
    })

    return jsonResponse(
      {
        user,
        token,
      },
      201,
      request.headers.get('origin')
    )
  } catch (error: any) {
    if (error.name === 'ZodError') {
      logger.warn('Register validation error:', error.errors)
      return errorResponse(error.errors[0].message, 400, request.headers.get('origin'))
    }
    logger.error('Register error:', error)
    return errorResponse('Internal server error', 500, request.headers.get('origin'))
  }
}
```

## Status Codes

<ResponseField name="201" type="Created">
  User successfully created
</ResponseField>

<ResponseField name="400" type="Bad Request">
  Validation error (invalid email format, password too short, etc.)
</ResponseField>

<ResponseField name="409" type="Conflict">
  User with this email already exists
</ResponseField>

<ResponseField name="403" type="Forbidden">
  Blocked by Arcjet (rate limit exceeded, bot detected, etc.)
</ResponseField>

<ResponseField name="500" type="Internal Server Error">
  Server error during user creation
</ResponseField>

## Example Request

```bash theme={null}
curl -X POST https://auth.nullpass.xyz/api/auth/register \
  -H "Content-Type: application/json" \
  -d '{
    "email": "user@example.com",
    "password": "securepassword123",
    "displayName": "John Doe"
  }'
```

## Example Response

```json theme={null}
{
  "user": {
    "id": "clx1234567890abcdef",
    "email": "user@example.com",
    "displayName": "John Doe",
    "createdAt": "2024-01-01T00:00:00.000Z"
  },
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
```

## Audit Events

This endpoint creates the following audit log entries:

* **USER\_REGISTER**: User account created
* **SESSION\_CREATE**: Initial session created

## Security Considerations

* Password is hashed with bcrypt (10 rounds) before storage
* IP address is encrypted using user-specific encryption key
* Email validation performed via Arcjet
* Rate limiting prevents abuse (2 requests per bucket)
* All actions are logged in audit trail


## OpenAPI

````yaml POST /auth/register
openapi: 3.1.0
info:
  title: Null Pass API
  description: >-
    Internal API documentation for Null Pass authentication and service
    management system
  version: 1.0.0
servers:
  - url: https://auth.nullpass.xyz/api
security: []
paths:
  /auth/register:
    post:
      tags:
        - Authentication
      summary: Register User
      description: Create a new user account
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RegisterRequest'
      responses:
        '201':
          description: User created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RegisterResponse'
        '400':
          description: Validation error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
      security: []
components:
  schemas:
    RegisterRequest:
      type: object
      required:
        - email
        - password
      properties:
        email:
          type: string
          format: email
        password:
          type: string
          minLength: 8
        username:
          type: string
    RegisterResponse:
      type: object
      properties:
        user:
          $ref: '#/components/schemas/User'
        token:
          type: string
    Error:
      type: object
      required:
        - error
        - message
      properties:
        error:
          type: string
        message:
          type: string
    User:
      type: object
      properties:
        id:
          type: string
        email:
          type: string
          format: email
        username:
          type: string
          nullable: true
        displayName:
          type: string
          nullable: true
        avatar:
          type: string
          nullable: true
        twoFactorEnabled:
          type: boolean
        createdAt:
          type: string
          format: date-time

````