KinesteX

Pagination & Caching

Pagination


The pagination object is identical on all three list endpoints and is always present, even when the page is empty.


json
1{
2  "total": 42,
3  "limit": 20,
4  "offset": 0,
5  "total_pages": 3,
6  "current_page": 1,
7  "has_next": true,
8  "has_prev": false
9}

FieldMeaning
totalDistinct rows matching every filter
limitPage size actually applied
offsetRows skipped
total_pagesPages at the current limit
current_pageDerived from offset / limit, 1-based
has_next / has_prevWhether another page exists in that direction

  • limit above 100 is silently clamped to 100. A zero, negative, or non-numeric value falls back to 10.
  • A negative or non-numeric offset falls back to 0.
  • total counts distinct rows, so it is safe to drive an infinite scroll from it.

Walking every page:


javascript
1async function fetchAllExercises(params = {}) {
2  const items = [];
3  let offset = 0;
4  const limit = 50;
5
6  for (;;) {
7    const query = new URLSearchParams({ ...params, limit, offset });
8    const res = await fetch(
9      `https://data.kinestex.com/api/exercises/client?` + query,
10      { headers: { "x-api-key": process.env.KINESTEX_API_KEY, Language: "en" } }
11    );
12    if (!res.ok) throw new Error(`Content API ` + res.status);
13
14    const page = await res.json();
15    items.push(...page.exercises);
16    if (!page.pagination.has_next) return items;
17    offset += limit;
18  }
19}

Caching


List responses are cached for up to 5 minutes, keyed per company, per language, and per exact query string, so two different filter combinations never serve each other's results. Single-item responses are cached for up to 15 minutes. Both caches are invalidated when the underlying content is edited, so in normal use you see changes quickly; allow for the window when you write tests that create content and immediately list it.


Performance tips


  • Keep include_exercises and include_weeks at their false default for browsing lists. Turn them on only for the screen that actually plays the content.
  • Prefer server-side filters over fetching everything and filtering client-side. Every filter listed here runs in SQL.
  • Keep page sizes moderate (10 to 20 for a UI, up to 100 for a sync job).
  • Use translation_languages as a filter when you need a fully localized catalog, rather than fetching everything and discarding items with a null translation.