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

Calling all Data Engineers! Fabric Data Engineer (Exam DP-700) live sessions are back! Starting October 16th. Sign up.

Reply
Ricardo_MSS
Helper II
Helper II

Help applying Query and Relative path to avoid dynamic data source for Service refresh

Hi All, 

 

I've a function built to paginate through an API call. It works very well on the Desktop service but when trying to refresh on PBI Service the following error is displayed: 

 

Ricardo_MSS_0-1609252381403.png

 

I've done some research and found a possible solution using Query= and Relative path= HERE but have not been able to apply it to my function. 

Could someone go over my code and help apply this solution, unless there is a better one? 

If you are feeling particularly generous with your time, it would be great to se the condition to terminate the List.Generate loop to exit when the previous bookmark = the current bookmark.  This is probably very simple somethig along the lines of creating a new variable to store the previous bookmark to then compare it with current bookmark, I've just not managed it programatically.

 

 

(ProjectID as text) =>
let
iterations = 20,
Bookmark1 = "0",
url = "https://field.dalux.com/service/APIv2/FieldRestService.svc/v2.2/Projects/" &
ProjectID &
"/Approvals?key=[PERSONAL KEY]=" &
Bookmark1,
FnGetOnePage=
(url) as record =>
let
Source = Json.Document(Web.Contents(url)),
data = try Source[ApprovalsList] otherwise null,
bookmark = try Source[NextBookmark] otherwise null,
res = [Data = data, Bookmark = bookmark]
in
res,
GeneratedList =
List.Generate(
() => [i=0, res = FnGetOnePage(url)],
each [i] < iterations,
each [i=[i]+1, Bookmark1 = [res][Bookmark], res = FnGetOnePage(url)],
each [res][Data] 
),
#"Converted to Table" = Table.FromList(GeneratedList, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
#"Expanded Column1" = Table.ExpandListColumn(#"Converted to Table", "Column1"),
#"Expanded Column2" = Table.ExpandRecordColumn(#"Expanded Column1", "Column1", {"CreatedByUser", "CreatedDateTime", "ExtensionsDataList", "InspectionType", "IsDeleted", "LocationList", "Project", "ApprovalID", "ApprovalNumber", "ApprovalRevisionList"}, {"Column1.CreatedByUser", "Column1.CreatedDateTime", "Column1.ExtensionsDataList", "Column1.InspectionType", "Column1.IsDeleted", "Column1.LocationList", "Column1.Project", "Column1.ApprovalID", "Column1.ApprovalNumber", "Column1.ApprovalRevisionList"})
in
#"Expanded Column2"

 

 

Thank you in advanced, any help is incredibly appreciated. 

 

Best regards, 

17 REPLIES 17
Syndicate_Admin
Administrator
Administrator

When fetching API data I can use the scheduled update without paging through the dynamic function.
When I use the dynamic function, I can't schedule anymore.
I've studied crhiss webbs' blog teaching you how to use RelativePath and Query, but none worked.

Has anyone managed the solution to the problem ?

tawis
New Member

What's the solution to this issue? I am experiencing the same.

Ricardo_MSS
Helper II
Helper II

Hi thank you for the response @v-janeyg-msft .

 

Needed to modify your suggestion as it did not include my personal API key. Unfortuntately it returned an nulled table. 

 

See how code was modified below - 

 

(ProjectID as text) => 
let iterations = 20, 
Bookmark1 = "0", 
url = "https://field.dalux.com/service/APIv2", 
Repath = "FieldRestService.svc/v2.2/Projects/"&ProjectID&"/Approvals?", 
Q = [key="key=INSERTED PERSONAL KEY&bookmark="&Bookmark1], 

FnGetOnePage= (url) as record => 

let Source = Json.Document(Web.Contents(url,[RelativePath=Repath, Query=Q])), 
data = try Source[ApprovalsList] otherwise null, 
bookmark = try Source[NextBookmark] otherwise null, 
res = [Data = data, Bookmark = bookmark] 

in res, 

