Public API
This endpoint is publicly accessible. No authentication required.
Login API
Authenticate users and obtain JWT access tokens for API access.
Overview
The Login API supports multiple authentication methods:
| Method | Use Case | Endpoint |
|---|---|---|
| Email/Password | Standard user login | POST /api/v1/auth/login |
| PIN | Staff quick login | POST /api/v1/auth/login/pin |
| Quick Login | PIN alias (accepts "code" field) | POST /api/v1/auth/quick-login |
| Badge | Staff badge scan login | POST /api/v1/auth/staff/badge |
Email/Password Login
Request
POST /api/v1/auth/login
Content-Type: application/json
{
"email": "user@restaurant.com",
"password": "securePassword123",
"tenant_id": "tenant-abc123",
"location_id": "loc-xyz789",
"remember_me": true
}
Parameters
| Field | Type | Required | Description |
|---|---|---|---|
email | string | Yes | User's email address |
password | string | Yes | User's password |
tenant_id | string | Yes | Tenant identifier |
location_id | string | No | Location for context (staff logins) |
remember_me | boolean | No | Extended session (30 days vs 24 hours) |
Response
{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"refresh_token": "dGhpcyBpcyBhIHJlZnJlc2ggdG9rZW4...",
"token_type": "Bearer",
"expires_in": 3600,
"user": {
"id": "user-123",
"email": "user@restaurant.com",
"name": "John Smith",
"roles": ["manager", "staff"],
"permissions": ["orders.read", "orders.write", "payments.process"]
},
"tenant": {
"id": "tenant-abc123",
"name": "Downtown Grill"
},
"location": {
"id": "loc-xyz789",
"name": "Main Street Location"
},
"mfa_required": false
}
Response Fields
| Field | Type | Description |
|---|---|---|
access_token | string | JWT for API authentication (1 hour) |
refresh_token | string | Token for obtaining new access tokens |
expires_in | number | Token lifetime in seconds |
user | object | Authenticated user details |
mfa_required | boolean | If true, MFA verification needed |
PIN Login
Quick authentication for staff using a 4-6 digit PIN.
Request
POST /api/v1/auth/login/pin
Content-Type: application/json
{
"pin": "1234",
"tenant_id": "tenant-abc123",
"location_id": "loc-xyz789",
"device_id": "device-001"
}
Parameters
| Field | Type | Required | Description |
|---|---|---|---|
pin | string | Yes | 4-6 digit PIN |
tenant_id | string | Yes | Tenant identifier |
location_id | string | Yes | Location identifier |
device_id | string | Yes | Registered device ID |
Response
Same as email/password login response.
Badge Login
For staff authentication via badge scan at a location.
Request
POST /api/v1/auth/staff/badge
Content-Type: application/json
{
"badge_code": "BADGE-12345",
"tenant_id": "tenant-abc123",
"location_id": "loc-xyz789"
}
Response
Returns the same token response as email/password login.
MFA Challenge Response
When mfa_required: true is returned, complete MFA verification.
Request
POST /api/v1/auth/login/mfa
Content-Type: application/json
{
"mfa_token": "mfa_challenge_token_here",
"code": "123456",
"method": "totp"
}
Response
Returns full login response with access and refresh tokens.
Error Responses
Invalid Credentials (401)
{
"error": {
"code": "INVALID_CREDENTIALS",
"message": "Email or password is incorrect",
"request_id": "req-abc123"
}
}
Account Locked (423)
{
"error": {
"code": "ACCOUNT_LOCKED",
"message": "Account locked due to too many failed attempts",
"unlock_at": "2026-01-18T15:30:00Z",
"request_id": "req-abc123"
}
}
Tenant Suspended (403)
{
"error": {
"code": "TENANT_SUSPENDED",
"message": "This account has been suspended",
"request_id": "req-abc123"
}
}
Rate Limiting
| Endpoint | Limit | Window |
|---|---|---|
/auth/login | 5 attempts | Per minute per IP |
/auth/login/pin | 10 attempts | Per minute per device |
/auth/staff/badge | 10 attempts | Per minute per device |
After exceeding limits, a 429 Too Many Requests response is returned.
Security Best Practices
- Always use HTTPS - Never send credentials over unencrypted connections
- Store tokens securely - Use secure storage (Keychain, Keystore, HttpOnly cookies)
- Implement token refresh - Refresh before expiration to maintain sessions
- Handle failures gracefully - Don't reveal whether email exists
- Log authentication events - For audit and security monitoring
Code Examples
cURL
# Login
TOKEN=$(curl -s -X POST https://dev.api.olympuscloud.ai/v1/auth/login \
-H "Content-Type: application/json" \
-d '{
"email": "manager@demo-restaurant.com",
"password": "DevPassword123!"
}' | jq -r '.status.access_token')
# Use the token for authenticated requests
curl -s https://dev.api.olympuscloud.ai/v1/commerce/orders \
-H "Authorization: Bearer $TOKEN" | jq .
JavaScript
// Login
const resp = await fetch('https://dev.api.olympuscloud.ai/v1/auth/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
email: 'manager@demo-restaurant.com',
password: 'DevPassword123!',
}),
});
const { status } = await resp.json();
const token = status.access_token;
// Authenticated requests
const orders = await fetch('https://dev.api.olympuscloud.ai/v1/commerce/orders', {
headers: { 'Authorization': `Bearer ${token}` },
}).then(r => r.json());
Python
import requests
# Login
resp = requests.post("https://dev.api.olympuscloud.ai/v1/auth/login", json={
"email": "manager@demo-restaurant.com",
"password": "DevPassword123!",
})
token = resp.json()["status"]["access_token"]
# Authenticated requests
orders = requests.get(
"https://dev.api.olympuscloud.ai/v1/commerce/orders",
headers={"Authorization": f"Bearer {token}"},
).json()
Related Documentation
- Authentication Overview - Authentication concepts
- OAuth & SSO - Social and enterprise login
- MFA - Multi-factor authentication
- Sessions - Session management