واجهة المطورين
نظام برمجي متكامل وسهل الاستخدام. اربط متجرك مع منصتنا خلال دقائق وابدأ عمليات التوصيل بكفاءة عالية.
Home
Home page and health check endpoints
Check API health status and server availability
Response Example
{
"status": "healthy"
}
Introduction Pages
Onboarding/introduction pages for mobile app first-time users
Get all active introduction pages for app onboarding. Returns pages ordered by page_number (1, 2, 3). Only active pages are returned. Use this endpoint to display introduction/onboarding screens in the mobile app.
Response Example
[
{
"created_at": "2024-12-25T00:00:00Z",
"id": 1,
"image": "https://wassel.delivery/static/uploads/introduction_pages/intro_page_1_abc123.jpg",
"is_active": true,
"page_number": 1,
"text1": "Welcome to our app",
"text2": "Discover amazing products",
"text3": "Start shopping now",
"updated_at": "2024-12-25T00:00:00Z"
},
{
"created_at": "2024-12-25T00:00:00Z",
"id": 2,
"image": "https://wassel.delivery/static/uploads/introduction_pages/intro_page_2_def456.jpg",
"is_active": true,
"page_number": 2,
"text1": "Fast delivery",
"text2": "Get your orders quickly",
"text3": "Track in real-time",
"updated_at": "2024-12-25T00:00:00Z"
},
{
"created_at": "2024-12-25T00:00:00Z",
"id": 3,
"image": "https://wassel.delivery/static/uploads/introduction_pages/intro_page_3_ghi789.jpg",
"is_active": true,
"page_number": 3,
"text1": "Secure payments",
"text2": "Your data is safe",
"text3": "Shop with confidence",
"updated_at": "2024-12-25T00:00:00Z"
}
]
Authentication
User registration, login, and token management
Register a new user account
Body Parameters
- username
- password
- full_name (optional)
- phone (optional)
Response Example
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"expires_in": 86400,
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "bearer",
"user": {
"avatar": null,
"created_at": "2024-12-08T10:30:00Z",
"email": "[email protected]",
"full_name": "John Doe",
"id": 1,
"is_active": true,
"is_verified": false,
"last_login": null,
"phone": "+1234567890",
"selected_currency_id": null,
"store_id": null,
"updated_at": "2024-12-08T10:30:00Z",
"user_type": "normal_user",
"username": "johndoe"
}
}
Login with email/username and password. Users can login with either their email address or username.
Body Parameters
- email (or username)
- password
Response Example
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"expires_in": 86400,
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "bearer",
"user": {
"avatar": null,
"created_at": "2024-12-08T10:30:00Z",
"email": "[email protected]",
"full_name": "John Doe",
"id": 1,
"is_active": true,
"is_verified": false,
"last_login": "2024-12-08T10:30:00Z",
"phone": "+1234567890",
"store_id": null,
"updated_at": "2024-12-08T10:30:00Z",
"user_type": "normal_user",
"username": "johndoe"
}
}
Refresh access token using refresh token
Body Parameters
- refresh_token
Response Example
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"expires_in": 86400,
"token_type": "bearer"
}
Logout user (client-side token removal)
Response Example
{
"message": "Logged out successfully"
}
Request password reset. User submits their email address. The system generates a secure password reset token and sends it via email to the user's registered email address. The token expires in 1 hour. For security reasons, the API always returns a success message regardless of whether the email exists (prevents email enumeration attacks). The reset link is sent to the user's email only - no token is returned in the API response.
Body Parameters
Response Example
{
"message": "If the email exists, a password reset link has been sent to your email.",
"success": true
}
SECURITY: The reset token is NEVER returned in the API response. It is sent ONLY via email to the registered email address. This prevents unauthorized access to password reset tokens. Always check the user's email inbox for the reset link.
Verify password reset token. Checks if the token is valid and not expired. Returns success if token is valid. Use this before showing the password reset form to ensure the token is still valid.
Body Parameters
- token
Response Example
{
"message": "Reset token is valid",
"success": true
}
Reset password using reset token. Resets the user's password and invalidates the reset token. Password must be at least 8 characters. After successful reset, user can login with the new password.
Body Parameters
- token
- new_password (minimum 8 characters)
Response Example
{
"message": "Password has been reset successfully",
"success": true
}
Profile
User profile management and information
Get current authenticated user profile. Returns user information including user type (normal_user or shop_owner), store_id if the user is a shop owner, and opening_hours for shop owners.
Response Example
{
"avatar": "https://example.com/avatar.jpg",
"created_at": "2024-12-08T10:30:00Z",
"email": "[email protected]",
"full_name": "John Doe",
"id": 1,
"is_active": true,
"is_verified": true,
"last_login": "2024-12-08T10:30:00Z",
"opening_hours": null,
"phone": "+1234567890",
"selected_currency_id": null,
"store_id": null,
"updated_at": "2024-12-08T10:30:00Z",
"user_type": "normal_user",
"username": "johndoe"
}
opening_hours is only returned for shop owners (user_type='shop_owner'). For regular users, opening_hours will be null. The opening_hours object contains all 7 days of the week (monday through sunday), each with is_closed (bool), open_time (HH:MM format, 24-hour, UTC+3), and close_time (HH:MM format, 24-hour, UTC+3). All times are in UTC+3 (Bahrain Time). Use is_closed=true to mark a day as closed. See opening_hours_example above for the structure.
Update current user profile with file upload support. Use multipart/form-data for avatar upload. You can update full_name, phone, upload avatar image file, and opening_hours (for shop owners only).
Response Example
{
"avatar": "https://wassel.delivery/static/uploads/users/user_1_a3b5c7d9.png",
"created_at": "2024-12-08T10:30:00Z",
"email": "[email protected]",
"full_name": "Jane Doe Updated",
"id": 1,
"is_active": true,
"is_verified": true,
"last_login": "2024-12-08T10:30:00Z",
"opening_hours": {
"friday": {
"close_time": "17:00",
"is_closed": false,
"open_time": "09:00"
},
"monday": {
"close_time": "17:00",
"is_closed": false,
"open_time": "09:00"
},
"saturday": {
"close_time": null,
"is_closed": true,
"open_time": null
},
"sunday": {
"close_time": null,
"is_closed": true,
"open_time": null
},
"thursday": {
"close_time": "17:00",
"is_closed": false,
"open_time": "09:00"
},
"tuesday": {
"close_time": "17:00",
"is_closed": false,
"open_time": "09:00"
},
"wednesday": {
"close_time": "17:00",
"is_closed": false,
"open_time": "09:00"
}
},
"phone": "+1987654321",
"store_id": "store_a1b2c3d4e5f6g7h8",
"updated_at": "2024-12-08T11:45:00Z",
"user_type": "shop_owner",
"username": "johndoe"
}
opening_hours is only applicable for shop owners (user_type='shop_owner'). For regular users, opening_hours will be null. Use is_closed=true to mark a day as closed. Times are in 24-hour format (HH:MM) and are in UTC+3 (Bahrain Time).
Update current user profile (JSON format). Use this for text fields only. For avatar file upload, use PUT /me with multipart/form-data. You can update full_name, phone, avatar (as URL string), and opening_hours (for shop owners only).
Body Parameters
- full_name (optional, string)
- phone (optional, string)
- avatar (optional, URL string)
- opening_hours (optional, object) - Opening hours for shop owners. Format: {"monday": {"is_closed": false, "open_time": "09:00", "close_time": "17:00"}, "tuesday": {"is_closed": true}, ...}. Days: monday, tuesday, wednesday, thursday, friday, saturday, sunday. Each day has is_closed (bool), open_time (HH:MM format, 24-hour), close_time (HH:MM format, 24-hour).
Response Example
{
"avatar": "https://example.com/avatar.jpg",
"created_at": "2024-12-08T10:30:00Z",
"email": "[email protected]",
"full_name": "Jane Doe Updated",
"id": 1,
"is_active": true,
"is_verified": true,
"last_login": "2024-12-08T10:30:00Z",
"opening_hours": {
"friday": {
"close_time": "17:00",
"is_closed": false,
"open_time": "09:00"
},
"monday": {
"close_time": "17:00",
"is_closed": false,
"open_time": "09:00"
},
"saturday": {
"close_time": null,
"is_closed": true,
"open_time": null
},
"sunday": {
"close_time": null,
"is_closed": true,
"open_time": null
},
"thursday": {
"close_time": "17:00",
"is_closed": false,
"open_time": "09:00"
},
"tuesday": {
"close_time": "17:00",
"is_closed": false,
"open_time": "09:00"
},
"wednesday": {
"close_time": "17:00",
"is_closed": false,
"open_time": "09:00"
}
},
"phone": "+1987654321",
"store_id": "store_a1b2c3d4e5f6g7h8",
"updated_at": "2024-12-08T11:45:00Z",
"user_type": "shop_owner",
"username": "johndoe"
}
opening_hours is only applicable for shop owners (user_type='shop_owner'). For regular users, opening_hours will be null. Use is_closed=true to mark a day as closed. Times are in 24-hour format (HH:MM) and are in UTC+3 (Bahrain Time).
Update user's selected currency preference. The selected currency will be stored in the user's profile and remembered for future sessions. Currency must be active.
Body Parameters
- currency_id
Response Example
{
"avatar": null,
"created_at": "2024-12-08T10:30:00Z",
"email": "[email protected]",
"full_name": "John Doe",
"id": 1,
"is_active": true,
"is_verified": true,
"last_login": "2024-12-08T10:30:00Z",
"phone": "+1234567890",
"selected_currency_id": 2,
"store_id": null,
"updated_at": "2024-12-09T12:00:00Z",
"user_type": "normal_user",
"username": "johndoe"
}
Returns updated user profile with selected_currency_id. Use this ID to convert prices in the app. Check /api/v1/settings endpoint to get currency details including exchange rates.
Branding
Branding and site configuration endpoints including dynamic app color customization (read-only)
Get current branding information including favicon, logos, copyright text, social media links, and dynamic app color customization. The response includes a 'colors' object with all customizable app colors for both light and dark modes. This endpoint enables dynamic theming - the Flutter app can fetch these colors and apply them automatically. All color fields are optional (nullable) - if a color is null or not provided, the app will use default fallback colors. This is a read-only endpoint. To update branding, use the admin panel at /admin/branding. To customize app colors, use the admin panel at /admin/app-colors.
Response Example
{
"app_name": "My Application",
"colors": {
"animation_base_color_dark": "#FFFFFF",
"animation_base_color_light": "#808080",
"animation_highlight_color_dark": "#161616",
"animation_highlight_color_light": "#FAFAFA",
"bg_color_dark": "#161616",
"bg_color_light": "#FAFAFA",
"border_color_dark": "#2A2A2A",
"border_color_light": "#DFDFDF",
"button_color_dark": "#A3D97A",
"button_color_light": "#76974C",
"card_color_dark": "#1E1E1E",
"card_color_light": "#FFFFFF",
"chat_other_side_color": "#2196F3",
"divider_color_dark": "#212121",
"divider_color_light": "#F1F1F1",
"error_color": "#FF6565",
"info_color": "#2196F3",
"light_button_color_dark": "#1D231C",
"light_button_color_light": "#EEF6E4",
"primary_text_dark": "#F2F2F2",
"primary_text_light": "#000000",
"regular_black_dark": "#F2F2F2",
"regular_black_light": "#000000",
"regular_white_dark": "#1E1E1E",
"regular_white_light": "#FFFFFF",
"secondary_text_dark": "#B8BFC7",
"secondary_text_light": "#808080",
"sub_title_color_dark": "#A7AFB8",
"sub_title_color_light": "#808080",
"success_color": "#4CAF50",
"warning_color": "#FF9800"
},
"copyright_text": "\u00a9 2024 SaaS E-commerce Platform. All rights reserved.",
"created_at": "2024-12-08T10:30:00Z",
"favicon": "https://wassel.delivery/static/uploads/branding/favicon.ico",
"id": 1,
"logo_dark": "https://wassel.delivery/static/uploads/branding/logo_dark.png",
"logo_light": "https://wassel.delivery/static/uploads/branding/logo_light.png",
"social_media": [
{
"icon": "https://wassel.delivery/static/uploads/branding/social_facebook.png",
"name": "Facebook",
"url": "https://facebook.com/yourcompany"
},
{
"icon": "https://wassel.delivery/static/uploads/branding/social_twitter.png",
"name": "Twitter",
"url": "https://twitter.com/yourcompany"
},
{
"icon": "https://wassel.delivery/static/uploads/branding/social_instagram.png",
"name": "Instagram",
"url": "https://instagram.com/yourcompany"
}
],
"updated_at": "2024-12-08T11:45:00Z"
}
DYNAMIC COLORS API: The 'colors' object enables dynamic app theming. Colors are organized by category: 📌 PRIMARY COLORS: - button_color_light/dark: Main button colors (default: #76974C/#A3D97A) - light_button_color_light/dark: Light button backgrounds (default: #EEF6E4/#1D231C) 🎨 BACKGROUND COLORS: - bg_color_light/dark: Main background (default: #FAFAFA/#161616) - card_color_light/dark: Card/surface colors (default: #FFFFFF/#1E1E1E) 📝 TEXT COLORS: - primary_text_light/dark: Primary text (default: #000000/#F2F2F2) - secondary_text_light/dark: Secondary text (default: #808080/#B8BFC7) - sub_title_color_light/dark: Subtitle text (default: #808080/#A7AFB8) 🔲 BORDER & DIVIDER COLORS: - border_color_light/dark: Border colors (default: #DFDFDF/#2A2A2A) - divider_color_light/dark: Divider colors (default: #F1F1F1/#212121) ⚫ STANDARD COLORS: - regular_black_light/dark: Black variant (default: #000000/#F2F2F2) - regular_white_light/dark: White variant (default: #FFFFFF/#1E1E1E) ✨ ANIMATION COLORS (for shimmer effects): - animation_base_color_light/dark: Base shimmer color (default: #808080/#FFFFFF) - animation_highlight_color_light/dark: Highlight shimmer (default: #FAFAFA/#161616) 🚦 STATUS COLORS (same for both modes): - error_color: Error/red (default: #FF6565) - success_color: Success/green (default: #4CAF50) - warning_color: Warning/orange (default: #FF9800) - info_color: Info/blue (default: #2196F3) - chat_other_side_color: Chat message color (default: #2196F3) 📋 COLOR FORMAT: - Colors are in hex format: #RRGGBB (6 digits) or #AARRGGBB (8 digits with alpha) - The # prefix is optional (both '#76974C' and '76974C' are accepted) - All color fields are optional (nullable) - partial customization is supported - If a color is null or empty, the app uses default fallback colors 💡 USAGE: - Fetch colors from this endpoint on app startup - Cache colors locally for offline use - Colors automatically adapt to light/dark mode - Changes in admin panel (/admin/app-colors) are reflected after app refresh
Settings
General platform settings and feature toggles. Use this endpoint to check if features like Events or Blogs are enabled before making API calls.
Get general platform settings including feature toggles and currencies. Returns events_enabled (shows if Events feature is active), blogs_enabled (shows if Blogs feature is active), top_sellers_enabled (shows if Top Sellers feature is active), shops_enabled (shows if Shops feature is active), chat_enabled (shows if Chat feature is active), support_enabled (shows if Support System feature is active), master_categories_enabled (shows if Master Categories feature is active), platform_fees_enabled, platform_fees_percentage, and currencies array with exchange rates. Always check these feature toggles before calling respective endpoints to know if features are available. Currencies are returned with their exchange rates against BHD (default currency).
Response Example
{
"blogs_enabled": true,
"chat_enabled": true,
"currencies": [
{
"created_at": "2024-12-09T10:30:00Z",
"flag_image": "https://wassel.delivery/static/uploads/currencies/flag_1_abc123.jpg",
"id": 1,
"is_active": true,
"is_default": true,
"rate": 1.0,
"symbol": "BHD",
"updated_at": "2024-12-09T10:30:00Z"
},
{
"created_at": "2024-12-09T10:35:00Z",
"flag_image": "https://wassel.delivery/static/uploads/currencies/flag_2_def456.jpg",
"id": 2,
"is_active": true,
"is_default": false,
"rate": 10.0,
"symbol": "SAR",
"updated_at": "2024-12-09T10:35:00Z"
}
],
"events_enabled": true,
"maintenance_mode": false,
"master_categories_enabled": true,
"platform_fees_enabled": false,
"platform_fees_percentage": 0.0,
"shops_enabled": true,
"support_enabled": true,
"top_sellers_enabled": true
}
If events_enabled is false, Events API endpoints return empty arrays or 404 errors. If blogs_enabled is false, Blogs API endpoints return empty arrays or 404 errors. If top_sellers_enabled is false, Top Sellers feature should be hidden in the app. If shops_enabled is false, Shops feature should be hidden in the app. If chat_enabled is false, Chat API endpoints will be unavailable. If support_enabled is false, Support System API endpoints will be unavailable. If master_categories_enabled is false, Master Categories feature should be hidden in the app and master categories API endpoints may return empty arrays. If maintenance_mode is true, the platform is in maintenance mode and users should see a maintenance message. Always check these settings first before displaying features in your app. Currencies array contains all active currencies with their exchange rates against BHD. The rate represents how many units of the currency equal 1 BHD (e.g., rate: 10 means 10 SAR = 1 BHD). The default currency (is_default: true) is BHD.
Popups
Popup images with deep linking support for products, stores, events, and external URLs
Get all active popups. Returns popups ordered by display order (ascending). Only active popups within their scheduled time range are returned by default. Use this endpoint to display popups in the mobile app.
Query Parameters
- is_active (optional, boolean) - Filter by active status. If not provided, returns only active popups.
Response Example
[
{
"createdAt": "2024-12-09T10:30:00Z",
"endAt": null,
"id": 12,
"image": "https://wassel.delivery/static/uploads/popups/popup_abc123.jpg",
"isActive": true,
"order": 0,
"startAt": null,
"targetId": "987",
"targetType": "product",
"title": "Limited offer",
"updatedAt": "2024-12-09T10:30:00Z",
"url": null
},
{
"createdAt": "2024-12-09T11:00:00Z",
"endAt": "2024-12-31T23:59:59Z",
"id": 13,
"image": "https://wassel.delivery/static/uploads/popups/popup_def456.jpg",
"isActive": true,
"order": 1,
"startAt": "2024-12-10T00:00:00Z",
"targetId": "https://example.com/promotion",
"targetType": "url",
"title": "Special Promotion",
"updatedAt": "2024-12-09T11:00:00Z",
"url": "https://example.com/promotion"
},
{
"createdAt": "2024-12-09T12:00:00Z",
"endAt": null,
"id": 14,
"image": "https://wassel.delivery/static/uploads/popups/popup_ghi789.jpg",
"isActive": true,
"order": 2,
"startAt": null,
"targetId": "store_a1b2c3d4e5f6g7h8",
"targetType": "store",
"title": "Visit Our Store",
"updatedAt": "2024-12-09T12:00:00Z",
"url": null
}
]
Blogs
Blog posts and articles management endpoints. Note: Description fields accept and return HTML formatted content from a rich text editor. When displaying in Flutter, use packages like 'flutter_html' or 'html_widget' to render the HTML content properly. Blogs feature can be enabled/disabled by admin. When disabled, API endpoints return empty results or 404 errors. Check /api/v1/settings endpoint to see if blogs feature is enabled.
List all active blogs. Filter by master_category_id to get blogs for a specific master category. Returns blogs ordered by creation date (newest first). Description fields contain HTML formatted content from the rich text editor. If blogs feature is disabled by admin, returns an empty list [].
Query Parameters
- master_category_id (optional, integer - filter by master category)
- skip (optional, default: 0)
- limit (optional, default: 100, max: 100)
- is_active (optional, default: true, boolean)
Response Example
[
{
"created_at": "2024-12-08T10:30:00Z",
"description_ar": "\u003cp\u003e\u062a\u0639\u0644\u0645 \u003cstrong\u003e\u0623\u0633\u0627\u0633\u064a\u0627\u062a \u0627\u0644\u0643\u0631\u0648\u0634\u064a\u0647\u003c/strong\u003e \u0648\u0627\u0628\u062f\u0623 \u0631\u062d\u0644\u062a\u0643...\u003c/p\u003e\u003cul\u003e\u003cli\u003e\u0627\u0644\u062e\u0637\u0648\u0629 1: \u0627\u062e\u062a\u0631 \u062e\u064a\u0648\u0637\u0643\u003c/li\u003e\u003cli\u003e\u0627\u0644\u062e\u0637\u0648\u0629 2: \u0627\u062e\u062a\u0631 \u0627\u0644\u062e\u0637\u0627\u0641\u0627\u062a\u003c/li\u003e\u003c/ul\u003e",
"description_en": "\u003cp\u003eLearn the \u003cstrong\u003ebasics of crochet\u003c/strong\u003e and start your journey...\u003c/p\u003e\u003cul\u003e\u003cli\u003eStep 1: Choose your yarn\u003c/li\u003e\u003cli\u003eStep 2: Select hooks\u003c/li\u003e\u003c/ul\u003e",
"id": 1,
"image": "https://wassel.delivery/static/uploads/blogs/blog_1_abc123.jpg",
"is_active": true,
"title_ar": "\u0645\u0642\u062f\u0645\u0629 \u0641\u064a \u0627\u0644\u0643\u0631\u0648\u0634\u064a\u0647",
"title_en": "Introduction to Crochet",
"updated_at": "2024-12-08T10:30:00Z"
},
{
"created_at": "2024-12-07T14:20:00Z",
"description_ar": "\u003cp\u003e\u0627\u0643\u062a\u0634\u0641 \u003cem\u003e\u0623\u0641\u0636\u0644 \u0623\u0646\u0648\u0627\u0639 \u0627\u0644\u062e\u064a\u0648\u0637\u003c/em\u003e \u0644\u0645\u0628\u062a\u062f\u0626\u064a \u0627\u0644\u0643\u0631\u0648\u0634\u064a\u0647...\u003c/p\u003e\u003cblockquote\u003e\u0627\u0644\u062c\u0648\u062f\u0629 \u0641\u064a \u0627\u0644\u062e\u064a\u0648\u0637 \u062a\u062d\u062f\u062b \u0627\u0644\u0641\u0631\u0642!\u003c/blockquote\u003e",
"description_en": "\u003cp\u003eDiscover the \u003cem\u003ebest yarn types\u003c/em\u003e for crochet beginners...\u003c/p\u003e\u003cblockquote\u003eQuality yarn makes all the difference!\u003c/blockquote\u003e",
"id": 2,
"image": "https://wassel.delivery/static/uploads/blogs/blog_2_def456.jpg",
"is_active": true,
"title_ar": "\u0623\u0641\u0636\u0644 \u0627\u0644\u062e\u064a\u0648\u0637 \u0644\u0644\u0645\u0628\u062a\u062f\u0626\u064a\u0646",
"title_en": "Best Yarn for Beginners",
"updated_at": "2024-12-07T14:20:00Z"
}
]
Get blog details by ID. Returns complete blog information including title, description (HTML formatted), and image in both English and Arabic. Description fields contain HTML content from the rich text editor and should be rendered in your Flutter app using HtmlWidget or similar package. If blogs feature is disabled by admin, returns 404 error with message 'Blogs feature is disabled'.
Response Example
{
"created_at": "2024-12-08T10:30:00Z",
"description_ar": "\u003ch2\u003e\u0627\u0644\u0628\u062f\u0621\u003c/h2\u003e\u003cp\u003e\u062a\u0639\u0644\u0645 \u0623\u0633\u0627\u0633\u064a\u0627\u062a \u0627\u0644\u0643\u0631\u0648\u0634\u064a\u0647 \u0648\u0627\u0628\u062f\u0623 \u0631\u062d\u0644\u062a\u0643 \u0641\u064a \u0639\u0627\u0644\u0645 \u0627\u0644\u062d\u0631\u0641 \u0627\u0644\u064a\u062f\u0648\u064a\u0629 \u0627\u0644\u0631\u0627\u0626\u0639. \u064a\u063a\u0637\u064a \u0647\u0630\u0627 \u0627\u0644\u062f\u0644\u064a\u0644 \u0627\u0644\u0634\u0627\u0645\u0644 \u0643\u0644 \u0645\u0627 \u062a\u062d\u062a\u0627\u062c \u0644\u0645\u0639\u0631\u0641\u062a\u0647 \u0644\u0644\u0628\u062f\u0621.\u003c/p\u003e\u003ch3\u003e\u0645\u0627 \u0633\u062a\u062d\u062a\u0627\u062c\u0647\u003c/h3\u003e\u003cul\u003e\u003cli\u003e\u003cstrong\u003e\u0627\u0644\u062e\u064a\u0648\u0637:\u003c/strong\u003e \u0627\u062e\u062a\u0631 \u062e\u064a\u0648\u0637 \u0645\u062a\u0648\u0633\u0637\u0629 \u0627\u0644\u0648\u0632\u0646\u003c/li\u003e\u003cli\u003e\u003cstrong\u003e\u0627\u0644\u062e\u0637\u0627\u0641:\u003c/strong\u003e \u0645\u0642\u0627\u0633 5.0 \u0645\u0644\u0645 \u0645\u0648\u0635\u0649 \u0628\u0647\u003c/li\u003e\u003cli\u003e\u003cstrong\u003e\u0645\u0642\u0635:\u003c/strong\u003e \u0632\u0648\u062c \u062d\u0627\u062f \u0644\u0644\u0642\u0637\u0639\u003c/li\u003e\u003c/ul\u003e\u003cp\u003e\u0644\u0645\u0632\u064a\u062f \u0645\u0646 \u0627\u0644\u0645\u0639\u0644\u0648\u0645\u0627\u062a\u060c \u0632\u0631 \u003ca href=\u0027https://example.com\u0027\u003e\u0645\u0648\u0642\u0639\u0646\u0627\u003c/a\u003e.\u003c/p\u003e",
"description_en": "\u003ch2\u003eGetting Started\u003c/h2\u003e\u003cp\u003eLearn the basics of crochet and start your journey into the wonderful world of yarn crafts. This comprehensive guide covers everything you need to know to get started.\u003c/p\u003e\u003ch3\u003eWhat You\u0027ll Need\u003c/h3\u003e\u003cul\u003e\u003cli\u003e\u003cstrong\u003eYarn:\u003c/strong\u003e Choose a medium weight yarn\u003c/li\u003e\u003cli\u003e\u003cstrong\u003eHook:\u003c/strong\u003e Size 5.0mm recommended\u003c/li\u003e\u003cli\u003e\u003cstrong\u003eScissors:\u003c/strong\u003e Sharp pair for cutting\u003c/li\u003e\u003c/ul\u003e\u003cp\u003eFor more information, visit our \u003ca href=\u0027https://example.com\u0027\u003ewebsite\u003c/a\u003e.\u003c/p\u003e",
"id": 1,
"image": "https://wassel.delivery/static/uploads/blogs/blog_1_abc123.jpg",
"is_active": true,
"title_ar": "\u0645\u0642\u062f\u0645\u0629 \u0641\u064a \u0627\u0644\u0643\u0631\u0648\u0634\u064a\u0647",
"title_en": "Introduction to Crochet",
"updated_at": "2024-12-08T10:30:00Z"
}
Custom Pages
Custom content pages management endpoints for creating and managing custom pages
List all active custom pages. Returns pages ordered by order field and creation date.
Query Parameters
- skip (optional, default: 0)
- limit (optional, default: 100)
- is_active (optional, default: true, boolean)
Response Example
[
{
"created_at": "2024-12-09T10:30:00Z",
"description_ar": "\u062a\u0639\u0631\u0641 \u0639\u0644\u0649 \u0627\u0644\u0645\u0632\u064a\u062f \u062d\u0648\u0644 \u0634\u0631\u0643\u062a\u0646\u0627 \u0648\u0645\u0647\u0645\u062a\u0646\u0627...",
"description_en": "Learn more about our company and mission...",
"id": 1,
"image": "https://wassel.delivery/static/uploads/custom_pages/page_1_abc123.jpg",
"is_active": true,
"order": 0,
"slug": "about-us",
"title_ar": "\u0645\u0646 \u0646\u062d\u0646",
"title_en": "About Us",
"updated_at": "2024-12-09T10:30:00Z"
},
{
"created_at": "2024-12-09T11:00:00Z",
"description_ar": "\u0634\u0631\u0648\u0637 \u0648\u0623\u062d\u0643\u0627\u0645 \u062e\u062f\u0645\u062a\u0646\u0627...",
"description_en": "Our terms and conditions of service...",
"id": 2,
"image": null,
"is_active": true,
"order": 1,
"slug": "terms-and-conditions",
"title_ar": "\u0627\u0644\u0634\u0631\u0648\u0637 \u0648\u0627\u0644\u0623\u062d\u0643\u0627\u0645",
"title_en": "Terms and Conditions",
"updated_at": "2024-12-09T11:00:00Z"
}
]
Get custom page by slug (URL-friendly identifier). Returns complete page information including title, description, and image in both English and Arabic.
Response Example
{
"created_at": "2024-12-09T10:30:00Z",
"description_ar": "\u062a\u0639\u0631\u0641 \u0639\u0644\u0649 \u0627\u0644\u0645\u0632\u064a\u062f \u062d\u0648\u0644 \u0634\u0631\u0643\u062a\u0646\u0627 \u0648\u0645\u0647\u0645\u062a\u0646\u0627. \u0646\u062d\u0646 \u0645\u0644\u062a\u0632\u0645\u0648\u0646 \u0628\u062a\u0642\u062f\u064a\u0645 \u0645\u0646\u062a\u062c\u0627\u062a \u0648\u062e\u062f\u0645\u0627\u062a \u0639\u0627\u0644\u064a\u0629 \u0627\u0644\u062c\u0648\u062f\u0629.",
"description_en": "Learn more about our company and mission. We are dedicated to providing quality products and services.",
"id": 1,
"image": "https://wassel.delivery/static/uploads/custom_pages/page_1_abc123.jpg",
"is_active": true,
"order": 0,
"slug": "about-us",
"title_ar": "\u0645\u0646 \u0646\u062d\u0646",
"title_en": "About Us",
"updated_at": "2024-12-09T10:30:00Z"
}
Get custom page by ID. Returns complete page information including title, description, and image in both English and Arabic.
Response Example
{
"created_at": "2024-12-09T10:30:00Z",
"description_ar": "\u062a\u0639\u0631\u0641 \u0639\u0644\u0649 \u0627\u0644\u0645\u0632\u064a\u062f \u062d\u0648\u0644 \u0634\u0631\u0643\u062a\u0646\u0627 \u0648\u0645\u0647\u0645\u062a\u0646\u0627. \u0646\u062d\u0646 \u0645\u0644\u062a\u0632\u0645\u0648\u0646 \u0628\u062a\u0642\u062f\u064a\u0645 \u0645\u0646\u062a\u062c\u0627\u062a \u0648\u062e\u062f\u0645\u0627\u062a \u0639\u0627\u0644\u064a\u0629 \u0627\u0644\u062c\u0648\u062f\u0629.",
"description_en": "Learn more about our company and mission. We are dedicated to providing quality products and services.",
"id": 1,
"image": "https://wassel.delivery/static/uploads/custom_pages/page_1_abc123.jpg",
"is_active": true,
"order": 0,
"slug": "about-us",
"title_ar": "\u0645\u0646 \u0646\u062d\u0646",
"title_en": "About Us",
"updated_at": "2024-12-09T10:30:00Z"
}
Delivery API
Bahrain-only delivery: cities dropdown, user addresses, price estimate, create delivery, delivery history and status (pending, assigned, accepted, preparing, ready_for_pickup, picked_up, on_the_way, arrived, delivered, customer_not_available, delivery_failed, cancelled, returned).
List Bahrain delivery cities for address dropdown. Only Bahrain is supported. Use for city picker when saving address or creating delivery.
Query Parameters
- is_active (optional, default: true)
Response Example
[
{
"id": 1,
"is_active": true,
"latitude": 26.2285,
"longitude": 50.586,
"name_ar": "\u0627\u0644\u0645\u0646\u0627\u0645\u0629",
"name_en": "Manama",
"order": 0,
"slug": "manama"
},
{
"id": 2,
"is_active": true,
"latitude": 26.2572,
"longitude": 50.6119,
"name_ar": "\u0627\u0644\u0645\u062d\u0631\u0642",
"name_en": "Muharraq",
"order": 1,
"slug": "muharraq"
}
]
List current user's saved addresses. Only Bahrain addresses are valid for delivery. Requires Bearer token.
Response Example
[
{
"address_line1": "Block 123, Road 456",
"city": "Manama",
"country": "Bahrain",
"delivery_city_id": 1,
"id": 1,
"is_active": true,
"is_default": true,
"label": "Home",
"user_id": 1
}
]
Add a new address. Country must be Bahrain. delivery_city_id must be from /delivery/cities. Requires Bearer token.
Body Parameters
- address_line1
- city
- country (must be Bahrain)
- delivery_city_id (optional, from cities list)
- label
- full_name
- phone
- is_default
Response Example
{
"address_line1": "Block 123",
"city": "Manama",
"country": "Bahrain",
"delivery_city_id": 1,
"id": 1,
"user_id": 1
}
Update a saved address. Country must remain Bahrain. Requires Bearer token.
Body Parameters
- address_line1
- city
- country
- delivery_city_id
- label
- phone
- is_default
- is_active
Response Example
{
"address_line1": "Block 123",
"city": "Manama",
"country": "Bahrain",
"id": 1
}
Delete a saved address. Requires Bearer token.
Reverse geocode: convert lat/lng (e.g. user selected point on map) to human-readable address and delivery_city_id. Use response address_line and delivery_city_id when calling POST /delivery or POST /delivery/addresses. Uses OpenRouteService if API key set, else Nominatim (OSM).
Query Parameters
- lat (required)
- lng (required)
- delivery_city_id (optional hint)
Response Example
{
"address_line": "Block 123, Road 456, Manama",
"city": "Manama",
"delivery_city_id": 1
}
Get driving route between pickup and destination for drawing on map and showing ETA. Returns polyline (list of [lat, lng]), distance_km, duration_minutes (typical driving time; no live traffic). Requires OPENROUTE_API_KEY.
Query Parameters
- from_lat
- from_lng
- to_lat
- to_lng
Response Example
{
"distance_km": 8.5,
"duration_minutes": 18.0,
"polyline": [
[
26.2285,
50.586
],
[
26.2572,
50.6119
]
]
}
Get fixed price by delivery_type (normal | express). One price for all cities. Optional from_city_id, to_city_id for distance_km/duration_minutes.
Body Parameters
- delivery_type (string: normal | express)
- from_city_id (optional)
- to_city_id (optional)
Response Example
{
"delivery_type": "normal",
"distance_km": 8.5,
"duration_minutes": 18.0,
"price_bhd": 2.0
}
Create a delivery request (pickup + destination). Price is fixed per delivery_type (normal|express). Requires Bearer token.
Body Parameters
- pickup_address_line
- pickup_city_id
- pickup_phone (optional)
- pickup_lat/lng (optional)
- destination_address_line
- destination_city_id
- destination_phone (optional)
- destination_lat/lng (optional)
- notes (optional)
Response Example
{
"created_at": "2024-12-09T10:00:00Z",
"destination_address_line": "Road 456",
"destination_city_id": 2,
"distance_km": 10.2,
"duration_minutes": 22.0,
"id": 1,
"pickup_address_line": "Block 123",
"pickup_city_id": 1,
"price_bhd": 1.5,
"status": "pending",
"user_id": 1
}
List current user's delivery history. Optional status_filter: pending, assigned, accepted, preparing, ready_for_pickup, picked_up, on_the_way, arrived, delivered, customer_not_available, delivery_failed, cancelled, returned. Requires Bearer token.
Query Parameters
- status_filter (optional)
- skip (default: 0)
- limit (default: 50, max: 100)
Response Example
[
{
"created_at": "2024-12-09T10:00:00Z",
"destination_address_line": "Road 456",
"id": 1,
"pickup_address_line": "Block 123",
"price_bhd": 1.5,
"status": "pending"
}
]
Get a delivery by ID. User can only access their own deliveries. Requires Bearer token.
Response Example
{
"created_at": "2024-12-09T10:00:00Z",
"delivered_at": null,
"destination_address_line": "Road 456",
"distance_km": 10.2,
"duration_minutes": 22.0,
"id": 1,
"pickup_address_line": "Block 123",
"price_bhd": 1.5,
"status": "in_transit",
"user_id": 1
}
Notifications
Notifications management endpoints. Admins can create and manage notifications with titles and descriptions in English and Arabic. Notifications can be displayed to users in the mobile app. The system also automatically sends notifications for: order creation, order status changes, event reminders (1 day before), and course reminders (1 day before).
List all active notifications. Returns notifications ordered by order field, then by creation date. Use is_active query parameter to filter by active status.
Query Parameters
- skip (optional, default: 0)
- limit (optional, default: 100, max: 100)
- is_active (optional, default: true, boolean)
Response Example
[
{
"createdAt": "2024-12-10T10:00:00Z",
"descriptionAr": "\u062a\u062d\u0642\u0642 \u0645\u0646 \u0645\u064a\u0632\u0629 \u0627\u0644\u062f\u0648\u0631\u0627\u062a \u0627\u0644\u062c\u062f\u064a\u062f\u0629!",
"descriptionEn": "Check out our new courses feature!",
"id": 1,
"isActive": true,
"order": 0,
"titleAr": "\u0645\u064a\u0632\u0629 \u062c\u062f\u064a\u062f\u0629 \u0645\u062a\u0627\u062d\u0629",
"titleEn": "New Feature Available",
"updatedAt": "2024-12-10T10:00:00Z"
}
]
Get notification details by ID. Returns complete notification information including title and description in both languages.
Response Example
{
"createdAt": "2024-12-10T10:00:00Z",
"descriptionAr": "\u062a\u062d\u0642\u0642 \u0645\u0646 \u0645\u064a\u0632\u0629 \u0627\u0644\u062f\u0648\u0631\u0627\u062a \u0627\u0644\u062c\u062f\u064a\u062f\u0629!",
"descriptionEn": "Check out our new courses feature!",
"id": 1,
"isActive": true,
"isGlobal": true,
"order": 0,
"titleAr": "\u0645\u064a\u0632\u0629 \u062c\u062f\u064a\u062f\u0629 \u0645\u062a\u0627\u062d\u0629",
"titleEn": "New Feature Available",
"updatedAt": "2024-12-10T10:00:00Z"
}
Get all notifications for the current authenticated user. Returns both global notifications (sent to all users) and user-specific notifications (sent only to this user). Includes read status for user-specific notifications.
Query Parameters
- skip (optional, default: 0)
- limit (optional, default: 100, max: 100)
- is_read (optional, boolean - filter by read status)
- include_global (optional, default: true, boolean - include global notifications)
Response Example
[
{
"createdAt": "2024-12-10T10:00:00Z",
"descriptionAr": "\u062a\u062d\u0642\u0642 \u0645\u0646 \u0645\u064a\u0632\u0629 \u0627\u0644\u062f\u0648\u0631\u0627\u062a \u0627\u0644\u062c\u062f\u064a\u062f\u0629!",
"descriptionEn": "Check out our new courses feature!",
"id": 1,
"isActive": true,
"isGlobal": true,
"isRead": null,
"order": 0,
"readAt": null,
"titleAr": "\u0645\u064a\u0632\u0629 \u062c\u062f\u064a\u062f\u0629 \u0645\u062a\u0627\u062d\u0629",
"titleEn": "New Feature Available",
"updatedAt": "2024-12-10T10:00:00Z"
},
{
"createdAt": "2024-12-10T11:00:00Z",
"descriptionAr": "\u0644\u062f\u064a\u0643 \u0643\u0648\u062f \u062e\u0635\u0645 \u062e\u0627\u0635!",
"descriptionEn": "You have a special discount code!",
"id": 2,
"isActive": true,
"isGlobal": false,
"isRead": false,
"order": 1,
"readAt": null,
"titleAr": "\u0639\u0631\u0636 \u062e\u0627\u0635 \u0644\u0643",
"titleEn": "Special Offer for You",
"updatedAt": "2024-12-10T11:00:00Z",
"userNotificationId": 123
}
]
Mark a user-specific notification as read. Only works for user-specific notifications (not global notifications).
Response Example
{
"is_read": true,
"message": "Notification marked as read",
"notification_id": 2,
"success": true
}
Get count of unread notifications for the current user. Useful for displaying notification badges.
Response Example
{
"unread_count": 5
}
Mark all unread notifications as read for the current user.
Response Example
{
"count": 5,
"message": "5 notifications marked as read",
"success": true
}
Delete a specific user notification. Only the user who owns the notification can delete it. Use the userNotificationId from the /my-notifications response.
Response Example
{
"message": "Notification deleted successfully",
"success": true,
"user_notification_id": 123
}
Delete all read notifications for the current user. Useful for clearing old notifications.
Response Example
{
"count": 10,
"message": "10 read notifications deleted",
"success": true
}
Chat API
Real-time chat between users and shop owners using Pusher. All messages are stored in the database. Users can start conversations with shop owners, send text messages, upload media (images, videos, audio, files), record voice messages, and receive real-time updates via Pusher. Shop owners can manage conversations through the Shop Owner API. Supported media types: images (.jpg, .png, .gif, .webp), videos (.mp4, .avi, .mov, .webm), audio files (.mp3, .wav, .ogg, .m4a, .aac), voice recordings (.webm), and documents (.pdf, .doc, .docx). Max file size: 50MB.
Create a new chat conversation with a shop owner. If a conversation already exists with this store, returns the existing one. Optionally include an initial message.
Body Parameters
- store_id (required, string)
- initial_message (optional, string)
Response Example
{
"conversation_type": "user",
"created_at": "2024-12-12T10:30:00Z",
"id": 1,
"is_active": true,
"last_message": {
"conversation_id": 1,
"created_at": "2024-12-12T10:30:00Z",
"file_name": null,
"id": 1,
"is_read": false,
"media_url": null,
"message": "Hello, I have a question about your products",
"message_type": "text",
"sender_id": 10,
"sender_name": "John Doe"
},
"last_message_at": "2024-12-12T10:30:00Z",
"shop_owner_avatar": "https://wassel.delivery/static/uploads/users/user_5_def456.jpg",
"shop_owner_id": 5,
"shop_owner_name": "Shop Owner Name",
"store_id": "store_a1b2c3d4e5f6g7h8",
"unread_count": 0,
"updated_at": "2024-12-12T10:30:00Z",
"user_avatar": "https://wassel.delivery/static/uploads/users/user_10_abc123.jpg",
"user_id": 10,
"user_name": "John Doe"
}
conversation_type indicates the role of the current user in this conversation: 'shop' if the current user is the shop owner (chatting with customers), 'user' if the current user is the customer (chatting with a shop). This field helps filter conversations in the app - shop owners can separate their store conversations from their customer conversations.
List all chat conversations for the current user. Shop owners see conversations for their store (as shop_owner) AND conversations where they are the user (as customer). Each conversation includes a 'conversation_type' field ('shop' or 'user') to help filter conversations in the app.
Query Parameters
- skip (optional, int, default: 0)
- limit (optional, int, default: 100)
Response Example
[
{
"conversation_type": "user",
"created_at": "2024-12-12T10:30:00Z",
"id": 1,
"is_active": true,
"last_message": {
"conversation_id": 1,
"created_at": "2024-12-12T10:30:00Z",
"file_name": null,
"id": 1,
"is_read": true,
"media_url": null,
"message": "Hello, I have a question",
"message_type": "text",
"sender_id": 10,
"sender_name": "John Doe"
},
"last_message_at": "2024-12-12T10:30:00Z",
"shop_owner_avatar": "https://wassel.delivery/static/uploads/users/user_5_def456.jpg",
"shop_owner_id": 5,
"shop_owner_name": "Shop Owner Name",
"store_id": "store_a1b2c3d4e5f6g7h8",
"unread_count": 0,
"updated_at": "2024-12-12T10:30:00Z",
"user_avatar": "https://wassel.delivery/static/uploads/users/user_10_abc123.jpg",
"user_id": 10,
"user_name": "John Doe"
},
{
"conversation_type": "shop",
"created_at": "2024-12-12T09:00:00Z",
"id": 2,
"is_active": true,
"last_message": {
"conversation_id": 2,
"created_at": "2024-12-12T11:00:00Z",
"file_name": null,
"id": 5,
"is_read": false,
"media_url": null,
"message": "When will my order arrive?",
"message_type": "text",
"sender_id": 15,
"sender_name": "Jane Smith"
},
"last_message_at": "2024-12-12T11:00:00Z",
"shop_owner_avatar": "https://wassel.delivery/static/uploads/users/user_10_abc123.jpg",
"shop_owner_id": 10,
"shop_owner_name": "Current User (Shop Owner)",
"store_id": "store_current_user_store",
"unread_count": 1,
"updated_at": "2024-12-12T11:00:00Z",
"user_avatar": "https://wassel.delivery/static/uploads/users/user_15_xyz789.jpg",
"user_id": 15,
"user_name": "Jane Smith"
}
]
conversation_type field: 'shop' = current user is the shop owner (chatting with customers), 'user' = current user is the customer (chatting with a shop). Shop owners who also use the app as customers will see both types. Filter conversations by conversation_type to separate 'My Store' chats from 'My Customer' chats in the app UI.
Get a specific conversation. User can only access their own conversations. Shop owners can access conversations for their store (as shop_owner) AND conversations where they are the user (as customer). Response includes conversation_type field ('shop' or 'user') to help filter conversations.
Response Example
{
"conversation_type": "user",
"created_at": "2024-12-12T10:30:00Z",
"id": 1,
"is_active": true,
"last_message": {
"conversation_id": 1,
"created_at": "2024-12-12T10:30:00Z",
"file_name": null,
"id": 1,
"is_read": true,
"media_url": null,
"message": "Hello, I have a question",
"message_type": "text",
"sender_id": 10,
"sender_name": "John Doe"
},
"last_message_at": "2024-12-12T10:30:00Z",
"shop_owner_avatar": "https://wassel.delivery/static/uploads/users/user_5_def456.jpg",
"shop_owner_id": 5,
"shop_owner_name": "Shop Owner Name",
"store_id": "store_a1b2c3d4e5f6g7h8",
"unread_count": 0,
"updated_at": "2024-12-12T10:30:00Z",
"user_avatar": "https://wassel.delivery/static/uploads/users/user_10_abc123.jpg",
"user_id": 10,
"user_name": "John Doe"
}
Get messages for a conversation. Messages are automatically marked as read when fetched. User can only access their own conversations.
Query Parameters
- skip (optional, int, default: 0)
- limit (optional, int, default: 100)
Response Example
[
{
"conversation_id": 1,
"created_at": "2024-12-12T10:30:00Z",
"file_name": null,
"id": 1,
"is_read": true,
"media_url": null,
"message": "Hello, I have a question",
"message_type": "text",
"read_at": "2024-12-12T10:31:00Z",
"sender_avatar": "https://wassel.delivery/static/uploads/users/user_10_abc123.jpg",
"sender_id": 10,
"sender_name": "John Doe"
},
{
"conversation_id": 1,
"created_at": "2024-12-12T10:32:00Z",
"file_name": "product.jpg",
"id": 2,
"is_read": false,
"media_url": "https://wassel.delivery/static/uploads/chat/chat_2_abc123.jpg",
"message": "Check this out!",
"message_type": "image",
"read_at": null,
"sender_avatar": "https://wassel.delivery/static/uploads/users/user_10_abc123.jpg",
"sender_id": 10,
"sender_name": "John Doe"
},
{
"conversation_id": 1,
"created_at": "2024-12-12T10:33:00Z",
"file_name": "voice_1234567890.webm",
"id": 3,
"is_read": false,
"media_url": "https://wassel.delivery/static/uploads/chat/chat_3_xyz789.webm",
"message": null,
"message_type": "audio",
"read_at": null,
"sender_avatar": "https://wassel.delivery/static/uploads/users/user_5_def456.jpg",
"sender_id": 5,
"sender_name": "Shop Owner"
}
]
Send a message in a conversation. Supports text messages, media uploads (images, videos, audio, files), and voice recordings. Message is broadcasted via Pusher in real-time. User can only send messages in their own conversations. Either 'message' (text) or 'file' (media) is required. Both can be sent together (text with media).
Response Example
{
"conversation_id": 1,
"created_at": "2024-12-12T10:35:00Z",
"file_name": "product_image.jpg",
"file_size": 245760,
"id": 2,
"is_read": false,
"media_url": "https://wassel.delivery/static/uploads/chat/chat_2_abc123def.jpg",
"message": "Check out this image!",
"message_type": "image",
"read_at": null,
"sender_avatar": "https://wassel.delivery/static/uploads/users/user_10_abc123.jpg",
"sender_id": 10,
"sender_name": "John Doe"
}
Authenticate Pusher private channel subscription. This endpoint is called automatically by Pusher when subscribing to private channels. Channel format: private-chat-{conversation_id}
Body Parameters
- socket_id (required, string)
- channel_name (required, string)
Response Example
{
"auth": "e18960692a059cc4fafb:abc123def456..."
}
Live Support System
Real-time support chat between users and admin support team using Pusher. Users can create support tickets, send messages with media attachments, and receive real-time responses from admins. Supports conversation status tracking (open, in_progress, resolved, closed), priority levels (low, normal, high, urgent), and unread message counts. All messages are stored in the database. Supported media types: images (.jpg, .png, .gif, .webp), videos (.mp4, .avi, .mov, .webm), audio files (.mp3, .wav, .ogg, .m4a, .aac), and documents (.pdf, .doc, .docx). Max file size: 50MB.
Create a new support conversation. Users can only have one open conversation at a time. If an open conversation exists, returns an error. Optionally include a subject and initial message.
Body Parameters
- subject (optional, string, max 255 characters) - Conversation subject/title
- initial_message (optional, string, max 5000 characters) - Initial message
- priority (optional, string, default: 'normal') - Priority level: 'low', 'normal', 'high', 'urgent'
Response Example
{
"admin_avatar": null,
"admin_id": null,
"admin_name": null,
"created_at": "2024-12-25T10:00:00Z",
"id": 1,
"is_active": true,
"last_message": null,
"last_message_at": null,
"message_count": 0,
"priority": "normal",
"status": "open",
"subject": "Order issue",
"unread_count": 0,
"updated_at": "2024-12-25T10:00:00Z",
"user_avatar": "https://...",
"user_id": 123,
"user_name": "John Doe"
}
List all support conversations for the current user. Returns conversations sorted by last message time (most recent first).
Query Parameters
- skip (optional, int, default: 0)
- limit (optional, int, default: 50)
Response Example
[
{
"admin_avatar": "https://...",
"admin_id": 5,
"admin_name": "Support Admin",
"created_at": "2024-12-25T10:00:00Z",
"id": 1,
"is_active": true,
"last_message": {
"conversation_id": 1,
"created_at": "2024-12-25T10:30:00Z",
"id": 10,
"message": "We\u0027re looking into your issue...",
"message_type": "text",
"sender_id": 5,
"sender_name": "Support Admin",
"sender_type": "admin"
},
"last_message_at": "2024-12-25T10:30:00Z",
"message_count": 10,
"priority": "normal",
"status": "in_progress",
"subject": "Order issue",
"unread_count": 2,
"updated_at": "2024-12-25T10:30:00Z",
"user_avatar": "https://...",
"user_id": 123,
"user_name": "John Doe"
}
]
Get details of a specific support conversation. User can only access their own conversations.
Response Example
{
"admin_avatar": "https://...",
"admin_id": 5,
"admin_name": "Support Admin",
"created_at": "2024-12-25T10:00:00Z",
"id": 1,
"is_active": true,
"last_message": {
"conversation_id": 1,
"created_at": "2024-12-25T10:30:00Z",
"id": 10,
"message": "We\u0027re looking into your issue",
"message_type": "text",
"sender_id": 5,
"sender_name": "Support Admin",
"sender_type": "admin"
},
"last_message_at": "2024-12-25T10:30:00Z",
"message_count": 10,
"priority": "normal",
"status": "in_progress",
"subject": "Order issue",
"unread_count": 2,
"updated_at": "2024-12-25T10:30:00Z",
"user_avatar": "https://...",
"user_id": 123,
"user_name": "John Doe"
}
Get messages for a support conversation. Messages are returned in chronological order (oldest first). Admin messages are automatically marked as read when fetched. User can only access their own conversations.
Query Parameters
- skip (optional, int, default: 0)
- limit (optional, int, default: 100)
Response Example
[
{
"conversation_id": 1,
"created_at": "2024-12-25T10:00:00Z",
"file_name": null,
"file_size": null,
"id": 1,
"is_read": true,
"media_url": null,
"message": "I need help with my order",
"message_type": "text",
"read_at": "2024-12-25T10:05:00Z",
"sender_avatar": "https://...",
"sender_id": 123,
"sender_name": "John Doe",
"sender_type": "user"
},
{
"conversation_id": 1,
"created_at": "2024-12-25T10:05:00Z",
"file_name": null,
"file_size": null,
"id": 2,
"is_read": true,
"media_url": null,
"message": "We\u0027re looking into your issue",
"message_type": "text",
"read_at": "2024-12-25T10:05:00Z",
"sender_avatar": "https://...",
"sender_id": 5,
"sender_name": "Support Admin",
"sender_type": "admin"
}
]
Send a message in a support conversation. Supports text messages and media uploads (images, videos, audio, files). Message is broadcasted via Pusher in real-time. Either 'message' (text) or 'file' (media) is required. Both can be sent together (text with media).
Response Example
{
"conversation_id": 1,
"created_at": "2024-12-25T10:40:00Z",
"file_name": "screenshot.jpg",
"file_size": 245678,
"id": 10,
"is_read": false,
"media_url": "https://...",
"message": "Here\u0027s a screenshot of the issue",
"message_type": "image",
"read_at": null,
"sender_avatar": "https://...",
"sender_id": 123,
"sender_name": "John Doe",
"sender_type": "user"
}
List all support conversations (admin view). Can filter by status and priority. Returns conversations sorted by last message time (most recent first).
Query Parameters
- status_filter (optional, string) - Filter by status: 'open', 'in_progress', 'resolved', 'closed'
- priority_filter (optional, string) - Filter by priority: 'low', 'normal', 'high', 'urgent'
- skip (optional, int, default: 0)
- limit (optional, int, default: 50)
Response Example
"Array of SupportConversationResponse objects with user and admin information"
Get a specific support conversation (admin view). Conversation is automatically assigned to the current admin if unassigned, and status is set to 'in_progress'.
Response Example
"SupportConversationResponse object with full conversation details"
Update a support conversation (status, priority, assignment). Admins can change conversation status, priority, assign to another admin, or update the subject.
Body Parameters
- status (optional, string) - Status: 'open', 'in_progress', 'resolved', 'closed'
- priority (optional, string) - Priority: 'low', 'normal', 'high', 'urgent'
- admin_id (optional, int) - Assign conversation to specific admin
- subject (optional, string, max 255 characters) - Update conversation subject
Response Example
"SupportConversationResponse object with updated conversation details"
Get messages for a support conversation (admin view). User messages are automatically marked as read when fetched.
Query Parameters
- skip (optional, int, default: 0)
- limit (optional, int, default: 100)
Response Example
"Array of SupportMessageResponse objects"
Send a message in a support conversation (admin). Supports text messages and media uploads. Message is broadcasted via Pusher in real-time. Conversation is automatically assigned to current admin if unassigned.
Response Example
{
"conversation_id": 1,
"created_at": "2024-12-25T10:45:00Z",
"file_name": null,
"file_size": null,
"id": 11,
"is_read": false,
"media_url": null,
"message": "We\u0027ve resolved your issue",
"message_type": "text",
"read_at": null,
"sender_avatar": "https://...",
"sender_id": 5,
"sender_name": "Support Admin",
"sender_type": "admin"
}
Authenticate Pusher private channel subscription for support chat. This endpoint is called automatically by Pusher when subscribing to private channels. Channel format: private-support-{conversation_id}. Supports both user tokens (Bearer) and admin cookies.
Response Example
{
"auth": "e18960692a059cc4fafb:abc123def456..."
}