GeneratedList = List.Generate( 
() => 
[i=0, res = FnGetOnePage(url)], 
each [i] < iterations, 
each [i=[i]+1, Bookmark1 = [res][Bookmark], res = FnGetOnePage(url)],
each [res][Data] ), 

#"Converted to Table" = Table.FromList(GeneratedList, Splitter.SplitByNothing(), null, null, ExtraValues.Error), 
#"Expanded Column1" = Table.ExpandListColumn(#"Converted to Table", "Column1"), 
#"Expanded Column2" = Table.ExpandRecordColumn(#"Expanded Column1", "Column1", {"CreatedByUser", "CreatedDateTime", "ExtensionsDataList", "InspectionType", "IsDeleted", "LocationList", "Project", "ApprovalID", "ApprovalNumber", "ApprovalRevisionList"}, {"Column1.CreatedByUser", "Column1.CreatedDateTime", "Column1.ExtensionsDataList", "Column1.InspectionType", "Column1.IsDeleted", "Column1.LocationList", "Column1.Project", "Column1.ApprovalID", "Column1.ApprovalNumber", "Column1.ApprovalRevisionList"}) 

in 

#"Expanded Column2" 

 

Just for reference - below is a successful API call for the first bookmark:

 

=Json.Document(Web.Contents("https://field.dalux.com/service/APIv2/FieldRestService.svc/v2.2/Projects/135353//Approvals?key=PERSONAL KEY&bookmark=0"))

 

Can [Query= ] option to Web.Contents() have two parameters? One for the static API key and the second for the bookmark which would be dynamic?

 

2021-01-04 12_51_08-DaluxTest - Power Query Editor.png

 

 

 

 

 

Hi,  @Ricardo_MSS 

 

Try to delete '?' in the url.

3.png

Best Regards

Janey Guo

 

If this post helps, then please consider Accept it as the solution to help the other members find it more quickly.

Hi @v-janeyg-msft , 

 

I've removed the '?' from the URL still resulting in an empty table. 

 

See the updated function and results below: 

 

(ProjectID as text) => 
    let iterations = 20, 
    Bookmark1 = "0", 
    url = "https://field.dalux.com/service/APIv2", 
    Repath = "FieldRestService.svc/v2.2/Projects/"&ProjectID&"/Approvals", 
    Q = [key="key=API KEY HERE&bookmark="&Bookmark1], 

        FnGetOnePage= (url) as record => 

        let Source = Json.Document(Web.Contents(url,[RelativePath=Repath, Query=Q])), 
        data = try Source[ApprovalsList] otherwise null, 
        bookmark = try Source[NextBookmark] otherwise null, 
        res = [Data = data, Bookmark = bookmark] 

        in res, 

    GeneratedList = List.Generate( 
    () => 
    [i=0, res = FnGetOnePage(url)], 
    each [i] < iterations, 
    each [i=[i]+1, Bookmark1 = [res][Bookmark], res = FnGetOnePage(url)],
    each [res][Data] ), 

    #"Converted to Table" = Table.FromList(GeneratedList, Splitter.SplitByNothing(), null, null, ExtraValues.Error), 
    #"Expanded Column1" = Table.ExpandListColumn(#"Converted to Table", "Column1"), 
    #"Expanded Column2" = Table.ExpandRecordColumn(#"Expanded Column1", "Column1", {"CreatedByUser", "CreatedDateTime", "ExtensionsDataList", "InspectionType", "IsDeleted", "LocationList", "Project", "ApprovalID", "ApprovalNumber", "ApprovalRevisionList"}, {"Column1.CreatedByUser", "Column1.CreatedDateTime", "Column1.ExtensionsDataList", "Column1.InspectionType", "Column1.IsDeleted", "Column1.LocationList", "Column1.Project", "Column1.ApprovalID", "Column1.ApprovalNumber", "Column1.ApprovalRevisionList"}) 

in 

#"Expanded Column2"

 

Ricardo_MSS_0-1609827995395.png

 

FYI - 

 

The following works both in excel and in Desktop.

 

let
    Source = (ProjectID as text) =>
