# Pagination scripts

## Introduction

If a standard pagination type can't meet your pagination requirements, you can create a [custom script](https://doc.wearepatchworks.com/product-documentation/developer-hub/custom-scripting/pagination-scripts) and [apply this as the pagination method for endpoints](https://doc.wearepatchworks.com/product-documentation/developer-hub/connector-builder/building-your-own-connector/4-endpoints/endpoint-options/pagination/script-pagination).&#x20;

## Elements of a pagination script

Pagination scripts typically include:

* [Inputs](#inputs)
* [Outputs](#outputs)

### Inputs

Expected inputs must be inside the `payload` key of the `data` array. These are summarised below:

* [Request](#request)
* [Response](#response)&#x20;
* [Payload](#payload)

#### Request

An array/object representing the request parts for the current page:

<table data-full-width="false"><thead><tr><th width="150.89453125">Field</th><th width="200.54296875">Summary</th><th>Example</th></tr></thead><tbody><tr><td><code>body</code></td><td>A string version of the body.</td><td><pre class="language-php" data-overflow="wrap"><code class="lang-php">$returnPayload['body'] = $payload['request']['body'];
</code></pre></td></tr><tr><td><code>headers</code></td><td>An array/object containing a key/value map of request headers. </td><td><pre class="language-php" data-overflow="wrap"><code class="lang-php">$returnPayload['headers'] = $payload['request']['headers'];
</code></pre></td></tr><tr><td><code>method</code></td><td>The HTTP method. </td><td><pre class="language-php" data-overflow="wrap"><code class="lang-php"> $returnPayload = [ 'has_next_page' => false, 'method' => 'GET' ];
</code></pre></td></tr><tr><td><code>url</code></td><td>The entire URL used in the request.</td><td><pre class="language-php" data-overflow="wrap"><code class="lang-php">$returnPayload['url'] = $nextPage;
</code></pre></td></tr></tbody></table>

#### **Response**

An array/object containing the response parts returned from the request:

<table data-full-width="false"><thead><tr><th width="149.60546875">Field</th><th width="200.54296875">Summary</th><th>Example</th></tr></thead><tbody><tr><td><code>headers</code></td><td>An array/object containing a key/value map or response headers.</td><td><pre class="language-php" data-overflow="wrap"><code class="lang-php">$links = $payload['response']['headers']['link'][0];
</code></pre></td></tr><tr><td><code>status_code</code></td><td>The HTTP response code. </td><td></td></tr></tbody></table>

#### **Payload**

The content saved as the payload. For example:

```php
$payload = json_decode($data['payload'], true);
```

### Outputs

If `has_next_page` is true, a JSON-encoded array/object should be returned (within the `payload` field) with the following:

<table data-full-width="false"><thead><tr><th width="155.69921875">Field</th><th width="200.54296875">Summary</th><th>Example</th></tr></thead><tbody><tr><td><code>has_next_page</code></td><td>Whether or not there is another page to be fetched.</td><td><pre class="language-php" data-overflow="wrap"><code class="lang-php">$returnPayload['has_next_page'] = true;
</code></pre></td></tr><tr><td><code>url</code></td><td>The URL to use for the next page request.</td><td><pre class="language-php" data-overflow="wrap"><code class="lang-php">$returnPayload['url'] = $nextPage;
</code></pre></td></tr><tr><td><code>headers</code></td><td>The headers to use for the next page request.</td><td><pre class="language-php" data-overflow="wrap"><code class="lang-php">$returnPayload['headers'] = $payload['request']['headers'];
</code></pre></td></tr><tr><td><code>method</code></td><td>The HTTP method to use for the next page request.</td><td><pre class="language-php" data-overflow="wrap"><code class="lang-php">$returnPayload['method'] = $payload['request']['method'];
</code></pre></td></tr><tr><td><code>body</code></td><td>The body content to use in the next request.</td><td><pre class="language-php" data-overflow="wrap"><code class="lang-php">$returnPayload['body'] = $payload['request']['body'];
</code></pre></td></tr></tbody></table>

## Pagination script example

The sample script below demonstrates `link header` functionality.

<details>

<summary><img src="https://2440044887-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLYNcUBVQwSkOMG6KjZfz%2Fuploads%2FoTQs7eEfsfqZUPfRoiT7%2Ficon_code.svg?alt=media&#x26;token=b4a6f8e5-8ebf-4ef8-ab24-a130d29b50c5" alt="" data-size="line"> Link header pagination script</summary>

{% code lineNumbers="true" %}

```php
 <?php

/**
 * Handler function.
 *
 * @param array $data [
 *      'payload'   => (string|null) the payload as a string|null
 *      'variables' => (array[string]string) any variables as key/value
 *      'meta'      => (array[string]string) any meta as key/value
 *      'flow'      => (array[mixed]) current flow data, including variables
 *    ]
 *
 * @return array $data Structure as above, plus 'logs' => (array[string]) Logs to be written to flow run log after script execution
 */


/**
 * Get next page url from link header string
 */
function getNext(string $linkHeaderString): string|null {
    if (!str_contains($linkHeaderString, 'rel="next"')) {
        return null;
    }

    $stringParts = explode(',', $linkHeaderString);

    $nextLinkString = count($stringParts) === 1 ? $stringParts[0] : $stringParts[1]; 

    $matches = [];

    preg_match_all('/<(.+)>;\s?rel="([A-z]*)"/', $nextLinkString, $matches);

    return $matches[1][0];
}

function handle($data)
{
    $payload = json_decode($data['payload'], true);

    $returnPayload = [
        'has_next_page' => false,
        'method' => 'GET'
    ];

    if (array_key_exists('response', $payload)) {
        if (array_key_exists('headers', $payload['response'])) {
            if (array_key_exists('link', $payload['response']['headers'])) {
                /** check if the header contains the next page link
                    Header will be in the format:

                    <https://custom-peaks-1.myshopify.com/admin/api/2023-04/customers.json?limit=50&page_info=eyJkaXJlY3Rpb24iOiJwcmV2IiwibGFzdF9pZCI6NzIyMjM0MzA0MTE4MiwibGFzdF92YWx1ZSI6MTcwMzE2NDgxMDAwMH0>; rel="previous", <https://custom-peaks-1.myshopify.com/admin/api/2023-04/customers.json?limit=50&page_info=eyJkaXJlY3Rpb24iOiJuZXh0IiwibGFzdF9pZCI6Njg2MjY2MjUzMzI3OCwibGFzdF92YWx1ZSI6MTY4NjM1MDU1OTAwMH0>; rel="next"
                */
                $links = $payload['response']['headers']['link'][0];

                $nextPage = getNext($links);

                if ($nextPage) {
                    $returnPayload['has_next_page'] = true;
                    $returnPayload['url'] = $nextPage;
                    $returnPayload['body'] = $payload['request']['body'];
                    $returnPayload['headers'] = $payload['request']['headers'];
                }
            }
        }
    }


    return [
        'payload' => json_encode($returnPayload)
    ];
}
```

{% endcode %}

</details>
