# Wallet

**Author**: Josh S. Sakweli, Backend Lead Team  
**Last Updated**: 2025-10-02  
**Version**: v1.0

**Base URL**: `https://apinexgate.glueauth.com/api/v1/wallet`

**Short Description**: The Wallet API manages user digital wallets for storing and using funds within the platform. It handles wallet creation, balance queries, top-ups from external sources, withdrawals to external accounts, and wallet status management. All balances are maintained through the underlying ledger system ensuring accurate double-entry bookkeeping.

**Hints**: 
- Wallets are automatically created for users on first access
- All monetary values are in TZS (Tanzanian Shillings)
- Actual balance is stored in the ledger system, not the wallet entity
- Wallets can be deactivated for security reasons
- Minimum top-up/withdrawal amount is 1 TZS
- All operations create transaction history entries
- Top-ups represent money entering the platform from external sources (M-Pesa, bank transfer, etc.)
- Withdrawals represent money leaving the platform to external accounts
- Each user can have only one wallet

---

## Standard Response Format

All API responses follow a consistent structure using our Globe Response Builder pattern:

### Success Response Structure
```json
{
  "success": true,
  "httpStatus": "OK",
  "message": "Operation completed successfully",
  "action_time": "2025-10-02T10:30:45",
  "data": {
    // Actual response data goes here
  }
}
```

### Error Response Structure
```json
{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Error description",
  "action_time": "2025-10-02T10:30:45",
  "data": "Error description"
}
```

### Standard Response Fields
| Field | Type | Description |
|-------|------|-------------|
| `success` | boolean | Always `true` for successful operations, `false` for errors |
| `httpStatus` | string | HTTP status name (OK, CREATED, BAD_REQUEST, NOT_FOUND, etc.) |
| `message` | string | Human-readable message describing the operation result |
| `action_time` | string | ISO 8601 timestamp of when the response was generated |
| `data` | object/string | Response payload for success, error details for failures |

---

## HTTP Method Badge Standards

For better visual clarity, all endpoints use colored badges for HTTP methods with the following standard colors:

- **GET** - <span style="background-color: #28a745; color: white; padding: 4px 8px; border-radius: 4px; font-family: monospace; font-size: 12px; font-weight: bold;">GET</span> - Green (Safe, read-only operations)
- **POST** - <span style="background-color: #007bff; color: white; padding: 4px 8px; border-radius: 4px; font-family: monospace; font-size: 12px; font-weight: bold;">POST</span> - Blue (Create new resources)
- **PUT** - <span style="background-color: #ffc107; color: black; padding: 4px 8px; border-radius: 4px; font-family: monospace; font-size: 12px; font-weight: bold;">PUT</span> - Yellow (Full updates)

---

## Endpoints

## 1. Get My Wallet
**Purpose**: Retrieves the authenticated user's wallet information including wallet ID, account details, current balance, and status. If wallet doesn't exist, it is automatically created.

**Endpoint**: <span style="background-color: #28a745; color: white; padding: 4px 8px; border-radius: 4px; font-family: monospace; font-size: 12px; font-weight: bold;">GET</span> `{base_url}/my-wallet`

**Access Level**: 🔒 Protected (Requires Authentication)

**Authentication**: Bearer Token required in Authorization header

**Request Headers**:
| Header | Type | Required | Description |
|--------|------|----------|-------------|
| Authorization | string | Yes | Bearer token for authenticated user |

**Success Response JSON Sample**:
```json
{
  "success": true,
  "httpStatus": "OK",
  "message": "Wallet retrieved successfully",
  "action_time": "2025-10-02T10:30:45",
  "data": {
    "walletId": "w1a2l3l4-e5t6-7890-abcd-ef1234567890",
    "accountId": "a1c2c3o4-u5n6-7890-abcd-ef1234567890",
    "accountUserName": "john_doe",
    "currentBalance": 150000.00,
    "isActive": true,
    "createdAt": "2025-09-15T08:20:30",
    "updatedAt": "2025-10-02T10:15:20"
  }
}
```

**Success Response Fields**:
| Field | Description |
|-------|-------------|
| walletId | Unique identifier for the wallet |
| accountId | User account UUID this wallet belongs to |
| accountUserName | Username of the wallet owner |
| currentBalance | Current wallet balance in TZS (from ledger system) |
| isActive | Whether the wallet is currently active |
| createdAt | ISO 8601 timestamp when wallet was created |
| updatedAt | ISO 8601 timestamp of last wallet update |

**Error Response Examples**:

