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

Compete to become Power BI Data Viz World Champion! First round ends August 18th. Get started.

Reply
MarkusEng1998
Resolver II
Resolver II

List.Generate API Pagination based on rel="next"

I am using list.generate to seed the [skip] & [top] values for the URI pagination. I have to guess how many records will be returned, e.g. if I know there are 1000+ records, I set the list.generate condition [skip]< 1100.

 

When the response header no longer returns rel="next" then there are no more records. Where do I include this?

 

Here is my initial code where I manually guess the pagination values. The last step of Table.ExpandListColumns I find the last record [dRofusRecord] = null.

 

2024-04-30_10-03-34.jpg

 

 

 

let
	
    Source = #"200Rooms",
    #"01filterProj" = Table.SelectRows(Source, each ([projName] = projectFilter)),
    #"10listGenerate100" = Table.AddColumn( #"01filterProj", "dRofusRecord", each List.Generate(() =>
    [skip = 0,  top = 10 ],
        each [skip] <= rmSkip,   // rmsSkip is my guess of the record number.
        each [skip = [skip] + [top], 
      top = [top] ]
)),
    #"11expandList" = Table.ExpandListColumn(#"10listGenerate100", "dRofusRecord"),
    #"12expandDrofusRecord" = Table.ExpandRecordColumn(#"11expandList", "dRofusRecord", {"skip", "top"}, {"skip", "top"}),
    #"13changeType" = Table.TransformColumnTypes(#"12expandDrofusRecord",{{"skip", Int64.Type}, {"top", Int64.Type}}),
    
    // API call
    #"20getProjURI" = Table.AddColumn(#"13changeType", "drofusRecord", each getProjectURIpaginated([top], [skip])),

    #"21expandProjURI" = Table.ExpandListColumn(#"20getProjURI", "drofusRecord")
in
    #"21expandProjURI"

 

 

 

 

Here is the getProjectURIpaginated()

 

 

 

(topVal as number, skipVal as number)=>
let
    #"FilterColumnTable" = Table.SelectRows(#"111APIitemsA1", each ([ObjectType] = "items")),
    GetWebContents =
        Web.Contents(
            "https://api-us.drofus.com/api/company/",
            [
                RelativePath= "143"
                & "/items" 
                & "?$select=" & Text.Combine(#"FilterColumnTable"[dRofus.ID], ",")
                & "&$top=" & Number.ToText(topVal)
                & "&$skip=" & Number.ToText(skipVal) 
            ]
        ),            
    GetBody = Json.Document(GetWebContents)    
in
    GetBody

 

 

 

I have seen videos where I incorporate getProjectURIpaginated() into the list.generate function, but get confused.

Thank you for any help.

1 ACCEPTED SOLUTION
MarkusEng1998
Resolver II
Resolver II

Thank you @Anonymous  for your help! I decided to take a U-Turn and rethink the solution how to end the API pagination automatically. Fortunately, I found a post by @lbendlin using List.IsEmpty().

 

I revised the List.Generate() section to include the List.Empty().

 

= Table.AddColumn(#"01filterProject", "dRofusRecord", each List.Generate(() =>
[projNo = [projNo], skip = 0,  top = 50, recordList = getURI(projNo, top, skip)],

each not List.IsEmpty([recordList]),
each [projNo = [projNo],
      skip = [skip] + [top], 
      top = [top],
       recordList = getURI(projNo, top, skip)]
))

 

 

 

getURI()

 

(projNo as text, topVal as number, skipVal as number)=>
let
    #"FilterColumnTable" = Table.SelectRows(#"102APImapRooms100", each ([ObjectType] = "rooms")),
    GetWebContents =
        Web.Contents(
            "https://api-us.drofus.com/api/company/",
            [
                RelativePath= projNo
                & "/rooms" 
                & "?$select=" & Text.Combine(#"FilterColumnTable"[dRofus.ID], ",")
                & "&$top=" & Number.ToText(topVal)
                & "&$skip=" & Number.ToText(skipVal) 
            ]
        ),
    convertedJson = Json.Document(GetWebContents,65001),     
        in
            convertedJson

 

 

 

View solution in original post

6 REPLIES 6
MarkusEng1998
Resolver II
Resolver II

Thank you @Anonymous  for your help! I decided to take a U-Turn and rethink the solution how to end the API pagination automatically. Fortunately, I found a post by @lbendlin using List.IsEmpty().

 

I revised the List.Generate() section to include the List.Empty().

 

= Table.AddColumn(#"01filterProject", "dRofusRecord", each List.Generate(() =>
[projNo = [projNo], skip = 0,  top = 50, recordList = getURI(projNo, top, skip)],

each not List.IsEmpty([recordList]),
each [projNo = [projNo],
      skip = [skip] + [top], 
      top = [top],
       recordList = getURI(projNo, top, skip)]
))

 

 

 

getURI()

 

