Skip to main content
POST
Verify Email

Endpoint

Base URL: http://localhost:3000/api/v1
This endpoint is public and does not require authentication.

Request Body

string
required
The email address to verify (must match the registered email).
string
required
The 6-digit OTP code sent to the email. Must be exactly 6 numeric digits.

Request Shape

Response

Success Response (200 OK)

TypeScript Types

For Job Seeker

For Company

boolean
Indicates if the verification was successful.
object
Contains the complete user/company data and access token.
string
Success message: “Email verified successfully. You are now logged in.”
object
Request metadata from global response interceptor.
The refresh token is automatically set as an HTTP-only cookie named refreshToken. You MUST use credentials: 'include' in your fetch requests to enable cookie handling.
The server sets a cookie with these properties:
  • Name: refreshToken
  • HttpOnly: true (cannot be accessed via JavaScript)
  • Secure: true (in production, requires HTTPS)
  • SameSite: Strict
  • Max-Age: 86400 seconds (24 hours)
This cookie is sent automatically with subsequent requests when you use credentials: 'include'.

What Happens on Verification

1

OTP Validation

System verifies the OTP code against the stored value in Redis.
2

User Type Detection

System determines if the user is a Job Seeker or Company based on stored OTP data.
3

Email Status Update

User’s isVerified field is set to true in the database.
4

Login Timestamp Update

For job seekers, lastLoginAt is updated to current timestamp.
5

OTP Deletion

Used OTP is immediately deleted from Redis.
6

Token Generation

New JWT access and refresh tokens are generated.
7

Refresh Token Storage

Refresh token is stored in Redis with 24-hour expiration and set as HTTP-only cookie.
8

User Logged In

User is now authenticated and can access protected endpoints.

Error Responses

400 Bad Request - Validation Error

Returned when request validation fails.
Common validation errors:
  • Invalid email format - Email is not in valid format
  • OTP must be exactly 6 digits - Code is not exactly 6 characters
  • OTP must contain only numbers - Code contains non-numeric characters

401 Unauthorized - Invalid OTP

Returned when OTP is incorrect or expired.
Possible causes:
  • OTP code is incorrect
  • OTP has expired (10 minutes validity)
  • OTP was already used
  • Email doesn’t match registration email
  • OTP was never generated for this email

401 Unauthorized - User Not Found

Returned when no user exists with the provided email.

401 Unauthorized - Verification Failed

Generic error for other verification issues.
Error responses follow the global API envelope: success: false and an error object containing message, statusCode, timestamp, path, method, and details.

Validation Rules

OTP Behavior

OTP Validity: Each OTP is valid for 10 minutes from generation. After expiration, users need to request a new code (feature in development).
Single Use: Each OTP can only be used once. After successful verification, the OTP is immediately deleted from Redis.
Case Insensitive Email: Email comparison is case-insensitive, so john@example.com and JOHN@example.com are treated as the same.

After Verification

Once email is verified, the user:
  1. ✅ Is automatically logged in
  2. ✅ Receives access token (1 hour validity)
  3. ✅ Has refresh token stored in HTTP-only cookie (24 hours validity)
  4. ✅ Can access all protected endpoints
  5. ✅ Can login normally without re-verification
  6. ✅ Has isVerified: true in their account