================================================================================ ๐Ÿ“ฑ USER FRONTEND API DOCUMENTATION - HishabPlus Backend ================================================================================ Complete API Reference for Building User Frontend (app.hishabplus.com) Technology-Agnostic Guide - Use with any frontend framework ================================================================================ ๐Ÿ“‹ TABLE OF CONTENTS ================================================================================ 1. Base URL & Authentication 2. Request/Response Format 3. Error Handling 4. Middleware & Rate Limiting 5. Authentication Endpoints 6. Dashboard Endpoint 7. Properties Management 8. Renters Management 9. SMS System 10. SMS Templates 11. Dues Management 12. Subscriptions 13. Payments 14. Transactions 15. Notifications 16. API Tokens 17. Database Structure Reference ================================================================================ 1๏ธโƒฃ BASE URL & AUTHENTICATION ================================================================================ Base URL: https://api.hishabplus.com/api (Development: http://localhost:8000/api) โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” Authentication Method: Laravel Sanctum (Bearer Token) โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” All protected endpoints require: Header: Authorization: Bearer {token} Token is obtained from: - POST /api/auth/register (returns token) - POST /api/auth/login (returns token) Token Storage: - Store token in localStorage, sessionStorage, or secure cookie - Include in every request header: Authorization: Bearer {token} - Token expires based on backend configuration (default: no expiration) โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” CSRF Protection โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” For stateful authentication (cookies), you may need: - X-XSRF-TOKEN header (if using cookies) - For API-only (Bearer tokens), CSRF is not required ================================================================================ 2๏ธโƒฃ REQUEST/RESPONSE FORMAT ================================================================================ Content-Type: application/json Accept: application/json All requests: JSON body All responses: JSON body Example Request: ```http POST /api/properties Authorization: Bearer {token} Content-Type: application/json { "category_id": 1, "title": "Green Villa", "address": "123 Main St", "default_rent_amount": 15000, "status": "vacant" } ``` Example Response: ```json { "message": "Property created successfully", "property": { "id": 1, "user_id": 5, "category_id": 1, "title": "Green Villa", "address": "123 Main St", "default_rent_amount": "15000.00", "status": "vacant", "created_at": "2025-11-10T10:30:00.000000Z", "updated_at": "2025-11-10T10:30:00.000000Z", "category": { "id": 1, "name": "House", "slug": "house" } } } ``` ================================================================================ 3๏ธโƒฃ ERROR HANDLING ================================================================================ Error Response Format: ```json { "message": "Error description", "errors": { "field_name": ["Validation error message"] } } ``` HTTP Status Codes: - 200 OK - Success - 201 Created - Resource created - 400 Bad Request - Invalid request data - 401 Unauthorized - Missing/invalid token - 403 Forbidden - Insufficient permissions / Account deactivated - 404 Not Found - Resource not found - 422 Unprocessable Entity - Validation errors - 429 Too Many Requests - Rate limit exceeded - 500 Internal Server Error - Server error Common Error Scenarios: 1. Unauthorized (401): ```json { "message": "Unauthenticated." } ``` Action: Redirect to login, clear token 2. Account Deactivated (403): ```json { "message": "Your account has been deactivated. Please contact support.", "error_code": "ACCOUNT_DEACTIVATED" } ``` Action: Show message, disable app features 3. Grace Period Ended (403): ```json { "message": "Your grace period has ended. Please renew your subscription.", "error_code": "GRACE_PERIOD_ENDED", "grace_ended_at": "2025-11-15T00:00:00.000000Z" } ``` Action: Show subscription renewal prompt 4. Validation Error (422): ```json { "message": "The given data was invalid.", "errors": { "email": ["The email has already been taken."], "password": ["The password must be at least 8 characters."] } } ``` Action: Display field-specific errors 5. Rate Limit (429): ```json { "message": "Too many SMS requests. Please try again later.", "retry_after": 45, "limit": 30, "current": 30 } ``` Action: Show countdown, disable send button ================================================================================ 4๏ธโƒฃ MIDDLEWARE & RATE LIMITING ================================================================================ โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” User Active Check (EnsureUserIsActive) โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” Applied to: All protected API routes Behavior: - Checks if user.is_active = true - If false โ†’ 403 error (ACCOUNT_DEACTIVATED) - Checks if grace_ends_at is past - If grace ended โ†’ 403 error (GRACE_PERIOD_ENDED) - Exception: Allows access to subscription endpoints even in grace period Frontend Action: - On 403 with ACCOUNT_DEACTIVATED: Show deactivation message - On 403 with GRACE_PERIOD_ENDED: Show subscription renewal prompt - Allow navigation to subscription/payment pages โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” SMS Rate Limiting (ThrottleSmsRequests) โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” Applied to: POST /api/sms/send, POST /api/sms/schedule Limit: 30 requests per minute per user (configurable) Response Headers: - X-RateLimit-Limit: 30 - X-RateLimit-Remaining: 25 - X-RateLimit-Reset: 1700123456 (Unix timestamp) On Rate Limit Exceeded (429): ```json { "message": "Too many SMS requests. Please try again later.", "retry_after": 45, "limit": 30, "current": 30 } ``` Frontend Action: - Track remaining count from headers - Disable send button when remaining = 0 - Show countdown timer using retry_after - Display warning when remaining < 5 โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” API Rate Limiting (Laravel Default) โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” Default: 60 requests per minute per IP/user Configurable in backend ================================================================================ 5๏ธโƒฃ AUTHENTICATION ENDPOINTS ================================================================================ โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” POST /api/auth/register โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” Description: Register a new user account (starts 14-day trial automatically) Auth Required: NO Request Body: ```json { "name": "John Doe", "email": "john@example.com", "password": "password123", "password_confirmation": "password123", "business_name": "John Properties", "phone": "+8801712345678", "timezone": "Asia/Dhaka" } ``` Validation Rules: - name: required|string|max:255 - email: required|email|unique:users,email - password: required|string|min:8|confirmed - business_name: nullable|string|max:255 - phone: nullable|string|max:20 - timezone: nullable|string|max:50 Success Response (201): ```json { "message": "User registered successfully", "user": { "id": 1, "name": "John Doe", "email": "john@example.com", "business_name": "John Properties", "phone": "+8801712345678", "timezone": "Asia/Dhaka", "is_active": true, "trial_ends_at": "2025-11-24T10:30:00.000000Z", "grace_ends_at": null, "current_subscription_id": null, "created_at": "2025-11-10T10:30:00.000000Z" }, "token": "1|abcdefghijklmnopqrstuvwxyz1234567890" } ``` Important: - Token is returned ONLY ONCE - store it immediately - Trial automatically starts (14 days from registration) - User is automatically active (is_active = true) Error Responses: - 422: Validation errors (email taken, weak password, etc.) โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” POST /api/auth/login โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” Description: Login with email and password Auth Required: NO Request Body: ```json { "email": "john@example.com", "password": "password123" } ``` Validation Rules: - email: required|email - password: required|string Success Response (200): ```json { "message": "Login successful", "user": { "id": 1, "name": "John Doe", "email": "john@example.com", "business_name": "John Properties", "phone": "+8801712345678", "timezone": "Asia/Dhaka", "is_active": true, "trial_ends_at": "2025-11-24T10:30:00.000000Z", "grace_ends_at": null, "current_subscription_id": null, "sms_balance": 10, "created_at": "2025-11-10T10:30:00.000000Z" }, "token": "2|xyzabcdefghijklmnopqrstuvwxyz123456" } ``` Error Responses: - 401: Invalid credentials ```json { "message": "Invalid credentials" } ``` โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” POST /api/auth/logout โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” Description: Logout current user (revokes token) Auth Required: YES Request Body: None Success Response (200): ```json { "message": "Logged out successfully" } ``` Frontend Action: - Clear stored token - Redirect to login page โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” GET /api/auth/me โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” Description: Get current authenticated user information Auth Required: YES Request Body: None Success Response (200): ```json { "user": { "id": 1, "name": "John Doe", "email": "john@example.com", "business_name": "John Properties", "phone": "+8801712345678", "timezone": "Asia/Dhaka", "is_active": true, "trial_ends_at": "2025-11-24T10:30:00.000000Z", "grace_ends_at": null, "current_subscription_id": 5, "created_at": "2025-11-10T10:30:00.000000Z", "updated_at": "2025-11-10T10:30:00.000000Z", "current_subscription": { "id": 5, "package_id": 2, "status": "active", "started_at": "2025-11-10T10:30:00.000000Z", "ends_at": "2025-12-10T10:30:00.000000Z", "package": { "id": 2, "name": "Basic", "slug": "basic", "price": "500.00", "billing_period": "monthly" } } } } ``` Use Cases: - Check authentication status on app load - Refresh user data - Get subscription status - Get SMS balance (calculate from user data) ================================================================================ 6๏ธโƒฃ DASHBOARD ENDPOINT ================================================================================ โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” GET /api/dashboard โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” Description: Get dashboard statistics and overview Auth Required: YES Request Body: None Success Response (200): ```json { "stats": { "properties": { "total": 15, "vacant": 3, "on_rent": 11, "maintenance": 1 }, "renters": { "active": 11, "total": 12 }, "financials": { "total_dues": 165000.00, "collected_this_month": 150000.00, "total_collected": 500000.00 }, "sms": { "balance": 45, "sent_this_month": 25, "total_sent": 150 } }, "subscription": { "package_name": "Basic", "status": "active", "ends_at": "2025-12-10T10:30:00.000000Z", "is_in_trial": false, "is_in_grace": false }, "trial_ends_at": null, "grace_ends_at": null, "recent_transactions": [ { "id": 100, "type": "rent_payment", "amount": "15000.00", "method": "cash", "created_at": "2025-11-09T14:20:00.000000Z", "renter": { "id": 5, "name": "Ahmed Khan", "phone": "+8801711111111" }, "property": { "id": 3, "title": "Green Villa" } } ], "upcoming_dues": [ { "id": 50, "renter_id": 5, "property_id": 3, "amount_due": 15000.00, "amount_paid": 0.00, "status": "open", "period_start": "2025-11-01", "period_end": "2025-11-30", "renter": { "id": 5, "name": "Ahmed Khan", "phone": "+8801711111111" }, "property": { "id": 3, "title": "Green Villa" } } ] } ``` Use Cases: - Display statistics cards - Show subscription status banner - List recent activity - Show upcoming dues ================================================================================ 7๏ธโƒฃ PROPERTIES MANAGEMENT ================================================================================ โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” GET /api/properties โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” Description: List user's properties with filtering and pagination Auth Required: YES Query Parameters: - status: string (vacant|on_rent|maintenance) - Filter by status - category_id: integer - Filter by category - search: string - Search in title and address - per_page: integer (default: 15) - Items per page - page: integer (default: 1) - Page number Example Request: GET /api/properties?status=on_rent&category_id=1&search=villa&per_page=20&page=1 Success Response (200) - Paginated: ```json { "data": [ { "id": 1, "user_id": 5, "category_id": 1, "title": "Green Villa", "address": "123 Main Street, Dhaka", "default_rent_amount": "15000.00", "status": "on_rent", "created_at": "2025-11-01T10:00:00.000000Z", "updated_at": "2025-11-01T10:00:00.000000Z", "category": { "id": 1, "name": "House", "slug": "house" } } ], "current_page": 1, "per_page": 15, "total": 15, "last_page": 1, "from": 1, "to": 15 } ``` โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” POST /api/properties โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” Description: Create a new property Auth Required: YES Request Format: multipart/form-data (if uploading image) OR application/json Request Body (JSON): ```json { "category_id": 1, "title": "Green Villa", "address": "123 Main Street, Dhaka", "default_rent_amount": 15000, "status": "vacant" } ``` Request Body (Form Data - with image): - category_id: 1 (integer) - title: "Green Villa" (string) - address: "123 Main Street, Dhaka" (string, optional) - image: [FILE] (image file, optional) - default_rent_amount: 15000 (number, optional) - status: "vacant" (string, optional) Validation Rules: - category_id: required|exists:property_categories,id - title: required|string|max:255 - address: nullable|string - image: nullable|image|mimes:jpeg,png,jpg,gif,webp|max:5120 (5MB max) - default_rent_amount: nullable|numeric|min:0 - status: nullable|in:vacant,on_rent,maintenance Image Upload Notes: - Supported formats: JPEG, PNG, JPG, GIF, WEBP - Maximum file size: 5MB (5120 KB) - Image is stored in: storage/app/public/properties/{user_id}/ - Image URL will be accessible via: {APP_URL}/storage/{image_path} Property Limit Check: - Backend checks subscription package limits - If limit reached โ†’ 403 error: ```json { "message": "Property limit reached for this category in your subscription plan." } ``` Success Response (201): ```json { "message": "Property created successfully", "property": { "id": 1, "user_id": 5, "category_id": 1, "title": "Green Villa", "address": "123 Main Street, Dhaka", "image_path": "properties/5/abc123def456.jpg", "image_url": "https://api.hishabplus.com/storage/properties/5/abc123def456.jpg", "default_rent_amount": "15000.00", "status": "vacant", "created_at": "2025-11-10T10:30:00.000000Z", "updated_at": "2025-11-10T10:30:00.000000Z", "category": { "id": 1, "name": "House", "slug": "house" } } } ``` Image Fields: - image_path: Storage path (null if no image uploaded) - image_url: Full accessible URL (null if no image uploaded) โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” GET /api/properties/{id} โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” Description: Get property details with statistics Auth Required: YES URL Parameters: - id: integer - Property ID Success Response (200): ```json { "property": { "id": 1, "user_id": 5, "category_id": 1, "title": "Green Villa", "address": "123 Main Street, Dhaka", "default_rent_amount": "15000.00", "status": "on_rent", "created_at": "2025-11-01T10:00:00.000000Z", "updated_at": "2025-11-01T10:00:00.000000Z", "category": { "id": 1, "name": "House", "slug": "house" }, "renters": [ { "id": 5, "name": "Ahmed Khan", "phone": "+8801711111111", "is_active": true } ] }, "stats": { "total_renters": 2, "active_renters": 1, "total_collected": 150000.00, "pending_dues": 15000.00 } } ``` Error Responses: - 404: Property not found or doesn't belong to user โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” PUT /api/properties/{id} โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” Description: Update property Auth Required: YES Request Format: multipart/form-data (if uploading image) OR application/json Request Body (all fields optional): ```json { "category_id": 1, "title": "Updated Villa Name", "address": "456 New Street", "default_rent_amount": 18000, "status": "on_rent" } ``` Request Body (Form Data - with image): - image: [FILE] (image file, optional - replaces existing image if provided) Validation Rules: Same as POST (but all optional with "sometimes") - image: nullable|image|mimes:jpeg,png,jpg,gif,webp|max:5120 Image Update Behavior: - If new image is uploaded, old image is automatically deleted - If no image is provided, existing image remains unchanged Success Response (200): ```json { "message": "Property updated successfully", "property": { "id": 1, "title": "Updated Villa Name", ... } } ``` โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” DELETE /api/properties/{id} โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” Description: Delete property (soft delete) Auth Required: YES Success Response (200): ```json { "message": "Property deleted successfully" } ``` Error Responses: - 403: Property has active renters ```json { "message": "Cannot delete property with active renters." } ``` Frontend Action: - Show confirmation dialog before delete - Check if property has active renters first - If has active renters, show warning ================================================================================ 8๏ธโƒฃ RENTERS MANAGEMENT ================================================================================ โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” GET /api/renters โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” Description: List user's renters with filtering Auth Required: YES Query Parameters: - property_id: integer - Filter by property - is_active: boolean - Filter by active status - search: string - Search in name, phone, NID - per_page: integer (default: 15) - page: integer (default: 1) Success Response (200) - Paginated: ```json { "data": [ { "id": 5, "user_id": 1, "property_id": 3, "name": "Ahmed Khan", "phone": "+8801711111111", "nid_number": "1234567890123", "address": "456 Renter Street", "father_name": "Rahman Khan", "mother_name": "Fatima Khan", "security_deposit": "30000.00", "advance_balance": "15000.00", "payment_type": "maser_surute", "rent_amount": "15000.00", "rent_start_date": "2025-01-01", "rent_day_of_month": 5, "is_active": true, "created_at": "2025-01-01T10:00:00.000000Z", "updated_at": "2025-11-10T10:00:00.000000Z", "property": { "id": 3, "title": "Green Villa" } } ], "current_page": 1, "per_page": 15, "total": 12 } ``` โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” POST /api/renters โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” Description: Create a new renter Auth Required: YES Request Format: multipart/form-data (if uploading images) OR application/json Request Body (JSON): ```json { "property_id": 3, "name": "Ahmed Khan", "phone": "+8801711111111", "nid_number": "1234567890123", "address": "456 Renter Street", "father_name": "Rahman Khan", "mother_name": "Fatima Khan", "security_deposit": 30000, "advance_balance": 15000, "payment_type": "maser_surute", "rent_amount": 15000, "rent_start_date": "2025-01-01", "rent_day_of_month": 5 } ``` Request Body (Form Data - with images): - property_id: 3 (integer) - name: "Ahmed Khan" (string) - phone: "+8801711111111" (string) - nid_number: "1234567890123" (string, optional) - photo: [FILE] (image file, optional - renter photo) - nid_card_image: [FILE] (image file, optional - NID card image) - address: "456 Renter Street" (string, optional) - father_name: "Rahman Khan" (string, optional) - mother_name: "Fatima Khan" (string, optional) - security_deposit: 30000 (number, optional) - advance_balance: 15000 (number, optional) - payment_type: "maser_surute" (string) - rent_amount: 15000 (number) - rent_start_date: "2025-01-01" (date) - rent_day_of_month: 5 (integer) Validation Rules: - property_id: required|exists:properties,id (must belong to user) - name: required|string|max:255 - phone: required|string|max:20 - nid_number: nullable|string|max:20 - photo: nullable|image|mimes:jpeg,png,jpg,gif,webp|max:5120 (5MB max) - nid_card_image: nullable|image|mimes:jpeg,png,jpg,gif,webp|max:5120 (5MB max) - address: nullable|string - father_name: nullable|string|max:255 - mother_name: nullable|string|max:255 - security_deposit: nullable|numeric|min:0 - advance_balance: nullable|numeric|min:0 - payment_type: required|in:maser_surute,maser_seshe - rent_amount: required|numeric|min:0 - rent_start_date: required|date - rent_day_of_month: required|integer|min:1|max:28 Image Upload Notes: - Supported formats: JPEG, PNG, JPG, GIF, WEBP - Maximum file size per image: 5MB (5120 KB) - Photo is stored in: storage/app/public/renters/photos/{user_id}/ - NID card image is stored in: storage/app/public/renters/nid-cards/{user_id}/ - Image URLs will be accessible via: {APP_URL}/storage/{image_path} Payment Type Explanation: - maser_surute: Rent due at beginning of month (on rent_day_of_month) - maser_seshe: Rent due at end of month Success Response (201): ```json { "message": "Renter created successfully", "renter": { "id": 5, "property_id": 3, "name": "Ahmed Khan", "phone": "+8801711111111", "nid_number": "1234567890123", "photo_path": "renters/photos/5/photo_abc123.jpg", "photo_url": "https://api.hishabplus.com/storage/renters/photos/5/photo_abc123.jpg", "nid_card_image_path": "renters/nid-cards/5/nid_xyz789.jpg", "nid_card_image_url": "https://api.hishabplus.com/storage/renters/nid-cards/5/nid_xyz789.jpg", "address": "456 Renter Street", "father_name": "Rahman Khan", "mother_name": "Fatima Khan", "security_deposit": "30000.00", "advance_balance": "15000.00", "payment_type": "maser_surute", "rent_amount": "15000.00", "rent_start_date": "2025-01-01", "rent_day_of_month": 5, "is_active": true, "created_at": "2025-11-10T10:30:00.000000Z", "updated_at": "2025-11-10T10:30:00.000000Z", "property": { "id": 3, "title": "Green Villa", "category": { "id": 1, "name": "House" } } } } ``` Image Fields: - photo_path: Storage path for renter photo (null if not uploaded) - photo_url: Full accessible URL for renter photo (null if not uploaded) - nid_card_image_path: Storage path for NID card image (null if not uploaded) - nid_card_image_url: Full accessible URL for NID card image (null if not uploaded) โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” GET /api/renters/{id} โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” Description: Get renter details Auth Required: YES Success Response (200): ```json { "renter": { "id": 5, "name": "Ahmed Khan", "phone": "+8801711111111", ... "property": { "id": 3, "title": "Green Villa" }, "transactions": [ { "id": 100, "type": "rent_payment", "amount": "15000.00", "created_at": "2025-11-05T10:00:00.000000Z" } ], "dues": [ { "id": 50, "amount_due": 15000.00, "amount_paid": 0.00, "status": "open", "period_start": "2025-11-01", "period_end": "2025-11-30" } ] }, "next_due_date": "2025-12-05T00:00:00.000000Z" } ``` โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” PUT /api/renters/{id} โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” Description: Update renter Auth Required: YES Request Format: multipart/form-data (if uploading images) OR application/json Request Body: Same as POST (all fields optional with "sometimes") - photo: [FILE] (image file, optional - replaces existing photo if provided) - nid_card_image: [FILE] (image file, optional - replaces existing NID card image if provided) Image Update Behavior: - If new photo is uploaded, old photo is automatically deleted - If new NID card image is uploaded, old NID card image is automatically deleted - If no images are provided, existing images remain unchanged Success Response (200): ```json { "message": "Renter updated successfully", "renter": { ... } } ``` โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” DELETE /api/renters/{id} โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” Description: Delete renter (soft delete) Auth Required: YES Success Response (200): ```json { "message": "Renter deleted successfully" } ``` โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” POST /api/renters/{id}/end-rent โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” Description: End rent agreement (deactivate renter) Auth Required: YES Request Body: ```json { "end_date": "2025-11-30", "refund_security_deposit": true, "refund_amount": 30000, "settlement_note": "Rent agreement ended amicably" } ``` Validation Rules: - end_date: required|date|after:rent_start_date - refund_security_deposit: boolean - refund_amount: nullable|numeric|min:0 - settlement_note: nullable|string|max:1000 Success Response (200): ```json { "message": "Rent agreement ended successfully", "renter": { "id": 5, "is_active": false, ... } } ``` Frontend Action: - Show confirmation dialog - Calculate refund amount automatically - Create transaction for refund if applicable ================================================================================ 9๏ธโƒฃ SMS SYSTEM ================================================================================ โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” GET /api/sms โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” Description: List SMS messages (sent/scheduled) Auth Required: YES Query Parameters: - status: string (queued|sent|failed|delivered|partial) - Filter by status - property_id: integer - Filter by property - renter_id: integer - Filter by renter - date_from: date (YYYY-MM-DD) - Filter from date - date_to: date (YYYY-MM-DD) - Filter to date - per_page: integer (default: 15) - page: integer (default: 1) Success Response (200) - Paginated: ```json { "data": [ { "id": 100, "user_id": 1, "property_id": 3, "renter_id": 5, "template_id": 2, "to_numbers": "+8801711111111,+8801722222222", "message": "Dear {{renter_name}}, your rent of {{amount_due}} is due on {{due_date}}.", "schedule_at": null, "sent_at": "2025-11-10T14:30:00.000000Z", "provider_message_id": "PROV123456", "status": "sent", "cost": 2, "created_at": "2025-11-10T14:25:00.000000Z", "property": { "id": 3, "title": "Green Villa" }, "renter": { "id": 5, "name": "Ahmed Khan" }, "template": { "id": 2, "title": "Rent Reminder (Bangla)" } } ], "current_page": 1, "per_page": 15, "total": 50 } ``` โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” POST /api/sms/send โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” Description: Send SMS immediately Auth Required: YES Rate Limited: YES (30 per minute) Request Body: ```json { "to_numbers": "+8801711111111,+8801722222222", "message": "Custom message text", "template_id": 2, "property_id": 3, "renter_id": 5 } ``` Validation Rules: - to_numbers: required|string - Comma-separated phone numbers (E.164 format) - message: required_without:template_id|string|max:1000 - template_id: required_without:message|exists:sms_templates,id - property_id: nullable|exists:properties,id (must belong to user) - renter_id: nullable|exists:renters,id (must belong to user) Important: - Either "message" OR "template_id" must be provided (not both required) - If template_id provided, message will be rendered from template - If renter_id/property_id provided with template, placeholders will be auto-filled SMS Cost Calculation: - Standard SMS: 160 characters per SMS - Unicode SMS (Bangla/Arabic): 70 characters per SMS - Cost = (message_length / char_limit) * recipient_count Balance Check: - Backend checks user's SMS balance before sending - If insufficient balance โ†’ 403 error: ```json { "message": "Insufficient SMS balance.", "required": 5, "balance": 2 } ``` Success Response (200): ```json { "message": "SMS queued for sending", "sms_message": { "id": 100, "status": "queued", "cost": 2, "to_numbers": "+8801711111111,+8801722222222", ... }, "estimated_cost": 2, "new_balance": 43 } ``` Note: - SMS is sent asynchronously via queue - Status will be "queued" initially, then "sent" or "failed" - Balance is deducted immediately when queued - Use GET /api/sms to check final status Error Responses: - 403: Insufficient balance - 429: Rate limit exceeded - 422: Validation errors โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” POST /api/sms/schedule โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” Description: Schedule SMS for future sending Auth Required: YES Rate Limited: YES (30 per minute) Request Body: ```json { "to_numbers": "+8801711111111", "message": "Scheduled message", "template_id": 2, "schedule_at": "2025-11-15 10:00:00", "property_id": 3, "renter_id": 5 } ``` Validation Rules: - schedule_at: required|date|after:now - All other fields same as POST /api/sms/send Success Response (200): ```json { "message": "SMS scheduled successfully", "sms_message": { "id": 101, "status": "queued", "schedule_at": "2025-11-15T10:00:00.000000Z", "cost": 1, ... }, "estimated_cost": 1 } ``` Note: - Balance is NOT deducted until SMS is actually sent - SMS will be sent automatically at schedule_at time - Use GET /api/sms to check status โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” POST /api/sms/purchase โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” Description: Purchase SMS credits (initiate payment) Auth Required: YES Request Body: ```json { "qty": 100, "payment_method": "sslcommerz" } ``` Validation Rules: - qty: required|integer|min:100 - payment_method: required|in:sslcommerz Success Response (200): ```json { "message": "SMS purchase initiated", "purchase": { "id": 10, "qty": 100, "price": "50.00", "status": "pending" }, "payment_url": "https://sandbox.sslcommerz.com/...", "amount": 50.00 } ``` Note: - This creates a payment intent - Redirect user to payment_url for SSLCommerz checkout - After payment, SMS balance will be updated automatically via webhook ================================================================================ ๐Ÿ”Ÿ SMS TEMPLATES ================================================================================ โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” GET /api/sms-templates โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” Description: List SMS templates (user's own + global defaults) Auth Required: YES Query Parameters: - lang: string (bn|en) - Filter by language - type: string (rent_reminder|due_notice|trial_expiry|custom) - Filter by type - per_page: integer (default: 15) - page: integer (default: 1) Success Response (200) - Paginated: ```json { "data": [ { "id": 1, "slug": "bn_rent_reminder_default", "title": "Rent Reminder (Bangla)", "type": "rent_reminder", "language": "bn", "body": "เฆชเงเฆฐเฆฟเฆฏเฆผ {{renter_name}}, เฆ†เฆชเฆจเฆพเฆฐ {{property_name}} เฆเฆฐ เฆญเฆพเฆกเฆผเฆพ {{amount_due}} เฆŸเฆพเฆ•เฆพ {{due_date}} เฆคเฆพเฆฐเฆฟเฆ–เง‡ เฆชเฆฐเฆฟเฆถเง‹เฆง เฆ•เฆฐเฆคเง‡ เฆนเฆฌเง‡เฅค", "is_default": true, "is_editable": true, "user_id": null, "created_at": "2025-11-01T10:00:00.000000Z" }, { "id": 5, "slug": "custom_template_1_1234567890", "title": "My Custom Template", "type": "custom", "language": "en", "body": "Hello {{renter_name}}, please pay rent.", "is_default": false, "is_editable": true, "user_id": 1, "created_at": "2025-11-10T10:00:00.000000Z" } ], "current_page": 1, "per_page": 15, "total": 8 } ``` Available Placeholders: - {{renter_name}} - Renter's name - {{property_name}} - Property title - {{month_name}} - Current month name - {{amount_due}} - Due amount - {{due_period}} - Due period (e.g., "November 2025") - {{user_business_name}} - User's business name - {{user_phone}} - User's phone number โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” POST /api/sms-templates โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” Description: Create user's own template Auth Required: YES Request Body: ```json { "title": "My Custom Template", "type": "custom", "language": "en", "body": "Hello {{renter_name}}, your rent of {{amount_due}} is due.", "slug": "optional-slug" } ``` Validation Rules: - title: required|string|max:255 - type: required|in:rent_reminder,due_notice,trial_expiry,custom - language: required|in:bn,en - body: required|string|max:1024 - slug: nullable|string|unique:sms_templates,slug Success Response (201): ```json { "message": "Template created successfully", "template": { "id": 10, "title": "My Custom Template", "type": "custom", "language": "en", "body": "Hello {{renter_name}}, your rent of {{amount_due}} is due.", "is_default": false, "is_editable": true, "user_id": 1, ... } } ``` โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” GET /api/sms-templates/{id} โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” Description: Get template details with available placeholders Auth Required: YES Success Response (200): ```json { "template": { "id": 1, "title": "Rent Reminder (Bangla)", "type": "rent_reminder", "language": "bn", "body": "เฆชเงเฆฐเฆฟเฆฏเฆผ {{renter_name}}, ...", "is_default": true, "is_editable": true, ... }, "available_placeholders": [ "renter_name", "property_name", "amount_due", "due_period", "user_business_name", "user_phone" ] } ``` โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” PUT /api/sms-templates/{id} โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” Description: Update user's own template Auth Required: YES Request Body (all optional): ```json { "title": "Updated Title", "body": "Updated body text", "language": "bn" } ``` Validation Rules: - title: sometimes|required|string|max:255 - body: sometimes|required|string|max:1024 - language: sometimes|required|in:bn,en Error Responses: - 403: Template is not editable ```json { "message": "This template cannot be edited." } ``` Success Response (200): ```json { "message": "Template updated successfully", "template": { ... } } ``` โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” DELETE /api/sms-templates/{id} โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” Description: Delete user's own template Auth Required: YES Error Responses: - 403: Cannot delete default or non-editable templates ```json { "message": "Default templates cannot be deleted." } ``` Success Response (200): ```json { "message": "Template deleted successfully" } ``` ================================================================================ 1๏ธโƒฃ1๏ธโƒฃ DUES MANAGEMENT ================================================================================ โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” GET /api/dues โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” Description: List dues (outstanding rent payments) Auth Required: YES Query Parameters: - status: string (open|partial|paid|written_off) - Filter by status - property_id: integer - Filter by property - renter_id: integer - Filter by renter - per_page: integer (default: 15) - page: integer (default: 1) Success Response (200) - Paginated: ```json { "data": [ { "id": 50, "user_id": 1, "renter_id": 5, "property_id": 3, "period_start": "2025-11-01", "period_end": "2025-11-30", "amount_due": 15000.00, "amount_paid": 0.00, "status": "open", "created_at": "2025-11-01T10:00:00.000000Z", "renter": { "id": 5, "name": "Ahmed Khan", "phone": "+8801711111111" }, "property": { "id": 3, "title": "Green Villa" } } ], "current_page": 1, "per_page": 15, "total": 5 } ``` โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” POST /api/dues/{id}/mark-paid โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” Description: Mark due as paid (creates transaction) Auth Required: YES Request Body: ```json { "amount": 15000, "method": "cash", "note": "Received in cash", "paid_date": "2025-11-10" } ``` Validation Rules: - amount: required|numeric|min:0|max:amount_due - method: required|in:cash,sslcommerz,manual,other - note: nullable|string|max:500 - paid_date: nullable|date Success Response (200): ```json { "message": "Due marked as paid successfully", "due": { "id": 50, "amount_due": 15000.00, "amount_paid": 15000.00, "status": "paid", ... }, "transaction": { "id": 100, "type": "rent_payment", "amount": "15000.00", "method": "cash", ... } } ``` Note: - Creates a Transaction record - Updates Due status (open โ†’ partial โ†’ paid) - If amount < amount_due, status becomes "partial" ================================================================================ 1๏ธโƒฃ2๏ธโƒฃ SUBSCRIPTIONS ================================================================================ โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” GET /api/subscriptions โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” Description: Get user's subscriptions and available packages Auth Required: YES Success Response (200): ```json { "current_subscription": { "id": 5, "user_id": 1, "package_id": 2, "status": "active", "started_at": "2025-11-01T10:00:00.000000Z", "ends_at": "2025-12-01T10:00:00.000000Z", "auto_renew": true, "is_primary": true, "package": { "id": 2, "name": "Basic", "slug": "basic", "price": "500.00", "billing_period": "monthly", "package_limits": [ { "property_category": "house", "max_properties": 5, "sms_limit": 50 }, { "property_category": "shop", "max_properties": 3, "sms_limit": 50 } ] } }, "subscriptions": [ { "id": 5, "status": "active", ... }, { "id": 4, "status": "expired", ... } ], "available_packages": [ { "id": 1, "name": "Trial", "slug": "trial", "price": "0.00", "billing_period": "monthly", "is_visible": true, "package_limits": [ ... ] }, { "id": 2, "name": "Basic", "slug": "basic", "price": "500.00", "billing_period": "monthly", "is_visible": true, "package_limits": [ ... ] } ], "is_in_trial": false, "is_in_grace_period": false, "trial_ends_at": null, "grace_ends_at": null } ``` โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” POST /api/subscriptions/checkout โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” Description: Initiate subscription checkout (DEPRECATED - Use /api/payments/checkout) Auth Required: YES Note: This endpoint exists but is deprecated. Use POST /api/payments/checkout instead. โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” POST /api/subscriptions/{id}/cancel โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” Description: Cancel active subscription Auth Required: YES Request Body: None Success Response (200): ```json { "message": "Subscription cancelled successfully", "subscription": { "id": 5, "status": "cancelled", "auto_renew": false, ... }, "grace_ends_at": "2025-11-17T10:30:00.000000Z" } ``` Note: - Sets grace period (7 days default) - User can still access subscription/payment pages during grace - After grace period, account is deactivated ================================================================================ 1๏ธโƒฃ3๏ธโƒฃ PAYMENTS ================================================================================ โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” POST /api/payments/checkout โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” Description: Initiate payment checkout (subscription or SMS topup) Auth Required: YES Request Body - Subscription: ```json { "type": "subscription", "package_id": 2 } ``` Request Body - SMS Topup: ```json { "type": "topup", "topup_qty": 100 } ``` Validation Rules: - type: required|in:subscription,topup - package_id: required_if:type,subscription|exists:packages,id - topup_qty: required_if:type,topup|integer|min:100 Success Response (200): ```json { "message": "Checkout initiated successfully", "payment": { "id": 20, "uuid": "550e8400-e29b-41d4-a716-446655440000", "user_id": 1, "package_id": 2, "type": "subscription", "amount": "500.00", "currency": "BDT", "status": "pending", "provider": "sslcommerz", "created_at": "2025-11-10T10:30:00.000000Z" }, "checkout_url": "https://sandbox.sslcommerz.com/checkout/..." } ``` Frontend Action: - Store payment UUID - Redirect user to checkout_url - After payment, SSLCommerz redirects to return URL - Poll payment status or show success page โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” GET /api/payments/sslcommerz/return โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” Description: Get payment status after SSLCommerz redirect Auth Required: NO (public endpoint) Query Parameters: - tran_id: string (UUID) - Payment UUID Success Response (200): ```json { "status": "completed", "payment_uuid": "550e8400-e29b-41d4-a716-446655440000", "amount": "500.00", "currency": "BDT", "message": "Payment successful! Your subscription has been activated." } ``` Status Values: - pending: Payment is being processed - completed: Payment successful - failed: Payment failed - cancelled: Payment cancelled Frontend Action: - Show success/failure message - Redirect to appropriate page - Refresh user data to show updated subscription/SMS balance Note: - Real processing happens via webhook (server-to-server) - This endpoint just returns status for display ================================================================================ 1๏ธโƒฃ4๏ธโƒฃ TRANSACTIONS ================================================================================ โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” GET /api/transactions โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” Description: List user's transactions Auth Required: YES Query Parameters: - type: string (rent_payment|security_deposit|advance_payment|refund|subscription_payment|sms_purchase) - Filter by type - property_id: integer - Filter by property - renter_id: integer - Filter by renter - date_from: date - Filter from date - date_to: date - Filter to date - per_page: integer (default: 15) - page: integer (default: 1) Success Response (200) - Paginated: ```json { "data": [ { "id": 100, "user_id": 1, "renter_id": 5, "property_id": 3, "type": "rent_payment", "amount": "15000.00", "method": "cash", "note": "Received in cash", "created_at": "2025-11-10T14:30:00.000000Z", "renter": { "id": 5, "name": "Ahmed Khan" }, "property": { "id": 3, "title": "Green Villa" } } ], "current_page": 1, "per_page": 15, "total": 50 } ``` Transaction Types: - rent_payment: Rent collection - security_deposit: Security deposit received - advance_payment: Advance payment received - refund: Refund given - subscription_payment: Subscription payment - sms_purchase: SMS credit purchase ================================================================================ 1๏ธโƒฃ5๏ธโƒฃ NOTIFICATIONS ================================================================================ โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” GET /api/notifications โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” Description: List user's notifications Auth Required: YES Query Parameters: - is_read: boolean - Filter by read status - type: string (package_notice|system|custom) - Filter by type - per_page: integer (default: 15) - page: integer (default: 1) Success Response (200) - Paginated: ```json { "data": [ { "id": 50, "user_id": 1, "type": "system", "title": "Payment Successful", "body": "Your subscription payment has been processed successfully.", "meta": { "payment_id": 20, "amount": "500.00" }, "is_read": false, "created_at": "2025-11-10T10:30:00.000000Z" } ], "current_page": 1, "per_page": 15, "total": 10, "unread_count": 3 } ``` โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” POST /api/notifications/{id}/mark-as-read โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” Description: Mark notification as read Auth Required: YES Request Body: None Success Response (200): ```json { "message": "Notification marked as read", "notification": { "id": 50, "is_read": true, ... } } ``` ================================================================================ 1๏ธโƒฃ6๏ธโƒฃ API TOKENS ================================================================================ โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” GET /api/api-tokens โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” Description: List user's API tokens Auth Required: YES Success Response (200): ```json { "tokens": [ { "id": 1, "name": "Mobile App", "scopes": ["properties:read", "renters:read"], "is_active": true, "expires_at": "2026-11-10T10:30:00.000000Z", "created_at": "2025-11-10T10:30:00.000000Z" } ] } ``` โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” POST /api/api-tokens โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” Description: Create API token Auth Required: YES Request Body: ```json { "name": "Mobile App", "scopes": ["properties:read", "renters:read", "sms:send"], "expires_at": "2026-11-10T10:30:00" } ``` Validation Rules: - name: required|string|max:255 - scopes: nullable|array - scopes.*: string|in:properties:read,properties:write,renters:read,renters:write,transactions:read,sms:send - expires_at: nullable|date|after:now Success Response (201): ```json { "message": "API token created successfully", "token": { "id": 1, "name": "Mobile App", ... }, "plain_text_token": "1|abcdefghijklmnopqrstuvwxyz1234567890" } ``` IMPORTANT: - plain_text_token is shown ONLY ONCE - Store it immediately - it cannot be retrieved again - Use this token for API authentication โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” DELETE /api/api-tokens/{id} โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” Description: Revoke API token Auth Required: YES Success Response (200): ```json { "message": "API token revoked successfully" } ``` ================================================================================ 1๏ธโƒฃ7๏ธโƒฃ DATABASE STRUCTURE REFERENCE ================================================================================ This section documents the database fields you'll receive in API responses. โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” User Model Fields โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” { "id": integer, "name": string, "email": string (unique), "business_name": string|null, "phone": string|null, "timezone": string|null, "is_active": boolean, "trial_ends_at": datetime|null, "grace_ends_at": datetime|null, "current_subscription_id": integer|null, "created_at": datetime, "updated_at": datetime, "deleted_at": datetime|null (soft delete) } โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” Property Model Fields โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” { "id": integer, "user_id": integer, "category_id": integer, "title": string, "address": string|null, "default_rent_amount": decimal (2 decimal places), "status": enum (vacant|on_rent|maintenance), "created_at": datetime, "updated_at": datetime, "deleted_at": datetime|null } PropertyCategory: { "id": integer, "name": string, "slug": string (unique) } โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” Renter Model Fields โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” { "id": integer, "user_id": integer, "property_id": integer, "name": string, "phone": string, "nid_number": string|null, "address": string|null, "father_name": string|null, "mother_name": string|null, "security_deposit": decimal (2 decimal places), "advance_balance": decimal (2 decimal places), "payment_type": enum (maser_surute|maser_seshe), "rent_amount": decimal (2 decimal places), "rent_start_date": date, "rent_day_of_month": integer (1-28), "is_active": boolean, "created_at": datetime, "updated_at": datetime, "deleted_at": datetime|null } โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” SmsMessage Model Fields โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” { "id": integer, "user_id": integer, "property_id": integer|null, "renter_id": integer|null, "template_id": integer|null, "to_numbers": string (comma-separated), "message": text, "schedule_at": datetime|null, "sent_at": datetime|null, "provider_message_id": string|null, "status": enum (queued|sent|failed|delivered|partial), "cost": integer (SMS units), "created_at": datetime, "updated_at": datetime, "deleted_at": datetime|null } โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” Subscription Model Fields โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” { "id": integer, "user_id": integer, "package_id": integer, "started_at": datetime, "ends_at": datetime, "status": enum (trial|active|expired|suspended|cancelled), "auto_renew": boolean, "is_primary": boolean, "payment_reference": string|null, "created_at": datetime, "updated_at": datetime } Package: { "id": integer, "name": string, "slug": string (unique), "price": decimal (2 decimal places), "billing_period": enum (monthly|yearly), "description": text|null, "is_visible": boolean } PackageLimit: { "id": integer, "package_id": integer, "property_category": enum (house|shop|other), "max_properties": integer, "sms_limit": integer } โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” Payment Model Fields โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” { "id": integer, "uuid": string (UUID), "user_id": integer, "package_id": integer|null, "type": enum (subscription|topup|manual|refund), "amount": decimal (2 decimal places), "currency": string (default: BDT), "status": enum (pending|completed|failed|cancelled|refunded), "provider": string (e.g., "sslcommerz"), "provider_transaction_id": string|null, "meta": json (gateway response, etc.), "created_at": datetime, "updated_at": datetime } โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” Transaction Model Fields โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” { "id": integer, "user_id": integer, "renter_id": integer|null, "property_id": integer|null, "type": enum (rent_payment|security_deposit|advance_payment|refund|subscription_payment|sms_purchase), "amount": decimal (2 decimal places), "method": enum (cash|sslcommerz|manual|other), "note": string|null, "created_at": datetime, "updated_at": datetime } โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” Due Model Fields โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” { "id": integer, "user_id": integer, "renter_id": integer, "property_id": integer, "period_start": date, "period_end": date, "amount_due": decimal (2 decimal places), "amount_paid": decimal (2 decimal places), "status": enum (open|partial|paid|written_off), "created_at": datetime, "updated_at": datetime } โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” Notification Model Fields โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” { "id": integer, "user_id": integer, "type": enum (package_notice|system|custom), "title": string, "body": text, "meta": json (additional data), "is_read": boolean, "created_at": datetime, "updated_at": datetime } ================================================================================ ๐Ÿ“ IMPORTANT NOTES FOR FRONTEND DEVELOPER ================================================================================ 1. SMS Balance Calculation: - Use User.smsRemaining() helper (calculated on backend) - Balance = (Package SMS limit + Purchases) - Used SMS - Balance is deducted when SMS is queued (not when sent) 2. Subscription Status: - Check trial_ends_at to show trial countdown - Check grace_ends_at to show grace period warning - Check current_subscription.status for active subscription 3. Property Limits: - Backend enforces limits based on subscription package - Show limit warnings before user tries to create property - Display current count vs limit in UI 4. Payment Flow: - User initiates checkout โ†’ Gets checkout_url - Redirect to SSLCommerz โ†’ User pays - SSLCommerz redirects to return URL - Poll payment status or show success page - Real processing happens via webhook (server-to-server) 5. SMS Sending: - SMS is sent asynchronously (queued) - Status starts as "queued", then "sent" or "failed" - Poll GET /api/sms to check final status - Balance is deducted immediately when queued 6. Date/Time Format: - All dates are in ISO 8601 format (UTC) - Example: "2025-11-10T10:30:00.000000Z" - Convert to user's timezone for display 7. Pagination: - All list endpoints support pagination - Use per_page and page query parameters - Response includes pagination metadata 8. Error Handling: - Always check HTTP status code - Display user-friendly error messages - Handle 401 (redirect to login) - Handle 403 (show deactivation/grace period message) - Handle 429 (show rate limit message with countdown) 9. Token Management: - Store token securely - Include in every request header - Clear token on 401 error - Implement token refresh if needed 10. Real-time Updates: - Poll endpoints periodically for status updates - Or implement WebSocket/SSE if backend supports it - SMS status, payment status, notifications can change ================================================================================ โœ… END OF USER FRONTEND API DOCUMENTATION ================================================================================ This guide contains everything you need to build the user frontend. All endpoints, request/response formats, validation rules, and error handling are documented above. For admin frontend, see: admin_frontend_api_guide.txt ================================================================================