(projNo as text, topVal as number, skipVal as number)=>
let
    #"FilterColumnTable" = Table.SelectRows(#"102APImapRooms100", each ([ObjectType] = "rooms")),
    GetWebContents =
        Web.Contents(
            "https://api-us.drofus.com/api/company/",
            [
                RelativePath= projNo
                & "/rooms" 
                & "?$select=" & Text.Combine(#"FilterColumnTable"[dRofus.ID], ",")
                & "&$top=" & Number.ToText(topVal)
                & "&$skip=" & Number.ToText(skipVal) 
            ]
        ),
    convertedJson = Json.Document(GetWebContents,65001),     
        in
            convertedJson

 

 

 

Anonymous
Not applicable

Hi @MarkusEng1998 ,

I’m delighted to hear that your issue has been resolved. Thank you for sharing the solution with our community. Your contribution could prove invaluable to other users who might encounter the same problem. Your efforts are greatly appreciated!

Best Regards

MarkusEng1998
Resolver II
Resolver II

GetHeaders() without the GetHeaders script. Results of GetWebContent.api 2024-05-01_08-52-48.jpg

MarkusEng1998
Resolver II
Resolver II

Thank you @Anonymous , I will give this a try.

Anonymous
Not applicable

Hi @MarkusEng1998 ,

Please make a littile adjustment as below on your codes and check if it can return your expected result...

1. Make modification on List.Generate() part

let
    Source = #"200Rooms",
    #"01filterProj" = Table.SelectRows(Source, each ([projName] = projectFilter)),
    #"10listGenerate" = Table.AddColumn(#"01filterProj", "dRofusRecord", each List.Generate(
        () => [skip = 0, top = 10],
        each [skip] <= rmSkip and GetHeaders([top], [skip]),
        each [skip = [skip] + [top], top = [top]]
    )),
    #"11expandList" = Table.ExpandListColumn(#"10listGenerate", "dRofusRecord"),
    #"12expandDrofusRecord" = Table.ExpandRecordColumn(#"11expandList", "dRofusRecord", {"skip", "top"}, {"skip", "top"}),
    #"13changeType" = Table.TransformColumnTypes(#"12expandDrofusRecord",{{"skip", Int64.Type}, {"top", Int64.Type}}),
    #"20getProjURI" = Table.AddColumn(#"13changeType", "drofusRecord", each getProjectURIpaginated([top], [skip])),
    #"21expandProjURI" = Table.ExpandListColumn(#"20getProjURI", "drofusRecord")
in
    #"21expandProjURI"

2. Change the code for the function getProjectURIpaginated()

  GetHeaders = (topVal as number, skipVal as number) =>
        let
            #"FilterColumnTable" = Table.SelectRows(#"111APIitemsA1", each ([ObjectType] = "items")),
            GetWebContents =
                Web.Contents(
                      "https://api-us.drofus.com/api/amazon/",
                    [
                        RelativePath= "143"
                        & "/items" 
                        & "?$select=" & Text.Combine(#"FilterColumnTable"[dRofus.ID], ",")
                        & "&$top=" & Number.ToText(topVal)
                        & "&$skip=" & Number.ToText(skipVal) 
                    ]
                ),
            GetHeaders = Record.FieldOrDefault(GetWebContents, "Headers", []),
            LinkHeader = Record.FieldOrDefault(GetHeaders, "Link", ""),
            RelNext = Text.Contains(LinkHeader, "rel=next")
        in
            RelNext

Best Regards

Thank you for the code for GetHeaders(). When I invoke this function, it returns a cannot convert binary to type record. I think this error is between GetWebContents (returns a JSON file) and GetHeaders (returns Binary error).

api 2024-05-01_08-56-15.jpg

I can bypass this error by converting the JSON, which returns a list of records. The GetHeaders is expecting a different input. revised GetHeaders()

 

(topVal as number, skipVal as number)=>
let
    #"FilterColumnTable" = Table.SelectRows(#"102APImapRooms100", each ([ObjectType] = "rooms")),
    GetWebContents =
        Web.Contents("https://api-us.drofus.com/api/amazon/",
            [
                RelativePath= "01" & "/rooms" 
                & "?$select=" & Text.Combine(#"FilterColumnTable"[dRofus.ID], ",")
                & "&$top=" & Number.ToText(topVal) & "&$skip=" & Number.ToText(skipVal) 
            ]
        ),
    convertedJson = Json.Document(GetWebContents,65001),
    convertedList = Table.FromList(convertedJson, Splitter.SplitByNothing(), null, null, ExtraValues.Error), 
 convertedRecord = Record.FromTable(convertedList),  
     GetHeaders = Record.FieldOrDefault(convertedRecord, "Headers", []),
            LinkHeader = Record.FieldOrDefault(GetHeaders, "Link", ""),
            RelNext = Text.Contains(LinkHeader, "next")
    
        in
            GetHeaders

 

 

error message at convertedRecord step.

api 2024-05-01_12-45-40.jpg

If I skip this step GetHeaders error: cannot convert value of type Table to type Record.

Helpful resources

Announcements
July 2025 community update carousel

Fabric Community Update - July 2025

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

July PBI25 Carousel

Power BI Monthly Update - July 2025

Check out the July 2025 Power BI update to learn about new features.