let
    iterations = 20,
    Bookmark1 = "0",
    url = "https://field.dalux.com/service/APIv2/FieldRestService.svc/v2.2/Projects/" &
    ProjectID &
    "/Approvals?key=API KEY HERE&bookmark=",
    FnGetOnePage=
        (url, Bookmark1) as record =>
        let
            Source = Json.Document(Web.Contents(url & Bookmark1)),
            data = try Source[ApprovalsList] otherwise null,
            bookmark = try Source[NextBookmark] otherwise null,
            res = [Data = data, Bookmark = bookmark]
        in
            res,
    GeneratedList =
        List.Generate(
            () => [i=0, res = FnGetOnePage(url, Bookmark1)],
            each [i] < iterations and [res][Bookmark] = [res][Bookmark],
            each [i=[i]+1, res = FnGetOnePage(url, [res][Bookmark])],
            each [res][Data]             
        ),
    #"Converted to Table" = Table.FromList(GeneratedList, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
    #"Expanded Column1" = Table.ExpandListColumn(#"Converted to Table", "Column1"),
    #"Expanded Column2" = Table.ExpandRecordColumn(#"Expanded Column1", "Column1", {"CreatedByUser", "CreatedDateTime", "ExtensionsDataList", "InspectionType", "IsDeleted", "LocationList", "Project", "ApprovalID", "ApprovalNumber", "ApprovalRevisionList"}, {"Column1.CreatedByUser", "Column1.CreatedDateTime", "Column1.ExtensionsDataList", "Column1.InspectionType", "Column1.IsDeleted", "Column1.LocationList", "Column1.Project", "Column1.ApprovalID", "Column1.ApprovalNumber", "Column1.ApprovalRevisionList"})
in
    #"Expanded Column2"
in
    Source

 

As a work around, I've 'cheated' by calling the information needed in an excel table then using it as a source in the PBI report which allows it to refresh online. 

 

It just creates an extra task of making sure the table is properly refreshed before updating the report in PBI Service. 

 

I really dislike resorting to these kind of tactics 😞 but the report will work until a proper solution is found. 

Hi, @Ricardo_MSS 

 

Try this:

Q = [key="API KEY HERE“,bookmark="Bookmark1"]

Best Regards

Janey Guo

Hi @v-janeyg-msft , 

 

This now work to call the information correctly. Unforetunately Still has an issue with refresh in PBI Service. 

 

(ProjectID as text) => 
    let iterations = 20, 
    Bookmark1 = "0", 
    url = "https://field.dalux.com/service/APIv2", 
    Repath = "FieldRestService.svc/v2.2/Projects/"&ProjectID&"/Approvals", 
    Q = [key="API KEY", bookmark= Bookmark1], 

        FnGetOnePage= (url) as record => 

        let Source = Json.Document(Web.Contents(url,[RelativePath=Repath, Query=Q])), 
        data = try Source[ApprovalsList] otherwise null, 
        bookmark = try Source[NextBookmark] otherwise null, 
        res = [Data = data, Bookmark = bookmark] 

        in res, 

    GeneratedList = List.Generate( 
    () => 
    [i=0, res = FnGetOnePage(url)], 
    each [i] < iterations, 
    each [i=[i]+1, Bookmark1 = [res][Bookmark], res = FnGetOnePage(url)],
    each [res][Data] ), 

    #"Converted to Table" = Table.FromList(GeneratedList, Splitter.SplitByNothing(), null, null, ExtraValues.Error), 
    #"Expanded Column1" = Table.ExpandListColumn(#"Converted to Table", "Column1"), 
    #"Expanded Column2" = Table.ExpandRecordColumn(#"Expanded Column1", "Column1", {"CreatedByUser", "CreatedDateTime", "ExtensionsDataList", "InspectionType", "IsDeleted", "LocationList", "Project", "ApprovalID", "ApprovalNumber", "ApprovalRevisionList"}, {"Column1.CreatedByUser", "Column1.CreatedDateTime", "Column1.ExtensionsDataList", "Column1.InspectionType", "Column1.IsDeleted", "Column1.LocationList", "Column1.Project", "Column1.ApprovalID", "Column1.ApprovalNumber", "Column1.ApprovalRevisionList"}) 

in 

#"Expanded Column2"

 

 

Ricardo_MSS_0-1609845032705.png

 

Ricardo_MSS_1-1609845204865.png

 

 Maybe the ProjectID has to be hard coded? 

 

If that funtion is modified to only pull bookmarks for each project. These could be recombined in a new column.

 

A function could then be invoked using the full url as parameter. In theory the url / source would not be dynamic.

 

I'll try that out see how it goes.  

parry2k
Super User
Super User

@Ricardo_MSS did you looked at the link I sent? You are not adding this data source to use gateway but in the gateway admin, you are turning on the setting to use cloud sources refresh thru this gateway. It was very clearly mentioned in my previous reply and I also send the link in that. Please take a moment to read that official documentation.



Subscribe to the @PowerBIHowTo YT channel for an upcoming video on List and Record functions in Power Query!!

Learn Power BI and Fabric - subscribe to our YT channel - Click here: @PowerBIHowTo

If my solution proved useful, I'd be delighted to receive Kudos. When you put effort into asking a question, it's equally thoughtful to acknowledge and give Kudos to the individual who helped you solve the problem. It's a small gesture that shows appreciation and encouragement! ❤


Did I answer your question? Mark my post as a solution. Proud to be a Super User! Appreciate your Kudos 🙂
Feel free to email me with any of your BI needs.

@parry2k hope I understood this correctly. 

 

My gateway was already set to Allow users cload data source. See below - 

Ricardo_MSS_0-1609311494795.png

 

The oringal report with out the query in question has many sharepoint links as sources as well as databases, excel files, and other SaaS. See below - 

 

Ricardo_MSS_1-1609311581573.png

 

 

As I mentioned before when the query with this code is included to the same report I get this - 

 

Ricardo_MSS_2-1609311717532.png

 

When I follow the link given by the error (https://aka.ms/dynamic-data-sources) it takes me here. 

 

Ricardo_MSS_3-1609311999406.png

 

I've found some resources to try this RelativePath and Query options but have not been able to figure out how to adapt the function to work with this.  

Hi, @Ricardo_MSS 

 

It’s my pleasure to answer for you.

According to your description,I think you can modify your query content. The URL parameter of content can't be a variable,you need to add the following things to the second parameter of web.content, then it may not show that it is a dynamic data source and you can refresh in service.

Like this:

 

(ProjectID as text) =>
let
iterations = 20,
Bookmark1 = "0",
url = "https://field.dalux.com/service/APIv2",
Repath = "FieldRestService.svc/v2.2/Projects/"&ProjectID&"/Approvals",
Q = [key=Bookmark1],
FnGetOnePage=
(url) as record =>
let
Source = Json.Document(Web.Contents(url,[RelativePath=Repath, Query=Q])),
data = try Source[ApprovalsList] otherwise null,
bookmark = try Source[NextBookmark] otherwise null,
res = [Data = data, Bookmark = bookmark]
in
res,
GeneratedList =
List.Generate(
() => [i=0, res = FnGetOnePage(url)],
each [i] < iterations,
each [i=[i]+1, Bookmark1 = [res][Bookmark], res = FnGetOnePage(url)],
each [res][Data]
),
#"Converted to Table" = Table.FromList(GeneratedList, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
#"Expanded Column1" = Table.ExpandListColumn(#"Converted to Table", "Column1"),
#"Expanded Column2" = Table.ExpandRecordColumn(#"Expanded Column1", "Column1", {"CreatedByUser", "CreatedDateTime", "ExtensionsDataList", "InspectionType", "IsDeleted", "LocationList", "Project", "ApprovalID", "ApprovalNumber", "ApprovalRevisionList"}, {"Column1.CreatedByUser", "Column1.CreatedDateTime", "Column1.ExtensionsDataList", "Column1.InspectionType", "Column1.IsDeleted", "Column1.LocationList", "Column1.Project", "Column1.ApprovalID", "Column1.ApprovalNumber", "Column1.ApprovalRevisionList"})
in
#"Expanded Column2"

 

If it doesn’t solve your problem, please feel free to ask me.

 

Best Regards

Janey Guo

 

If this post helps, then please consider Accept it as the solution to help the other members find it more quickly.

parry2k
Super User
Super User

@Ricardo_MSS exactly, that's why you need a gateway to refresh the online source through gateway as recommend in previous post.



Subscribe to the @PowerBIHowTo YT channel for an upcoming video on List and Record functions in Power Query!!

Learn Power BI and Fabric - subscribe to our YT channel - Click here: @PowerBIHowTo

If my solution proved useful, I'd be delighted to receive Kudos. When you put effort into asking a question, it's equally thoughtful to acknowledge and give Kudos to the individual who helped you solve the problem. It's a small gesture that shows appreciation and encouragement! ❤


Did I answer your question? Mark my post as a solution. Proud to be a Super User! Appreciate your Kudos 🙂
Feel free to email me with any of your BI needs.

@parry2k My apologies, I missed the link. 

Will check it out and try to apply solution. 

@parry2k I don't even get the option to set up the gateway when the query is in the report. 

First image includes query in question, second image the query is removed. 

 

Ricardo_MSS_0-1609307365193.png

 

 

Ricardo_MSS_1-1609307379163.png

 

 

 

lbendlin
Super User
Super User

The best option would be if your initial API call would return the number of pages (bookmarks). That would allow you to generate a list of URLs, call for each URL's content, and then concatenate them, all in one go.

 

If you don't have that  I would use a recursive function that keeps calling itself (and accumulating the returned data) until the bookmark stops changing.

 

Recursive Functions in Power BI / Power Query — Powered Solutions

Hi Ibendlin. 

 

I cannot go with the first option as the number of bookmarks are unknown before hand. 

 

The section of the code below, runs the function to make an API call, update the bookmark and then make another call untill the number of iterations reaches the set limit. I still need to figure out how to set it to stop when bookmarks don't change. Its there just badly coded.

 

GeneratedList =
List.Generate(
() => [i=0, res = FnGetOnePage(url)],
each [i] < iterations,
each [i=[i]+1, Bookmark1 = [res][Bookmark], res = FnGetOnePage(url)],
each [res][Data]
),

  

parry2k
Super User
Super User

@Ricardo_MSS if this works in desktop it means there is no issue with the code. I think you need to have gateway to refresh even though your data source is in cloud. In gateway settings, turn on  "Learn more

 

 



Subscribe to the @PowerBIHowTo YT channel for an upcoming video on List and Record functions in Power Query!!

Learn Power BI and Fabric - subscribe to our YT channel - Click here: @PowerBIHowTo

If my solution proved useful, I'd be delighted to receive Kudos. When you put effort into asking a question, it's equally thoughtful to acknowledge and give Kudos to the individual who helped you solve the problem. It's a small gesture that shows appreciation and encouragement! ❤


Did I answer your question? Mark my post as a solution. Proud to be a Super User! Appreciate your Kudos 🙂
Feel free to email me with any of your BI needs.

Hi Parry thank you for respoding. 

 

As you say the code runs well in Desktop and I am able to refresh online. 

 

Regarding the Gateway that might not be the issue. This query was recently added to an existing report that worked well both online and in desktop. The report stopped refreshing online when this query was added. 

When removed the report refreshed again online. 

Helpful resources

Announcements
FabCon Global Hackathon Carousel

FabCon Global Hackathon

Join the Fabric FabCon Global Hackathon—running virtually through Nov 3. Open to all skill levels. $10,000 in prizes!

October Power BI Update Carousel

Power BI Monthly Update - October 2025

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

FabCon Atlanta 2026 carousel

FabCon Atlanta 2026

Join us at FabCon Atlanta, March 16-20, for the ultimate Fabric, Power BI, AI and SQL community-led event. Save $200 with code FABCOMM.