> ## Documentation Index
> Fetch the complete documentation index at: https://docs.smartbills.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Pagination

> Apprenez à paginer les grands ensembles de résultats dans l'API Smartbills

## Aperçu

Tous les points d'accès de liste de l'API Smartbills retournent des résultats paginés. La pagination vous permet de récupérer efficacement de grands ensembles de données en les divisant en pages plus petites.

## Paramètres de requête

Tous les points d'accès de liste acceptent ces paramètres de pagination et de tri :

<ParamField query="page" type="integer" default="1">
  Numéro de page à récupérer (commence à 1)
</ParamField>

<ParamField query="pageSize" type="integer" default="20">
  Nombre d'éléments par page. Minimum : 1, Maximum : 100, Défaut : 20
</ParamField>

<ParamField query="sortBy" type="string" default="createdAt">
  Champ de tri des résultats (ex. : `createdAt`, `date`, `amount`)
</ParamField>

<ParamField query="sortOrder" type="string" default="desc">
  Direction du tri : `asc` (croissant) ou `desc` (decroissant)
</ParamField>

## Format de réponse

Les réponses paginéess incluent le tableau de données et un objet de métadonnées de pagination :

```json theme={null}
{
  "data": [
    {
      "id": 1,
      "merchant": "Bureau en Gros",
      "amount": 45.99
    },
    {
      "id": 2,
      "merchant": "Staples",
      "amount": 32.50
    }
  ],
  "pagination": {
    "page": 1,
    "pageSize": 20,
    "totalPages": 5,
    "totalCount": 95,
    "hasNext": true,
    "hasPrevious": false
  }
}
```

### Objet de pagination

<ResponseField name="pagination" type="object">
  Métadonnées de pagination

  <Expandable title="Propriétés">
    <ResponseField name="page" type="integer">
      Numéro de page actuel
    </ResponseField>

    <ResponseField name="pageSize" type="integer">
      Nombre d'éléments par page
    </ResponseField>

    <ResponseField name="totalPages" type="integer">
      Nombre total de pages disponibles
    </ResponseField>

    <ResponseField name="totalCount" type="integer">
      Nombre total d'éléments sur toutes les pages
    </ResponseField>

    <ResponseField name="hasNext" type="boolean">
      Indique s'il y à une page suivante disponible
    </ResponseField>

    <ResponseField name="hasPrevious" type="boolean">
      Indique s'il y à une page précédente disponible
    </ResponseField>
  </Expandable>
</ResponseField>

## Exemples de base

### Première page

Récupérer la première page de résultats avec tri :

