Skip to main content
cancel
Showing results for 
Search instead for 
Did you mean: 

Microsoft is giving away 50,000 FREE Microsoft Certification exam vouchers. Get Fabric certified for FREE! Learn more

Reply
smeetsh
Resolver II
Resolver II

using pagination to pull data from a REST api

Hi All,

 

I am using a pipeline in fabric to pull data from an API. In itself a simple task but the API is paginated and I can't get the copy activity to cycle through it correctly.

my relative url to pull the data is: /api/v1/livestock-events?page={page}. As a pagination rule I have set: header as a range, which starts at 1, has no end and an offset of one.

smeetsh_0-1744598456138.png

 

I can't find what i need to set as end condition.

The json from the API has some meta data that indicates things like current_page and last_page What is the expression for the end condition? The main problem is I cant hardcode the end of the range, since that will vary over time.

The json metadata looks like:

"meta": {
        "current_page": 2,
        "from": 3,
        "last_page": 159,
        "per_page": 2,
        "to": 4,
        "total": 318
    }



Thanks Hans




1 ACCEPTED SOLUTION
smeetsh
Resolver II
Resolver II

I managed to sort it out (in this scenario anyway). In the json response there are links to "next page"

 

In my json array 

 

there is an array named "links" and in that array is a key/value pair "next" The key  "next" stores the actual link to the next page, and if there is no more next page it will have a value null.

 

As an example:

-----

"links": {
        "first": "https://myurl/api/v1/events?page=1",
        "prev": null,
    },

-----

 

If the api response has this (and from what I can gather it is actually a standard), the solution for pagination is very simple. Under the pagination rules you have to enter the following

smeetsh_0-1744663520228.png

The thing I couldn't figure out (and copilot completely missed it) is that you use AbsoluteUrl, you leave the next column blank and under value you choose body with that value in my case links.next. Links comes from the array name "links",  and "next" is the key that holds the url for the next page, and if there is no more next page it becomes null, and the copy activity will end.

 

As another example: if the array name had been pagination and the key next_page, then the value would have been "pagination.next_page"

I hope this helps others to handle pagination. If your json response does not have an array  for pagination like mine had. It really becomes dependant on what the API is capable of and that could mean some how storing the last page value in in variable and looping through it.

Cheers

Hans

 

View solution in original post

3 REPLIES 3
smeetsh
Resolver II
Resolver II

I managed to sort it out (in this scenario anyway). In the json response there are links to "next page"

 

In my json array 

 

there is an array named "links" and in that array is a key/value pair "next" The key  "next" stores the actual link to the next page, and if there is no more next page it will have a value null.

 

As an example:

-----

"links": {
        "first": "https://myurl/api/v1/events?page=1",
        "prev": null,
    },

-----

 

If the api response has this (and from what I can gather it is actually a standard), the solution for pagination is very simple. Under the pagination rules you have to enter the following

smeetsh_0-1744663520228.png

The thing I couldn't figure out (and copilot completely missed it) is that you use AbsoluteUrl, you leave the next column blank and under value you choose body with that value in my case links.next. Links comes from the array name "links",  and "next" is the key that holds the url for the next page, and if there is no more next page it becomes null, and the copy activity will end.

 

As another example: if the array name had been pagination and the key next_page, then the value would have been "pagination.next_page"

I hope this helps others to handle pagination. If your json response does not have an array  for pagination like mine had. It really becomes dependant on what the API is capable of and that could mean some how storing the last page value in in variable and looping through it.

Cheers

Hans

 

v-pbandela-msft
Community Support
Community Support

Hi @smeetsh,

Thank you for reaching out in Microsoft Community Forum.

Please follow below steps for Dynamic Pagination;

1.Use a Web Activity to call the API for page 1.

2.Extract last_page from the response (body.meta.last_page).

3.Store last_page in a pipeline variable and Use a ForEach Activity that loops from 1 to last_page.

4.Inside the loop, use a Copy Activity to fetch data for each page (/api/v1/livestock-events?page=@{item()}).

Please continue using Microsoft community forum.

If you found this post helpful, please consider marking it as "Accept as Solution" and give it a 'Kudos'. if it was helpful. help other members find it more easily.

Regards,
Pavan.

Thanks for this, I had thought about looping and this sounds like a good way forward but how do I extract that value from the response? Would that be done by creating at table in my lakehouse map that value to a column in there? And then use a loop, reading that one specific value form the lakehouse table. How would I increment the value from one to last page though?

Helpful resources

Announcements
MarchFBCvideo - carousel

Fabric Monthly Update - March 2025

Check out the March 2025 Fabric update to learn about new features.

March2025 Carousel

Fabric Community Update - March 2025

Find out what's new and trending in the Fabric community.

