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

Join us for an expert-led overview of the tools and concepts you'll need to become a Certified Power BI Data Analyst and pass exam PL-300. Register now.

Reply
PunchBird
Helper V
Helper V

How create API with paging ?

Hi all,

 

I tried to compose power query M code for an API request that requires paging, because with a single request a maximum of 500 rows is returned. I looked at other posts, including this article, but so far I haven't been successful. Does anyone know how to code this?

  • For the paging,  hpp and offset are used as parameters.
  • The request URL is  

 

https://api.MYENDPOINT.com/api/v1/search/p/MYPROJECT/results?offset=MYOFFSETNUMBER&hpp=MYHPPNUMBER&sort_by=published&sort_order=desc&hl=true&pretty=true&access_token=MYTOKEN​

 

The request URL works but only returns 500 rows, it's the paging that I can't figure out.

Many thanks in advance!

1 ACCEPTED SOLUTION

 

There's a couple of things that immediately spring to mind:

 

1) Have you set up your paged call like this, using RelativePath?

BA_Pete_0-1681486231608.png

Using this RelativePath structure for the Web.Contents is a key aspect of avoiding Dynamic Data Source errors.

You may need to adjust which parts of the URL sit within the core/RelativePath sections.

You may also need to use the same structure for your original ping call, but I've never had issues with this initial call being the basic Web.Contents structure.

 

2) Have you deleted all unused queries in the Dataflow that don't use the correct Web.Contents structure?

I've found that, even if incorrectly-structured calls are disabled from loading, they still cause the entire DF to fail on initial query validation. Not sure why, just something I've experienced.

 

Pete



Now accepting Kudos! If my post helped you, why not give it a thumbs-up?

Proud to be a Datanaut!




View solution in original post

6 REPLIES 6
BA_Pete
Super User
Super User

Hi @PunchBird ,

 

We first need to get an initial response from the endpoint so we can see what we're aiming for so, for your scenario, your query Source step would be something like this:

let
    Source =
    Json.Document(
        Web.Contents( https://api.MYENDPOINT.com/api/v1/search/p/MYPROJECT/results?access_token=MYTOKEN​
        )
    )
in
    Source

 

Hopefully, this initial simple ping should bring back a record similar to the below example. The most important part of this record is the [total] value, which tells us how many records are available at that endpoint:

BA_Pete_0-1681398513668.png

 

What we need to do is break that total into max-500-record pieces, so the next query step would be something like this:

pageSizeList = List.Numbers(0, Number.RoundUp(Source[total] / 500), 500),

 

Convert the resultant list into a table and choose the column name - I've chosen 'pages':

BA_Pete_1-1681399116053.png

 

Now all you need to do is add a new custom column, something like this:

Json.Document(
    Web.Contents(
        "https://api.MYENDPOINT.com/api/"
        [
            RelativePath="v1/search/p/MYPROJECT/results"
            Query=
            [
                offset=Text.From([pages]),
                access_token=MYTOKEN​
            ]
        ]
    )
)

 

You can add all your other parameters into the Query=[..] record as well.

I've used this more in-depth Web.Contents structure as this method will work fine in Dataflows etc. where you may otherwise get 'Dynamic URL' errors without it.

 

Hopefully you should now have a max-500-record chunk of your data in each row: row one = records 0-499, row two = 500-999, row three = records 1,000-1,344. If you find you're getting duplicated records at the seams, then add a 'limit' parameter to limit the GET request to 499 records per row.

 

Hope this makes sense.

 

Pete



Now accepting Kudos! If my post helped you, why not give it a thumbs-up?

Proud to be a Datanaut!




@BA_Pete many thanks - your breakdown in steps is very helpful! By following your guidance I found out the total number of records is more than 25 million... way too much! I first need to figure out how I can make sure the endpoint only returns records up until a specific date, which doesn't seem to be a parameter I can choose from. The dates only become visible after expanding some records and lists. Any ideas how to tackle this in an efficient manner?

 

There will be a way to filter on fields that are nested within the records, but you'll need to read the API documentation for your specific source.

For example, on one of the sources I use, I can filter nested fields using a parameters like this:

&_ff[]=picklist_id
&_ft[]=eq
&_fc[]=190

Where:

_ff[] is the field to filter

_ft[] is the filter condition

_fc[] is the comparator value

 

So, this group of parameters filters the records to only those where the [picklist_id] field equals 190.

As above, you'll need to read your own API docs to find out how your endpoint needs the citeria presented, but I'm 99.9% sure it's doable.

 

Pete



Now accepting Kudos! If my post helped you, why not give it a thumbs-up?

Proud to be a Datanaut!




Hi @BA_Pete I managed to follow your instructions sucessfully, which is great!

However, when I want to save and close the dataflow, I get this error: One or more tables references a dynamic data source... is there any way to solve this?

 

 

 

There's a couple of things that immediately spring to mind:

 

1) Have you set up your paged call like this, using RelativePath?

BA_Pete_0-1681486231608.png

Using this RelativePath structure for the Web.Contents is a key aspect of avoiding Dynamic Data Source errors.

You may need to adjust which parts of the URL sit within the core/RelativePath sections.

You may also need to use the same structure for your original ping call, but I've never had issues with this initial call being the basic Web.Contents structure.

 

2) Have you deleted all unused queries in the Dataflow that don't use the correct Web.Contents structure?

I've found that, even if incorrectly-structured calls are disabled from loading, they still cause the entire DF to fail on initial query validation. Not sure why, just something I've experienced.

 

Pete



Now accepting Kudos! If my post helped you, why not give it a thumbs-up?

Proud to be a Datanaut!




Hi @BA_Pete - your 1)-suggestion was indeed the issue. The original ping call needed a RelativePath, and that solved the problem. Thanks so much, you're a star! 😊 🌟

Helpful resources

Announcements
Join our Fabric User Panel

Join our Fabric User Panel

This is your chance to engage directly with the engineering team behind Fabric and Power BI. Share your experiences and shape the future.

June 2025 Power BI Update Carousel

Power BI Monthly Update - June 2025

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

June 2025 community update carousel

Fabric Community Update - June 2025

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