---
source_hash: "b6bb50ed"
title: "API Requests"
weight: 150
---

# API Requests

SmartCommon provides the `useApi` hook which simplifies API calls with automatic JWT authentication management, token refresh, and error handling.

[ky Documentation](https://github.com/sindresorhus/ky) (HTTP client used)

## Configuration

### 1. Configure the Provider

The `ApiProvider` must be configured in your `LibConfigProvider`:

```javascript
// src/appConfig.js

export const appConfig = {
  debug: true,
  api: {
    prefixUrl: import.meta.env.VITE_API_URL,
    timeout: 30000,
    debug: true
  }
};
```

```javascript
// src/App.jsx

import { Provider } from '@cap-rel/smartcommon';
import { appConfig } from './appConfig';

export const App = () => {
  return (
    <Provider config={appConfig}>
      <Router />
    </Provider>
  );
};
```

## Using useApi

### Import the Hook

```javascript
import { useApi } from '@cap-rel/smartcommon';
```

### Returned Structure

The `useApi` hook returns an object with the following methods:

| Method | Description |
| --- | --- |
| `user` | Connected user object (from gst) |
| `login(body, options)` | User login, automatically stores tokens |
| `logout(options)` | Logout, removes tokens |
| `entities(options)` | Get available entities (before login) |
| `device(body, options)` | Register/select a device |
| `public` | ky instance for public requests |
| `private` | ky instance for authenticated requests |
| `get(url, options)` | Shortcut for authenticated GET request |
| `post(url, options)` | Shortcut for authenticated POST request |
| `put(url, options)` | Shortcut for authenticated PUT request |
| `patch(url, options)` | Shortcut for authenticated PATCH request |
| `del(url, options)` | Shortcut for authenticated DELETE request |

### Login Request

```javascript
import { useApi } from '@cap-rel/smartcommon';
import { Input, Button } from '@cap-rel/smartcommon';

export const Login = () => {
  const api = useApi();

  const handleSubmit = async (e) => {
    e.preventDefault();

    const formData = new FormData(e.target);
    const credentials = Object.fromEntries(formData.entries());

    try {
      const user = await api.login({
        ...credentials,
        rememberMe: true
      });

      console.log('Logged in:', user);
    } catch (error) {
      console.error('Login error:', error);
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <Input name="login" label="Email" type="email" />
      <Input name="password" label="Password" type="password" />
      <Button type="submit">Login</Button>
    </form>
  );
};
```

### Authenticated Requests

For requests requiring authentication, use `api.private`:

```javascript
import { useApi } from '@cap-rel/smartcommon';
import { useState, useEffect } from 'react';
import { List, ListItem, Spinner } from '@cap-rel/smartcommon';

export const ItemsList = () => {
  const api = useApi();
  const [items, setItems] = useState([]);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    const fetchItems = async () => {
      try {
        const data = await api.private.get('items').json();
        setItems(data);
      } catch (error) {
        console.error('Error:', error);
      } finally {
        setLoading(false);
      }
    };

    fetchItems();
  }, []);

  if (loading) return <Spinner />;

  return (
    <List>
      {items.map(item => (
        <ListItem key={item.id}>{item.name}</ListItem>
      ))}
    </List>
  );
};
```

### POST/PUT/DELETE Requests

```javascript
const api = useApi();

// POST - Create
const createItem = async (data) => {
  return api.private.post('items', { json: data }).json();
};

// PUT - Update
const updateItem = async (id, data) => {
  return api.private.put(`items/${id}`, { json: data }).json();
};

// DELETE - Delete
const deleteItem = async (id) => {
  return api.del(`items/${id}`);
};
```

### Shortcut Methods

In addition to `api.private.get(...).json()`, useApi exposes shortcut methods that automatically handle JSON deserialization and errors:

```javascript
const api = useApi();

// GET
const items = await api.get('items');

// POST with JSON body
const created = await api.post('items', { json: { label: 'New' } });

// PUT
const updated = await api.put(`items/${id}`, { json: data });

// PATCH
const patched = await api.patch(`items/${id}`, { json: { status: 1 } });

// DELETE
await api.del(`items/${id}`);
```

#### Raw Option (Binary Data)

To retrieve binary data (images, files), pass `raw: true`:

```javascript
// Download a file in binary
const response = await api.get(`file/${hash}/binary`, { raw: true });
const blob = await response.blob();
```

#### Silent Option (Suppress Errors)

By default, API errors trigger the `onApiError` callback (toast display). To suppress them:

```javascript
// Do not display toast on error
const data = await api.get('optional-endpoint', { silent: true });
```

### Global Error Handling

Configure `onApiError` in `appConfig` to centralize API error handling:

```javascript
// src/appConfig.js
import toast from 'react-hot-toast';

export const appConfig = {
  api: {
    prefixUrl: import.meta.env.VITE_API_URL,
    onApiError: (message) => {
      toast.error(message);
    },
  },
};
```

When a request fails, useApi:

- Extracts the error message from the JSON response body (`error` or `message` field)
- Calls `onApiError` with this message (unless `silent: true`)
- Also detects application errors (HTTP 200 with `error` field in body)

### Access Connected User

The `useApi` hook directly exposes the user object:

```javascript
const api = useApi();

// Direct access to user
const user = api.user;

if (user) {
  console.log(user.login, user.accessToken);
}
```

### Public Requests

For requests that do not require authentication:

```javascript
const api = useApi();

const fetchPublicData = async () => {
  return api.public.get('public/info').json();
};
```

## Automatic Features

### Token Management
- Access token is automatically added to private request headers
- Token is automatically refreshed before expiration
- On 401 error, a refresh is automatically attempted

### Circuit Breaker
- Protection against cascading requests in case of server error
- Temporary blocking of requests after multiple failures
- Automatic detection of internet connection

### Automatic Headers

Each request automatically includes:
- `Authorization: Bearer <token>` (private requests)
- `X-DEVICEID: <uuid>` (device identification)

## Classic Method (Native fetch)

If you prefer to use fetch directly (not recommended):

[Fetch API Documentation](https://developer.mozilla.org/fr/docs/Web/API/Fetch_API)

```javascript
const API_URL = import.meta.env.VITE_API_URL;

const request = {
  method: "POST",
  body: JSON.stringify(data),
  headers: {
    Accept: "application/json",
    "Content-Type": "application/json",
    Authorization: `Bearer ${token}`
  }
};

fetch(`${API_URL}/items`, request)
  .then(response => response.json())
  .then(json => console.log(json))
  .catch(error => console.error(error));
```

> [!TIP]
> It is recommended to use `useApi` rather than native fetch to benefit from automatic token management and circuit breaker.

## See Also
- [Data Storage](/front/stockage-de-donnees) - To persist data locally
- [Hooks](/front/hooks) - Full hook documentation
- [Back (PHP)](/back) - Server-side API route configuration
