# WABA SAAS - Admin API Documentation

Dokumentasi API lengkap untuk **Admin** pada sistem WABA SAAS.

---

## Overview

API ini digunakan oleh **Admin** untuk:
- Mengelola WABA Pool (nomor WhatsApp)
- Approve/reject request dedicated number
- Approve/reject request ganti nama
- Mengelola token Meta
- Melihat inbox messages
- Monitor transaksi dan billing

**Base URL:**
```
Production:  https://your-domain.com/api
Development: http://localhost:8001/api
```

---

## Authentication

Admin menggunakan **Bearer Token** via Laravel Sanctum:

```http
Authorization: Bearer {admin_sanctum_token}
```

> ⚠️ **Penting:** Token diperoleh setelah login ke panel admin.

---

## Response Format

### Success Response
```json
{
  "status": true,
  "message": "Operation successful",
  "data": { ... }
}
```

### Error Response
```json
{
  "status": false,
  "message": "Error description",
  "error_code": "ERROR_CODE"
}
```

### Error Codes (Admin)
| Code | Description |
|------|-------------|
| `UNAUTHORIZED` | Token tidak valid |
| `POOL_NOT_FOUND` | WABA Pool tidak ditemukan |
| `REQUEST_NOT_FOUND` | Request tidak ditemukan |
| `ALREADY_PROCESSED` | Request sudah diproses sebelumnya |
| `CLIENT_NOT_FOUND` | Client tidak ditemukan |
| `TOKEN_EXCHANGE_FAILED` | Gagal exchange token Meta |
| `VALIDATION_ERROR` | Data input tidak valid |

---

## 1. WABA Pool Token Management

### POST /api/admin/waba-pool/{id}/generate-token

Generate atau simpan permanent token untuk WABA Pool.

**Headers:**
```http
Authorization: Bearer {token}
Content-Type: application/json
```

#### Request Body - Exchange Short-Lived Token
```json
{
  "short_lived_token": "EAAxxxx..."
}
```

#### Request Body - Store Permanent Token Directly
```json
{
  "permanent_token": "EAAxxxx...",
  "skip_exchange": true
}
```

#### Parameters
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| short_lived_token | string | ❌ | Token dari Meta login (akan di-exchange) |
| permanent_token | string | ❌ | System User token (langsung disimpan) |
| skip_exchange | boolean | ❌ | true jika menyimpan permanent token langsung |

#### Response Success
```json
{
  "status": true,
  "message": "Token generated successfully",
  "data": {
    "token_stored": true,
    "generated_at": "2025-12-10T10:00:00Z",
    "expires_at": "2026-02-08T10:00:00Z",
    "days_until_expiry": 60
  }
}
```

#### cURL Example
```bash
curl -X POST "https://domain.com/api/admin/waba-pool/1/generate-token" \
  -H "Authorization: Bearer ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"short_lived_token": "EAAxxxx..."}'
```

#### PHP Example
```php
$response = Http::withToken($adminToken)
    ->post("https://domain.com/api/admin/waba-pool/{$poolId}/generate-token", [
        'short_lived_token' => 'EAAxxxx...'
    ]);
```

---

### PUT /api/admin/waba-pool/{id}/credentials

Update App ID dan App Secret untuk WABA Pool.

**Headers:**
```http
Authorization: Bearer {token}
Content-Type: application/json
```

#### Request Body
```json
{
  "app_id": "123456789012345",
  "app_secret": "abcdef1234567890abcdef1234567890"
}
```

#### Response
```json
{
  "status": true,
  "message": "Credentials updated successfully",
  "data": null
}
```

---

### GET /api/admin/waba-pool/{id}/token-status

Cek status token saat ini.

**Headers:**
```http
Authorization: Bearer {token}
```

#### Response
```json
{
  "status": true,
  "message": "Token status",
  "data": {
    "has_token": true,
    "token_status": "valid",
    "generated_at": "2025-12-10T10:00:00Z",
    "expires_at": "2026-02-08T10:00:00Z",
    "days_until_expiry": 60,
    "refresh_needed": false
  }
}
```

---

### POST /api/admin/waba-pool/{id}/validate-token

Validasi token dengan Meta Graph API.

**Headers:**
```http
Authorization: Bearer {token}
```

#### Response - Token Valid
```json
{
  "status": true,
  "message": "Token is valid",
  "data": {
    "valid": true,
    "app_id": "123456789012345",
    "expires_at": "2026-02-08T10:00:00Z"
  }
}
```

#### Response - Token Invalid
```json
{
  "status": false,
  "message": "Token is invalid or expired",
  "error_code": "TOKEN_INVALID"
}
```

---

### POST /api/admin/waba-pool/{id}/revoke-token

Hapus token dari database.

