API Consumption¶
HTTP client¶
Plain fetch (no axios, no ky). All requests funnel through a single request(...) function in src/services/api.ts (184 lines total).
const request = async (
url: string,
method: string,
body?: any,
contentType = "application/json",
params?: Record<string, string>,
customHeaders: Record<string, string> = {}
) => { ... };
Convenience methods on the exported api object: api.get, api.post, api.put, api.delete, plus ~25 named methods that wrap specific endpoints.
Base URL¶
ENV.API_URL (typed accessor in src/config/env.ts, reads import.meta.env.VITE_API_URL). Set at Vite build time via .env or .env.development / .env.production.
Headers¶
createAuthHeaders() always sets:
Apptype: <base64 of "admin-console">— hardcoded string (verify by readingcreateAuthHeaders). This means theApptypeheader doesn't actually useENV.APP_TYPE. Bug — see security.md.Content-Type: <as requested>(unless multipart/form-data — browser handles boundary)Token: <localStorage.auth_token>if token present
Notably, the FE sends Token: <encrypted> while AuthContext.tsx's checkAuth() uses Authorization: Bearer <token> to call /me. Two header conventions in the same FE for the same token. Inconsistency.
Token refresh¶
There is no token refresh. The encrypted token has no expiry encoded inside it (per Someli-admin-api/authentication.md), so refresh isn't really meaningful — the token works until it's manually revoked server-side.
What happens on a 401:
handleResponse()readsresponse.ok === false- Builds an error message from the response body's
.message(or status text) - Throws an
Error request()catches, shows a toast"Error", re-throws- The component's
try/catch(if any) handles it
There's no global 401 handler that forces logout. A user with a revoked token will see a toast on every action and have to manually log out + log in. Add a 401 → logout() handler in request().
Error handling¶
catch (error) {
console.error(`API ${method} request failed:`, error);
if (error instanceof Error) {
toast({ title: "Error", description: error.message, variant: "destructive" });
}
throw error;
}
A toast({title: "Error", ...}) is shown on every failed request. Components must not also toast (some do — see routing-and-state.md).
Retries¶
None. A network blip yields a single failure. No exponential backoff. For an internal tool, acceptable.
Request cancellation¶
None. Components do not pass AbortController to fetch. A user navigating away mid-request triggers a setState-on-unmounted-component warning if the response arrives after unmount.
Named methods (sample from api.ts)¶
| Method | Endpoint | Method |
|---|---|---|
getAllOwnerList |
/auth/getAllOwnerList?page=...&plan=...&role=...&status=... |
GET |
getAllAccountMembers |
/getAlltAccountMembers/:managerId/:page/:searchQuery |
GET |
addAccountManager |
/NewAccManager |
POST |
addOrUpdateAccountManagerMembers |
/addOrUpdateAccountManagersMembers |
POST |
getAccountManagersUserList |
/auth/AccountManagersaccountlist/:page/:type |
GET |
searchAccountManagers |
/searchAccountManagers |
POST |
searchUser |
/auth/searchAccountUser |
POST |
getUserDetail |
/getUserdetail:userId |
GET |
updateProfile |
/updateProfile |
POST |
uploadLogo |
/uploadLogo |
POST (multipart/form-data) |
uploadCompanyLogo |
/uploadCompanyLogo |
POST (multipart/form-data) |
getCountries |
/getCountries |
GET |
getStates |
/getStates |
GET |
getCities |
/getCities:countryId |
GET (note the : not /:) |
Path style mirrors the backend's inconsistency — some use /word/:param, some use /word:param (e.g., /getCities${countryId} produces a URL like /getCities5). See Someli-admin-api/API-inventory.md for the BE side.
Endpoints used (partial inventory)¶
The FE exercises endpoints in both routes/auth.js (/auth/...) and routes/routes.js (root-mounted) of Someli-admin-api. The complete cross-reference would require enumerating every call site in src/pages/*.tsx and comparing to Someli-admin-api/API-inventory.md. From src/services/api.ts alone, the FE calls at least:
- 7 endpoints from
routes/auth.js:getAllOwnerList,searchAccountUser,AccountManagersaccountlist - 18 endpoints from
routes/routes.js: account management, personnel, language models, geo, profile, affiliate, file upload (/uploadLogo,/uploadCompanyLogo— note: these don't appear in the BEAPI-inventory.md; drift between FE and BE inventories — see verify-markers.md)
Response shape handling¶
Most named methods return the raw envelope ({ status, data, code, message }) to the caller, who then reads .data. No automatic unwrap. Components do const result = await api.getX(); if (result.status) { setData(result.data); }.
Some methods are typed (request(url, "GET") as Promise<T>) where T is the envelope or the data — not consistent.
Recommendations¶
- Fix the hardcoded
Apptype— read fromENV.APP_TYPE. - Standardise on one header name for the token (
TokenvsAuthorization: Bearer). - Add a 401 handler in
request()that callslogout(). - Add
AbortControllerfor cancellable requests; use React Query's automatic cancellation for new code. - Add typed envelopes:
type ApiEnvelope<T> = { status: boolean; data: T; code: number; message: string }, returnPromise<ApiEnvelope<T>>consistently. - Reconcile FE-called endpoints vs BE-documented endpoints —
/uploadLogo,/uploadCompanyLogoaren't in the BE inventory.