"); $(".slidesjs-pagination" ).prependTo(".pagination_sec"); $(".slidesjs-pagination" ).append("
"); $(".slidesjs-play.slidesjs-navigation").appendTo(".playpause_sec"); $(".slidesjs-stop.slidesjs-navigation").appendTo(".playpause_sec"); $(".slidesjs-pagination" ).append(""); $(".slidesjs-pagination" ).append(""); } catch(e){ } /* End: This code is added by iTalent as part of iTrack COMPL-455 */ $(".slidesjs-previous.slidesjs-navigation").attr('tabindex', '0'); $(".slidesjs-next.slidesjs-navigation").attr('tabindex', '0'); /* start: This code is added by iTalent as part of iTrack 1859082 */ $('.slidesjs-play.slidesjs-navigation').attr('id','playtitle'); $('.slidesjs-stop.slidesjs-navigation').attr('id','stoptitle'); $('.slidesjs-play.slidesjs-navigation').attr('role','tab'); $('.slidesjs-stop.slidesjs-navigation').attr('role','tab'); $('.slidesjs-play.slidesjs-navigation').attr('aria-describedby','tip1'); $('.slidesjs-stop.slidesjs-navigation').attr('aria-describedby','tip2'); /* End: This code is added by iTalent as part of iTrack 1859082 */ }); $(document).ready(function() { if($("#slides .item").length < 2 ) { /* Fixing Single Slide click issue (commented following code)*/ // $(".item").css("left","0px"); $(".item.slidesjs-slide").attr('style', 'left:0px !important'); $(".slidesjs-stop.slidesjs-navigation").trigger('click'); $(".slidesjs-previous").css("display", "none"); $(".slidesjs-next").css("display", "none"); } var items_length = $(".item.slidesjs-slide").length; $(".slidesjs-pagination-item > button").attr("aria-setsize",items_length); $(".slidesjs-next, .slidesjs-pagination-item button").attr("tabindex","-1"); $(".slidesjs-pagination-item button").attr("role", "tab"); $(".slidesjs-previous").attr("tabindex","-1"); $(".slidesjs-next").attr("aria-hidden","true"); $(".slidesjs-previous").attr("aria-hidden","true"); $(".slidesjs-next").attr("aria-label","Next"); $(".slidesjs-previous").attr("aria-label","Previous"); //$(".slidesjs-stop.slidesjs-navigation").attr("role","button"); //$(".slidesjs-play.slidesjs-navigation").attr("role","button"); $(".slidesjs-pagination").attr("role","tablist").attr("aria-busy","true"); $("li.slidesjs-pagination-item").attr("role","list"); $(".item.slidesjs-slide").attr("tabindex","-1"); $(".item.slidesjs-slide").attr("aria-label","item"); /*$(".slidesjs-stop.slidesjs-navigation").on('click', function() { var itemNumber = parseInt($('.slidesjs-pagination-item > a.active').attr('data-slidesjs-item')); $($('.item.slidesjs-slide')[itemNumber]).find('.c-call-to-action').attr('tabindex', '0'); });*/ $(".slidesjs-stop.slidesjs-navigation, .slidesjs-pagination-item > button").on('click keydown', function() { $.each($('.item.slidesjs-slide'),function(i,el){ $(el).find('.c-call-to-action').attr('tabindex', '-1'); }); var itemNumber = parseInt($('.slidesjs-pagination-item > button.active').attr('data-slidesjs-item')); $($('.item.slidesjs-slide')[itemNumber]).find('.c-call-to-action').attr('tabindex', '0'); }); $(".slidesjs-play.slidesjs-navigation").on('click', function() { $.each($('.item.slidesjs-slide'),function(i,el){ $(el).find('.c-call-to-action').attr('tabindex', '-1'); }); }); $(".slidesjs-pagination-item button").keyup(function(e){ var keyCode = e.keyCode || e.which; if (keyCode == 9) { e.preventDefault(); $(".slidesjs-stop.slidesjs-navigation").trigger('click').blur(); $("button.active").focus(); } }); $(".slidesjs-play").on("click",function (event) { if (event.handleObj.type === "click") { $(".slidesjs-stop").focus(); } else if(event.handleObj.type === "keydown"){ if (event.which === 13 && $(event.target).hasClass("slidesjs-play")) { $(".slidesjs-stop").focus(); } } }); $(".slidesjs-stop").on("click",function (event) { if (event.handleObj.type === "click") { $(".slidesjs-play").focus(); } else if(event.handleObj.type === "keydown"){ if (event.which === 13 && $(event.target).hasClass("slidesjs-stop")) { $(".slidesjs-play").focus(); } } }); $(".slidesjs-pagination-item").keydown(function(e){ switch (e.which){ case 37: //left arrow key $(".slidesjs-previous.slidesjs-navigation").trigger('click'); e.preventDefault(); break; case 39: //right arrow key $(".slidesjs-next.slidesjs-navigation").trigger('click'); e.preventDefault(); break; default: return; } $(".slidesjs-pagination-item button.active").focus(); }); }); // Start This code is added by iTalent as part of iTrack 1859082 $(document).ready(function(){ $("#tip1").attr("aria-hidden","true").addClass("hidden"); $("#tip2").attr("aria-hidden","true").addClass("hidden"); $(".slidesjs-stop.slidesjs-navigation, .slidesjs-play.slidesjs-navigation").attr('title', ''); $("a#playtitle").focus(function(){ $("#tip1").attr("aria-hidden","false").removeClass("hidden"); }); $("a#playtitle").mouseover(function(){ $("#tip1").attr("aria-hidden","false").removeClass("hidden"); }); $("a#playtitle").blur(function(){ $("#tip1").attr("aria-hidden","true").addClass("hidden"); }); $("a#playtitle").mouseleave(function(){ $("#tip1").attr("aria-hidden","true").addClass("hidden"); }); $("a#play").keydown(function(ev){ if (ev.which ==27) { $("#tip1").attr("aria-hidden","true").addClass("hidden"); ev.preventDefault(); return false; } }); $("a#stoptitle").focus(function(){ $("#tip2").attr("aria-hidden","false").removeClass("hidden"); }); $("a#stoptitle").mouseover(function(){ $("#tip2").attr("aria-hidden","false").removeClass("hidden"); }); $("a#stoptitle").blur(function(){ $("#tip2").attr("aria-hidden","true").addClass("hidden"); }); $("a#stoptitle").mouseleave(function(){ $("#tip2").attr("aria-hidden","true").addClass("hidden"); }); $("a#stoptitle").keydown(function(ev){ if (ev.which ==27) { $("#tip2").attr("aria-hidden","true").addClass("hidden"); ev.preventDefault(); return false; } }); }); // End This code is added by iTalent as part of iTrack 1859082