Authenticate users with email and password credentials.
Endpoint
POST /api/auth/sign-in/email
Request parameters
Extend session duration if enabled
Request example
{
"email": "user@example.com",
"password": "securePassword123",
"rememberMe": true
}
Response
Success response
Authenticated user objectUnique user identifier (UUID)
User type: employee or organization
User’s professional designation
Account activation status
Associated organization ID (for employees)
Email verification status
Account creation timestamp (ISO 8601)
Last update timestamp (ISO 8601)
Session informationSession expiration timestamp (ISO 8601)
Success example
{
"user": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "user@example.com",
"name": "John Doe",
"type": "employee",
"profession": "Biotechnology Engineer",
"avatar": "https://example.com/avatar.jpg",
"isActive": true,
"organizationId": null,
"isEmailVerified": true,
"createdAt": "2026-01-15T10:30:00.000Z",
"updatedAt": "2026-02-28T14:22:00.000Z"
},
"session": {
"token": "session_abc123def456",
"expiresAt": "2026-03-07T14:22:00.000Z"
}
}
Error response
Error message describing the failure
Error example
{
"error": "Invalid email or password",
"code": "INVALID_CREDENTIALS"
}
Client usage
React hook
Use the signIn method from the auth client:
import { signIn } from "@/lib/auth-client"
const handleLogin = async () => {
const { data, error } = await signIn.email({
email: "user@example.com",
password: "securePassword123",
rememberMe: true,
})
if (error) {
console.error("Login failed:", error)
return
}
console.log("Logged in:", data.user)
}
Full component example
import { useState } from "react"
import { signIn } from "@/lib/auth-client"
export const LoginForm = () => {
const [email, setEmail] = useState("")
const [password, setPassword] = useState("")
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 signIn.email({
email,
password,
rememberMe: true,
})
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={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="Email"
required
/>
<input
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
placeholder="Password"
required
/>
{error && <p>{error}</p>}
<button type="submit" disabled={loading}>
{loading ? "Logging in..." : "Log in"}
</button>
</form>
)
}
Rate limiting
Login 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"
}
Session creation
Successful login creates a session with:
- Expiration: 7 days from login
- 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
Error codes
| Code | Description |
|---|
INVALID_CREDENTIALS | Email or password is incorrect |
RATE_LIMIT_EXCEEDED | Too many login attempts |
ACCOUNT_INACTIVE | User account is deactivated |
EMAIL_NOT_VERIFIED | Email verification required |