Skip to main content
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:

MethodUse CaseEndpoint
Email/PasswordStandard user loginPOST /api/v1/auth/login
PINStaff quick loginPOST /api/v1/auth/login/pin
Quick LoginPIN alias (accepts "code" field)POST /api/v1/auth/quick-login
BadgeStaff badge scan loginPOST /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

FieldTypeRequiredDescription
emailstringYesUser's email address
passwordstringYesUser's password
tenant_idstringYesTenant identifier
location_idstringNoLocation for context (staff logins)
remember_mebooleanNoExtended 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

FieldTypeDescription
access_tokenstringJWT for API authentication (1 hour)
refresh_tokenstringToken for obtaining new access tokens
expires_innumberToken lifetime in seconds
userobjectAuthenticated user details
mfa_requiredbooleanIf 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

FieldTypeRequiredDescription
pinstringYes4-6 digit PIN
tenant_idstringYesTenant identifier
location_idstringYesLocation identifier
device_idstringYesRegistered 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

EndpointLimitWindow
/auth/login5 attemptsPer minute per IP
/auth/login/pin10 attemptsPer minute per device
/auth/staff/badge10 attemptsPer minute per device

After exceeding limits, a 429 Too Many Requests response is returned.


Security Best Practices

  1. Always use HTTPS - Never send credentials over unencrypted connections
  2. Store tokens securely - Use secure storage (Keychain, Keystore, HttpOnly cookies)
  3. Implement token refresh - Refresh before expiration to maintain sessions
  4. Handle failures gracefully - Don't reveal whether email exists
  5. 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()