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

# Pagination

> Learn how to paginate through large datasets using offset-based pagination in the PlanD API

The PlanD API uses offset-based pagination for list endpoints, allowing you to efficiently retrieve large datasets by controlling the number of items returned and skipping items for pagination.

## Pagination Parameters

Based on the API specification, all list endpoints support these pagination parameters:

<ParamField query="limit" type="integer" default="100">
  Maximum number of items to return. Must be between 1 and 1000 for most endpoints.
</ParamField>

<ParamField query="offset" type="integer" default="0">
  Number of items to skip for pagination. Must be 0 or greater.
</ParamField>

<RequestExample>
  ```bash cURL theme={null}
  curl -X GET "https://cloud-api.pland.app/v2/users?limit=50&offset=100" \
    -H "Authorization: Bearer YOUR_JWT_TOKEN"
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={null}
  [
    {
      "_id": "507f1f77bcf86cd799439011",
      "general": {
        "firstName": "John",
        "lastName": "Doe"
      },
      "access": {
        "email": "john@example.com"
      }
    }
  ]
  ```
</ResponseExample>

## Pagination Implementation

<Steps>
  <Step title="Start with the first page">
    Begin with `offset=0` to get the first set of results

    ```bash theme={null}
    GET /users?limit=100&offset=0
    ```
  </Step>

  <Step title="Calculate subsequent pages">
    For each subsequent page, increase the offset by the limit value

    ```bash theme={null}
    # Page 1: offset = 0
    GET /users?limit=100&offset=0

    # Page 2: offset = 100  
    GET /users?limit=100&offset=100

    # Page 3: offset = 200
    GET /users?limit=100&offset=200
    ```
  </Step>

  <Step title="Detect the end of results">
    When the response contains fewer items than the limit, you've reached the end

    <Check>
      If you request 100 items but only receive 50, there are no more pages
    </Check>
  </Step>
</Steps>

## Code Examples

<CodeGroup>
  ```javascript Node.js theme={null}
  async function getAllUsers() {
    const allUsers = [];
    let offset = 0;
    const limit = 100;
    
    while (true) {
      const response = await fetch(
        `https://cloud-api.pland.app/v2/users?limit=${limit}&offset=${offset}`,
        {
          headers: {
            'Authorization': `Bearer ${process.env.PLAND_JWT_TOKEN}`
          }
        }
      );
      
      const users = await response.json();
      allUsers.push(...users);
      
      // If we got fewer results than requested, we're done
      if (users.length < limit) {
        break;
      }
      
      offset += limit;
    }
    
    return allUsers;
  }
  ```

  ```python Python theme={null}
  import requests
  import os

  def get_all_users():
      all_users = []
      offset = 0
      limit = 100
      
      headers = {
          'Authorization': f'Bearer {os.getenv("PLAND_JWT_TOKEN")}'
      }
      
      while True:
          response = requests.get(
              f'https://cloud-api.pland.app/v2/users?limit={limit}&offset={offset}',
              headers=headers
          )
          
          users = response.json()
          all_users.extend(users)
          
          # If we got fewer results than requested, we're done
          if len(users) < limit:
              break
              
          offset += limit
      
      return all_users
  ```

  ```bash cURL Script theme={null}
  #!/bin/bash
  LIMIT=100
  OFFSET=0
  ALL_USERS=""

  while true; do
    RESPONSE=$(curl -s -X GET \
      "https://cloud-api.pland.app/v2/users?limit=${LIMIT}&offset=${OFFSET}" \
      -H "Authorization: Bearer ${PLAND_JWT_TOKEN}")
    
    COUNT=$(echo "$RESPONSE" | jq length)
    
    if [ "$COUNT" -lt "$LIMIT" ]; then
      break
    fi
    
    OFFSET=$((OFFSET + LIMIT))
  done
  ```
</CodeGroup>

## Special Pagination Cases

<AccordionGroup>
  <Accordion title="Payment Terms Endpoint">
    The `/paymentTerms` endpoint uses different parameter names:

    ```bash theme={null}
    GET /paymentTerms?limit=50&skip=100&sortKey=created&sortDirection=asc
    ```

    * Uses `skip` instead of `offset`
    * Maximum limit is 100
    * Has special sort parameters
  </Accordion>

  <Accordion title="Time Tracking Endpoint">
    The `/timeTracking` endpoint has a lower maximum limit:

    ```bash theme={null}
    GET /timeTracking?limit=50&offset=0
    ```

    * Default limit: 50
    * Maximum limit: 500
  </Accordion>

  <Accordion title="User Filtering Endpoint">
    The `POST /users/filter` endpoint uses different parameter names:

    ```json theme={null}
    {
      "filters": [...],
      "limit": 100,
      "skip": 0
    }
    ```

    * Uses `skip` instead of `offset`
    * Parameters are in the request body
  </Accordion>
</AccordionGroup>
