Skip to main content

Portal Login (v1)

Method & Path

POST /api/v1/nutrition/portal/:slug/login

Description

Authenticates a nutrition client using their username and password. Returns a JWT token for subsequent API calls.

Authentication

Required: None (public endpoint)

Headers

HeaderRequiredDescription
Content-TypeYesapplication/json

Path Parameters

ParameterTypeRequiredDescription
slugstringYesSpecialist's portal slug

Request Body

{
"username": "ahmed.mohamed",
"password": "mypassword123"
}

Body Fields

FieldTypeRequiredDescription
usernamestringYesClient's username
passwordstringYesClient's password

Response 200 OK

{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"client": {
"id": "507f1f77bcf86cd799439011",
"name": "أحمد محمد",
"email": "ahmed@example.com"
},
"mustChangePassword": false
}

Response Fields

FieldTypeDescription
tokenstringJWT token for API authentication
clientobjectBasic client information
mustChangePasswordbooleanIf true, client must change password before using other endpoints

Token Claims

The returned JWT token contains:

{
"workspaceId": "507f1f77bcf86cd799439012",
"clientId": "507f1f77bcf86cd799439011",
"role": "nutrition_client",
"type": "nutrition_portal_access"
}

Common Errors

  • 401 Unauthorized: Invalid username or password
  • 403 Forbidden: Account is disabled
  • 404 Not Found: Portal not found (invalid slug)

Usage Example

const response = await fetch('/api/v1/nutrition/portal/dr-ahmed/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
username: 'ahmed.mohamed',
password: 'mypassword123'
})
});

const { token, client, mustChangePassword } = await response.json();

// Store token for subsequent requests
localStorage.setItem('portal_token', token);