*Unauthorized (401):*
```json
{
  "success": false,
  "httpStatus": "UNAUTHORIZED",
  "message": "Authentication token is required",
  "action_time": "2025-10-02T10:30:45",
  "data": "Authentication token is required"
}
```

---

## 2. Get My Balance
**Purpose**: Retrieves only the current balance of the authenticated user's wallet. This is a lightweight endpoint for quick balance checks.

**Endpoint**: <span style="background-color: #28a745; color: white; padding: 4px 8px; border-radius: 4px; font-family: monospace; font-size: 12px; font-weight: bold;">GET</span> `{base_url}/balance`

**Access Level**: 🔒 Protected (Requires Authentication)

**Authentication**: Bearer Token required in Authorization header

**Request Headers**:
| Header | Type | Required | Description |
|--------|------|----------|-------------|
| Authorization | string | Yes | Bearer token for authenticated user |

**Success Response JSON Sample**:
```json
{
  "success": true,
  "httpStatus": "OK",
  "message": "Balance retrieved successfully",
  "action_time": "2025-10-02T10:35:45",
  "data": {
    "balance": 150000.00,
    "currency": "TZS"
  }
}
```

**Success Response Fields**:
| Field | Description |
|-------|-------------|
| balance | Current wallet balance |
| currency | Currency code (always TZS) |

**Error Response Examples**:

*Unauthorized (401):*
```json
{
  "success": false,
  "httpStatus": "UNAUTHORIZED",
  "message": "Authentication token is required",
  "action_time": "2025-10-02T10:35:45",
  "data": "Authentication token is required"
}
```

---


## 3. Get Wallet by ID (Admin)
**Purpose**: Retrieves detailed information about any wallet by its ID. This is an administrative endpoint requiring SUPER_ADMIN or STAFF_ADMIN role, or wallet ownership.

**Endpoint**: <span style="background-color: #28a745; color: white; padding: 4px 8px; border-radius: 4px; font-family: monospace; font-size: 12px; font-weight: bold;">GET</span> `{base_url}/{walletId}`

**Access Level**: 🔒 Protected (Requires Authentication + Admin Role or Ownership)

**Authentication**: Bearer Token required in Authorization header

**Request Headers**:
| Header | Type | Required | Description |
|--------|------|----------|-------------|
| Authorization | string | Yes | Bearer token for authenticated admin or owner |

**Path Parameters**:
| Parameter | Type | Required | Description | Validation |
|-----------|------|----------|-------------|------------|
| walletId | string (UUID) | Yes | Unique identifier of the wallet | Valid UUID format |

**Success Response JSON Sample**:
```json
{
  "success": true,
  "httpStatus": "OK",
  "message": "Wallet retrieved successfully",
  "action_time": "2025-10-02T10:50:45",
  "data": {
    "walletId": "w1a2l3l4-e5t6-7890-abcd-ef1234567890",
    "accountId": "a1c2c3o4-u5n6-7890-abcd-ef1234567890",
    "accountUserName": "john_doe",
    "currentBalance": 150000.00,
    "isActive": true,
    "createdAt": "2025-09-15T08:20:30",
    "updatedAt": "2025-10-02T10:15:20"
  }
}
```

**Error Response Examples**:

*Not Found - No Permission (404):*
```json
{
  "success": false,
  "httpStatus": "NOT_FOUND",
  "message": "You do not have permission to access this wallet",
  "action_time": "2025-10-02T10:50:45",
  "data": "You do not have permission to access this wallet"
}
```

---

## 4. Activate Wallet (Admin)
**Purpose**: Activates a previously deactivated wallet, allowing the user to perform transactions again. Requires SUPER_ADMIN role or wallet ownership.

**Endpoint**: <span style="background-color: #ffc107; color: black; padding: 4px 8px; border-radius: 4px; font-family: monospace; font-size: 12px; font-weight: bold;">PUT</span> `{base_url}/{walletId}/activate`

**Access Level**: 🔒 Protected (Requires Authentication + SUPER_ADMIN Role or Ownership)

**Authentication**: Bearer Token required in Authorization header

**Request Headers**:
| Header | Type | Required | Description |
|--------|------|----------|-------------|
| Authorization | string | Yes | Bearer token for authenticated admin or owner |

**Path Parameters**:
| Parameter | Type | Required | Description | Validation |
|-----------|------|----------|-------------|------------|
| walletId | string (UUID) | Yes | Unique identifier of the wallet to activate | Valid UUID format |

**Success Response JSON Sample**:
```json
{
  "success": true,
  "httpStatus": "OK",
  "message": "Wallet activated successfully",
  "action_time": "2025-10-02T10:55:45",
  "data": null
}
```

