# API User Guide

## Overview

This guide provides comprehensive instructions for integrating with the Azotel Simpler Mobile App API. The API is designed to provide secure customer authentication and self-service features for mobile applications.

## Base URL

```
https://yourdomain.com/api/v1
```

## Authentication

The API uses JWT (JSON Web Tokens) for authentication. All endpoints except authentication endpoints require a valid JWT token.

### Token Usage

Include the JWT token in the Authorization header:

```
Authorization: Bearer <your_jwt_token>
```

## Content Type

All requests should use `application/json` content type:

```
Content-Type: application/json
```

## Response Format

All API responses follow a consistent format:

```json
{
  "success": true|false,
  "data": {}, // Present on success
  "error": "ERROR_CODE", // Present on failure
  "message": "Human readable message"
}
```

## HTTP Status Codes

- `200` - Success
- `201` - Created
- `400` - Bad Request
- `401` - Unauthorized
- `403` - Forbidden
- `404` - Not Found
- `405` - Method Not Allowed
- `500` - Internal Server Error

## Authentication Flow

### Step 1: Check Customer Existence

**Endpoint:** `POST /auth/check-customer`

**Purpose:** Verify customer credentials and determine next authentication step.

**Request:**
```json
{
  "invoicing_id": "CUSTOMER123",
  "phone_number": "0821234567"
}
```

**Possible Responses:**

#### Invalid Client ID
```json
{
  "success": false,
  "error": "INVALID_CLIENT_ID",
  "message": "Client ID not found in our system"
}
```

#### Invalid Phone Number
```json
{
  "success": false,
  "error": "INVALID_PHONE_NUMBER",
  "message": "Phone number does not match our records"
}
```

#### Customer Exists - No Password Set
```json
{
  "success": true,
  "status": "NO_PASSWORD",
  "message": "Please set your password.",
  "user_id": 123,
  "customer_data": {
    "invoicing_id": "CUSTOMER123",
    "name": "John Doe",
    "email": "john@example.com",
    "phone": "0821234567"
  }
}
```

#### Customer Exists - Password Set
```json
{
  "success": true,
  "status": "PASSWORD_REQUIRED",
  "message": "Please enter your password.",
  "user_id": 123,
  "customer_data": {
    "invoicing_id": "CUSTOMER123",
    "name": "John Doe",
    "email": "john@example.com",
    "phone": "0821234567"
  }
}
```

### Step 2a: Set Password (First Time Users)

**Endpoint:** `POST /auth/set-password`

**Purpose:** Set password for first-time users.

**Request:**
```json
{
  "user_id": 123,
  "password": "SecurePassword123"
}
```

**Success Response:**
```json
{
  "success": true,
  "message": "Password set successfully",
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "user_data": {
    "user_id": 123,
    "invoicing_id": "CUSTOMER123",
    "name": "John Doe",
    "email": "john@example.com",
    "phone": "0821234567"
  }
}
```

**Error Response:**
```json
{
  "success": false,
  "error": "INVALID_USER_ID",
  "message": "User ID not found"
}
```

### Step 2b: Login (Existing Users)

**Endpoint:** `POST /auth/login`

**Purpose:** Authenticate existing users with password.

**Request:**
```json
{
  "user_id": 123,
  "password": "SecurePassword123"
}
```

**Success Response:**
```json
{
  "success": true,
  "message": "Login successful",
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "user_data": {
    "user_id": 123,
    "invoicing_id": "CUSTOMER123",
    "name": "John Doe",
    "email": "john@example.com",
    "phone": "0821234567"
  }
}
```

**Error Response:**
```json
{
  "success": false,
  "error": "INVALID_PASSWORD",
  "message": "Password is incorrect"
}
```

## Customer Data Endpoints

### Get Customer Information

**Endpoint:** `GET /customer/info`

**Purpose:** Retrieve authenticated customer's information.

**Headers:**
```
Authorization: Bearer <jwt_token>
```

**Success Response:**
```json
{
  "success": true,
  "data": {
    "invoicing_id": "CUSTOMER123",
    "name": "John Doe",
    "email": "john@example.com",
    "phone": "0821234567",
    "account_status": "active",
    "last_updated": "2024-01-15T10:30:00Z"
  }
}
```

### Get Account Balance

**Endpoint:** `GET /customer/balance`

**Purpose:** Retrieve current account balance.

**Headers:**
```
Authorization: Bearer <jwt_token>
```