<CodeGroup>
  ```bash cURL theme={null}
  curl --request GET \
    --url 'https://api.smartbills.io/v1/expenses?page=1&pageSize=20&sortBy=date&sortOrder=desc' \
    --header 'Authorization: Bearer VOTRE_CLE_API' \
    --header 'x-tenant-id: 123'
  ```

  ```javascript JavaScript theme={null}
  import { SmartbillsClient } from '@smartbills/sdk';

  const client = new SmartbillsClient({
    accessToken: 'VOTRE_CLE_API',
    businessId: 123
  });

  const result = await client.expenses.list({
    page: 1,
    pageSize: 20,
    sortBy: 'date',
    sortOrder: 'desc'
  });

  console.log(`Page ${result.pagination.page} sur ${result.pagination.totalPages}`);
  console.log(`Total d'éléments : ${result.pagination.totalCount}`);
  ```

  ```python Python theme={null}
  from smartbills import SmartbillsClient

  client = SmartbillsClient(access_token="VOTRE_CLE_API", business_id=123)

  result = client.expenses.list(
      page=1,
      page_size=20,
      sort_by="date",
      sort_order="desc"
  )

  print(f"Page {result.pagination.page} sur {result.pagination.total_pages}")
  print(f"Total d'éléments : {result.pagination.total_count}")
  ```
</CodeGroup>

### Page suivante

Naviguer à la page suivante en verifiant `hasNext` :

<CodeGroup>
  ```bash cURL theme={null}
  curl --request GET \
    --url 'https://api.smartbills.io/v1/expenses?page=2&pageSize=20&sortBy=date&sortOrder=desc' \
    --header 'Authorization: Bearer VOTRE_CLE_API' \
    --header 'x-tenant-id: 123'
  ```

  ```javascript JavaScript theme={null}
  if (result.pagination.hasNext) {
    const nextPage = result.pagination.page + 1;
    const nextResult = await client.expenses.list({
      page: nextPage,
      pageSize: 20,
      sortBy: 'date',
      sortOrder: 'desc'
    });
  }
  ```

  ```python Python theme={null}
  if result.pagination.has_next:
      next_page = result.pagination.page + 1
      next_result = client.expenses.list(
          page=next_page,
          page_size=20,
          sort_by="date",
          sort_order="desc"
      )
  ```
</CodeGroup>

## Parcourir toutes les pages

### Iteration simple

Parcourir toutes les pages pour récupérer tous les résultats :

<CodeGroup>
  ```javascript JavaScript theme={null}
  async function getAllExpenses(client) {
    const allExpenses = [];
    let page = 1;
    let hasMore = true;

    while (hasMore) {
      const result = await client.expenses.list({
        page: page,
        pageSize: 100
      });

      allExpenses.push(...result.data);
      hasMore = result.pagination.hasNext;
      page++;
    }

    return allExpenses;
  }

  const client = new SmartbillsClient({
    accessToken: 'VOTRE_CLE_API',
    businessId: 123
  });

  const expenses = await getAllExpenses(client);
  console.log(`${expenses.length} dépenses récupérées`);
  ```

  ```python Python theme={null}
  def get_all_expenses(client):
      all_expenses = []
      page = 1
      has_more = True

      while has_more:
          result = client.expenses.list(page=page, page_size=100)
          all_expenses.extend(result.data)
          has_more = result.pagination.has_next
          page += 1

      return all_expenses

  client = SmartbillsClient(access_token="VOTRE_CLE_API", business_id=123)

  expenses = get_all_expenses(client)
  print(f"{len(expenses)} dépenses récupérées")
  ```
</CodeGroup>

### Avec gestion des erreurs et limitation de débit

Pagination prête pour la production avec gestion des erreurs :

<CodeGroup>
  ```javascript JavaScript theme={null}
  async function getAllExpensesSafely(client) {
    const allExpenses = [];
    let page = 1;
    const maxPages = 100; // Limite de sécurité

    while (page <= maxPages) {
      try {
        const result = await client.expenses.list({
          page: page,
          pageSize: 100
        });

        allExpenses.push(...result.data);
        console.log(`Page ${page}/${result.pagination.totalPages} recuperee`);

        if (!result.pagination.hasNext) {
          break;
        }

        page++;
        // Petit delai pour respecter les limites de debit
        await new Promise(resolve => setTimeout(resolve, 100));
      } catch (error) {
        console.error(`Erreur lors de la récupération de la page ${page} :`, error);
        throw error;
      }
    }

    return allExpenses;
  }
  ```

  ```python Python theme={null}
  import time

  def get_all_expenses_safely(client):
      all_expenses = []
      page = 1
      max_pages = 100  # Limite de sécurité

      while page <= max_pages:
          try:
              result = client.expenses.list(page=page, page_size=100)
              all_expenses.extend(result.data)
              print(f"Page {page}/{result.pagination.total_pages} recuperee")

              if not result.pagination.has_next:
                  break

              page += 1
              time.sleep(0.1)  # Petit delai pour respecter les limites de debit
          except Exception as e:
              print(f"Erreur lors de la récupération de la page {page} : {e}")
              raise

      return all_expenses
  ```
</CodeGroup>

## Pagination avec filtres

Combinez la pagination avec le filtrage pour affiner vos résultats :

<CodeGroup>
  ```bash cURL theme={null}
  curl --request GET \
    --url 'https://api.smartbills.io/v1/expenses?page=1&pageSize=50&status=pending&sortBy=amount&sortOrder=desc' \
    --header 'Authorization: Bearer VOTRE_CLE_API' \
    --header 'x-tenant-id: 123'
  ```

  ```javascript JavaScript theme={null}
  const result = await client.expenses.list({
    page: 1,
    pageSize: 50,
    status: 'pending',
    sortBy: 'amount',
    sortOrder: 'desc'
  });
  ```

  ```python Python theme={null}
  result = client.expenses.list(
      page=1,
      page_size=50,
      status="pending",
      sort_by="amount",
      sort_order="desc"
  )
  ```
</CodeGroup>

## Limites de pagination

### Taille maximale de page

* **Maximum** : 100 éléments par page
* **Défaut** : 20 éléments par page
* **Minimum** : 1 élément par page

<Warning>
  Demander plus de 100 éléments par page entrainera une erreur de validation 400 Bad Request.
</Warning>

## Bonnes pratiques

<AccordionGroup>
  <Accordion title="Utiliser des tailles de page appropriees" icon="list">
    * **Petites pages (20-50)** : Mieux pour la pagination UI et une réponse initiale plus rapide
    * **Grandes pages (100)** : Mieux pour le traitement en lot et moins d'appels API
    * **Défaut (20)** : Bon equilibre pour la plupart des cas d'utilisation
  </Accordion>

  <Accordion title="Toujours vérifier hasNext" icon="check">
    Vérifiez toujours `hasNext` avant de récupérer la page suivante. Cela evite les appels API inutiles lorsque vous avez atteint la fin des résultats.
  </Accordion>

  <Accordion title="Gérer les limites de débit" icon="gauge">
    Ajoutez de petits délais entre les requêtes lors de la récupération de plusieurs pages pour eviter d'atteindre les limites de débit. Consultez [Limites de débit](/fr/api-reference/rate-limits) pour plus de détails.
  </Accordion>

  <Accordion title="Mettre en cache les résultats" icon="database">
    Mettez en cache les résultats paginés pour réduire les appels API redondants, surtout pour les données qui ne changent pas frequemment.
  </Accordion>

  <Accordion title="Utiliser des filtres pour réduire les données" icon="filter">
    Appliquez des filtres pour affiner les résultats avant de paginer, réduisant le nombre total de pages et d'appels API nécessaires.
  </Accordion>
</AccordionGroup>

## Dépannage

<AccordionGroup>
  <Accordion title="Résultats vides sur une page valide" icon="circle-question">
    **Causes possibles** : Les données ont été supprimées entre les requêtes, les filtres sont trop restrictifs, ou une condition de concurrence avec des modifications simultanées. **Solution** : Recommencez depuis le début ou ajustez vos filtres.
  </Accordion>

  <Accordion title="Nombre de pages incohérent" icon="calculator">
    **Raison** : C'est normal. Les données peuvent être ajoutees ou supprimées pendant la pagination. **Solution** : Utilisez `hasNext` au lieu de `totalPages` pour la logique d'iteration.
  </Accordion>

  <Accordion title="Performance de pagination lente" icon="hourglass">
    **Solutions** : Utilisez des tailles de page plus grandes (jusqu'a 100), ajoutez des filtres pour réduire le jeu de données total, mettez en cache les résultats, ou utilisez des webhooks pour les mises à jour en temps réel au lieu du polling.
  </Accordion>
</AccordionGroup>

## Ressources connexes

<CardGroup cols={2}>
  <Card title="Limites de débit" icon="gauge" href="/fr/api-reference/rate-limits">
    Comprendre la limitation de débit de l'API
  </Card>

  <Card title="Gestion des erreurs" icon="triangle-exclamation" href="/fr/api-reference/errors">
    Gérer les erreurs de pagination
  </Card>

  <Card title="Lister les dépenses" icon="receipt" href="/fr/api-reference/introduction">
    Point d'accès de liste des dépenses
  </Card>

  <Card title="Webhooks" icon="webhook" href="/fr/api-reference/webhooks">
    Notifications en temps réel
  </Card>
</CardGroup>
