API Connector Documentation
Pagination Handling
Many API servers return only a limited number of rows in each response, and require that you loop through multiple pages to retrieve records for a given request. This is known as "pagination".
The API Connector add-on for Sheets provides automatic pagination handling for most types of paginated API responses.
Contents
- Overview of Pagination Types
- Set Cursor Pagination
- Set Cursor Body Pagination
- Set Next Page URL Pagination
- Set Offset-Limit Pagination
- Set Offset-Limit Body Pagination
- Set Page Parameter Pagination
- Set Page Parameter Body Pagination
- "Run Until" Options
- Troubleshooting
- Notes
Overview of Pagination Types
There are several common types of pagination:
- Cursor (Examples: Asana, Facebook, Stripe).
The API responds to each request with a token (aka 'cursor'). Sending this token back in a URL parameter tells the API where to start the next response.- Page 1:
https://example.com/api
- Page 2:
https://example.com/api?starting_after=ch_1GFKhoIdg4lVxjo0eKhB4dkD
- Page 1:
- Cursor body (Examples: Crunchbase, Notion)
As above, the API responds to each request with a token (aka 'cursor'). Sending this token back in the request body tells the API where to start the next response.- Page 1 body:
{"after_id":""}
- Page 2 body:
{"after_id":"gh82slf"}
- Page 1 body:
- Next-page URL (Examples: Asana, Facebook, Harvest, Shopify)
The API returns a field containing the URL for the next page. This URL may be provided in the body of the response or the response headers, and may contain the entire URL or just the relative path. Next page URLs are usually provided in conjunction with another pagination type. - Offset-limit (Examples: ActiveCampaign, Mailchimp)
Parameters are set in the URL to tell the API the starting point and size of each slice of data.- Page 1:
https://example.com/api?offset=0&limit=100
- Page 2:
https://example.com/api?offset=100&limit=100
- Page 1:
- Offset-limit body (Examples: Google Search Console, Hubspot)
Parameters are set in the request body to tell the API the starting point and size of each slice of data.- Page 1 body:
{"startRow":0, "rowLimit": 1000}
- Page 2 body:
{"startRow":1000, "rowLimit": 1000}
- Page 1 body:
- Page (Examples: Harvest, Toggl)
A parameter is set in the URL that identifies which page number you'd like to fetch. Sometimes an additional parameter can be included that sets the size of each page.- Page 1:
https://example.com/api?page=1&pageSize=100
- Page 2:
https://example.com/api?page=2&pageSize=100
- Page 1:
- Page Parameter Body (Example: Clockify)
A parameter is set in the request body to identify which page number you'd like to fetch. Sometimes an additional parameter can be included to set the page size.- Page 1 body:
{"page":1, "pageSize": 1000}
- Page 2 body:
{"page":2, "pageSize": 1000}
- Page 1 body:
The pagination type varies for each API, so if you need to retrieve paginated responses, please consult your API documentation for details. You can usually find this information by searching for terms like "paging", "pagination", and "limit".
Set Cursor Pagination
- Pagination type:
cursor
- Next token parameter: enter the name of the parameter in the URL that sends the token.
- Next token path: enter the path to the field in your sheet that contains the token, using dot notation for nested values. This field will be pre-populated with a drop-down list if the request has been run at least once.
- Run until: choose when the request should stop running. More info >
Set Cursor Body Pagination
- Pagination type:
cursor body
- Next token parameter: enter the name of the parameter in the request body that sends the token.
- Next token path: enter the path to the field in your sheet that contains the token, using dot notation for nested values. This field will be pre-populated with a drop-down list if the request has been run at least once.
- Run until: choose when the request should stop running. More info >
Set Next Page URL Pagination
- Pagination type:
next page URL
- Next page path: enter the path to the field in your sheet containing the next page URL, using dot notation for nested values. This field will be pre-populated with a drop-down list if the request has been run at least once, or you can type in your own field name manually (You will need to manually type in the word
Link
for most APIs that paginate through response headers). - Run until: choose when the request should stop running. More info >
Next Page URL Variations
Two variations on next page URLs are also supported:
- Next page URLs in response headers. If the next page URL field name is not found in the response body, API Connector will automatically check the response header. This is useful for APIs like Shopify and Okta, which paginate via next page URLs in the response headers.
- "Relative" next page URLs. In some cases the next page URL contains only the path and not the full URL. API Connector will automatically detect and append the hostname for these relative paths.
Set Offset-Limit Pagination
- Pagination type:
offset-limit
- Offset parameter: enter the name of the offset parameter in the URL. This is usually
offset
, but some APIs use a different term likeafter
,start
, orskip
. - Limit parameter: enter the name of the limit parameter in the URL. This is usually
limit
, but some APIs use a different term likecount
,num
, ortop
. - Run until: choose when the request should stop running. More info >
Set Offset-Limit Body Pagination
- Pagination type:
offset-limit body
- Offset body parameter: enter the path to the offset parameter in the request body.
- Limit body parameter: enter the path to the limit parameter in the body.
- Run until: choose when the request should stop running. More info >
Set Page Parameter Pagination
- Pagination type:
page parameter
- Page parameter: enter the name of the page parameter in the URL. This is almost always
page
, but occasionally APIs use a different parameter likep
. - Run until: choose when the request should stop running. More info >
Set Page Parameter Body Pagination
- Pagination type:
page parameter body
- Page body parameter: enter the path to the page parameter in the request body.
- Run until: choose when the request should stop running. More info >
"Run Until" Options
The "Run until" option tells API Connector when to stop looping through your paginated request.
- Page count equals
Run your request a specific number of times. - Response field empty
Run your request until a specific field is no longer populated. This field will be pre-populated with a drop-down list if the request has been run at least once, or you can type in your own field name. Choose a field that appears in every record of your desired results set, e.g. an ID or name. When this field is no longer populated, the request will stop looping. - No data returned
Run your request until the API stops returning data.
Tip: This option is most suitable for APIs that use cursor or next page URL pagination. Other pagination types may time out (see the Troubleshooting section for more info).
Troubleshooting
- Running pagination until no data is returned may cause some requests to time out, particularly those that use page parameter or offset-limit pagination. This is because these pagination types often continue returning metadata even after the results set is complete, such that the response is never totally empty. To address, set the request to stop running once a page count has been reached or a specific field is empty.
- Large levels of pagination tend to bump up against Google Sheets' limits (most commonly the 6 mins/execution limit) and risk failing altogether. In those cases you will see a 'Failed to run request' error message. If you run into issues with queries timing out, try splitting your requests by other parameters, and then paginating through them separately.
- These pagination methods are designed for standard REST APIs and will not work with GraphQL or XML request bodies.
Notes
- Google tracks each call as a urlfetch, so if you run a request that fetches 5 pages, Google will count 5 urlfetch calls towards your daily quota.
- When running paginated requests, a 2 second delay is automatically inserted between requests to avoid rate limits.
- The nine pagination methods (7 main methods + 2 variations) listed above are the most common pagination types, but it's possible you will encounter an API that uses some other method of pagination. In those cases, feel free to post below or contact us with details of your API so we can consider adding support in a future release.
Can you add a feature for a data range in the pagination parameters? I have an API that can only pull data 180 days at a time, and don't know how to do that here. Thank you!
Hey Al, I think stacking your request URLs would work. That way you can list out all your URLs and API Connector will run through them one after the other.
hi Ana,
with regards to pagination handling for shopify, i can't seem to get the next page example to work.
i'm still hitting the 250 records limit.
That's weird, mind messaging me via the contact form so I can take a look?
strike that, managed to solve this by using 'link' instead of 'paging.next' that i lifted wholesale from the example.
Yeah, Shopify paginates with a "link" URL in the header. Glad you got it working!
For this API, how would you suggest I setup the pagination settings?
https://developers.karbonhq.com/api#operation/WorkItems_Get
Hey Chad, based on that link you should be able to set it up like this:
Please try that and let me know how it goes!
When using that method, it only brought up the default 100 line items.
So I tried: offset-limit and that worked.
Offset parameter: $skip
Limit parameter: count
Limit value: 100
Number of pages: 5
That gave me 500 records.
I tried 'all pages' but that timed out.
Is there a way to download to google sheets, say, 2500 records at a time until all records are downloaded?
I'm able to do it manually by adding a url parameter of $skip=2500 (where 2500 = the number of rows already in the spreadsheet) using an append output mode. But it'd be cool if this could be done automatically!
Thanks!
Interesting, I'm not sure why that didn't work. I wonder if it's because you have to specify the $top variable in the initial request URL, like
https://api.karbonhq.com/v3/WorkItems?$top=100
Their docs aren't that clear, but anyway I'm glad you've got it sorted with offset/limit pagination instead.
Hi!
My API request is
https://api.u-on.ru/APIKEY/requests/2021-08-01/2021-09-30/1.json
where 1 is page number.
As you can see there isn't a parameter like "page".
So can I handle with such URL using pagination feature? I need that so much.
Hi Alex, you can use multi-query requests for this. If you check the section called "Why Use the Multi-Query Function", there's an example of using that function for this use case (it's called 'page directory pagination'). Basically you just list your URLs in the URL box, like this:
https://api.u-on.ru/APIKEY/requests/2021-08-01/2021-09-30/1.json
https://api.u-on.ru/APIKEY/requests/2021-08-01/2021-09-30/2.json
Yes, thanks. And I am using this option now. I have no choice)
But it is very uncomfortable for us. Because requests dates are changing very often and we have a lot of pages. So we need to use CONCAT Google Sheet function all the time to generate URLs and then copy/paste them.
May be you can consider such option.
For example there is a parameter like +++pagination+++. We insert it in our URL, indicate a starting point (for example "1") and get incremental pagination.
Like
https://api.u-on.ru/APIKEY/requests/2021-08-01/2021-09-30/+++pagination+++.json
It would be fantastic for us.
Thank you for the suggestion, I'll definitely consider adding a new type of pagination for this.
For now, how about creating a tab that contains all the numbers you need in a column, say from 1 to 100. Then you can just make a single URL that says
https://api.u-on.ru/APIKEY/requests/2021-08-01/2021-09-30/+++Sheet1!A1:A100+++.json
and it will substitute in all 100 digits so it runs through all 100 pages. You can do that with the existing multi-query function.Wow! I didn't know about this option. It is much easier. Thank you!
There is only one problem. In our case we don't know exact number of pages. It may be 1 page, and may be 100 or even 150 pages. So we have to make 100 calls everytime and thus make excessive load on the server. And our provider is very angry for that.
It seems a bit unreasonable that they provide non-standard pagination, and then don't like that people can't easily paginate it :p
I suppose you can make one call and then set your cycle count based on the total number of records (assuming they return that in the first response).
Feel free to email me through support if you'd like to think through some ideas together.
Ok, thank you. Don't want to divert you. I will discuss this question with provider. Thank you again.
Hi Ana - I'm running into a couple issues with pagination for Recurly's API: https://developers.recurly.com/api/v2021-02-25/index.html#tag/account
When it returns the paginated URL, it returns it without the
https://v3.recurly.com
. So when I use next page pagination, I get the below error message:Bad request: http:///accounts?cursor=ppgsqfv41tq3%3A1634130820.0&limit=10&sort=created_at&subscriber=true
When I try to use cursor pagination, the response appears to add additional characters to the id (see above, after the % in the cursor value) which causes it to throw an error for invalid request.
{"error":{"type":"validation","message":"Please provide valid values for these parameters: cursor","params":[{"param":"cursor","message":"format is invalid"}]}}
Any thoughts?
Thanks, I created a Recurly account and verified what you said. Recurly's next page URL isn't the complete URL, and the cursor they provide isn't the complete cursor either. So unfortunately we don't currently have a pagination method for this. I'll try to add pagination handling for "next-page relative URLs" in the future, that should take care of it. For now, though, I'm afraid you can only do this semi-manually, by running your request with the limit=200 maximum, then creating a new URL with
https://v3.recurly.com
+ the value in the "next" field, and running it in append mode to stick it onto the end of your existing setup. Of course that might not be practical at all if you're pulling a lot of data. Sorry about that.Thanks for the quick response and for taking the time to investigate! Your suggestion should work for us in the short term as we'll only need ~2000 records.
Update: we now support relative URLs through the "next page" pagination type. I've updated the article to reflect this.
Ana! First of all, thank you for of your help on the forums!
If we have a large data set in harvest with over 1300 pages, what would be the command to request that? Is there a way to place a timed break in between of the multi requests?
Hello Art! Thank you for your nice comment 🙂 1300 pages will be hard to manage through this extension, since requests time out after about 6 minutes. Even just pasting in 130,000 records (1300 pages * 100 records each) without calling an API can make Sheets quite slow, since Sheets isn't great at handling large data sets.
So this might not be the best tool for the job, but this is what I would try:
page=X
parameter in your request URL. Repeat as many times as you need until you get all your data, using Append mode so it all appends into the same sheet.Depending on what you're looking for, an alternative method could be to export all the historical data while logged into Harvest, then use the API just to fetch new data.
I am trying Zoom's API and they use next_page_token pagination. Isee the page token when I pull data, but don't know how to implement
Hey Tim, that would be cursor pagination, you should be able to set it up like this:
Pagination type: cursor
Next token parameter: next_page_token
Next token path: next_page_token
Please check if that works for you.
Awesome, thanks this is very empowering!
Hello Ana! Thank you for all the information on this forum. I am currently looking to import data from Vimeo into Google Sheets (the name, file, password etc of videos), and I am using the Vimeo API for the video page and I'm unsure which pagination option to use to return all the data into google sheets from all the pages of videos. When I first tried it without the pagination option it only returned the first page of videos that show up on Vimeo.
Hi Sofia, Vimeo uses both 'page parameter' and 'next page URL' pagination. I added some info on it to this article, please check.
How can I use this with Facebook Insights? I'm having this problem
https://prnt.sc/Fh6_DLjbGW5J
That's cursor pagination. You can check this article for instructions and a screenshot for setting up pagination for Facebook.
Hi there, Im trying to use this for
https://developer.fleetio.com/reference/vehicles
which specifies pagination settings here
https://developer.fleetio.com/reference/pagination
which is simple :
https://secure.fleetio.com/api/v1/vehicles?page=2
I tried using pagination option "next page url" and specified the path (
https://secure.fleetio.com/api/v1/vehicles?page=2
) but i still see only results from page 1 (first 100 rows)The path is for the location of the next page URL in the API response, it shouldn't be a URL.
In this case I believe you should just be using page parameter pagination, entering the word
page
as the page parameter.Hi,
I am using this https://developers.livechat.com/docs/management/configuration-api/v2.0#get-list-of-chats-deprecated which returns the number of pages in the initial call.
The number of pages available is dynamic - when attempting to use the page parameter pagination - I would like to set the variable to the number of pages to retrieve. Could you advise on how to handle this situation? i.e. not hard code the "Number of pages" variable.
Thank in advance for your assistance.
Warren
We don't have a dynamic page option, but you can set your request to stop running when a field is no longer returning data. For example you could set it to stop running when the
chats.id
field is empty, then it will stop running when the data set completes without needing to specify a particular number of pages.Thank you for this advice! I managed to get the pagination working when doing a test when directly running this function (from the sheet UI).
When attempting to call this request from a cell using the IMPORTAPI function, the pagination does not seem to work? Is there anything in addition I should be doing?
Thanks for your prompt assistance so far!
Regards, Warren
Hey Warren, there should be no difference between running the request from the sidebar via calling it via IMPORTAPI so I'm not yet sure why it's not working. Are you getting an error, and, if so, what does it say?
Hi Ana,
Thanks again, there isn’t any error thrown. The importAPI just returns the first page of results, the “UI” paginates and returns all pages.. I also looked at comparison table and see there is a 30 second limit on ImportAPI calls.. could this be what is causing the issue? Thanks again, Warren
Sorry, I can't replicate that, in my tests IMPORTAPI always returns any pagination that was applied to the saved request. It's also relatively rare for a request to take more than 30 seconds to complete, so I don't think that's the issue either. Mind contacting support with more information about your request configuration so I can take a look?
Hello Ana I am trying to select the "pagina" for the Page parameter body, but the "param[0].pagina" notation isn't working. I'm using the page parameter body with Run until response field empty. The only part that is missing is the array nesting.
Request below:
{
"call": "ListarProdutos",
"app_key": "***",
"app_secret": "***",
"param": [
{
"pagina": 1,
"registros_por_pagina": 1,
"apenas_importado_api": "N",
"filtrar_apenas_omiepdv": "N"
}
]
}
This looks like a request to Omie. Please check here for information on paginating through their API: https://mixedanalytics.com/knowledge-base/import-omie-data-to-google-sheets/#documentation. In this case the page parameter is likely param[].pagina, not param[0].pagina
Hi,
I have a whole series of APIs that end with the following:
https://......./event/1
https://......./event/2
https://......./event/3
etc
Is there a way to set up a GET pagination with this suffix?
Would really love to avoid inputting all 38 (and they are weekly so it would be weekly inputs, or scheduling)
Thanks
Hi - unfortunately there isn't a way to do this directly with pagination, but you can use multi-query requests. Please see this comment for reference: https://mixedanalytics.com/knowledge-base/pagination-handling/#comment-25371