Skip to main content

Admin Panel API: Fetch client

Page summary:

Use useFetchClient inside React components and getFetchClient elsewhere to call Strapi APIs with the user's authentication token attached. Both expose get, post, put, and del methods with automatic token refresh on 401 responses.

Strapi provides a built-in HTTP client for the admin panel that manages authentication automatically. Plugin developers should use it instead of raw fetch or axios.

Both useFetchClient and getFetchClient are exported from @strapi/strapi/admin and expose the same get, post, put, and del methods. Choose based on where the call is made from:

Entry pointUse when
useFetchClientInside a React component (auto-cancels requests on unmount)
getFetchClientServices, utility functions, event handlers, or any non-React code
Prerequisites

Before diving deeper into the concepts on this page, please ensure you have:

Fetching data

The most common operation is fetching data with get. Import the client, destructure the methods you need, and await the result:

Inside a React component

useFetchClient is a React hook that automatically provides an AbortSignal tied to the component lifecycle, so requests are cancelled when the component unmounts:

my-plugin/admin/src/components/MyComponent.js
import { useFetchClient } from '@strapi/strapi/admin';

const MyComponent = () => {
const { get } = useFetchClient();

const fetchData = async () => {
const { data } = await get('/my-plugin/my-endpoint');
// data contains the parsed JSON response
};
};

Outside a React component

getFetchClient works in any JavaScript context. The typical pattern is to wrap calls inside exported helper functions that the rest of the plugin imports:

my-plugin/admin/src/utils/api.js
import { getFetchClient } from '@strapi/strapi/admin';

const { get, del } = getFetchClient();

export const fetchItems = async () => {
const { data } = await get('/my-plugin/items');
return data;
};

export const deleteItem = async (id) => {
await del(`/my-plugin/items/${id}`);
};
Note

The del method is named this way because delete is a reserved word in JavaScript.

Sending data with post and put

The post and put methods accept a payload as their second argument:

my-plugin/admin/src/utils/api.js
import { getFetchClient } from '@strapi/strapi/admin';

const { post, put } = getFetchClient();

// Create a new item
export const createItem = async (payload) => {
const { data } = await post('/my-plugin/items', payload);
return data;
};

// Update an existing item
export const updateItem = async (id, payload) => {
const { data } = await put(`/my-plugin/items/${id}`, payload);
return data;
};
Tip

When sending FormData (for example, file uploads), the fetch client automatically removes the Content-Type header so the browser can set the correct multipart boundary.

Configuring requests

All methods accept an options object as their last argument:

OptionTypeDescription
paramsobjectQuery string parameters. Serialized automatically.
headersRecord<string, string>Additional request headers. Merged with defaults.
signalAbortSignalUsed to cancel requests. useFetchClient provides one automatically.
validateStatus(status: number) => boolean | nullCustom function that determines which HTTP statuses should throw.
responseType'json' | 'blob' | 'text' | 'arrayBuffer'Controls response parsing (see Response types). Only effective on get.

Query parameters

Pass params to serialize query strings automatically:

my-plugin/admin/src/components/MyComponent.js
const { data } = await get('/content-manager/collection-types/api::article.article', {
params: {
page: 1,
pageSize: 10,
sort: 'title:asc',
},
});

Response types

By default, responses are parsed as JSON. The get method accepts a responseType option to handle non-JSON responses such as file downloads, CSV exports, or binary data:

responseType valueResponse parsed as
jsonJSON object (default)
blobBlob
textPlain text string
arrayBufferArrayBuffer

Non-JSON responses include status and headers in the return object:

my-plugin/admin/src/components/DownloadButton.js
import { useFetchClient } from '@strapi/strapi/admin';

const DownloadButton = () => {
const { get } = useFetchClient();

const downloadFile = async (url) => {
const { data: blob, status, headers } = await get(url, { responseType: 'blob' });
// Process the blob, for example to trigger a file download
};
};

Handling errors

The fetch client throws a FetchError when a request fails. Use the isFetchError utility to check errors safely:

my-plugin/admin/src/components/MyComponent.js
import { useFetchClient, isFetchError } from '@strapi/strapi/admin';

const MyComponent = () => {
const { get } = useFetchClient();

const fetchData = async () => {
try {
const { data } = await get('/my-plugin/my-endpoint');
// handle success
} catch (error) {
if (isFetchError(error)) {
// error.status contains the HTTP status code
console.error('Request failed:', error.status, error.message);
} else {
throw error; // re-throw non-fetch errors
}
}
};
};
Note

When a request returns a 401 status, the fetch client automatically refreshes the authentication token and retries the request before throwing an error. This automatic retry does not apply to authentication endpoints themselves.

👉 For server-side error handling (controllers, services, middlewares), see Error handling.