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

# Pagination & expanding

> How to walk lists and how to fetch related objects in one round-trip.

## Pagination

Every list method returns a cursor envelope:

```json theme={null}
{
  "data": [ /* up to `limit` records */ ],
  "has_more": true,
  "next_cursor": "crs_01HX9..."
}
```

The default limit is **20**. The maximum is **100**.

<CodeGroup>
  ```ts TypeScript theme={null}
  let cursor: string | undefined;
  do {
    const page = await hk.courses.list({ limit: 100, starting_after: cursor });
    for (const c of page.data) console.log(c.id);
    cursor = page.has_more ? page.next_cursor : undefined;
  } while (cursor);
  ```

  ```php PHP theme={null}
  $cursor = null;
  do {
      $page = $hk->courses->list(['limit' => 100, 'starting_after' => $cursor]);
      foreach ($page->data as $c) {
          echo $c->id . "\n";
      }
      $cursor = $page->has_more ? $page->next_cursor : null;
  } while ($cursor);
  ```
</CodeGroup>

For ergonomics, all list methods are also iterable — the iterator
transparently fetches the next page when you reach the end of the
current one.

<CodeGroup>
  ```ts TypeScript theme={null}
  for await (const course of hk.courses.list({ limit: 100 })) {
    console.log(course.id);
  }
  ```

  ```php PHP theme={null}
  foreach ($hk->courses->list(['limit' => 100])->autoPagingIterator() as $course) {
      echo $course->id . "\n";
  }
  ```
</CodeGroup>

## Expanding related objects

Most retrieval methods accept `expand` to inline related resources in
the same response, à la SQL `JOIN`. This avoids the N+1 problem.

<CodeGroup>
  ```ts TypeScript theme={null}
  const course = await hk.courses.retrieve("crs_123", {
    expand: ["cohorts", "cohorts.lessons", "cohorts.lessons.activities"],
  });

  // course.cohorts[0].lessons[0].activities[0] is a fully-hydrated Activity
  ```

  ```php PHP theme={null}
  $course = $hk->courses->retrieve('crs_123', [
      'expand' => ['cohorts', 'cohorts.lessons', 'cohorts.lessons.activities'],
  ]);

  // $course->cohorts[0]->lessons[0]->activities[0] is a fully-hydrated Activity
  ```
</CodeGroup>

You can expand up to **3 levels deep**, and up to **5 paths per call**.
Expanding past the limit returns `400 invalid_request_error` with
`code: "expand_too_deep"`.

### What's expandable on each resource

| Resource     | Expandable paths                                                            |
| ------------ | --------------------------------------------------------------------------- |
| `Course`     | `cohorts`, `cohorts.units`, `cohorts.lessons`, `cohorts.lessons.activities` |
| `Cohort`     | `course`, `units`, `lessons`, `students`, `teachers`                        |
| `Unit`       | `lessons`, `lessons.activities`                                             |
| `Lesson`     | `unit`, `activities`, `content`, `assignment`                               |
| `Activity`   | `questions`, `lesson`                                                       |
| `Assignment` | `lesson`, `submissions`                                                     |
| `Submission` | `assignment`, `student`                                                     |
| `User`       | `cohorts`, `courses`                                                        |

Anything not in this table is fetched lazily — i.e. you'll need a
separate retrieval call.

## Filtering on lists

List methods accept resource-specific filters as parameters:

<CodeGroup>
  ```ts TypeScript theme={null}
  hk.cohorts.list({ course_id: "crs_123", status: "active" });
  hk.lessons.list({ cohort_id: "coh_123", type: "video" });
  hk.submissions.list({ assignment_id: "asg_123", student_id: "usr_123" });
  ```

  ```php PHP theme={null}
  $hk->cohorts->list(['course_id' => 'crs_123', 'status' => 'active']);
  $hk->lessons->list(['cohort_id' => 'coh_123', 'type' => 'video']);
  $hk->submissions->list(['assignment_id' => 'asg_123', 'student_id' => 'usr_123']);
  ```
</CodeGroup>

Refer to each list method's API reference for the exhaustive list.
