Frontend API Adapter Documentation¶
This document describes the modifications made to the frontend API service to work with the new Medusa v2 backend.
Overview¶
The frontend API service (frontend/store/src/services/api.js) has been updated to communicate with the Medusa v2 backend instead of the previous Supabase-based backend. The changes include:
- Updated API base URL
- Updated endpoint paths for custom modules
- Updated response data extraction for new API formats
- Added new store API functions for custom modules
Changes Made¶
1. API Base URL¶
Before:
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || (isLocalhost ? 'http://localhost:8000/api' : 'https://api.azhar.store/api');
After:
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || (isLocalhost ? 'http://localhost:9000/store' : 'https://api.azhar.store/store');
Rationale: Medusa v2 serves the store API at /store prefix on port 9000 by default.
2. Store API Endpoints for Custom Modules¶
Added new store API functions for the custom modules:
// Store API endpoints for custom modules
export const getTranslations = () => api.get('/translations').then(res => res.data);
export const getSettings = () => api.get('/settings').then(res => res.data);
export const getAdvertisements = () => api.get('/advertisements').then(res => res.data.advertisements);
Response Formats:
-
Translations: Returns i18next-compatible bundle directly
-
Settings: Returns typed settings object
-
Advertisements: Returns object with advertisements array
3. Admin API Endpoints for Custom Modules¶
Updated admin API functions to use the correct request format:
// Admin API endpoints for custom modules (require admin authentication)
export const updateTranslation = ({ id, value }) => api.patch(`/admin/translations/${id}`, { value });
export const createTranslation = (data) => api.post('/admin/translations', data);
export const updateAppSettings = (data) => api.patch('/admin/settings', { settings: data });
Request Formats:
- Update Settings: Requires settings wrapped in object
4. Order Creation¶
Updated order creation to extract the order from the response:
Response Format:
5. Updated apiService Methods¶
Updated the duplicate methods in apiService object to match the new API:
getAppSettings: () => api.get('/settings').then(res => res.data),
updateAppSettings: (data) => api.patch('/admin/settings', { settings: data }),
getTranslations: () => api.get('/translations').then(res => res.data),
getAdvertisements: () => api.get('/advertisements').then(res => res.data.advertisements),
API Endpoints Reference¶
Store Endpoints (Public)¶
| Endpoint | Method | Description | Response |
|---|---|---|---|
/store/translations |
GET | Get all translations as i18next bundle | Translation bundle |
/store/settings |
GET | Get application settings | Settings object |
/store/advertisements |
GET | Get active advertisements | { advertisements: [...] } |
/store/orders |
POST | Create order via workflow | { order: {...} } |
Admin Endpoints (Authenticated)¶
| Endpoint | Method | Description | Request Body |
|---|---|---|---|
/admin/translations |
GET | List all translations | - |
/admin/translations |
POST | Create translation | { language_code, key, value, section } |
/admin/translations/:id |
PATCH | Update translation | { language_code, key, value, section } |
/admin/translations/:id |
DELETE | Delete translation | - |
/admin/settings |
GET | Get all settings | - |
/admin/settings |
PATCH | Bulk update settings | { settings: {...} } |
/admin/advertisements |
GET | List all advertisements | - |
/admin/advertisements |
POST | Create advertisement | { title, image_url, link_url, location, display_order, is_active } |
/admin/advertisements/:id |
PATCH | Update advertisement | { title, image_url, link_url, location, display_order, is_active } |
/admin/advertisements/:id |
DELETE | Delete advertisement | - |
Authentication¶
The API adapter uses JWT token authentication via the Authorization header:
api.interceptors.request.use(
(config) => {
const token = localStorage.getItem('token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
},
(error) => Promise.reject(error)
);
Note: For admin endpoints, Medusa uses cookie-based authentication by default. The frontend may need to be updated to use cookie authentication for admin operations, or the backend may need to be configured to accept JWT tokens for admin endpoints.
Error Handling¶
The API adapter includes automatic 401 handling:
api.interceptors.response.use(
(response) => response,
(error) => {
if (error.response?.status === 401) {
localStorage.removeItem('token');
window.location.href = '/login';
}
return Promise.reject(error);
}
);
Environment Variables¶
The API base URL can be overridden using the VITE_API_BASE_URL environment variable:
Or for production:
Usage Examples¶
Fetching Translations¶
import { getTranslations } from './services/api';
const translations = await getTranslations();
// Returns: { ar: { common: { welcome: "مرحبا" } } }
Fetching Settings¶
import { getSettings } from './services/api';
const settings = await getSettings();
// Returns: { free_delivery_threshold: 1000, pickup_message: "...", ceo_whatsapp: "..." }
Fetching Advertisements¶
import { getAdvertisements } from './services/api';
const ads = await getAdvertisements();
// Returns: [{ id: "adv_001", title: "Summer Sale", image_url: "...", ... }]
Creating an Order¶
import { apiService } from './services/api';
const order = await apiService.createOrder({
items: [
{ product_id: "prod_001", quantity: 2 }
],
shipping_address: {
first_name: "John",
last_name: "Doe",
address_1: "123 Main St",
city: "Manama",
country_code: "BH"
},
shipping_method: "standard"
});
// Returns: { id: "order_001", status: "pending", ... }
Updating Settings (Admin)¶
import { updateAppSettings } from './services/api';
await updateAppSettings({
free_delivery_threshold: 1500,
pickup_message: "Updated message"
});
Migration Notes¶
Breaking Changes¶
- Base URL Changed: From
localhost:8000/apitolocalhost:9000/store - Response Format Changes: Some endpoints now return wrapped responses (e.g.,
{ advertisements: [...] }instead of direct array) - Settings Update Format: Settings updates now require
{ settings: {...} }wrapper
Compatibility¶
The following endpoints remain unchanged and should work without modification:
- Products endpoints (if using Medusa's product module)
- Categories endpoints (if using Medusa's product category module)
- Customers endpoints (if using Medusa's customer module)
Testing Checklist¶
After updating the frontend, verify:
- [ ] Store loads without errors
- [ ] Advertisements display on homepage
- [ ] Settings are applied (delivery threshold, pickup message)
- [ ] Translations load correctly
- [ ] Order creation works
- [ ] Admin pages load (if using admin UI)
- [ ] Admin CRUD operations work for custom modules
Troubleshooting¶
404 Errors on API Calls¶
Problem: API calls return 404 Not Found
Solution: 1. Verify the backend is running on port 9000 2. Check the API base URL in environment variables 3. Verify the endpoint path matches the Medusa route
CORS Errors¶
Problem: Browser shows CORS errors
Solution:
1. Verify CORS is configured in medusa-config.ts
2. Ensure the store URL is in the CORS allowed origins
3. Check that the backend is running with CORS enabled
Authentication Errors¶
Problem: 401 Unauthorized on admin endpoints
Solution: 1. Verify admin is logged in 2. Check that authentication cookies are being sent 3. Consider updating to use cookie-based authentication for admin endpoints
Response Format Mismatches¶
Problem: Frontend code expects different response format
Solution: 1. Check the actual response format in browser dev tools 2. Update the API service to extract the correct data 3. Refer to the API documentation for expected formats
Future Enhancements¶
Potential improvements to the API adapter:
- TypeScript Migration: Convert to TypeScript for better type safety
- API Client Generation: Generate API client from OpenAPI/Swagger spec
- Retry Logic: Add automatic retry for failed requests
- Request Caching: Add caching for GET requests
- Request Cancelation: Add ability to cancel pending requests
- Error Boundaries: Add better error handling and user feedback
- Loading States: Add built-in loading state management