Authentication
Learn how to authenticate with the 1House Global API
The 1House Global API uses a two-layer authentication system with platform-based access control.
Two-Layer Security
All API requests require two layers: API Key (platform level) and JWT token (user level) for secure access.
Authentication Layers
The 1House Global API uses a two-layer authentication system:
Layer 1: API Key (Platform Level)
All API requests require an X-API-Key header:
X-API-Key: your-api-key-herePurpose: Identifies which application is making the request (Mobile app, Web platform, CRM, etc.)
Layer 2: JWT Token (User Level)
Most endpoints also require a JWT token:
Authorization: Bearer your-jwt-token-herePurpose: Identifies which user is making the request
Getting Your API Keys
API keys are managed by administrators. Contact your administrator to get API keys for both environments (development and production).
Available API Key Types:
- Mobile App - For mobile applications
- Live Platform - For web applications
- CRM - For internal CRM systems
- Third Party - For external integrations
- Admin - For administrative access
Each key type has different rate limits and permissions.
You'll need separate API keys for development and production environments. Request both from your administrator.
Platform Types
Platform Parameter Required
All sign-in requests must include a platform parameter to specify which 1House platform you're accessing.
Supported platforms: See Platform Types for the full list of valid values, SKU requirements, and access windows.
User Authentication Flow
Sign In
Authenticate existing user (External Backoffice authentication):
POST /v1/auth/signin
X-API-Key: your-api-key
Content-Type: application/jsonExternal Backoffice Authentication
Sign-in authenticates against the External Backoffice backend and validates platform-specific service access.
{
"email": "user@example.com",
"password": "password123",
"platform": "app", // REQUIRED: see Platform Types
"device": "mobile", // Optional: mobile | web | tablet
"deviceId": "device-uuid-123" // Optional: unique device identifier
}Required Fields:
email- User email addresspassword- User passwordplatform- Platform type (validates service access)
Optional Fields:
device- Device type (default: web)deviceId- Unique device identifier
{
"success": true,
"status": 200,
"message": "Signed in to Mobile App successfully",
"data": {
"user": {
"id": "user_123",
"email": "user@example.com",
"firstName": "John",
"lastName": "Doe",
"role": "user",
"customerId": "33"
},
"accessToken": "eyJhbGciOiJIUzI1NiIs...",
"refreshToken": "eyJhbGciOiJIUzI1NiIs...",
"sessionId": "def-456-ghi-789", // MongoDB session UUID
"platform": "app",
"platformName": "Mobile App",
"expiration": "2025-12-31T23:59:59.000Z", // External Backoffice service expiration
"backofficeAccessToken": "eyJhbGciOiJIUzI1NiIs...", // Token for direct backoffice API calls
"backofficeRefreshToken": "eyJhbGciOiJIUzI1NiIs..." // Refresh token for backoffice
},
"meta": {
"timestamp": "2025-10-21T12:00:00.000Z",
"version": "v1"
}
}Backoffice Tokens: The backofficeAccessToken and backofficeRefreshToken are returned from the 1houseglobal.dev backoffice. Use the backofficeAccessToken with the X-Backoffice-Token header for endpoints like /user/get and /user/customer-status:
X-Backoffice-Token: {backofficeAccessToken}{
"success": false,
"status": 403,
"message": "No access to Mobile App. Missing services: 34, 35",
"error": "No access to Mobile App. Missing services: 34, 35",
"errorId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"meta": {
"timestamp": "2025-10-21T12:00:00.000Z",
"version": "v1",
"errorId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}
}Error UUID: Use the errorId for quick error lookup and support requests.
Try it out:
Sign In (Single Sign-On)
Authenticate by customer ID or user ID (no password). Returns the same payload as normal sign-in (user, JWT tokens, session, backoffice tokens).
Supported platforms (SSO)
See Platform Types for the full list. Only livestream is used for redirect-based SSO: use platform=livestream to get the redirect URL or 302 redirect.
Ways to call SSO:
| Method | Use case |
|---|---|
| GET with query params | Single URL (link or redirect). When platform=livestream, the server responds with 302 redirect to the livestream app with a single JWT containing all data. |
| POST with JSON body | API clients. When platform=livestream, the JSON response includes redirectUrl (URL with JWT) so the client can redirect the user. |
Required backoffice tokens
Every request must include the backoffice accessToken (bearer) and refreshToken. They are echoed back as backofficeAccessToken and backofficeRefreshToken for backoffice API calls (e.g. X-Backoffice-Token).
Livestream redirect: With platform=livestream, the backend returns a 302 to {LIVESTREAM_SSO_REDIRECT_URL}/sso?token={jwt}. The JWT (5 min) holds user, tokens, and session data; the livestream app verifies it with the shared JWT secret. Set LIVESTREAM_SSO_REDIRECT_URL on the auth service.
- GET – Query params (table below).
platform=livestreamreturns 302 to livestream app; otherwise 200 JSON. - POST – JSON body:
customerIdoruserId,accessToken,refreshToken(required);platform,device,deviceId(optional). 200 JSON; ifplatform=livestream, response includesdata.redirectUrl.
Query parameters (GET /v1/auth/signin-sso):
| Parameter | Type | Required | Description |
|---|---|---|---|
customerId | string | One of with userId | Customer ID from backoffice |
userId | string | One of with customerId | User ID (MongoDB ObjectId) |
accessToken | string | Yes | Backoffice bearer token |
refreshToken | string | Yes | Backoffice refresh token |
platform | string | No | Use livestream for redirect; default app. See Platform Types. |
device | string | No | e.g. web |
deviceId | string | No | Device identifier |
noRedirect | string | No | Set to 1 or true to return 200 JSON with data.redirectUrl instead of 302 redirect. Use when testing (e.g. in api-docs) so the redirect URL is shown instead of following the redirect. |
Example GET URL: GET /v1/auth/signin-sso?customerId=33&accessToken=...&refreshToken=...&platform=livestream
For testing in api-docs, add &noRedirect=1 so the response is 200 JSON with data.redirectUrl instead of a 302 redirect.
{
"customerId": "33",
"accessToken": "eyJhbGciOiJIUzI1NiIs...",
"refreshToken": "eyJhbGciOiJIUzI1NiIs...",
"platform": "livestream",
"device": "web",
"deviceId": "device-uuid-123"
}Use userId (MongoDB ObjectId) instead of customerId if preferred. For GET, pass the same fields as query parameters (see table above).
GET with platform=livestream: 302 redirect. No JSON body. Location header is {LIVESTREAM_SSO_REDIRECT_URL}/sso?token={jwt}. The JWT payload (decode with auth service JWT secret) contains: type: "sso-redirect", userId, sessionId, user, accessToken, refreshToken, backofficeAccessToken, backofficeRefreshToken. JWT expiry: 5 minutes. With noRedirect=1: returns 200 with data.redirectUrl (same URL) so you can test without following the redirect.
200 JSON (POST, or GET):
{
"success": true,
"status": 200,
"message": "Signed in successfully",
"data": {
"user": { "id": "...", "customerId": "33", "email": "...", "firstName": "...", "lastName": "...", "role": "user", "permissions": [] },
"accessToken": "eyJhbGciOiJIUzI1NiIs...",
"refreshToken": "eyJhbGciOiJIUzI1NiIs...",
"sessionId": "def-456-ghi-789",
"backofficeAccessToken": "eyJhbGciOiJIUzI1NiIs...",
"backofficeRefreshToken": "eyJhbGciOiJIUzI1NiIs...",
"redirectUrl": "https://1house.tv/sso?token=eyJhbGciOiJIUzI1NiIs..."
},
"meta": { "timestamp": "...", "version": "v1" }
}When platform=livestream, data.redirectUrl is the livestream base URL with ?token={jwt} (e.g. https://www.1h.tv/sso?token=...).
Try it out (POST):
Try it out (GET with noRedirect=1 — returns redirect URL in JSON instead of 302):
Use Access Token
Include the access token in subsequent requests:
GET /v1/user/profile
X-API-Key: your-api-key
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...The session created during sign-in is tracked in MongoDB and includes:
- Platform and device information
- Session expiration (7 days)
- Activity tracking
- Automatic cleanup after expiration
Refresh Token
Token Expiration
Access tokens expire after 15 minutes. Implement automatic token refresh to maintain seamless user experience.
Access tokens expire after 15 minutes. Use the refresh token to get a new one:
# Development
POST https://api-gateway.dev.1houseglobalservices.com/v1/auth/refresh-token
X-API-Key: your-development-api-key
Content-Type: application/json
# Production
POST https://api-gateway.prod.1houseglobalservices.com/v1/auth/refresh-token
X-API-Key: your-production-api-key
Content-Type: application/json{
"refreshToken": "eyJhbGciOiJIUzI1NiIs..."
}Response:
{
"success": true,
"status": 200,
"message": "Token refreshed successfully",
"data": {
"accessToken": "eyJhbGciOiJIUzI1NiIs...",
"refreshToken": "eyJhbGciOiJIUzI1NiIs..."
},
"meta": {
"timestamp": "2025-10-21T12:00:00.000Z",
"version": "v1"
}
}Token Lifecycle
| Token Type | Expiration | Purpose | Storage |
|---|---|---|---|
| Access Token | 15 minutes | API requests | Memory/localStorage |
| Refresh Token | 7 days | Renew access token | Secure storage |
Best Practices
**Store tokens securely
- Use httpOnly cookies for web apps
- Use secure storage for mobile apps
- Never expose tokens in URLs
**Handle token expiration
// Example: Auto-refresh on 401
if (response.status === 401) {
const newToken = await refreshAccessToken();
// Retry original request with new token
}**Clear tokens on logout
localStorage.removeItem('accessToken');
localStorage.removeItem('refreshToken');Session Management
MongoDB Sessions
All authentication creates persistent sessions in MongoDB with platform, device, and activity tracking.
Session Properties
- sessionId - Unique UUID for the session
- platform - Which platform (see Platform Types)
- device - Device type (mobile, web, tablet)
- isActive - Session status
- expiresAt - Auto-expiration (7 days)
- lastActivityAt - Last request timestamp
Get User
Retrieve user information from the backoffice system. Can accept either a customerId (string) or MongoDB ObjectId.
POST /v1/user/get
X-API-Key: your-api-key
Authorization: Bearer your-access-token
X-Backoffice-Token: backoffice-access-token
Content-Type: application/jsonBackoffice Integration
This endpoint calls the external backoffice API to retrieve user data.
Required Headers:
Authorization: Bearer token for backend authentication (your JWT)X-Backoffice-Token: ThebackofficeAccessTokenreturned from sign-in (used for backoffice API calls)
With customerId (string):
{
"customerId": "33"
}With userId (MongoDB ObjectId):
{
"userId": "507f1f77bcf86cd799439011"
}Snake case is also supported:
{
"customer_id": "33"
}or
{
"user_id": "507f1f77bcf86cd799439011"
}Note: If a MongoDB ObjectId is provided via userId or user_id, the system will automatically query MongoDB to find the user and retrieve their customerId before calling the backoffice API.
{
"success": true,
"status": 200,
"message": "User info retrieved successfully",
"data": {
"user": {
"id": 33,
"wordpress_user_id": null,
"username": "dahmeyon",
"email": "dahmeyon@younivision.com",
"is_super_admin": 0,
"is_sub_admin": 0,
"sponsor": 6,
"active": 1,
"customer": 0,
"rank_id": 1,
"unilevel_rank_id": 1,
"is_vested_binary": 0,
"is_vested_unilevel": 0,
"vested_binary_rank": null,
"vested_unilevel_rank": null,
"package_id": 0,
"block_type": null,
"is_turn_on_email": 1,
"public_key": null,
"effective_start_date": null,
"effective_until": null,
"breakage_share": 0,
"created_at": "2025-12-08T17:29:03.000000Z",
"updated_at": "2025-12-08T17:29:03.000000Z",
"email_verified_at": null,
"remember_token": null,
"google2fa_secret": "0",
"google2fa_secret_url": "0",
"advanced_reporting": 0
},
"services": []
},
"meta": {
"timestamp": "2025-10-21T12:00:00.000Z",
"version": "v1"
}
}Try it out:
Get Customer Status
Retrieve customer status from the 1houseglobal.dev backoffice. This endpoint provides a structured response with customer status, active state, and associated services.
POST /v1/user/customer-status
X-API-Key: your-api-key
Authorization: Bearer your-access-token
X-Backoffice-Token: backoffice-access-token
Content-Type: application/jsonFlexible Identifier & Required Headers
This endpoint accepts either a customerId (backoffice ID) or userId (MongoDB ObjectId). If a MongoDB ObjectId is provided, the system automatically looks up the user's customerId before calling the backoffice.
Required Headers:
Authorization: Bearer token for backend authentication (your JWT)X-Backoffice-Token: ThebackofficeAccessTokenreturned from sign-in (used for backoffice API calls)
With customerId:
{
"customerId": "33"
}With userId (MongoDB ObjectId):
{
"userId": "65a1b2c3d4e5f6789abcdef0"
}Snake case is also supported:
{
"customer_id": "33"
}or
{
"user_id": "65a1b2c3d4e5f6789abcdef0"
}{
"success": true,
"status": 200,
"message": "Customer status retrieved successfully",
"data": {
"customerId": "33",
"userId": "65a1b2c3d4e5f6789abcdef0",
"status": {
"active": true,
"email": "user@example.com",
"username": "johndoe",
"createdAt": "2025-01-15T10:30:00.000Z",
"lastLogin": "2025-01-21T08:45:00.000Z"
},
"services": [
{
"id": 34,
"name": "Mobile App Access",
"active": true
},
{
"id": 35,
"name": "Live Platform Access",
"active": true
}
],
"raw": {
"user": { /* full backoffice user object */ },
"services": [ /* full services array */ ]
}
},
"meta": {
"timestamp": "2025-01-21T12:00:00.000Z",
"version": "v1"
}
}User not found:
{
"success": false,
"status": 404,
"message": "User not found in MongoDB",
"errorId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}User has no customerId:
{
"success": false,
"status": 400,
"message": "User does not have a customerId linked to backoffice",
"errorId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}Try it out:
Sign Out
Invalidate sessions with granular control. For platform users (users with customerId), this also signs them out from the external backoffice system.
POST /v1/auth/signout
X-API-Key: your-api-key
Authorization: Bearer your-access-token
Content-Type: application/jsonBackoffice Integration
For platform users (users with a customerId), signing out will also automatically sign them out from the external backoffice system. The bearer token is forwarded to the backoffice for authentication.
Sign out from all devices and platforms:
{}Response:
{
"success": true,
"status": 200,
"message": "Signed out successfully",
"data": {
"message": "Signed out successfully",
"device": null,
"platform": null
},
"meta": {
"timestamp": "2025-10-21T12:00:00.000Z",
"version": "v1"
}
}Sign out from specific platform only:
{
"platform": "app"
}Deactivates all "app" sessions, keeps "livestream", "scanners", "web", and "backoffice" sessions active.
Sign out from specific device and platform:
{
"device": "mobile",
"platform": "app"
}Deactivates only mobile+app sessions, keeps other combinations active.
Sign out a specific user by customerId or MongoDB ObjectId:
{
"customerId": "33"
}or
{
"customerId": "507f1f77bcf86cd799439011"
}Note: If a MongoDB ObjectId is provided, the system will automatically query MongoDB to find the user before signing them out.
Try it out:
Admin User Management
Admin user management endpoints live under /v1/admin/auth/users. They require admin authentication.
Base Path: /v1/admin/auth/users
List Users (Admin)
GET /v1/admin/auth/usersQuery Parameters:
| Parameter | Type | Description |
|---|---|---|
| page | number | Page number (default: 1) |
| limit | number | Results per page (default: 20) |
| search | string | Search by name or email |
| role | string | Filter by role: user, educator, admin |
Create User (Admin)
Create a new user (e.g. for educators or backoffice mapping).
POST /v1/admin/auth/usersRequest Body:
{
"firstName": "Jane",
"lastName": "Doe",
"email": "jane.doe@example.com",
"password": "SecurePass123!",
"role": "educator",
"customerId": "42",
"username": "janedoe",
"permissions": ["educator"],
"phone": "+1234567890",
"profileImage": "https://cdn.1houseglobal.com/avatar.jpg"
}Required Fields:
firstName- First name (2–50 characters)lastName- Last name (2–50 characters)email- Email addresspassword- Password (min 8 characters)
Optional Fields:
role- One ofuser,admin,moderator,educator(default:user). Often used to derivepermissions.username- Display/login username. If omitted, a unique username is auto-generated from the email.customerId- Backoffice customer ID; links this user to the external backoffice (mapped user).permissions- Array of permission strings (e.g.["educator"],["admin"]). Can be set from role.phone- E.164 formatprofileImage- URL
Update User (Admin)
Update an existing user. Use this to map a user to the backoffice (customerId) or change profile/role.
PUT /v1/admin/auth/users/:userIdRequest Body (all optional):
{
"firstName": "Jane",
"lastName": "Doe",
"email": "jane.doe@example.com",
"customerId": "42",
"role": "educator",
"profileImage": "https://cdn.1houseglobal.com/avatar.jpg",
"educator_title": "Senior Educator",
"educator_bio": "Trading and education.",
"skills": ["Trading", "Education"]
}Mapping to backoffice: Set customerId (and optionally email) to link a user to the external backoffice. Users with a customerId are considered "mapped"; sign-in and profile can use backoffice data.
Optional educator fields: educator_title, educator_bio, banner_image, specialty, skills, socials, etc. See User Profile and Educators for full lists.
Password Reset
Request Reset
POST /v1/auth/forgot-password{
"email": "user@example.com"
}Reset Password
POST /v1/auth/reset-password{
"token": "reset-token-from-email",
"newPassword": "NewSecurePass123!"
}Email Verification
Verify Email
POST /v1/auth/verify-email{
"token": "verification-token-from-email"
}Resend Verification
POST /v1/auth/resend-verificationX-API-Key: your-api-key
Authorization: Bearer your-access-tokenSecurity Features
Rate Limiting
- Per API key
- Per endpoint
- Configurable limits by tier
Token Blacklisting
- Logout invalidates tokens
- Tokens cannot be reused
- Stored in Redis for fast lookup
Password Requirements
- Minimum 8 characters
- Must include uppercase letter
- Must include lowercase letter
- Must include number
- Must include special character
Failed Login Protection
- Account locked after 5 failed attempts
- 15-minute lockout period
- Email notification on lockout
Error Handling
4xx forwarding
The API gateway forwards 4xx status codes and error messages from the auth service. Validation and auth errors (e.g. duplicate email, invalid credentials) are returned with the correct status (400, 401, 403, 404) instead of being converted to 500.
Error UUIDs
All errors include a unique errorId (UUID) for quick reference and support lookup. The error is logged centrally with complete context.
Error Response Format
{
"success": false,
"status": 403,
"message": "No access to Mobile App. Missing services: 34, 35",
"error": "No access to Mobile App. Missing services: 34, 35",
"errorId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"meta": {
"timestamp": "2025-10-21T12:00:00.000Z",
"version": "v1",
"errorId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}
}Using Error UUIDs:
- Include
errorIdin support requests for quick debugging - Error details stored in centralized error-log-service
- Full request context, stack traces, and user info available
- Automatic sensitive data sanitization
Error Codes
| Status Code | Error | Description |
|---|---|---|
| 400 | Bad Request | Invalid platform or missing required fields |
| 401 | Unauthorized | Missing or invalid API key |
| 401 | Invalid Token | JWT token is invalid or expired |
| 401 | Token Expired | Access token has expired, refresh it |
| 403 | Forbidden | No access to platform (missing required SKU) or account inactive |
| 429 | Too Many Requests | Rate limit exceeded |
Platform Access Errors
| Platform | Error | Reason |
|---|---|---|
| app | Missing services: 34, 35 | User doesn't have both required services |
| livestream | No access to Live Platform. A valid subscription (SKU) is required. | User has no required SKU for livestream |
| app | No access to Mobile App. A valid subscription (SKU) is required. | User has no required SKU for app |
| scanners | No access to Scanners. A valid subscription (SKU) is required. | User has no required SKU for scanners (when SKUs defined) |
Code Examples
// Configure environment URLs and API keys
const DEV_API_URL = 'https://api-gateway.dev.1houseglobalservices.com';
const PROD_API_URL = 'https://api-gateway.prod.1houseglobalservices.com';
const DEV_API_KEY = 'your-development-api-key';
const PROD_API_KEY = 'your-production-api-key';
// Use appropriate environment
const apiUrl = process.env.NODE_ENV === 'production' ? PROD_API_URL : DEV_API_URL;
const apiKey = process.env.NODE_ENV === 'production' ? PROD_API_KEY : DEV_API_KEY;
// Sign in with platform
const response = await fetch(`${apiUrl}/v1/auth/signin`, {
method: 'POST',
headers: {
'X-API-Key': apiKey,
'Content-Type': 'application/json'
},
body: JSON.stringify({
email: 'user@example.com',
password: 'password123',
platform: 'app', // REQUIRED: see Platform Types
device: 'mobile', // Optional
deviceId: 'device-uuid' // Optional
})
});
if (!response.ok) {
const error = await response.json();
console.error(`Error ${error.errorId}: ${error.message}`);
// Include errorId in support requests
throw new Error(error.message);
}
const { data } = await response.json();
const { accessToken, refreshToken, sessionId, platform, platformName } = data;
// Store tokens and session info
localStorage.setItem('accessToken', accessToken);
localStorage.setItem('refreshToken', refreshToken);
localStorage.setItem('sessionId', sessionId);
localStorage.setItem('platform', platform);
// Make authenticated request
const profileResponse = await fetch(`${apiUrl}/v1/user/profile`, {
headers: {
'X-API-Key': apiKey,
'Authorization': `Bearer ${accessToken}`
}
});import requests
import os
# Configure environment URLs and API keys
DEV_API_URL = 'https://api-gateway.dev.1houseglobalservices.com'
PROD_API_URL = 'https://api-gateway.prod.1houseglobalservices.com'
DEV_API_KEY = 'your-development-api-key'
PROD_API_KEY = 'your-production-api-key'
# Use appropriate environment
api_url = PROD_API_URL if os.getenv('ENVIRONMENT') == 'production' else DEV_API_URL
api_key = PROD_API_KEY if os.getenv('ENVIRONMENT') == 'production' else DEV_API_KEY
# Sign in with platform (current backoffice does not support sign-up)
response = requests.post(
f'{api_url}/v1/auth/signin',
headers={
'X-API-Key': api_key,
'Content-Type': 'application/json'
},
json={
'email': 'user@example.com',
'password': 'SecurePass123!',
'platform': 'app', # REQUIRED
'device': 'mobile', # Optional
'deviceId': 'device-uuid' # Optional
}
)
data = response.json()
access_token = data['data']['accessToken']
refresh_token = data['data']['refreshToken']
# Make authenticated request
profile = requests.get(
f'{api_url}/v1/user/profile',
headers={
'X-API-Key': api_key,
'Authorization': f'Bearer {access_token}'
}
)# Development - Sign in (current backoffice does not support sign-up)
curl -X POST https://api-gateway.dev.1houseglobalservices.com/v1/auth/signin \
-H "X-API-Key: your-development-api-key" \
-H "Content-Type: application/json" \
-d '{
"email": "user@example.com",
"password": "password123",
"platform": "app"
}'
# Production - Sign in
curl -X POST https://api-gateway.prod.1houseglobalservices.com/v1/auth/signin \
-H "X-API-Key: your-production-api-key" \
-H "Content-Type: application/json" \
-d '{
"email": "user@example.com",
"password": "SecurePass123!",
"platform": "app"
}'