**Error Response Examples**:

*Not Found - No Permission (404):*
```json
{
  "success": false,
  "httpStatus": "NOT_FOUND",
  "message": "You do not have permission to activate this wallet",
  "action_time": "2025-10-02T10:55:45",
  "data": "You do not have permission to activate this wallet"
}
```

---

## 5. Deactivate Wallet (Admin)
**Purpose**: Deactivates a wallet for security or administrative reasons. Once deactivated, the wallet cannot perform any transactions until reactivated. Requires SUPER_ADMIN or STAFF_ADMIN role, or wallet ownership.

**Endpoint**: <span style="background-color: #ffc107; color: black; padding: 4px 8px; border-radius: 4px; font-family: monospace; font-size: 12px; font-weight: bold;">PUT</span> `{base_url}/{walletId}/deactivate`

**Access Level**: 🔒 Protected (Requires Authentication + Admin Role or Ownership)

**Authentication**: Bearer Token required in Authorization header

**Request Headers**:
| Header | Type | Required | Description |
|--------|------|----------|-------------|
| Authorization | string | Yes | Bearer token for authenticated admin or owner |

**Path Parameters**:
| Parameter | Type | Required | Description | Validation |
|-----------|------|----------|-------------|------------|
| walletId | string (UUID) | Yes | Unique identifier of the wallet to deactivate | Valid UUID format |

**Query Parameters**:
| Parameter | Type | Required | Description | Validation |
|-----------|------|----------|-------------|------------|
| reason | string | Yes | Reason for deactivation | Required, cannot be empty |

**Success Response JSON Sample**:
```json
{
  "success": true,
  "httpStatus": "OK",
  "message": "Wallet deactivated successfully",
  "action_time": "2025-10-02T11:00:45",
  "data": null
}
```

**Error Response Examples**:

*Not Found - No Permission (404):*
```json
{
  "success": false,
  "httpStatus": "NOT_FOUND",
  "message": "You do not have permission to deactivate this wallet",
  "action_time": "2025-10-02T11:00:45",
  "data": "You do not have permission to deactivate this wallet"
}
```

---

## Integration Examples

### Example 1: Check Balance Before Purchase

**Step 1: Get Current Balance**
```http
GET /api/v1/wallet/balance
Authorization: Bearer {token}
```

**Response:**
```json
{
  "success": true,
  "httpStatus": "OK",
  "message": "Balance retrieved successfully",
  "action_time": "2025-10-02T11:10:45",
  "data": {
    "balance": 150000.00,
    "currency": "TZS"
  }
}
```

**Step 2: Proceed to Checkout if Sufficient**
If balance >= purchase amount, continue to checkout session.

---

### Example 2: Top-up and Purchase Flow

**Step 1: Check Insufficient Balance**
```http
GET /api/v1/wallet/balance
Authorization: Bearer {token}
```

**Response shows: 50000 TZS (insufficient for 100000 TZS purchase)**

**Step 2: Top-up Wallet**
```http
POST /api/v1/wallet/topup
Authorization: Bearer {token}
Content-Type: application/json

{
  "amount": 60000.00,
  "description": "M-Pesa top-up"
}
```

**Step 3: Confirm New Balance**
```http
GET /api/v1/wallet/balance
Authorization: Bearer {token}
```

**Response shows: 110000 TZS (now sufficient)**

---

### Example 3: Withdrawal Flow

**Step 1: Get Wallet Info**
```http
GET /api/v1/wallet/my-wallet
Authorization: Bearer {token}
```

**Step 2: Request Withdrawal**
```http
POST /api/v1/wallet/withdraw
Authorization: Bearer {token}
Content-Type: application/json

{
  "amount": 50000.00,
  "description": "Withdraw to CRDB Bank - Account 1234567890"
}
```

**Step 3: Verify New Balance**
```http
GET /api/v1/wallet/balance
Authorization: Bearer {token}
```

---

## Rate Limiting

**Rate Limits:**
- Get Wallet/Balance: 60 requests per minute per user
- Top-up: 10 requests per minute per user
- Withdraw: 10 requests per minute per user
- Admin Operations: 30 requests per minute per admin

**Rate Limit Headers:**
```
X-RateLimit-Limit: 10
X-RateLimit-Remaining: 7
X-RateLimit-Reset: 1696258800
```

**Rate Limit Exceeded:**
```json
{
  "success": false,
  "httpStatus": "TOO_MANY_REQUESTS",
  "message": "Rate limit exceeded. Please try again later.",
  "action_time": "2025-10-02T11:20:45",
  "data": "Rate limit exceeded. Please try again later."
}
```

---