# Pagination

For large result sets, use pagination with the `lastDocId` parameter to fetch subsequent pages.

**How it works:**
1. **First request:** Omit `lastDocId` to get the first page
2. **Store the ID:** Save the `lastDocId` from the response
3. **Next request:** Pass the saved ID as `lastDocId` to get the next page
4. **Repeat:** Continue until no more results are returned

**Paginated Fetching**

_Swift (iOS)_
```swift
// Fetch all workouts with pagination
func fetchAllWorkouts() async throws -> [WorkoutModel] {
    var allWorkouts: [WorkoutModel] = []
    var lastDocId: String? = nil

    repeat {
        let result = await kinestex.fetchWorkouts(
            category: "Fitness",
            limit: 10,
            lastDocId: lastDocId
        )

        switch result {
        case .success(let response):
            allWorkouts.append(contentsOf: response.workouts)
            lastDocId = response.lastDocId

            // If lastDocId is empty or nil, we've reached the end
            if lastDocId?.isEmpty ?? true {
                lastDocId = nil
            }

            print("Fetched page with \(response.workouts.count) workouts")

        case .failure(let error):
            throw error
        }
    } while lastDocId != nil

    print("Total workouts fetched: \(allWorkouts.count)")
    return allWorkouts
}
```

_Kotlin (Android)_
```kotlin
// Fetch all workouts with pagination
suspend fun fetchAllWorkouts(): List<WorkoutModel> {
    val allWorkouts = mutableListOf<WorkoutModel>()
    var lastDocId: String? = null

    do {
        val result = KinesteXSDK.api.fetchAPIContentData(
            contentType = ContentType.WORKOUT,
            category = "Fitness",
            limit = 10,
            lastDocId = lastDocId
        )

        when (result) {
            is APIContentResult.Workouts -> {
                allWorkouts.addAll(result.workouts)
                lastDocId = result.lastDocId?.takeIf { it.isNotEmpty() }

                Log.d("API", "Fetched page with ${result.workouts.size} workouts")
            }
            is APIContentResult.Error -> {
                throw Exception(result.message)
            }
            else -> {
                lastDocId = null
            }
        }
    } while (lastDocId != null)

    Log.d("API", "Total workouts fetched: ${allWorkouts.size}")
    return allWorkouts
}
```

_Flutter_
```dart
// Fetch all workouts with pagination
Future<List<WorkoutModel>> fetchAllWorkouts() async {
  final allWorkouts = <WorkoutModel>[];
  String? lastDocId;

  do {
    final result = await KinesteXAIFramework.apiService.fetchContent(
      contentType: ContentType.workout,
      category: "Fitness",
      limit: 10,
      lastDocId: lastDocId,
    );

    switch (result) {
      case WorkoutsResult(:final response):
        allWorkouts.addAll(response.workouts);
        lastDocId = response.lastDocId.isNotEmpty ? response.lastDocId : null;

        print('Fetched page with ${response.workouts.length} workouts');

      case ErrorResult(:final message):
        throw Exception(message);

      default:
        lastDocId = null;
    }
  } while (lastDocId != null);

  print('Total workouts fetched: ${allWorkouts.length}');
  return allWorkouts;
}
```

_React Native_
```jsx
// Fetch all workouts with pagination
const fetchAllWorkouts = async (category: string): Promise<WorkoutModel[]> => {
  const allWorkouts: WorkoutModel[] = [];
  let lastDocId: string | undefined = undefined;

  do {
    const params = new URLSearchParams({
      category,
      limit: '10',
    });

    if (lastDocId) {
      params.append('lastDocId', lastDocId);
    }

    const response = await fetch(
      `${BASE_URL}/workouts?${params}`,
      { headers }
    );

    if (!response.ok) {
      throw new Error(`API Error: ${response.status}`);
    }

    const data = await response.json();
    allWorkouts.push(...data.workouts);
    lastDocId = data.lastDocId || undefined;

    console.log(`Fetched page with ${data.workouts.length} workouts`);

  } while (lastDocId);

  console.log(`Total workouts fetched: ${allWorkouts.length}`);
  return allWorkouts;
};
```

_HTML / JavaScript_
```html
// Fetch all workouts with pagination
async function fetchAllWorkouts(category) {
  const allWorkouts = [];
  let lastDocId = null;

  do {
    const params = new URLSearchParams({
      category,
      limit: '10',
    });

    if (lastDocId) {
      params.append('lastDocId', lastDocId);
    }

    const response = await fetch(
      `${BASE_URL}/workouts?${params}`,
      { headers }
    );

    if (!response.ok) {
      throw new Error(`API Error: ${response.status}`);
    }

    const data = await response.json();
    allWorkouts.push(...data.workouts);
    lastDocId = data.lastDocId || null;

    console.log(`Fetched page with ${data.workouts.length} workouts`);

  } while (lastDocId);

  console.log(`Total workouts fetched: ${allWorkouts.length}`);
  return allWorkouts;
}
```

_React (TypeScript)_
```tsx
// Fetch all workouts with pagination
const fetchAllWorkouts = async (category: string): Promise<WorkoutModel[]> => {
  const allWorkouts: WorkoutModel[] = [];
  let lastDocId: string | undefined = undefined;

  do {
    const params = new URLSearchParams({
      category,
      limit: '10',
    });

    if (lastDocId) {
      params.append('lastDocId', lastDocId);
    }

    const response = await fetch(
      `${BASE_URL}/workouts?${params}`,
      { headers }
    );

    if (!response.ok) {
      throw new Error(`API Error: ${response.status}`);
    }

    const data: WorkoutsResponse = await response.json();
    allWorkouts.push(...data.workouts);
    lastDocId = data.lastDocId || undefined;

    console.log(`Fetched page with ${data.workouts.length} workouts`);

  } while (lastDocId);

  console.log(`Total workouts fetched: ${allWorkouts.length}`);
  return allWorkouts;
};
```

---
Source: https://kinestex.com/docs/content-api/content-api-pagination · Index: https://kinestex.com/llms.txt