**Success Response:**
```json
{
  "success": true,
  "data": {
    "current_balance": 150.75,
    "currency": "ZAR",
    "last_updated": "2024-01-15T10:30:00Z"
  }
}
```

### Get Transaction History

**Endpoint:** `GET /customer/transactions`

**Purpose:** Retrieve transaction history.

**Headers:**
```
Authorization: Bearer <jwt_token>
```

**Query Parameters:**
- `limit` (optional): Number of transactions to return (default: 10, max: 100)
- `offset` (optional): Number of transactions to skip (default: 0)

**Success Response:**
```json
{
  "success": true,
  "data": {
    "transactions": [
      {
        "id": "TXN123",
        "type": "payment",
        "amount": 100.00,
        "description": "Monthly subscription",
        "date": "2024-01-15T10:30:00Z",
        "status": "completed"
      }
    ],
    "total_count": 25,
    "has_more": true
  }
}
```

## System Information Endpoints

### Get System Status

**Endpoint:** `GET /system/status`

**Purpose:** Check API system status.

**Headers:**
```
Authorization: Bearer <jwt_token>
```

**Success Response:**
```json
{
  "success": true,
  "data": {
    "status": "operational",
    "version": "1.0.0",
    "timestamp": "2024-01-15T10:30:00Z",
    "services": {
      "database": "operational",
      "azotel_api": "operational"
    }
  }
}
```

## Error Handling

### Common Error Codes

- `INVALID_CLIENT_ID` - Customer ID not found
- `INVALID_PHONE_NUMBER` - Phone number doesn't match records
- `INVALID_USER_ID` - User ID not found
- `INVALID_PASSWORD` - Password is incorrect
- `WEAK_PASSWORD` - Password doesn't meet requirements
- `UNAUTHORIZED` - Missing or invalid JWT token
- `FORBIDDEN` - Access denied
- `RATE_LIMIT_EXCEEDED` - Too many requests
- `INTERNAL_ERROR` - Server error

### Error Response Format

```json
{
  "success": false,
  "error": "ERROR_CODE",
  "message": "Human readable error message",
  "details": {} // Optional additional error details
}
```

## Rate Limiting

The API implements rate limiting to prevent abuse:

- **Authentication endpoints:** 5 requests per minute per IP
- **Data endpoints:** 60 requests per minute per authenticated user

Rate limit headers are included in responses:
```
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 59
X-RateLimit-Reset: 1642248000
```

## Password Requirements

Passwords must meet the following criteria:
- Minimum 8 characters
- At least one uppercase letter
- At least one lowercase letter
- At least one number
- At least one special character

## Phone Number Format

Phone numbers should be provided in one of these formats:
- `0821234567` (South African format)
- `27821234567` (International format)
- `+27821234567` (International format with plus)

## Integration Examples

### Frontend Authentication Flow

```javascript
// Step 1: Check customer
async function checkCustomer(invoicingId, phoneNumber) {
  const response = await fetch('/api/v1/auth/check-customer', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      invoicing_id: invoicingId,
      phone_number: phoneNumber
    })
  });
  
  const data = await response.json();
  
  if (data.success) {
    if (data.status === 'NO_PASSWORD') {
      // Show password setup form
      return { needsPassword: true, userId: data.user_id };
    } else if (data.status === 'PASSWORD_REQUIRED') {
      // Show login form
      return { needsLogin: true, userId: data.user_id };
    }
  } else {
    // Handle error
    throw new Error(data.message);
  }
}

// Step 2a: Set password
async function setPassword(userId, password) {
  const response = await fetch('/api/v1/auth/set-password', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      user_id: userId,
      password: password
    })
  });
  
  const data = await response.json();
  
  if (data.success) {
    // Store token and user data
    localStorage.setItem('jwt_token', data.token);
    localStorage.setItem('user_data', JSON.stringify(data.user_data));
    return data;
  } else {
    throw new Error(data.message);
  }
}

// Step 2b: Login
async function login(userId, password) {
  const response = await fetch('/api/v1/auth/login', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      user_id: userId,
      password: password
    })
  });
  
  const data = await response.json();
  
  if (data.success) {
    // Store token and user data
    localStorage.setItem('jwt_token', data.token);
    localStorage.setItem('user_data', JSON.stringify(data.user_data));
    return data;
  } else {
    throw new Error(data.message);
  }
}

// Making authenticated requests
async function getCustomerInfo() {
  const token = localStorage.getItem('jwt_token');
  
  const response = await fetch('/api/v1/customer/info', {
    method: 'GET',
    headers: {
      'Authorization': `Bearer ${token}`,
      'Content-Type': 'application/json'
    }
  });
  
  const data = await response.json();
  
  if (data.success) {
    return data.data;
  } else {
    if (data.error === 'UNAUTHORIZED') {
      // Token expired, redirect to login
      localStorage.removeItem('jwt_token');
      localStorage.removeItem('user_data');
      window.location.href = '/login';
    }
    throw new Error(data.message);
  }
}
```

