Skip to main content

Authentication API

Base URL: /api/auth

All authentication endpoints are public (no authentication required for signup/login).


POST /api/auth/signup

Register a new user and create an organization (or join via invitation).

Request Body

{
"email": "user@example.com",
"password": "SecurePass123!",
"name": "John Doe",
"organizationName": "Acme Corp",
"inviteToken": "abc123..."
}
FieldRequiredRules
emailYesValid email format
passwordYesMin 8 chars, uppercase, lowercase, number, special char
nameYesUser's full name
organizationNameConditionalRequired if no inviteToken
inviteTokenNoValid invitation token (if joining existing org)

Response (201 Created)

{
"success": true,
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"user": {
"id": "507f1f77bcf86cd799439011",
"email": "user@example.com",
"name": "John Doe",
"role": "admin",
"organizationId": "507f191e810c19729de860ea",
"organizationName": "Acme Corp"
}
}

Error Responses

StatusErrorDescription
400Missing required fieldsEmail, password, or name not provided
400Weak passwordPassword doesn't meet strength requirements
400Invalid invitation tokenToken not found or expired
409Email already registeredAccount already exists
429Rate limit exceeded5/min per IP

POST /api/auth/login

Authenticate user and return JWT token.

Request Body

{
"email": "user@example.com",
"password": "SecurePass123!"
}

Response (200 OK)

{
"success": true,
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"user": {
"id": "507f1f77bcf86cd799439011",
"email": "user@example.com",
"name": "John Doe",
"role": "admin",
"organizationId": "507f191e810c19729de860ea",
"organizationName": "Acme Corp"
}
}

Error Responses

StatusErrorDescription
401Invalid credentialsEmail or password incorrect
429Account temporarily locked5 failed attempts → 15-minute lockout

Account Lockout

  • Threshold: 5 failed attempts within 15 minutes
  • Lockout Duration: 15 minutes (Redis TTL)
  • Reset: Automatic after lockout expires, or on successful login

GET /api/auth/me

Get current user information from JWT token.

Headers

Authorization: Bearer <jwt-token>

Response (200 OK)

{
"success": true,
"data": {
"id": "507f1f77bcf86cd799439011",
"email": "user@example.com",
"name": "John Doe",
"role": "admin",
"organization": {
"id": "507f191e810c19729de860ea",
"name": "Acme Corp",
"plan": "free",
"limits": { "maxProjects": 1, "maxTestRuns": 50, "maxUsers": 3, "maxConcurrentRuns": 1, "maxStorageBytes": 524288000 },
"aiAnalysisEnabled": true
}
}
}

POST /api/auth/logout

Logout (client-side token removal).

Response (200 OK)

{
"success": true,
"message": "Logged out successfully"
}

JWT Token

  • Algorithm: HS256
  • Expiration: 24h (configurable via JWT_EXPIRY)
  • Claims: { userId, organizationId, role, iat, exp }

cURL Examples

# Signup
curl -X POST https://api.agnox.dev/api/auth/signup \
-H "Content-Type: application/json" \
-d '{"email":"user@example.com","password":"SecurePass123!","name":"John Doe","organizationName":"Acme Corp"}'

# Login
curl -X POST https://api.agnox.dev/api/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"user@example.com","password":"SecurePass123!"}'

# Get current user
curl https://api.agnox.dev/api/auth/me \
-H "Authorization: Bearer <jwt-token>"