# AnchorX REST API Documentation
## For Flutter Mobile App Integration

**Base URL:** `https://yourdomain.com/anchorx/api/v1`  
**Content-Type:** `application/json`  
**Auth:** `Authorization: Bearer {access_token}`

---

## Overview

All responses follow this structure:
```json
{
  "success": true,
  "message": "OK",
  "data": { ... }
}
```
Errors:
```json
{
  "success": false,
  "message": "Error description",
  "errors": ["field specific errors"]
}
```

---

## Authentication

### POST /auth/login
Login and receive JWT tokens.

**Request:**
```json
{
  "email": "contact@hedgefund.com",
  "password": "securepassword"
}
```
**Headers:**
```
X-Device-ID: unique-device-uuid
X-Platform: ios | android
X-App-Version: 1.0.0
```
**Response:**
```json
{
  "data": {
    "institution": {
      "id": 1,
      "account_number": "AX-AB12CD34EF",
      "firm_name": "Apex Capital Fund",
      "contact_name": "John Smith",
      "email": "john@apexcapital.com",
      "status": "approved",
      "kyb_status": "approved",
      "credit_line": 5000000.00,
      "margin_ratio": 10.00,
      "trading_mode": "demo"
    },
    "tokens": {
      "access_token": "eyJ...",
      "refresh_token": "a1b2c3...",
      "token_type": "Bearer",
      "expires_in": 86400
    }
  }
}
```

---

### POST /auth/refresh
Get a new access token using the refresh token.

**Request:**
```json
{ "refresh_token": "a1b2c3..." }
```
**Response:**
```json
{
  "data": {
    "access_token": "eyJ...",
    "token_type": "Bearer",
    "expires_in": 86400
  }
}
```

---

### POST /auth/logout
```json
{
  "refresh_token": "a1b2c3...",
  "all_devices": false
}
```
Set `all_devices: true` to revoke all sessions.

---

### POST /auth/register
Submit a new institution application.

```json
{
  "firm_name": "Apex Capital Fund",
  "legal_entity": "Apex Capital Fund Ltd",
  "institution_type": "hedge_fund",
  "contact_name": "John Smith",
  "contact_title": "Head of Trading",
  "email": "john@apexcapital.com",
  "password": "securepassword",
  "phone": "+2348012345678",
  "country": "Nigeria",
  "aum_range": "$50M-$100M"
}
```
Valid `institution_type` values: `hedge_fund`, `family_office`, `corporate`, `bank`, `asset_manager`, `venture_fund`, `other`

---

### GET /auth/me
Returns full profile of the logged-in institution.

---

### POST /auth/push-token
Register FCM push notification token.
```json
{
  "fcm_token": "firebase-device-token",
  "platform": "android"
}
```

### POST /auth/change-password
```json
{
  "current_password": "oldpass",
  "new_password": "newpass123"
}
```
⚠️ Revokes all refresh tokens — user must log in again.

---

## Dashboard

### GET /dashboard
Returns portfolio summary, recent trades, open RFQs, RM info.

```json
{
  "data": {
    "summary": {
      "live_portfolio_usd": 250000.00,
      "demo_portfolio_usd": 10000000.00,
      "total_pnl": 12450.00,
      "credit_line": 5000000.00,
      "margin_ratio": 10.0,
      "trading_mode": "demo"
    },
    "stats": {
      "total_trades": 24,
      "pending_deposits": 1,
      "pending_withdrawals": 0,
      "quotes_awaiting_action": 2
    },
    "recent_trades": [...],
    "open_rfqs": [...],
    "relationship_manager": {
      "name": "Sarah Johnson",
      "email": "sarah@anchorx.io"
    }
  }
}
```

---

## Markets

### GET /markets *(public — no auth needed)*
```json
{
  "data": {
    "markets": [
      { "pair": "BTC/USDT", "price": 67420.00, "change_24h": 2.34, "updated_at": "..." },
      { "pair": "ETH/USDT", "price": 3842.50, "change_24h": 1.87, "updated_at": "..." }
    ],
    "count": 12
  }
}
```

---

## Custody

### GET /custody
Returns all asset balances with USD valuations.

```json
{
  "data": {
    "accounts": [
      {
        "asset": "BTC",
        "live_balance": 2.45,
        "demo_balance": 150.0,
        "locked_balance": 0.0,
        "price_usd": 67420.00,
        "change_24h": 2.34,
        "live_usd_value": 165179.00,
        "demo_usd_value": 10113000.00
      }
    ],
    "live_total_usd": 165179.00,
    "demo_total_usd": 10500000.00,
    "credit_line": 5000000.00,
    "trading_mode": "demo"
  }
}
```

---

## RFQ / Trading

### GET /rfq
List RFQ requests.

| Param | Type | Description |
|-------|------|-------------|
| `page` | int | Page number (default: 1) |
| `per_page` | int | Results per page (max: 100) |
| `status` | string | Filter: `requested`, `quoted`, `accepted`, `settled`, `expired` |
| `is_demo` | 0/1 | Filter by demo/live |

---

### POST /rfq
Submit a new trade request.

```json
{
  "pair": "BTC/USDT",
  "side": "buy",
  "quantity": 0.5,
  "is_demo": 1
}
```

**Demo mode:** Executes instantly at market price. Returns `status: "settled"`.  
**Live mode:** Creates pending RFQ. Returns `status: "requested"`. Admin provides a firm quote.

**Response (demo):**
```json
{
  "data": {
    "rfq": {
      "id": 42,
      "quote_ref": "RFQ-AB123456-20251219",
      "pair": "BTC/USDT",
      "side": "buy",
      "quantity": 0.5,
      "final_price": 67420.00,
      "total_value": 33710.00,
      "status": "settled",
      "is_demo": true
    },
    "status": "settled"
  }
}
```

