Authentication
Authentication endpoints for AsaHome Cloud.
Endpoints Overview
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| POST | /auth/login | Login and get tokens | No |
| POST | /auth/refresh | Refresh access token | No |
| POST | /auth/logout | Logout and revoke token | Yes |
| POST | /auth/sync-customer | Sync customer from Laravel | API Key |
Base URL: https://cloud.asahome.io/api/v1
POST Login
Authenticate a user and receive JWT tokens.
Request
POST /api/v1/auth/login
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
email | string | Yes | User email address |
password | string | Yes | User password |
Example
curl -X POST "https://cloud.asahome.io/api/v1/auth/login" \
-H "Content-Type: application/json" \
-d '{
"email": "user@example.com",
"password": "yourPassword123"
}'
Response
{
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"expiresIn": 900,
"user": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "user@example.com",
"firstName": "John",
"lastName": "Doe",
"role": "user"
}
}
Token Specifications
| Token | Lifetime | Purpose |
|---|---|---|
accessToken | 15 minutes | API authentication |
refreshToken | 30 days | Obtain new access tokens |
Error Responses
Invalid Credentials (401)
{
"statusCode": 401,
"message": "Invalid email or password",
"error": "Unauthorized"
}
Account Inactive (403)
{
"statusCode": 403,
"message": "Account is inactive",
"error": "Forbidden"
}
POST Refresh Token
Exchange a refresh token for new access and refresh tokens.
Request
POST /api/v1/auth/refresh
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
refreshToken | string | Yes | Valid refresh token |
Example
curl -X POST "https://cloud.asahome.io/api/v1/auth/refresh" \
-H "Content-Type: application/json" \
-d '{
"refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}'
Response
{
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"expiresIn": 900
}
Each refresh invalidates the previous refresh token and issues a new one. Store the new refresh token for future refreshes.
Error Responses
Token Expired (401)
{
"statusCode": 401,
"message": "Refresh token has expired",
"error": "Unauthorized"
}
Token Revoked (401)
{
"statusCode": 401,
"message": "Refresh token has been revoked",
"error": "Unauthorized"
}
POST Logout
Invalidate the current session by revoking the refresh token.
Request
POST /api/v1/auth/logout
Headers
| Header | Required | Description |
|---|---|---|
Authorization | Yes | Bearer <accessToken> |
Example
curl -X POST "https://cloud.asahome.io/api/v1/auth/logout" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
Response
{
"message": "Successfully logged out"
}
After logout, the access token remains valid until expiry (up to 15 minutes). For immediate invalidation, implement client-side token removal.
POST Sync Customer
Synchronize customer data from an external Laravel application. This endpoint creates or updates a user based on the Laravel customer data.
Authentication
This endpoint uses internal API key authentication instead of JWT.
Request
POST /api/v1/auth/sync-customer
Headers
| Header | Required | Description |
|---|---|---|
X-Internal-Api-Key | Yes | Internal API key |
Content-Type | Yes | application/json |
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
id | integer | Yes | Customer ID in Laravel |
user_id | integer | No | Associated user ID |
company_name | string | No | Company/organization name |
first_name | string | Yes | Customer first name |
last_name | string | Yes | Customer last name |
email | string | Yes | Customer email (unique) |
user_type | integer | No | User type identifier |
mrr | decimal | No | Monthly recurring revenue |
active | boolean | Yes | Account active status |
contract_language | string | No | Preferred language |
created_by | integer | No | Admin who created |
status | integer | No | Customer status code |
Example
curl -X POST "https://cloud.asahome.io/api/v1/auth/sync-customer" \
-H "X-Internal-Api-Key: your-internal-api-key" \
-H "Content-Type: application/json" \
-d '{
"id": 123,
"user_id": 456,
"company_name": "Acme Corp",
"first_name": "John",
"last_name": "Doe",
"email": "john@acme.com",
"user_type": 1,
"mrr": 99.99,
"active": true,
"contract_language": "en",
"created_by": 1,
"status": 1
}'
Response
{
"success": true,
"user": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"sync_id": 123,
"email": "john@acme.com",
"firstName": "John",
"lastName": "Doe",
"isActive": true,
"createdAt": "2024-01-15T10:30:00.000Z"
},
"created": true
}
| Field | Description |
|---|---|
success | Whether the sync was successful |
user | The created or updated user object |
created | true if new user, false if updated |
Error Responses
Invalid API Key (401)
{
"statusCode": 401,
"message": "Invalid API key",
"error": "Unauthorized"
}
Email Conflict (409)
{
"success": false,
"error": "Email already exists with different sync_id",
"code": "CONFLICT"
}
Validation Error (400)
{
"statusCode": 400,
"message": ["email must be an email", "first_name should not be empty"],
"error": "Bad Request"
}
JWT Token Structure
Access Token Claims
{
"sub": "550e8400-e29b-41d4-a716-446655440000",
"email": "user@example.com",
"role": "user",
"iat": 1700000000,
"exp": 1700000900
}
| Claim | Description |
|---|---|
sub | User ID (UUID) |
email | User email address |
role | User role (user or admin) |
iat | Issued at timestamp |
exp | Expiration timestamp |
Using the Access Token
Include the token in the Authorization header for all authenticated requests:
curl -X GET "https://cloud.asahome.io/api/v1/devices" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"