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

# Pagination

> Page through list endpoint results using cursor-based pagination.

All list endpoints in the Deck API use cursor-based pagination. Each response includes a `data` array, a `has_more` flag, and a `next_cursor` value you pass on subsequent requests to fetch the next page.

## Request parameters

| Parameter | Type    | Default | Description                                               |
| --------- | ------- | ------- | --------------------------------------------------------- |
| `limit`   | integer | 20      | Number of results per page. Min 1, max 100.               |
| `cursor`  | string  |         | Cursor from a previous response. Omit for the first page. |

```bash theme={null}
curl "https://api.deck.co/v2/agents?limit=50" \
  -H "Authorization: Bearer sk_live_your_key_here"
```

## Response format

Every list response has the same shape:

<ResponseField name="data" type="array">
  Array of resource objects for the current page.
</ResponseField>

<ResponseField name="has_more" type="boolean">
  `true` if there are more results beyond this page. `false` on the last page.
</ResponseField>

<ResponseField name="next_cursor" type="string or null">
  An opaque string to pass as the `cursor` query parameter on the next request. `null` when there are no more pages.
</ResponseField>

<ResponseField name="request_id" type="string">
  Unique identifier for the API request.
</ResponseField>

```json theme={null}
{
  "data": [
    { "id": "agt_abc...", "object": "agent", "name": "Hotel Reservations" },
    { "id": "agt_def...", "object": "agent", "name": "Expense Reports" }
  ],
  "has_more": true,
  "next_cursor": "eyJpZCI6ImFnZW50X2RlZiJ9",
  "request_id": "req_a1b2c3d4..."
}
```

## Fetching the next page

Pass `next_cursor` from the previous response as the `cursor` query parameter:

```bash theme={null}
curl "https://api.deck.co/v2/agents?limit=50&cursor=eyJpZCI6ImFnZW50X2RlZiJ9" \
  -H "Authorization: Bearer sk_live_your_key_here"
```

Continue until `has_more` is `false`.

## Paginating through all results

<CodeGroup>
  ```javascript Node.js theme={null}
  async function fetchAll(endpoint) {
    const results = []
    let cursor = null

    do {
      const url = new URL(`https://api.deck.co/v2/${endpoint}`)
      url.searchParams.set('limit', '100')
      if (cursor) url.searchParams.set('cursor', cursor)

      const res = await fetch(url, {
        headers: { 'Authorization': `Bearer ${process.env.DECK_API_KEY}` },
      })

      const page = await res.json()
      results.push(...page.data)
      cursor = page.next_cursor
    } while (cursor)

    return results
  }

  const allAgents = await fetchAll('agents')
  ```

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

  def fetch_all(endpoint):
      results = []
      cursor = None

      while True:
          params = {"limit": 100}
          if cursor:
              params["cursor"] = cursor

          res = requests.get(
              f"https://api.deck.co/v2/{endpoint}",
              headers={"Authorization": f"Bearer {DECK_API_KEY}"},
              params=params,
          )

          page = res.json()
          results.extend(page["data"])

          if not page["has_more"]:
              break
          cursor = page["next_cursor"]

      return results

  all_agents = fetch_all("agents")
  ```

  ```go Go theme={null}
  func fetchAll(endpoint string) ([]json.RawMessage, error) {
  	var results []json.RawMessage
  	cursor := ""

  	for {
  		u := fmt.Sprintf("https://api.deck.co/v2/%s?limit=100", endpoint)
  		if cursor != "" {
  			u += "&cursor=" + cursor
  		}

  		req, _ := http.NewRequest("GET", u, nil)
  		req.Header.Set("Authorization", "Bearer "+os.Getenv("DECK_API_KEY"))

  		resp, err := http.DefaultClient.Do(req)
  		if err != nil {
  			return nil, err
  		}
  		defer resp.Body.Close()

  		var page struct {
  			Data       []json.RawMessage `json:"data"`
  			HasMore    bool              `json:"has_more"`
  			NextCursor *string           `json:"next_cursor"`
  		}
  		json.NewDecoder(resp.Body).Decode(&page)
  		results = append(results, page.Data...)

  		if !page.HasMore || page.NextCursor == nil {
  			break
  		}
  		cursor = *page.NextCursor
  	}

  	return results, nil
  }
  ```
</CodeGroup>

## Filtering and sorting

List endpoints may accept additional query parameters for filtering. Filters are applied server-side before pagination, so the `limit` applies to filtered results.

```bash theme={null}
curl "https://api.deck.co/v2/task-runs?credential_id=cred_abc123&limit=50" \
  -H "Authorization: Bearer sk_live_your_key_here"
```

Results are returned in reverse chronological order (newest first) by default.

## Cursors are opaque

Cursor values are opaque strings. Do not parse, construct, or store them long-term. They encode internal position state and may change format between API versions.

* Pass them exactly as received from the API.
* Do not reuse cursors across different endpoints or filter combinations.
* If a cursor becomes invalid, the API returns a `400` error with `cursor_invalid`. Start from the first page.

## Stable ordering

Deck guarantees stable ordering within a paginated sequence. If no records are created or deleted between requests, every record appears exactly once across all pages. Records created after you begin paginating may or may not appear depending on their position in the sort order.
