Hi! If you saw my previous posts, I’m working on using the search API within Power BI. I haven’t worked with APIs before in the past, so would appreciate any guidance. We’re pretty set on using the APIs within Power BI directly rather than a custom connector. My current idea is getting the total number of pages needed to get all the data and looping my function until I have all identities. However, I’m running into some issues with my code and would love some help.
Here is my full code:
let
access_token = #"token from previous step",
fetchPage = (nextID as nullable text, limit as number, pagenum as number) =>
let
api_url = "some_url",
searchAfterPart = if pagenum >1 then Text.Format(", ""searchAfter"": [""{0}""]", {nextID}) else "", // adding this to the body is when it stops working
headers = [
#"Authorization" = "Bearer " & access_token,
#"Content-Type" = "application/json"
],
body = Text.ToBinary(
"{
""indices"": [""identities""],
""query"": {
""query"": ""*""
},
""sort"": [""id""] " & searchAfterPart & "
}"
),
response = Json.Document(Web.Contents(api_url, [Headers=headers, Content=body])),
data = Table.FromList(response, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
expand = Table.ExpandRecordColumn(data, "Column1", {"id", "other columns of interest"}),
newNextID = if Table.RowCount(expand) > 0 then expand{Table.RowCount(expand) - 1}[id] else null
in
[data = expand, nextID = newNextID],
limit = 250,
count = countIdentities,
totalPages = Number.RoundUp(count / limit),
// Fetch the first page of data, structured this way because including it in the loop was causing problems earlier as well
firstPage = fetchPage(null, limit, 1),
initialData = firstPage[data],
initialNextID = firstPage[nextID],
// Loop to fetch subsequent pages, with page counter
allData = List.Generate(
() => [data = initialData, nextID = initialNextID, currentPage = 1],
each [nextID] <> null and [currentPage] <= totalPages, // Continue as long as there are pages left and currentPage <= totalPages
each let
pageData = fetchPage([nextID], limit, [currentPage]+1), // Fetch next page
newData = Table.Combine({[data], pageData[data]}), // Combine current data with new page data
newNextID = pageData[nextID] // Get nextID for the next iteration
in
[data = newData, nextID = newNextID, currentPage = [currentPage]+1], // Move to the next page
each [data] // Return the accumulated data
),
#"Converted to Table" = Table.FromList(allData, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
#"Expanded Column1" = Table.ExpandTableColumn(#"Converted to Table", "Column1", {"id", "other columns of interest"})
in
#"Expanded Column1"
Here are the issues and observations I have:
-
The code as is returns an error after the first call, so only the first call outside of the loop to fetchPage is successful:
“Expression.Error: The column ‘Column1’ of the table wasn’t found.
Details:
Column1” -
If I set a static value to searchAfter and define it within the body, the code is able to loop properly and do the correct amount of calls, returning the same data every time due to the static search after value
body = Text.ToBinary(
"{
""indices"": [""identities""],
""query"": {
""query"": ""*""
},
""sort"": [""id""] ",
**""searchAfter"" : ""some static id""**
"}"
),
- If I set a static value to searchAfter and define it within my searchAfterPart, I receive a 400 error:
DataSource.Error: Web.Contents failed to get contents from ‘https://hostname.api.identitynow.com/v3/search?limit=250’ (400):
Details:
DataSourceKind=Web
DataSourcePath=https://hostname.api.identitynow.com/v3/search
Url=https://hostname.api.identitynow.com/v3/search?limit=250