# createApi

&#x20;

## `createApi`

`createApi` is the core of RTK Query's functionality. It allows you to define a set of endpoints describe how to retrieve data from a series of endpoints, including configuration of how to fetch and transform that data. It generates [an "API slice" structure](/my-docs/redux/repos/redux-toolkit/docs/rtk-query/api/created-api/overview.md) that contains Redux logic (and optionally React hooks) that encapsulate the data fetching and caching process for you.

```ts
// file: src/services/types.ts noEmit
export type Pokemon = {}

// file: src/services/pokemon.ts
// Need to use the React-specific entry point to allow generating React hooks
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
import type { Pokemon } from './types'

// highlight-start
// Define a service using a base URL and expected endpoints
export const pokemonApi = createApi({
  reducerPath: 'pokemonApi',
  baseQuery: fetchBaseQuery({ baseUrl: 'https://pokeapi.co/api/v2/' }),
  endpoints: (builder) => ({
    getPokemonByName: builder.query<Pokemon, string>({
      query: (name) => `pokemon/${name}`,
    }),
  }),
})
//highlight-end

// highlight-start
// Export hooks for usage in function components, which are
// auto-generated based on the defined endpoints
export const { useGetPokemonByNameQuery } = pokemonApi
// highlight-end
```

### Parameters

`createApi` accepts a single configuration object parameter with the following options:

```ts
  baseQuery(args: InternalQueryArgs, api: BaseQueryApi): any;
  endpoints(build: EndpointBuilder<InternalQueryArgs, TagTypes>): Definitions;
  tagTypes?: readonly TagTypes[];
  reducerPath?: ReducerPath;
  serializeQueryArgs?: SerializeQueryArgs<InternalQueryArgs>;
  keepUnusedDataFor?: number; // value is in seconds
  refetchOnMountOrArgChange?: boolean | number; // value is in seconds
  refetchOnFocus?: boolean;
  refetchOnReconnect?: boolean;
```

#### `baseQuery`

