> For the complete documentation index, see [llms.txt](https://jacksonkasi.gitbook.io/tablecraft/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://jacksonkasi.gitbook.io/tablecraft/integrations-and-adapters/rest.md).

# REST & Axios

If your backend is a standard REST API, or if your project relies heavily on `axios` for request interceptors (like automatically attaching auth tokens or handling 401 refreshes), TableCraft makes it incredibly easy to connect your data.

***

## 1. "Hello World" (Static Data Adapter)

To understand how simple an adapter can be, here is one that returns static, hardcoded data. It ignores pagination and filtering entirely but satisfies the contract.

```typescript
import type { DataAdapter } from '@tablecraft/table';

interface User { id: number; name: string; }

const myStaticAdapter: DataAdapter<User> = {
  async query(params) {
    const data = [
      { id: 1, name: "Alice" },
      { id: 2, name: "Bob" }
    ];
    
    return {
      data,
      meta: {
        total: data.length,
        page: params.page,
        pageSize: params.pageSize,
        totalPages: 1
      }
    };
  }
};
```

***

## 2. Example: Native `fetch` Adapter

TableCraft provides a built-in helper called `createRestAdapter`. You just need to supply the `queryFn` that maps the `QueryParams` to your URL string.

This is a robust example of connecting TableCraft to a generic REST API using the native `fetch` API.

```typescript
import { createRestAdapter } from '@tablecraft/table';
import type { QueryParams } from '@tablecraft/table';

export function createMyFetchAdapter<T>(baseUrl: string, getToken: () => string | null) {
  return createRestAdapter<T>({
    queryFn: async (params: QueryParams) => {
      const url = new URL(baseUrl);
      
      // 1. Map Pagination (Assuming your API uses 1-indexed pages)
      url.searchParams.set('page', String(params.page + 1));
      url.searchParams.set('limit', String(params.pageSize));

      // ... map sorting, searching, and filtering

      // 5. Fetch the Data (Inject token via function argument)
      const token = getToken();
      const headers: HeadersInit = {};
      if (token) headers['Authorization'] = `Bearer ${token}`;

      const response = await fetch(url.toString(), { headers });

      if (!response.ok) throw new Error('Failed to fetch data');
      
      // Assume API returns: { items: [...], totalCount: 150 }
      const json = await response.json();

      // 6. Return strict QueryResult shape
      return {
        data: json.items,
        meta: {
          total: json.totalCount,
          page: params.page,
          pageSize: params.pageSize,
          totalPages: Math.ceil(json.totalCount / params.pageSize)
        }
      };
    }
  });
}

// Usage in React:
// const getToken = () => localStorage.getItem('token'); // Safe for CSR, modify for SSR
// const adapter = createMyFetchAdapter('/api/users', getToken);
// <DataTable adapter={adapter} />
```

***

## 3. Example: `axios` Adapter

Many enterprise applications use `axios` because it allows you to configure global instances with interceptors. You can easily wrap your existing Axios setup in a `DataAdapter`.

First, you might have an Axios instance set up in your project:

```typescript
// src/api/client.ts
import axios from 'axios';

export const apiClient = axios.create({
  baseURL: 'https://api.example.com',
  timeout: 5000,
});

apiClient.interceptors.request.use((config) => {
  const token = localStorage.getItem('access_token');
  if (token) {
    config.headers.Authorization = `Bearer ${token}`;
  }
  return config;
});
```

Then, you create an adapter that uses that instance:

```typescript
import { createRestAdapter } from '@tablecraft/table';
import { apiClient } from '../api/client';
import type { QueryParams } from '@tablecraft/table';

export function createAxiosTableAdapter<T>(endpoint: string) {
  return createRestAdapter<T>({
    queryFn: async (params: QueryParams) => {
      try {
        // Axios makes parameter mapping clean
        const response = await apiClient.get(endpoint, {
          params: {
            ...params.filters, // Spreading filters first so explicit params always win
            page: params.page + 1,
            limit: params.pageSize,
            sortBy: params.sort,
            sortOrder: params.sortOrder,
            search: params.search,
          }
        });

        // Your backend response structure
        const { data, meta } = response.data;

        return {
          data,
          meta: {
            total: meta.totalCount,
            page: params.page,
            pageSize: params.pageSize,
            totalPages: Math.ceil(meta.totalCount / params.pageSize)
          }
        };
      } catch (error) {
        console.error("Table fetch failed:", error);
        // Throwing the error allows TableCraft's <DataTable /> to catch it
        // and display an Error State component to the user automatically.
        throw error; 
      }
    }
  });
}
```

This pattern completely decouples your `<DataTable>` component from knowing *how* the data is fetched. The component just renders, and the Axios adapter handles all the heavy lifting and interceptor logic.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## 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, and the optional `goal` query parameter:

```
GET https://jacksonkasi.gitbook.io/tablecraft/integrations-and-adapters/rest.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
