API Layer
Dual Axios Instances
The app communicates with two backend APIs via two axios instances defined in src/lib/axios.ts:
apiV1 — Legacy API
export const apiV1 = createAxiosInstance(`${env.EXPO_PUBLIC_API_V1_URL}`, false);- Base URL:
EXPO_PUBLIC_API_V1_URL(e.g.,https://staging.api.uk.housr.com/api/) - Content-Type:
application/x-www-form-urlencoded(default) - Auth: Plain JWT in
Authorizationheader (no “Bearer” prefix) - Token in body: On POST/PATCH/PUT requests, the JWT is also injected as a
jwtfield in the request body (FormData or object) - Endpoints: PHP-based (e.g.,
user.php,viewings.php,getHouse.php,roomie/getProfiles.php)
apiV2 — Current API
export const apiV2 = createAxiosInstance(`${env.EXPO_PUBLIC_API_V2_URL}`, true);- Base URL:
EXPO_PUBLIC_API_V2_URL(e.g.,https://v2.staging.api.uk.housr.com/) - Content-Type:
application/x-www-form-urlencoded(default), but PATCH requests automatically switch toapplication/json - Auth:
Bearer <token>in Authorization header - Token in body: JWT also injected in body for POST/PATCH/PUT (same as v1)
- Endpoints: RESTful paths (e.g.,
properties/v1/houses,events,perks,rideshare/)
Shared Behavior
Both instances share:
- Timeout: 30 seconds
- Request interceptor: Automatically retrieves the JWT from secure storage and attaches it to every request
Token Storage
JWT tokens are stored in expo-secure-store via src/lib/token-storage.ts:
getToken() // Retrieves JWT from secure storage
setToken() // Saves JWT to secure storage
deleteToken() // Removes JWT (used on sign-out)The key name is jwt_token.
API Function Pattern
Raw API functions live in src/features/<feature>/api/. They call the appropriate axios instance and return typed data:
// src/features/explore/api/list-houses.ts
import { apiV2 } from '@/lib/axios';
import type { ListHousesParams, ListHousesResponse } from '../types';
export const listHouses = async (params: ListHousesParams): Promise<ListHousesResponse> => {
const queryParams: Record<string, any> = {};
// ... build query params from filters
const response = await apiV2.get<ListHousesResponse>('properties/v1/houses', {
params: queryParams,
});
return response.data;
};// src/features/explore/api/get-house.ts
import { apiV1 } from '@/lib/axios';
export const getHouse = async (houseId: string | number): Promise<House> => {
const response = await apiV1.post<GetHouseResponse>('getHouse.php', { house_id: houseId });
// ...
};Which API to Use
| Feature | API | Notes |
|---|---|---|
| House listings | v2 | properties/v1/houses |
| House detail | v1 | getHouse.php |
| Viewings | v1 | viewings.php, requestViewing.php |
| Events | v2 | events, events/applications, events/tickets |
| Perks | v2 | perks, perks/search, perks/tokens |
| Rideshare | v2 | rideshare/ namespace |
| Roomie profiles | v1 | roomie/getProfiles.php |
| Auth (login) | v1 | appleSignin.php, googleSignin.php |
| User | v1 | user.php |
| Feature flags | v1 | featureFlags.php |
| Cities | v2 | properties/cities |
| Screens (server-driven UI) | v2 | screens/<screen> |
Regional API URLs
Set via EAS build profiles in eas.json:
| Profile | v1 URL | v2 URL |
|---|---|---|
| uk-staging | https://staging.api.uk.housr.com/api/ | https://v2.staging.api.uk.housr.com/ |
| us-staging | https://staging.api.us.housr.com/api/ | https://v2.staging.api.us.housr.com/ |
| uk-production | https://api.uk.housr.com/api/ | https://v2.temp-prod.api.uk.housr.com/ |
| us-production | https://api.us.housr.com/api/ | https://v2.api.us.housr.com/ |
| demo | https://demo.api.us.housr.com/api/ | https://v2.demo.api.us.housr.com/ |
Last updated on