[summary](docblock://query/createApi.ts?token=CreateApiOptions.baseQuery)

**baseQuery function arguments**

* `args` - The return value of the `query` function for a given endpoint
* `api` - The `BaseQueryApi` object, containing `signal`, `dispatch` and `getState` properties
  * `signal` - An [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) object that may be used to abort DOM requests and/or read whether the request is aborted.
  * `dispatch` - The `store.dispatch` method for the corresponding Redux store
  * `getState` - A function that may be called to access the current store state
* `extraOptions` - The value of the optional `extraOptions` property provided for a given endpoint

**baseQuery function signature**

```ts
export type BaseQueryFn<
  Args = any,
  Result = unknown,
  Error = unknown,
  DefinitionExtraOptions = {},
  Meta = {}
> = (
  args: Args,
  api: BaseQueryApi,
  extraOptions: DefinitionExtraOptions
) => MaybePromise<QueryReturnValue<Result, Error, Meta>>

export interface BaseQueryApi {
  signal: AbortSignal
  dispatch: ThunkDispatch<any, any, any>
  getState: () => unknown
}

export type QueryReturnValue<T = unknown, E = unknown, M = unknown> =
  | {
      error: E
      data?: undefined
      meta?: M
    }
  | {
      error?: undefined
      data: T
      meta?: M
    }
```

[examples](docblock://query/createApi.ts?token=CreateApiOptions.baseQuery)

#### `endpoints`

[summary](docblock://query/createApi.ts?token=CreateApiOptions.endpoints)

See [Anatomy of an endpoint](#anatomy-of-an-endpoint) for details on individual properties.

**Query endpoint definition**

```ts
export type QueryDefinition<
  QueryArg,
  BaseQuery extends BaseQueryFn,
  TagTypes extends string,
  ResultType,
  ReducerPath extends string = string
> = {
  query(arg: QueryArg): BaseQueryArg<BaseQuery>

  /* either `query` or `queryFn` can be present, but not both simultaneously */
  queryFn(
    arg: QueryArg,
    api: BaseQueryApi,
    extraOptions: BaseQueryExtraOptions<BaseQuery>,
    baseQuery: (arg: Parameters<BaseQuery>[0]) => ReturnType<BaseQuery>
  ): MaybePromise<QueryReturnValue<ResultType, BaseQueryError<BaseQuery>>>

  /* transformResponse only available with `query`, not `queryFn` */
  transformResponse?(
    baseQueryReturnValue: BaseQueryResult<BaseQuery>,
    meta: BaseQueryMeta<BaseQuery>
  ): ResultType | Promise<ResultType>

  extraOptions?: BaseQueryExtraOptions<BaseQuery>

  providesTags?: ResultDescription<
    TagTypes,
    ResultType,
    QueryArg,
    BaseQueryError<BaseQuery>
  >

  keepUnusedDataFor?: number

  onQueryStarted?(
    arg: QueryArg,
    {
      dispatch,
      getState,
      extra,
      requestId,
      queryFulfilled,
      getCacheEntry,
      updateCachedData, // available for query endpoints only
    }: QueryLifecycleApi
  ): Promise<void>

  onCacheEntryAdded?(
    arg: QueryArg,
    {
      dispatch,
      getState,
      extra,
      requestId,
      cacheEntryRemoved,
      cacheDataLoaded,
      getCacheEntry,
      updateCachedData, // available for query endpoints only
    }: QueryCacheLifecycleApi
  ): Promise<void>
}
```

**Mutation endpoint definition**

```ts
export type MutationDefinition<
  QueryArg,
  BaseQuery extends BaseQueryFn,
  TagTypes extends string,
  ResultType,
  ReducerPath extends string = string,
  Context = Record<string, any>
> = {
  query(arg: QueryArg): BaseQueryArg<BaseQuery>

  /* either `query` or `queryFn` can be present, but not both simultaneously */
  queryFn(
    arg: QueryArg,
    api: BaseQueryApi,
    extraOptions: BaseQueryExtraOptions<BaseQuery>,
    baseQuery: (arg: Parameters<BaseQuery>[0]) => ReturnType<BaseQuery>
  ): MaybePromise<QueryReturnValue<ResultType, BaseQueryError<BaseQuery>>>

  /* transformResponse only available with `query`, not `queryFn` */
  transformResponse?(
    baseQueryReturnValue: BaseQueryResult<BaseQuery>,
    meta: BaseQueryMeta<BaseQuery>
  ): ResultType | Promise<ResultType>

  extraOptions?: BaseQueryExtraOptions<BaseQuery>

  invalidatesTags?: ResultDescription<TagTypes, ResultType, QueryArg>

  onQueryStarted?(
    arg: QueryArg,
    {
      dispatch,
      getState,
      extra,
      requestId,
      queryFulfilled,
      getCacheEntry,
    }: MutationLifecycleApi
  ): Promise<void>

  onCacheEntryAdded?(
    arg: QueryArg,
    {
      dispatch,
      getState,
      extra,
      requestId,
      cacheEntryRemoved,
      cacheDataLoaded,
      getCacheEntry,
    }: MutationCacheLifecycleApi
  ): Promise<void>
}
```

**How endpoints get used**

When defining a key like `getPosts` as shown below, it's important to know that this name will become exportable from `api` and be able to referenced under `api.endpoints.getPosts.useQuery()`, `api.endpoints.getPosts.initiate()` and `api.endpoints.getPosts.select()`. The same thing applies to `mutation`s but they reference `useMutation` instead of `useQuery`.

```ts
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
interface Post {
  id: number
  name: string
}
type PostsResponse = Post[]

const api = createApi({
  baseQuery: fetchBaseQuery({ baseUrl: '/' }),
  tagTypes: ['Posts'],
  endpoints: (build) => ({
    getPosts: build.query<PostsResponse, void>({
      query: () => 'posts',
      providesTags: (result) =>
        result ? result.map(({ id }) => ({ type: 'Posts', id })) : [],
    }),
    addPost: build.mutation<Post, Partial<Post>>({
      query: (body) => ({
        url: `posts`,
        method: 'POST',
        body,
      }),
      invalidatesTags: ['Posts'],
    }),
  }),
})

// Auto-generated hooks
export const { useGetPostsQuery, useAddPostMutation } = api

// Possible exports
export const { endpoints, reducerPath, reducer, middleware } = api
// reducerPath, reducer, middleware are only used in store configuration
// endpoints will have:
// endpoints.getPosts.initiate(), endpoints.getPosts.select(), endpoints.getPosts.useQuery()
// endpoints.addPost.initiate(), endpoints.addPost.select(), endpoints.addPost.useMutation()
// see `createApi` overview for _all exports_
```

#### `tagTypes`

[summary](docblock://query/createApi.ts?token=CreateApiOptions.tagTypes)

[examples](docblock://query/createApi.ts?token=CreateApiOptions.tagTypes)

#### `reducerPath`

[summary](docblock://query/createApi.ts?token=CreateApiOptions.reducerPath)

[examples](docblock://query/createApi.ts?token=CreateApiOptions.reducerPath)

#### `serializeQueryArgs`

[summary](docblock://query/createApi.ts?token=CreateApiOptions.serializeQueryArgs)

By default, this function will take the query arguments, sort object keys where applicable, stringify the result, and concatenate it with the endpoint name. This creates a cache key based on the combination of arguments + endpoint name (ignoring object key order), such that calling any given endpoint with the same arguments will result in the same cache key.

#### `keepUnusedDataFor`

[summary](docblock://query/createApi.ts?token=CreateApiOptions.keepUnusedDataFor)

#### `refetchOnMountOrArgChange`

[summary](docblock://query/createApi.ts?token=CreateApiOptions.refetchOnMountOrArgChange)

:::note You can set this globally in `createApi`, but you can also override the default value and have more granular control by passing `refetchOnMountOrArgChange` to each individual hook call or similarly by passing `forceRefetch: true` when dispatching the [`initiate`](/my-docs/redux/repos/redux-toolkit/docs/rtk-query/api/created-api/endpoints.md#initiate) action. :::

#### `refetchOnFocus`

[summary](docblock://query/createApi.ts?token=CreateApiOptions.refetchOnFocus)

:::note You can set this globally in `createApi`, but you can also override the default value and have more granular control by passing `refetchOnFocus` to each individual hook call or when dispatching the [`initiate`](/my-docs/redux/repos/redux-toolkit/docs/rtk-query/api/created-api/endpoints.md#initiate) action.

If you specify `track: false` when manually dispatching queries, RTK Query will not be able to automatically refetch for you. :::

#### `refetchOnReconnect`

[summary](docblock://query/createApi.ts?token=CreateApiOptions.refetchOnReconnect)

:::note You can set this globally in `createApi`, but you can also override the default value and have more granular control by passing `refetchOnReconnect` to each individual hook call or when dispatching the [`initiate`](/my-docs/redux/repos/redux-toolkit/docs/rtk-query/api/created-api/endpoints.md#initiate) action.

If you specify `track: false` when manually dispatching queries, RTK Query will not be able to automatically refetch for you. :::

### Anatomy of an endpoint

#### `query`

*(required if no `queryFn` provided)*

[summary](docblock://query/endpointDefinitions.ts?token=EndpointDefinitionWithQuery.query)

[examples](docblock://query/endpointDefinitions.ts?token=EndpointDefinitionWithQuery.query)

#### `queryFn`

*(required if no `query` provided)*

[summary](docblock://query/endpointDefinitions.ts?token=EndpointDefinitionWithQueryFn.queryFn)

Called with the same arguments as `baseQuery`, as well as the provided `baseQuery` function itself. It is expected to return an object with either a `data` or `error` property, or a promise that resolves to return such an object.

See also [Customizing queries with queryFn](/my-docs/redux/repos/redux-toolkit/docs/rtk-query/usage/customizing-queries.md#customizing-queries-with-queryfn).

```ts
queryFn(
  arg: QueryArg,
  api: BaseQueryApi,
  extraOptions: BaseQueryExtraOptions<BaseQuery>,
  baseQuery: (arg: Parameters<BaseQuery>[0]) => ReturnType<BaseQuery>
): MaybePromise<
| {
    error: BaseQueryError<BaseQuery>
    data?: undefined
  }
| {
    error?: undefined
    data: ResultType
  }
>

export interface BaseQueryApi {
  signal: AbortSignal
  dispatch: ThunkDispatch<any, any, any>
  getState: () => unknown
}
```

**queryFn function arguments**

* `args` - The argument provided when the query itself is called
* `api` - The `BaseQueryApi` object, containing `signal`, `dispatch` and `getState` properties
  * `signal` - An [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) object that may be used to abort DOM requests and/or read whether the request is aborted.
  * `dispatch` - The `store.dispatch` method for the corresponding Redux store
  * `getState` - A function that may be called to access the current store state
* `extraOptions` - The value of the optional `extraOptions` property provided for the endpoint
* `baseQuery` - The `baseQuery` function provided to the api itself

[examples](docblock://query/endpointDefinitions.ts?token=EndpointDefinitionWithQueryFn.queryFn)

#### `transformResponse`

*(optional, not applicable with `queryFn`)*

[summary](docblock://query/endpointDefinitions.ts?token=EndpointDefinitionWithQuery.transformResponse)

In some cases, you may want to manipulate the data returned from a query before you put it in the cache. In this instance, you can take advantage of `transformResponse`.

See also [Customizing query responses with `transformResponse`](/my-docs/redux/repos/redux-toolkit/docs/rtk-query/usage/customizing-queries.md#customizing-query-responses-with-transformresponse)

```ts
transformResponse: (response) => response.some.deeply.nested.collection
```

#### `extraOptions`

*(optional)*

Passed as the third argument to the supplied `baseQuery` function

#### `providesTags`

*(optional, only for query endpoints)*

[summary](docblock://query/endpointDefinitions.ts?token=QueryExtraOptions.providesTags)

See also [Providing cache data](/my-docs/redux/repos/redux-toolkit/docs/rtk-query/usage/automated-refetching.md#providing-cache-data).

[examples](docblock://query/endpointDefinitions.ts?token=QueryExtraOptions.providesTags)

#### `invalidatesTags`

*(optional, only for mutation endpoints)*

[summary](docblock://query/endpointDefinitions.ts?token=MutationExtraOptions.invalidatesTags)

See also [Invalidating cache data](/my-docs/redux/repos/redux-toolkit/docs/rtk-query/usage/automated-refetching.md#invalidating-cache-data).

[examples](docblock://query/endpointDefinitions.ts?token=MutationExtraOptions.invalidatesTags)

#### `keepUnusedDataFor`

*(optional, only for query endpoints)*

Overrides the api-wide definition of `keepUnusedDataFor` for this endpoint only.

[summary](docblock://query/createApi.ts?token=CreateApiOptions.keepUnusedDataFor)

[examples](docblock://query/createApi.ts?token=CreateApiOptions.keepUnusedDataFor)

#### `onQueryStarted`

*(optional)*

Available to both [queries](/my-docs/redux/repos/redux-toolkit/docs/rtk-query/usage/queries.md) and [mutations](/my-docs/redux/repos/redux-toolkit/docs/rtk-query/usage/mutations.md).

A function that is called when you start each individual query or mutation. The function is called with a lifecycle api object containing properties such as `queryFulfilled`, allowing code to be run when a query is started, when it succeeds, and when it fails (i.e. throughout the lifecycle of an individual query/mutation call).

Can be used in `mutations` for [optimistic updates](/my-docs/redux/repos/redux-toolkit/docs/rtk-query/usage/optimistic-updates.md).

**Lifecycle API properties**

* `dispatch` - The dispatch method for the store.
* `getState` - A method to get the current state for the store.
* `extra` - `extra` as provided as `thunk.extraArgument` to the `configureStore` `getDefaultMiddleware` option.
* `requestId` - A unique ID generated for the query/mutation.
* `queryFulfilled` - A Promise that will resolve with the (transformed) query result. If the query fails, this Promise will reject with the error. This allows you to `await` for the query to finish.
* `getCacheEntry` - A function that gets the current value of the cache entry.
* `updateCachedData` *(query endpoints only)* - A function that accepts a 'recipe' callback specifying how to update the data for the corresponding cache at the time it is called. This uses `immer` internally, and updates can be written 'mutably' while safely producing the next immutable state.

```ts
async function onQueryStarted(
  arg: QueryArg,
  {
    dispatch,
    getState,
    extra,
    requestId,
    queryFulfilled,
    getCacheEntry,
  }: MutationLifecycleApi
): Promise<void>
```

```ts
async function onQueryStarted(
  arg: QueryArg,
  {
    dispatch,
    getState,
    extra,
    requestId,
    queryFulfilled,
    getCacheEntry,
    updateCachedData, // available for query endpoints only
  }: QueryLifecycleApi
): Promise<void>
```

```ts
// file: notificationsSlice.ts noEmit
export const messageCreated = (msg: string) => ({
  type: 'notifications/messageCreated',
  payload: msg,
})

// file: api.ts
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query'
import { messageCreated } from './notificationsSlice'

export interface Post {
  id: number
  name: string
}

const api = createApi({
  baseQuery: fetchBaseQuery({
    baseUrl: '/',
  }),
  endpoints: (build) => ({
    getPost: build.query<Post, number>({
      query: (id) => `post/${id}`,
      async onQueryStarted(id, { dispatch, queryFulfilled }) {
        // `onStart` side-effect
        dispatch(messageCreated('Fetching post...'))
        try {
          const { data } = await queryFulfilled
          // `onSuccess` side-effect
          dispatch(messageCreated('Post received!'))
        } catch (err) {
          // `onError` side-effect
          dispatch(messageCreated('Error fetching post!'))
        }
      },
    }),
  }),
})
```

#### `onCacheEntryAdded`

*(optional)*

Available to both [queries](/my-docs/redux/repos/redux-toolkit/docs/rtk-query/usage/queries.md) and [mutations](/my-docs/redux/repos/redux-toolkit/docs/rtk-query/usage/mutations.md).

A function that is called when a new cache entry is added, i.e. when a new subscription for the endpoint + query parameters combination is created. The function is called with a lifecycle api object containing properties such as `cacheDataLoaded` & `cacheDataRemoved`, allowing code to be run when a cache entry is added, when cache data is loaded, and when the cache entry is removed (i.e. throughout the lifecycle of a cache entry).

Can be used for [streaming updates](/my-docs/redux/repos/redux-toolkit/docs/rtk-query/usage/streaming-updates.md).

**Cache Lifecycle API properties**

* `dispatch` - The dispatch method for the store.
* `getState` - A method to get the current state for the store.
* `extra` - `extra` as provided as `thunk.extraArgument` to the `configureStore` `getDefaultMiddleware` option.
* `requestId` - A unique ID generated for the cache entry.
* `cacheEntryRemoved` - A Promise that allows you to wait for the point in time when the cache entry has been removed from the cache, by not being used/subscribed to any more in the application for too long or by dispatching `api.util.resetApiState`.
* `cacheDataLoaded` - A Promise that will resolve with the first value for this cache key. This allows you to `await` until an actual value is in the cache.\
  Note: If the cache entry is removed from the cache before any value has ever been resolved, this Promise will reject with `new Error('Promise never resolved before cacheEntryRemoved.')` to prevent memory leaks. You can just re-throw that error (or not handle it at all) - it will be caught outside of `cacheEntryAdded`.
* `getCacheEntry` - A function that gets the current value of the cache entry.
* `updateCachedData` *(query endpoints only)* - A function that accepts a 'recipe' callback specifying how to update the data at the time it is called. This uses `immer` internally, and updates can be written 'mutably' while safely producing the next immutable state.

```ts
async function onCacheEntryAdded(
  arg: QueryArg,
  {
    dispatch,
    getState,
    extra,
    requestId,
    cacheEntryRemoved,
    cacheDataLoaded,
    getCacheEntry,
  }: MutationCacheLifecycleApi
): Promise<void>
```

```ts
async function onCacheEntryAdded(
  arg: QueryArg,
  {
    dispatch,
    getState,
    extra,
    requestId,
    cacheEntryRemoved,
    cacheDataLoaded,
    getCacheEntry,
    updateCachedData, // available for query endpoints only
  }: QueryCacheLifecycleApi
): Promise<void>
```

### Return value

See [the "created Api" API reference](https://github.com/bgoonz/Learning-Redux/blob/master/repos/redux-toolkit/docs/rtk-query/api/created-api/overview/README.md)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://bryan-guner.gitbook.io/my-docs/redux/repos/redux-toolkit/docs/rtk-query/api/createapi.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
