---
title: "Requêtes API"
weight: 150
---

# Requêtes API

SmartCommon fournit le hook `useApi` qui simplifie les appels API avec gestion automatique de l'authentification JWT, du rafraîchissement de token et de la gestion des erreurs.

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

## Configuration

### 1. Configurer le Provider

Le `ApiProvider` doit être configuré dans votre `LibConfigProvider` :

```
// src/appConfig.js

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

```
// src/App.jsx

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

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

## Utilisation de useApi

### Importer le hook

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

### Structure retournée

Le hook `useApi` retourne un objet avec les méthodes suivantes :

| Méthode | Description |
| --- | --- |
| `user` | Objet utilisateur connecté (depuis gst) |
| `login(body, options)` | Connexion utilisateur, stocke automatiquement les tokens |
| `logout(options)` | Déconnexion, supprime les tokens |
| `entities(options)` | Récupère les entités disponibles (avant login) |
| `device(body, options)` | Enregistre/sélectionne un appareil |
| `public` | Instance ky pour les requêtes publiques |
| `private` | Instance ky pour les requêtes authentifiées |
| `get(url, options)` | Raccourci pour requête GET authentifiée |
| `post(url, options)` | Raccourci pour requête POST authentifiée |
| `put(url, options)` | Raccourci pour requête PUT authentifiée |
| `patch(url, options)` | Raccourci pour requête PATCH authentifiée |
| `del(url, options)` | Raccourci pour requête DELETE authentifiée |

### Requête de connexion

```
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('Connecté:', user);
    } catch (error) {
      console.error('Erreur de connexion:', error);
    }
  };

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

### Requêtes authentifiées

Pour les requêtes nécessitant une authentification, utilisez `api.private` :

```
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('Erreur:', error);
      } finally {
        setLoading(false);
      }
    };

    fetchItems();
  }, []);

  if (loading) return <Spinner />;

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

### Requêtes POST/PUT/DELETE

```
const api = useApi();

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

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

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

### Méthodes raccourcies

En plus de `api.private.get(...).json()`, useApi expose des méthodes raccourcies qui gèrent automatiquement la désérialisation JSON et les erreurs :

```
const api = useApi();

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

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

// 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}`);
```

#### Option raw (données binaires)

Pour récupérer des données binaires (images, fichiers), passez `raw: true` :

```
// Télécharger un fichier en binaire
const response = await api.get(`file/${hash}/binary`, { raw: true });
const blob = await response.blob();
```

#### Option silent (suppression des erreurs)

Par défaut, les erreurs API déclenchent le callback `onApiError` (affichage toast). Pour les supprimer :

```
// Ne pas afficher de toast en cas d'erreur
const data = await api.get('optional-endpoint', { silent: true });
```

### Gestion globale des erreurs

Configurez `onApiError` dans `appConfig` pour centraliser la gestion des erreurs API :

```
// 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);
    },
  },
};
```

Quand une requête échoue, useApi :

- Extrait le message d'erreur du body JSON de la réponse (champ `error` ou `message`)
- Appelle `onApiError` avec ce message (sauf si `silent: true`)
- Détecte aussi les erreurs applicatives (HTTP 200 avec champ `error` dans le body)

### Accès à l'utilisateur connecté

Le hook `useApi` expose directement l'objet utilisateur :

```
const api = useApi();

// Accès direct à l'utilisateur
const user = api.user;

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

### Requêtes publiques

Pour les requêtes ne nécessitant pas d'authentification :

```
const api = useApi();

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

## Fonctionnalités automatiques

### Gestion des tokens
- Le token d'accès est automatiquement ajouté aux headers des requêtes privées
- Le token est rafraîchi automatiquement avant expiration
- En cas d'erreur 401, un refresh est tenté automatiquement

### Circuit breaker
- Protection contre les requêtes en cascade en cas d'erreur serveur
- Blocage temporaire des requêtes après plusieurs échecs
- Détection automatique de la connexion internet

### Headers automatiques

Chaque requête inclut automatiquement :
- `Authorization: Bearer <token>` (requêtes privées)
- `X-DEVICEID: <uuid>` (identification de l'appareil)

## Méthode classique (fetch natif)

Si vous préférez utiliser fetch directement (non recommandé) :

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

```
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]
> Il est recommandé d'utiliser `useApi` plutôt que fetch natif pour bénéficier de la gestion automatique des tokens et du circuit breaker.

## Voir aussi
- [Stockage de données](/front/stockage-de-donnees) - Pour persister les données localement
- [Hooks](/front/hooks) - Documentation complète des hooks
- [Back (PHP)](/back) - Configuration des routes API côté serveur
