API

Auth - Owner Registration

Owner registration flow with OTP verification and business details.

Base path: /api/v1/auth

The owner registration flow requires 3 steps: (1) Request OTP → (2) Verify OTP → (3) Create account.

Used by: cms-booki-web-app · Role: guest (unauthenticated)
organizationId: Not applicable at registration time — the organization is created as part of step 3.

POST /api/v1/auth/register/owner/otp — Send OTP

Auth: Public
Description: Send a 6-digit OTP to the provided email for owner registration verification.

Request

{
  "email": "jane@example.com"
}

Fields:

  • email (string, required): Valid email address where OTP will be sent

Response (200 OK)

{
  "message": "Owner email OTP sent successfully. Kindly check your email for the OTP."
}

Error Responses

400 Bad Request — Invalid email or email already registered:

{
  "statusCode": 400,
  "message": "Email already registered as an owner account"
}

cURL Example

curl -X POST http://localhost:4001/api/v1/auth/register/owner/otp \
  -H "Content-Type: application/json" \
  -d '{"email": "jane@example.com"}'

POST /api/v1/auth/register/owner/otp/verify — Verify OTP

Auth: Public
Description: Verify the OTP code sent to email. OTP valid for 1 hour.

Request

{
  "otp": "123456"
}

Fields:

  • otp (string, required): 6-digit code from email

Response (200 OK)

{
  "message": "OTP verified successfully.",
  "valid": true
}

Error Responses

400 Bad Request — Invalid or expired OTP:

{
  "statusCode": 400,
  "message": "Invalid or expired OTP"
}

404 Not Found — OTP not found for email:

{
  "statusCode": 404,
  "message": "No OTP found for this email"
}

cURL Example

curl -X POST http://localhost:4001/api/v1/auth/register/owner/otp/verify \
  -H "Content-Type: application/json" \
  -d '{"otp": "123456"}'

POST /api/v1/auth/register/owner — Create Owner Account

Auth: Public
Description: Complete owner registration with OTP, business details, and password.

Request

{
  "otp": "123456",
  "password": "SecureP@ss123",
  "ownerDetails": {
    "firstName": "Jane",
    "middleName": "Marie", // (optional)
    "lastName": "Doe",
    "phone": "09171234567"
  },
  "businessDetails": {
    "service": "69dcbe3f1a79a4eac35bc717",
    "name": "Jane's Beauty Salon",
    "businessPermit": "BP-2024-001",
    "businessRegistration": "BR-2024-001",
    "branch": 1,
    "slug": "janes-salon",
    "businessAddress": {
      "region": "NCR",
      "province": "Metro Manila",
      "municipalOrCity": "Quezon City",
      "barangay": "Doña Julia",
      "zip": "1100",
      "street": "Main Avenue", // (optional)
      "address": "123 Business Complex" // (optional)
    }
  }
}

Fields:

  • otp (string, required): OTP from previous verification step
  • password (string, required): Min 8 chars, must include uppercase, lowercase, number, special character
  • ownerDetails (object, required):
    • firstName (string, required): First name (max 255 chars)
    • middleName (string, optional): Middle name
    • lastName (string, required): Last name (max 255 chars)
    • phone (string, required): Phone number (10-20 chars)
  • businessDetails (object, required):
    • service (string, required): Booking service category ID (24-hex)
    • name (string, required): Business name (max 255 chars)
    • businessPermit (string, required): Permit documentation reference
    • businessRegistration (string, required): Registration number
    • branch (number, required): Number of branches (min 1)
    • slug (string, required): Business slug (max 255 chars)
    • businessAddress (object, required):
      • region: Region name (required, max 255)
      • province: Province name (required, max 255)
      • municipalOrCity: Municipality/City (required, max 255)
      • barangay: Barangay (required, max 255)
      • zip: ZIP code (required, max 20)
      • street: Street name (optional, max 255)
      • address: Full address (optional, max 255)

Response (201 Created)

{
  "message": "Business owner added successfully."
}

Error Responses

400 Bad Request — Invalid password or missing fields:

{
  "statusCode": 400,
  "message": "Password must contain at least one uppercase letter, one lowercase letter, one number, and one special character"
}

409 Conflict — Business slug already in use:

{
  "statusCode": 409,
  "message": "Business slug 'janes-salon' is already taken"
}

cURL Example

curl -X POST http://localhost:4001/api/v1/auth/register/owner \
  -H "Content-Type: application/json" \
  -d '{
    "otp": "123456",
    "password": "SecureP@ss123",
    "ownerDetails": {
      "firstName": "Jane",
      "middleName": "Marie",
      "lastName": "Doe",
      "phone": "09171234567"
    },
    "businessDetails": {
      "service": "69dcbe3f1a79a4eac35bc717",
      "name": "Jane'\''s Beauty Salon",
      "businessPermit": "BP-2024-001",
      "businessRegistration": "BR-2024-001",
      "branch": 1,
      "slug": "janes-salon",
      "businessAddress": {
        "region": "NCR",
        "province": "Metro Manila",
        "municipalOrCity": "Quezon City",
        "barangay": "Doña Julia",
        "zip": "1100",
        "street": "Main Avenue",
        "address": "123 Business Complex"
      }
    }
  }'

Notes

  • OTP codes expire after 1 hour.
  • Business slug must be unique; recommended format: lowercase name with hyphens (e.g., janes-salon, acme-services).
  • Password complexity is strictly enforced; all 4 character types required.
  • Owner account is created with ACTIVE status and default branch automatically created.
  • See booki-api/src/validations/user.validation.ts for exact field requirements.