RNJet LogoRNJet
Guides

API Layer

How the Axios-based API layer works in RNJet.

API Layer

RNJet's API layer lives in src/api/ and provides typed wrappers around Axios with built-in logging, retry, and token handling.


File Structure

src/api/
├── client.ts             # Axios instance (with auth token)
├── clientWithoutToken.ts # Axios instance (public endpoints)
├── apiWrapping.ts        # Request/response wrapping and interceptors
├── apiUtils.ts           # logApi + curl generator
├── apiType.d.ts          # Shared types (ApiProps, ApiError, etc.)
└── index.ts              # Export definition

Two Clients

ClientUse for
clientAuthenticated requests — auto-attaches Authorization: Bearer <token>
clientWithoutTokenPublic requests — login, register, etc.

To attach a token, update the request interceptor in client.ts:

// src/api/client.ts
client.interceptors.request.use(async (config) => {
	const token = await handlerGetItem(Keys.userToken); // from MMKV
	if (token) {
		config.headers.Authorization = "Bearer " + token;
	}
	return config;
});

ApiProps

All API functions accept a single ApiProps object:

PropTypeDescription
urlstringEndpoint path (no base URL needed)
bodyanyRequest body (POST only)
tagsstringLabel for logs — omit to silence logging
retrynumberAuto-retry count on failure
headersanyExtra request headers
configAxiosRequestConfigAdditional Axios config
fullResponsebooleanReturn full Axios response instead of data
resHeadersbooleanReturn response headers instead of data

Making API Calls

GET (authenticated):

import { apiGet } from "@/api";
import { URL_PATH } from "@/constants/url";

const data = await apiGet<UserProfile>({ url: URL_PATH.user.profile });

GET (public):

const data = await apiGetWithoutToken({ url: URL_PATH.auth.verify });

POST (public — e.g. login/register):

const data = await apiPostWithoutToken({
	url: URL_PATH.auth.register,
	body: { name, email, password },
	tags: "registerAuth",
});

POST (authenticated):

const data = await apiPost({
	url: URL_PATH.user.updateProfile,
	body: { name },
	tags: "updateProfile",
});

With retry:

apiGet({ url: URL_PATH.user.profile, retry: 2 }); // retries up to 2x on failure

Error Handling

All functions reject with a normalized ApiError object:

type ApiError<T = unknown> = {
	success: boolean;
	message: string;
	errors?: T; // typed per endpoint e.g. ApiError<AuthErrorResponse[]>
};

Use it with TanStack Query's onError:

useMutation<RegisterResponse, ApiError<AuthErrorResponse[]>>({
  mutationFn: async () => { ... },
  onError: (error) => {
    console.log(error.message);
    console.log(error.errors?.[0]?.field);
  },
});

Logging

Pass a tags string to any API call to enable logging. The logApi utility will print status code, URL, request body, response data, and a ready-to-copy curl command to the console.

apiGet({ url: URL_PATH.user.profile, tags: "fetchProfile" });
// → logs: fetchProfile statusCode, url, body, data + curl

Omit tags to silence all logs for that call.

On this page