Skip to content

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 reading createAuthHeaders). This means the Apptype header doesn't actually use ENV.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:

  1. handleResponse() reads response.ok === false
  2. Builds an error message from the response body's .message (or status text)
  3. Throws an Error
  4. request() catches, shows a toast "Error", re-throws
  5. 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 BE API-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

  1. Fix the hardcoded Apptype — read from ENV.APP_TYPE.
  2. Standardise on one header name for the token (Token vs Authorization: Bearer).
  3. Add a 401 handler in request() that calls logout().
  4. Add AbortController for cancellable requests; use React Query's automatic cancellation for new code.
  5. Add typed envelopes: type ApiEnvelope<T> = { status: boolean; data: T; code: number; message: string }, return Promise<ApiEnvelope<T>> consistently.
  6. Reconcile FE-called endpoints vs BE-documented endpoints/uploadLogo, /uploadCompanyLogo aren't in the BE inventory.