Pagination


Pagination

Ce document décrit l'utilisation de la pagination implémentée dans les API de Skalin.

# Vue d'ensemble

L'API Skalin utilise la pagination par curseur (keyset pagination) comme méthode principale. Au lieu d'un offset numérique, chaque réponse inclut un token opaque (nextCursor) à passer dans la requête suivante pour obtenir la page suivante.

Info

La pagination par curseur est stateless, efficace sur de grands volumes de données et garantit une cohérence même si des enregistrements sont ajoutés ou supprimés entre deux appels. La pagination par offset (page=) reste disponible mais est déconseillée sur de grands volumes.

# Endpoints supportés

La pagination par curseur est disponible sur les routes suivantes :

Méthode Route Ressource
GET /customers Customers
GET /contacts Contacts
GET /agreements Agreements
GET /customers/:customerId/contacts Contacts
GET /customers/:customerId/agreements Agreements

# Paramètres de requête

size integer Nombre de résultats par page. Défaut : 100. Maximum : 500.
cursor string Token opaque retourné par la page précédente. À omettre pour la première requête. Incompatible avec page.
page integer Index de page pour la pagination par offset. Défaut : 1. Ignoré si cursor est présent.

# Structure de la réponse

L'objet metadata.pagination de la réponse contient le curseur vers la page suivante.

Réponse API avec pagination par curseur

{
  "status": "success",
  "data": ["..."],
  "metadata": {
    "pagination": {
      "size": 100,
      "hasNextPage": true,
      "nextCursor": "eyJmaWVsZCI6ImNyZWF0ZWRBdCIsImRpciI6ImRlc2MiLCJ0aWVicmVha2VycyI6WyJBY21lIiwiMjAyNC0wMS0xMFQxMjowMDowMFoiLCIxMjMiXX0="
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11
  • hasNextPage: true — il existe une page suivante ; passer nextCursor dans la prochaine requête
  • hasNextPage: false — c'est la dernière page ; nextCursor vaut null
  • nextCursor est un token base64url opaque — ne pas l'interpréter ni le conserver entre sessions

# Parcourir les pages

Première page — omettre cursor :

GET /customers?size=50&sort=createdAt.desc
1

Pages suivantes — passer la valeur nextCursor retournée par la réponse précédente :

GET /customers?size=50&sort=createdAt.desc&cursor=eyJmaWVsZCI6ImNyZWF0ZWRBdCIs...
1

Répéter jusqu'à ce que hasNextPage soit false.

# Tri

Le paramètre sort contrôle l'ordre des résultats selon le format sort=champ.direction (ex. sort=createdAt.desc). Toujours utiliser la même valeur de sort sur toutes les pages d'un même parcours.

# Customers — /customers

Champ Description
createdAt Date de création
updatedAt Date de dernière mise à jour

# Contacts — /contacts, /customers/:id/contacts

Champ Description
createdAt Date de création
updatedAt Date de dernière mise à jour

# Agreements — /agreements, /customers/:id/agreements

Champ Description
mrr Monthly Recurring Revenue
arr Annual Recurring Revenue
status Statut du contrat
startDate Date de début
endDate Date de fin
engagement Jours restants avant l'engagement
notice Jours restants avant le préavis

# Pagination par offset

La pagination par offset utilise le paramètre page à la place de cursor. Elle est disponible sur tous les endpoints paginés mais déconseillée sur de grands volumes — les performances se dégradent significativement au-delà de quelques milliers de lignes.

page integer Index de page. Défaut : 1. Ignoré si cursor est présent.
size integer Nombre de résultats par page. Défaut : 100. Maximum : 500.

La réponse contient hasNextPage, page et total à la place de nextCursor.

Réponse API avec pagination par offset

{
  "status": "success",
  "data": ["..."],
  "metadata": {
    "pagination": {
      "size": 50,
      "page": 2,
      "total": 82,
      "hasNextPage": false
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11
12

# Valeurs nulles et ordre

Les valeurs nulles sont toujours placées en dernier (NULLS LAST), quelle que soit la direction du tri. L'ordre est déterministe : des tiebreakers internes (nom, date de création, ID) sont appliqués automatiquement lorsque plusieurs enregistrements partagent la même valeur de tri.

# Bonnes pratiques

  • Ne pas conserver un curseur entre sessions. Il encode l'état du tri et peut devenir invalide si le schéma évolue.
  • Utiliser le même paramètre sort sur toutes les pages d'un même parcours.
  • Privilégier la pagination par curseur pour les grands volumes. La pagination par offset (page=) se dégrade significativement au-delà de quelques milliers de lignes.
  • Pour exporter tous les enregistrements, boucler jusqu'à ce que hasNextPage === false.
Contributeurs: Julien