---

### POST /rfq/{id}/accept
Accept a firm quote provided by admin.  
Only valid when RFQ `status === "quoted"`.

### POST /rfq/{id}/reject
Reject a quoted RFQ.

---

## Trades

### GET /trades

| Param | Type | Description |
|-------|------|-------------|
| `page` | int | |
| `per_page` | int | |
| `is_demo` | 0/1 | |
| `pair` | string | e.g. `BTC/USDT` |
| `status` | string | `executed`, `settled`, `cancelled` |

---

## Deposits

### GET /deposits

### POST /deposits
```json
{
  "asset": "BTC",
  "amount": 1.5,
  "network": "Bitcoin",
  "txn_hash": "abc123...",
  "is_demo": 0
}
```

---

## Withdrawals

### GET /withdrawals

### POST /withdrawals
```json
{
  "asset": "USDT",
  "amount": 50000,
  "network": "TRC20",
  "destination_address": "TXxxxxxx...",
  "is_demo": 0
}
```

---

## Profile

### GET /profile
Full institution profile.

### PUT /profile
Updatable fields only:
```json
{
  "contact_title": "Head of Trading",
  "phone": "+2348012345678",
  "website": "https://apexcapital.com"
}
```

---

## Notifications

### GET /notifications
```json
{
  "data": {
    "notifications": [
      {
        "type": "action_required",
        "title": "Quote Ready",
        "body": "You have firm quotes awaiting your acceptance.",
        "read": false,
        "time": "2025-12-19 14:30:00"
      },
      ...
    ],
    "unread_count": 2
  }
}
```
Types: `action_required`, `trading`, `deposit`, `withdrawal`, `security`, `account`, `general`

---

## Health Check

### GET /health *(public)*
```json
{ "data": { "status": "ok", "version": "v1", "timestamp": 1734567890 } }
```

---

## HTTP Status Codes

| Code | Meaning |
|------|---------|
| 200 | Success |
| 201 | Created |
| 204 | No Content |
| 400 | Bad Request |
| 401 | Unauthorized / Invalid token |
| 403 | Forbidden (account suspended, etc.) |
| 404 | Not Found |
| 409 | Conflict (duplicate email, etc.) |
| 422 | Validation Error |
| 429 | Rate Limited (60 req/min) |
| 500 | Server Error |

---

## Rate Limiting

60 requests per minute per IP. Headers returned:
```
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 58
X-RateLimit-Reset: 1734567950
```

---

## Flutter Integration Example

```dart
// lib/services/api_service.dart

import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:flutter_secure_storage/flutter_secure_storage.dart';

class ApiService {
  static const baseUrl = 'https://yourdomain.com/anchorx/api/v1';
  static const storage = FlutterSecureStorage();

  static Future<Map<String, String>> _headers({bool auth = true}) async {
    final headers = {
      'Content-Type': 'application/json',
      'X-Platform': Platform.isIOS ? 'ios' : 'android',
      'X-App-Version': '1.0.0',
      'X-Device-ID': await _getDeviceId(),
    };
    if (auth) {
      final token = await storage.read(key: 'access_token');
      if (token != null) headers['Authorization'] = 'Bearer $token';
    }
    return headers;
  }

  static Future<Map> login(String email, String password) async {
    final res = await http.post(
      Uri.parse('$baseUrl/auth/login'),
      headers: await _headers(auth: false),
      body: jsonEncode({'email': email, 'password': password}),
    );
    final data = jsonDecode(res.body);
    if (data['success'] == true) {
      await storage.write(key: 'access_token',  value: data['data']['tokens']['access_token']);
      await storage.write(key: 'refresh_token', value: data['data']['tokens']['refresh_token']);
    }
    return data;
  }

  static Future<Map> getDashboard() async {
    final res = await _get('/dashboard');
    return res;
  }

  static Future<Map> getMarkets() async {
    return await _get('/markets');
  }

  static Future<Map> submitRfq(String pair, String side, double quantity, {bool demo = true}) async {
    return await _post('/rfq', {
      'pair': pair, 'side': side, 'quantity': quantity, 'is_demo': demo ? 1 : 0
    });
  }

  static Future<Map> _get(String path) async {
    final res = await http.get(
      Uri.parse('$baseUrl$path'),
      headers: await _headers(),
    );
    return jsonDecode(res.body);
  }

  static Future<Map> _post(String path, Map body) async {
    final res = await http.post(
      Uri.parse('$baseUrl$path'),
      headers: await _headers(),
      body: jsonEncode(body),
    );
    return jsonDecode(res.body);
  }

  static Future<void> refreshToken() async {
    final refresh = await storage.read(key: 'refresh_token');
    if (refresh == null) return;
    final res = await http.post(
      Uri.parse('$baseUrl/auth/refresh'),
      headers: {'Content-Type': 'application/json'},
      body: jsonEncode({'refresh_token': refresh}),
    );
    final data = jsonDecode(res.body);
    if (data['success'] == true) {
      await storage.write(key: 'access_token', value: data['data']['access_token']);
    }
  }
}
```

---

## Setup Checklist

- [ ] Run `api_migration.sql` in your database
- [ ] Run `trading_mode_migration.sql`
- [ ] Add API constants to `includes/config.php` (see `CONFIG_ADDITIONS.php`)
- [ ] Change `JWT_SECRET` to a random 64-char string
- [ ] Enable mod_rewrite and copy `.htaccess` to `api/v1/`
- [ ] Test: `GET /anchorx/api/v1/health`
- [ ] Test login with admin credentials
- [ ] Configure Firebase FCM for push notifications