**Headers:**
```http
Authorization: Bearer {token}
```

#### Response
```json
{
  "status": true,
  "message": "Token revoked successfully",
  "data": null
}
```

---

## 2. Dedicated Number Management

### GET /api/admin/dedicated-numbers

Melihat semua assign dedicated number.

**Headers:**
```http
Authorization: Bearer {token}
```

#### Response
```json
{
  "status": true,
  "message": "Dedicated numbers retrieved",
  "data": [
    {
      "id": 1,
      "client_id": 10,
      "client_name": "PT Client Satu",
      "reseller_name": "Reseller A",
      "waba_pool_id": 5,
      "phone_number": "628123456789",
      "label": "Nomor CS Utama",
      "status": "active",
      "price": 550000,
      "assigned_by": "Admin",
      "assigned_at": "2025-12-01T10:00:00Z"
    }
  ]
}
```

---

### GET /api/admin/dedicated-numbers/requests

Melihat daftar request assign yang pending.

**Headers:**
```http
Authorization: Bearer {token}
```

#### Response
```json
{
  "status": true,
  "message": "Pending requests",
  "data": [
    {
      "id": 15,
      "client_id": 12,
      "client_name": "PT Client Baru",
      "reseller_name": "Reseller B",
      "waba_pool_id": 7,
      "phone_number": "628123456791",
      "status": "pending",
      "base_price": 600000,
      "margin": 60000,
      "total_price": 660000,
      "client_balance": 1000000,
      "requested_label": "Nomor Baru",
      "requested_at": "2025-12-10T10:00:00Z"
    }
  ]
}
```

---

### POST /api/admin/dedicated-numbers/direct-assign

Assign nomor langsung ke client (tanpa request dari client).

**Headers:**
```http
Authorization: Bearer {token}
Content-Type: application/json
```

#### Request Body
```json
{
  "client_id": 10,
  "waba_pool_id": 5,
  "label": "Nomor dari Admin",
  "notes": "Assign khusus untuk promo"
}
```

#### Response
```json
{
  "status": true,
  "message": "Nomor berhasil di-assign",
  "data": {
    "assign_id": 25,
    "client_id": 10,
    "waba_pool_id": 5,
    "phone_number": "628123456789",
    "price": 550000,
    "status": "active"
  }
}
```

---

### POST /api/admin/dedicated-numbers/{id}/approve

Approve request assign dedicated number.

**Headers:**
```http
Authorization: Bearer {token}
Content-Type: application/json
```

#### Request Body (Optional)
```json
{
  "notes": "Approved per request"
}
```

#### Response Success
```json
{
  "status": true,
  "message": "Request approved. Saldo client telah dipotong.",
  "data": {
    "request_id": 15,
    "assign_id": 26,
    "client_balance_before": 1000000,
    "client_balance_after": 340000,
    "amount_charged": 660000
  }
}
```

#### Response Error - Saldo Tidak Cukup
```json
{
  "status": false,
  "message": "Saldo client tidak mencukupi",
  "error_code": "INSUFFICIENT_BALANCE"
}
```

---

### POST /api/admin/dedicated-numbers/{id}/reject

Reject request assign.

**Headers:**
```http
Authorization: Bearer {token}
Content-Type: application/json
```

#### Request Body
```json
{
  "reason": "Nomor sedang dalam maintenance"
}
```

#### Response
```json
{
  "status": true,
  "message": "Request rejected",
  "data": {
    "request_id": 15,
    "status": "rejected",
    "rejection_reason": "Nomor sedang dalam maintenance"
  }
}
```

---

### DELETE /api/admin/dedicated-numbers/{id}

Unassign nomor dedicated.

**Headers:**
```http
Authorization: Bearer {token}
```

#### Response
```json
{
  "status": true,
  "message": "Nomor berhasil di-unassign",
  "data": null
}
```

---

## 3. Name Change Request Management

### GET /api/admin/number-name-requests

Melihat daftar request ganti nama yang pending.

**Headers:**
```http
Authorization: Bearer {token}
```

#### Response
```json
{
  "status": true,
  "message": "Name change requests",
  "data": [
    {
      "id": 5,
      "dedicated_assign_id": 1,
      "client_id": 10,
      "client_name": "PT Client Satu",
      "phone_number": "628123456789",
      "current_name": "Nomor CS Utama",
      "requested_name": "Hotline Support 24 Jam",
      "status": "pending",
      "created_at": "2025-12-10T10:00:00Z"
    }
  ]
}
```

---

### POST /api/admin/number-name-requests/{id}/approve

Approve request ganti nama.

**Headers:**
```http
Authorization: Bearer {token}
```

#### Response
```json
{
  "status": true,
  "message": "Request approved. Nama berhasil diubah.",
  "data": {
    "request_id": 5,
    "old_name": "Nomor CS Utama",
    "new_name": "Hotline Support 24 Jam"
  }
}
```