### React Native Example

```javascript
// AuthService.js
import AsyncStorage from '@react-native-async-storage/async-storage';

const API_BASE_URL = 'https://yourdomain.com/api/v1';

export class AuthService {
  static async checkCustomer(invoicingId, phoneNumber) {
    try {
      const response = await fetch(`${API_BASE_URL}/auth/check-customer`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          invoicing_id: invoicingId,
          phone_number: phoneNumber,
        }),
      });
      
      const data = await response.json();
      return data;
    } catch (error) {
      throw new Error('Network error: ' + error.message);
    }
  }
  
  static async setPassword(userId, password) {
    try {
      const response = await fetch(`${API_BASE_URL}/auth/set-password`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          user_id: userId,
          password: password,
        }),
      });
      
      const data = await response.json();
      
      if (data.success) {
        await AsyncStorage.setItem('jwt_token', data.token);
        await AsyncStorage.setItem('user_data', JSON.stringify(data.user_data));
      }
      
      return data;
    } catch (error) {
      throw new Error('Network error: ' + error.message);
    }
  }
  
  static async login(userId, password) {
    try {
      const response = await fetch(`${API_BASE_URL}/auth/login`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          user_id: userId,
          password: password,
        }),
      });
      
      const data = await response.json();
      
      if (data.success) {
        await AsyncStorage.setItem('jwt_token', data.token);
        await AsyncStorage.setItem('user_data', JSON.stringify(data.user_data));
      }
      
      return data;
    } catch (error) {
      throw new Error('Network error: ' + error.message);
    }
  }
  
  static async getCustomerInfo() {
    try {
      const token = await AsyncStorage.getItem('jwt_token');
      
      const response = await fetch(`${API_BASE_URL}/customer/info`, {
        method: 'GET',
        headers: {
          'Authorization': `Bearer ${token}`,
          'Content-Type': 'application/json',
        },
      });
      
      const data = await response.json();
      
      if (!data.success && data.error === 'UNAUTHORIZED') {
        await AsyncStorage.removeItem('jwt_token');
        await AsyncStorage.removeItem('user_data');
        // Navigate to login screen
      }
      
      return data;
    } catch (error) {
      throw new Error('Network error: ' + error.message);
    }
  }
}
```

## Testing

### Test Endpoints

You can test the API using the provided test page at `/tests/auth-test.html` or use tools like:

- **Postman**: Create a collection with the endpoints
- **curl**: Command-line testing
- **Insomnia**: REST client

### Example curl Commands

```bash
# Check customer
curl -X POST https://yourdomain.com/api/v1/auth/check-customer \
  -H "Content-Type: application/json" \
  -d '{"invoicing_id":"CUSTOMER123","phone_number":"0821234567"}'

# Set password
curl -X POST https://yourdomain.com/api/v1/auth/set-password \
  -H "Content-Type: application/json" \
  -d '{"user_id":123,"password":"SecurePassword123"}'

# Login
curl -X POST https://yourdomain.com/api/v1/auth/login \
  -H "Content-Type: application/json" \
  -d '{"user_id":123,"password":"SecurePassword123"}'

# Get customer info (with token)
curl -X GET https://yourdomain.com/api/v1/customer/info \
  -H "Authorization: Bearer YOUR_JWT_TOKEN"
```

## Security Considerations

1. **Always use HTTPS** in production
2. **Store JWT tokens securely** (not in localStorage for sensitive apps)
3. **Implement token refresh** for long-lived sessions
4. **Validate all inputs** on the client side
5. **Handle errors gracefully** without exposing sensitive information
6. **Implement logout** to invalidate tokens
7. **Use strong passwords** and validate them

## Support

For technical support or questions about the API:

1. Check the documentation first
2. Review the error codes and messages
3. Test with the provided test page
4. Contact the development team with specific error details

## Changelog

### Version 1.0.0
- Initial release with multi-step authentication
- Customer data endpoints
- System status endpoints
- JWT token authentication
- Rate limiting
- Comprehensive error handling