---

### POST /api/admin/number-name-requests/{id}/reject

Reject request ganti nama.

**Headers:**
```http
Authorization: Bearer {token}
Content-Type: application/json
```

#### Request Body
```json
{
  "reason": "Nama mengandung kata terlarang"
}
```

#### Response
```json
{
  "status": true,
  "message": "Request rejected",
  "data": {
    "request_id": 5,
    "status": "rejected",
    "rejection_reason": "Nama mengandung kata terlarang"
  }
}
```

---

## 4. Inbox Messages API

### GET /api/admin/waba-pool/{id}/messages

Melihat inbox messages untuk WABA Pool tertentu.

**Headers:**
```http
Authorization: Bearer {token}
```

#### Query Parameters
| Parameter | Type | Description |
|-----------|------|-------------|
| page | integer | Halaman |
| per_page | integer | Items per halaman (max 100) |
| date_from | date | Filter dari tanggal |
| date_to | date | Filter sampai tanggal |
| from_number | string | Filter nomor pengirim |
| type | string | Filter tipe pesan |
| unread_only | boolean | Hanya yang belum dibaca |

#### Response
```json
{
  "status": true,
  "message": "Inbox messages retrieved",
  "data": {
    "waba_pool": {
      "id": 1,
      "phone_number": "628123456789",
      "account_name": "My Business"
    },
    "messages": [
      {
        "id": 1,
        "wa_message_id": "wamid.xxx",
        "from_number": "628987654321",
        "to_number": "628123456789",
        "message_type": "text",
        "message_body": "Hello!",
        "is_read": false,
        "message_timestamp": "2025-12-10T10:00:00Z"
      }
    ],
    "pagination": {
      "current_page": 1,
      "per_page": 50,
      "total": 100,
      "last_page": 2
    }
  }
}
```

---

### GET /api/admin/waba-pool/{id}/messages/stats

Statistik inbox.

**Headers:**
```http
Authorization: Bearer {token}
```

#### Response
```json
{
  "status": true,
  "message": "Inbox stats",
  "data": {
    "total_messages": 1500,
    "unread_messages": 25,
    "unique_senders": 350,
    "today_messages": 45
  }
}
```

---

### GET /api/admin/waba-pool/{id}/messages/conversations

Daftar percakapan (grouped by sender).

**Headers:**
```http
Authorization: Bearer {token}
```

#### Response
```json
{
  "status": true,
  "message": "Conversations",
  "data": {
    "conversations": [
      {
        "from_number": "628987654321",
        "message_count": 25,
        "unread_count": 3,
        "last_message_at": "2025-12-10T10:00:00Z"
      }
    ]
  }
}
```

---

### POST /api/admin/waba-pool/{id}/messages/read-all

Tandai semua pesan sebagai dibaca.

**Headers:**
```http
Authorization: Bearer {token}
```

#### Response
```json
{
  "status": true,
  "message": "50 messages marked as read",
  "data": {
    "updated_count": 50
  }
}
```

---

## 5. Webhook Configuration

### Webhook URL

```
GET  /api/webhook/waba  → Verifikasi
POST /api/webhook/waba  → Terima pesan
```

### Setup di Meta Developer Console

1. **Callback URL:** `https://your-domain.com/api/webhook/waba`
2. **Verify Token:** Set `WABA_WEBHOOK_VERIFY_TOKEN` di `.env`
3. **Subscribed Fields:** `messages`

### Verify Token per WABA Pool

Setiap WABA Pool bisa memiliki `webhook_verify_token` sendiri di database.

---

## 6. Transaction & Billing Logs

### Transaksi Otomatis

Setiap assign dedicated number akan:
1. Potong saldo client
2. Catat transaksi di `number_transactions`
3. Hitung margin reseller (jika ada)

### Struktur Transaksi

```json
{
  "id": 101,
  "client_id": 10,
  "waba_pool_id": 5,
  "reseller_id": 1,
  "type": "assign",
  "base_price": 500000,
  "margin": 50000,
  "total_amount": 550000,
  "balance_before": 1000000,
  "balance_after": 450000,
  "processed_by": 1,
  "notes": "Dedicated number assignment",
  "created_at": "2025-12-10T10:00:00Z"
}
```

---

## Notes & Best Practices

1. **Token Management**: Refresh token sebelum expired (60 hari untuk long-lived)
2. **Approve Request**: Pastikan saldo client cukup sebelum approve
3. **Webhook**: Selalu return 200 OK ke Meta untuk menghindari retry
4. **Audit Trail**: Semua aksi tercatat di `activity_logs`

---

## Support

Untuk bantuan teknis atau akses developer, hubungi tim teknis.
