Advance your Data & AI career with 50 days of live learning, dataviz contests, hands-on challenges, study groups & certifications and more!
Get registeredGet Fabric Certified for FREE during Fabric Data Days. Don't miss your chance! Request now
Hi Team,
We ae trying to import the data from Jira Cloud to Power BI.
Our Major requirements are as follows.
1. We would like to fetch the jiras dynamically and in live/Direct/Import Modes.
2. We should be able to fetch all the jira assigned to any individual or basis on any jira project (jiras created in last one year for ex.)
3. Should be able to fetch the fields configured in jira projects with all issues/stories/epic etc
4. Can we have the main work request number (Story’s) and the Impact Assessments (subtasks) linking to the main work reception ticket
5. Will it be possible to show the name of the individual the impact assessment is assigned too or the team area it is attached too
6. Is it possible to see why something has not went ahead – can we get details on closed work requests that have not been completed
7. Will it be possible for PowerBI to give a full report from when he board was created to present day
Thanks,
Gaurav
Solved! Go to Solution.
Hi @GauravSinghPBI ,
We are following up once again regarding your query. Could you please confirm if the issue has been resolved through the support ticket with Microsoft?
If the issue has been resolved, we kindly request you to share the resolution or key insights here to help others in the community.
Thank you.
I’ve dealt with similar Jira-to-Power BI setups - handling pagination and date filters is key. For incremental loads and snapshots, I’ve used Skyvia to sync the data into a database first, then connected Power BI to that. It simplified things a lot.
Could you please tell me if the REST API end points are still usable?
I see that they are depreciated as per: https://developer.atlassian.com/changelog/#CHANGE-2046
Hey @GauravSinghPBI,
That's expected behavior! The API returns empty because you haven't provided any search parameters yet.
Quick Fix Steps:
1. Add JQL Query Parameter In Power Query Editor:
https://xxxxxxx.atlassian.net/rest/api/3/search?jql=project="YOUR_PROJECT_KEY"
2. Basic JQL Examples to Try:
3. Authentication Check Make sure you're using:
4. Expand the Data Once you get results:
5. Test Connection First Try this simple URL to verify connection:
https://xxxxxxx.atlassian.net/rest/api/3/myself
This should return your user info if auth is working.
The empty result you're seeing just means "no search criteria = no results". Add the JQL parameter and you'll see your data flowing in.
Let me know if you hit any snags!
Fixed? ✓ Mark it • Share it • Help others!
Best Regards,
Jainesh Poojara | Power BI Developer
@jaineshp - I tested the link point no. 5 and working for me.
https://xxxx.atlassian.net/rest/api/3/myself
I went to Power BI Desktop - Get Data - Web - with Basic option put the below URL and click ok
https://xxxxxxx.atlassian.net/rest/api/3/search
Power Query Editor opens and Query named "search" is appearing but there is no data except one row with below columns and values
startAt maxResults total issues
0 50 0
After that i went to advance editor and change
from
Source = Json.Document(Web.Contents("https://xxxx.atlassian.net/rest/api/3/search")),
to
Source = Json.Document(Web.Contents("https://xxxx.atlassian.net/rest/api/3/search?jql=project="PPPP"")),
when i click ok - it provides some error "Expression.SyntaxError: Token Comma expected."
Kindly help.
Thanks,
Gaurav
@GauravSinghPBI,
It's a simple syntax issue with the quotes in your JQL parameter.
Try the below one: -
Source = Json.Document(Web.Contents("https://xxxx.atlassian.net/rest/api/3/search?jql=project=""PPPP""")),
Alternative Approach: If you keep getting syntax errors, try this simpler JQL first:
Source = Json.Document(Web.Contents("https://xxxx.atlassian.net/rest/api/3/search?jql=order by created DESC")),
After fixing the syntax, you should see:
The syntax error happens because Power Query needs proper quote escaping for nested strings.
Fixed? ✓ Mark it • Share it • Help others!
Best Regards,
Jainesh Poojara | Power BI Developer
Thanks @jaineshp
After i changed the Project within ""PPPP""
Web.Contents failed to get contents from 'https://xxxx.atlassian.net/rest/api/3/search?jql=project=%22PPPP%22' (400): Bad Request
But when i followed the alternative approach
https://xxxx.atlassian.net/rest/api/3/search?jql=order by created DESC"
It provides
Don't know what mistake i am doing. Till now i have not followed any other steps on auth etc.
Thanks
Gaurav
Hey @GauravSinghPBI,
The 400 Bad Request and total = 0 clearly indicates authentication issues. You can't access Jira REST API without proper auth.
Quick Fix Steps:
Source = Json.Document(Web.Contents("https://xxxx.atlassian.net/rest/api/3/search?jql=order by created DESC",
[Headers=[Authorization="Basic " & Binary.ToText(Text.ToBinary("your-email@domain.com:your-api-token"), BinaryEncoding.Base64)]]))
Why it's failing:
Try the auth fix first - that should resolve both issues!
Best Regards,
Jainesh Poojara | Power BI Developer
Thanks @jaineshp
I have used authorization and other details and able to fetch the data but records are not matching perfectly for ex.
"https://xxxx.atlassian.net/rest/api/3/search?jql=project=PPPP order by created DESC"
is returning 838 rows (in Jira Application) and total column in PBI also shows 838 value.
but when i added created >= -30d as below
"https://natwest.atlassian.net/rest/api/3/search?jql=project=FNWR&created >= -30d order by created DESC"
query should retun 23 records as i see in jira tool but total column still shows 838 in PBI.
In above both scenarios - i am getting only 50 rows in PBI and maxResults column also shows 50
Thanks,
Gaurav
Hey @GauravSinghPBI,
Looking at Gaurav's response, there are two separate issues here:
The query created >= -30d has incorrect syntax. In JQL, you need quotes around the date value:
Wrong: jql=project=PPPP&created >= -30d order by created DESC
Correct: jql=project=PPPP AND created >= "-30d" ORDER BY created DESC
Fix the JQL syntax:
Source = Json.Document(Web.Contents("https://xxxx.atlassian.net/rest/api/3/search?jql=project=PPPP AND created >= ""-30d"" ORDER BY created DESC", [Headers=[Authorization="Basic " & Binary.ToText(Text.ToBinary("your-email@domain.com:your-api-token"), BinaryEncoding.Base64)]]))
Jira API returns maximum 50 results per call by default. To get all 838 records, you need pagination.
Add these parameters:
Updated Query:
Source = Json.Document(Web.Contents("https://xxxx.atlassian.net/rest/api/3/search?jql=project=PPPP ORDER BY created DESC&maxResults=1000&startAt=0", [Headers=[Authorization="Basic " & Binary.ToText(Text.ToBinary("your-email@domain.com:your-api-token"), BinaryEncoding.Base64)]]))
For complete pagination in Power BI: You'll need a custom function to loop through all pages if you have more than 1000 records.
Quick test: Try the corrected JQL syntax first with maxResults=100 to see if you get the right filtered count!
Fixed? ✓ Mark it • Share it • Help others!
Best Regards,
Jainesh Poojara | Power BI Developer
@jaineshp Thanks for the response.
let
Source = Json.Document(Web.Contents("https://xxxx.atlassian.net/rest/api/3/search?jql=project=PPPP order by created DESC&maxResults=1000&startAt=0",
[Headers=[Authorization="Basic " & Binary.ToText(Text.ToBinary("mail id:API token"), BinaryEncoding.Base64)]])),
#"Converted to Table" = Table.FromRecords({Source}),
#"Expanded issues" = Table.ExpandListColumn(#"Converted to Table", "issues"),
#"Changed Type" = Table.TransformColumnTypes(#"Expanded issues",{{"startAt", Int64.Type}, {"maxResults", Int64.Type}, {"total", Int64.Type}, {"issues", type any}})
in
#"Changed Type"
"https://xxxx.atlassian.net/rest/api/3/search?jql=project=PPPP&created >= ""-10d"" order by created DESC"
Thanks,
Gaurav
Hey @GauravSinghPBI,
Looking at your responses, I can see 3 specific issues that need addressing:
Issue 1: 100 records limit despite maxResults=1000 This suggests your Jira instance has a server-side limit. Many organizations set max limits around 100-200. Solution: Contact your Jira admin to check the server configuration or use pagination with smaller batches (maxResults=50-100).
Issue 2: Date filter returning wrong count (50 vs 11 expected) Your JQL syntax is still incorrect - you're missing AND operator: Wrong: jql=project=PPPP&created >= "-10d" Correct: jql=project=PPPP AND created >= "-10d"
Fixed Query:
"https://xxxx.atlassian.net/rest/api/3/search?jql=project=PPPP AND created >= ""-10d"" ORDER BY created DESC"
Issue 3: Direct Query & Auto Refresh Limitations You're right - API method won't support DirectQuery mode. Here are your options:
Option A: Import Mode with Scheduled Refresh
Option B: Power BI Dataflows
Option C: Jira Connector (if available)
Immediate Action Plan:
Quick Test: Try this corrected query first:
jql=project=PPPP AND created >= "-10d" ORDER BY created DESC&maxResults=50
Fixed? ✓ Mark it • Share it • Help others!
Best Regards,
Jainesh Poojara | Power BI Developer
@jaineshp Thanks for the response.
https://xxxx.atlassian.net/rest/api/3/search?jql=project=PPPP AND created >= ""-10d"" order by created DESC
https://xxxx.atlassian.net/rest/api/3/search?jql=project=FNWR AND created >= ""-365d"" order by created DESC&maxResults=1000&startAt=0
Thanks,
Gaurav
1. Why maxResults shows 50 when no maxResults parameter specified: When you don't specify maxResults in your URL, Jira API defaults to 50. The API response always shows what limit was applied, even if fewer records exist. So:
2. 100 row server limitation confirmed: Yes, your Jira instance has a hard limit of 100 records per API call. Even though you requested maxResults=1000, the server only returned 100. The total=111 confirms there are more records available.
3. Pagination implementation: Here's how to fetch all 1k+ rows using pagination:
Multiple Web.Contents calls in Power Query M:
let
Page1 = Json.Document(Web.Contents("https://xxxx.atlassian.net/rest/api/3/search?jql=project=FNWR AND created >= ""-365d""&maxResults=100&startAt=0")),
Page2 = Json.Document(Web.Contents("https://xxxx.atlassian.net/rest/api/3/search?jql=project=FNWR AND created >= ""-365d""&maxResults=100&startAt=100")),
Page3 = Json.Document(Web.Contents("https://xxxx.atlassian.net/rest/api/3/search?jql=project=FNWR AND created >= ""-365d""&maxResults=100&startAt=200")),
CombinedIssues = Page1[issues] & Page2[issues] & Page3[issues],
ConvertToTable = Table.FromList(CombinedIssues, Splitter.SplitByNothing(), null, null, ExtraValues.Error)
in
ConvertToTable
Fixed? ✓ Mark it • Share it • Help others!
Best Regards,
Jainesh Poojara | Power BI Developer
@jaineshp Thanks for the response.
I used Copilot to prepare the script (under Script ----------->). It created the script and fetching 200+ records now. Nor i have Key, Summary, Status Name etc column. But all column values are Error (hyperlink) and when i click beside the Error value in cell I get. DOn't know how to concert this in simple table which gives me values from jira board. Please help.
"DataFormat.Error: There were more columns in the result than expected.
Details:
Count=1"
Script ----------->
let
// === Configuration ===
BaseUrl = "https://xxxx.atlassian.net/rest/api/3/search?",
JQL = "jql=project=PPPP AND created >= -365d",
PageSize = 100,
Email = "my email", // Replace with your Atlassian email
APIToken = "Actual APi token", // Replace with your API token
// === Function to Get a Page of Issues ===
GetPage = (StartAt as number) =>
let
Url = BaseUrl & JQL & "&startAt=" & Number.ToText(StartAt) & "&maxResults=" & Number.ToText(PageSize),
Source = Json.Document(Web.Contents(Url, [
Headers = [
#"Authorization" = "Basic " & Binary.ToText(Text.ToBinary(Email & ":" & APIToken), BinaryEncoding.Base64),
#"Accept" = "application/json"
]
])),
Issues = Source[issues]
in
Issues,
// === Generate All Pages ===
Pages = List.Generate(
() => [i = 0, data = GetPage(0)],
each List.Count([data]) > 0,
each [i = [i] + PageSize, data = GetPage([i])],
each [data]
),
// === Flatten and Convert to Table ===
Flattened = List.Combine(Pages),
Table = Table.FromList(Flattened, Record.FieldValues, {"Issue"}),
// === Expand Fields ===
Expanded = Table.ExpandRecordColumn(Table, "Issue", {
"key", "fields"
}),
FieldsExpanded = Table.ExpandRecordColumn(Expanded, "fields", {
"summary", "status", "assignee", "created", "updated", "customfield_10007"
}, {
"Summary", "Status", "Assignee", "Created", "Updated", "Sprint"
}),
StatusExpanded = Table.ExpandRecordColumn(FieldsExpanded, "Status", {"name"}, {"Status Name"}),
AssigneeExpanded = Table.ExpandRecordColumn(StatusExpanded, "Assignee", {"displayName"}, {"Assignee Name"}),
FinalTable = AssigneeExpanded
in
FinalTable
Hi @GauravSinghPBI ,
Thanks for reaching out to the Microsoft fabric community forum.
I would also take a moment to thank @jaineshp , for actively participating in the community forum and for the solutions you’ve been sharing in the community forum. Your contributions make a real difference.
By default, Jira’s REST API only returns 50 issues per request. You can increase this limit in your query string
.../rest/api/3/search?jql=project=FNWR AND created >= -30d order by created DESC&maxResults=1000
Replace 1000 with the number you need (maximum allowed is usually 1000).
If you need more than that, you’ll need to retrieve data in pages using the startAt parameter and combine the results in Power Query.
When combining multiple filters, join them with AND . This ensures Jira interprets both filters correctly.
To avoid pulling all records every time, configure Incremental Refresh in Power BI:
Create RangeStart and RangeEnd parameters in Power Query (type: Date/Time).
Filter your Jira dataset so that [created] is between these parameters.
Enable Incremental Refresh on the table from the Model view.
Publish and set up a refresh schedule in the Power BI Service.
If I misunderstand your needs or you still have problems on it, please feel free to let us know.
Best Regards,
Community Support Team
Hey @v-menakakota,
Thank you for the kind recognition - always happy to contribute to our community's success!
Best Regards,
Jainesh Poojara | Power BI Developer
@jaineshp Thanks for the response.
The code which i pasted on last week Tuesday as below. I am facing below issues still.
let
// === Configuration ===
BaseUrl = "https://natwest.atlassian.net/rest/api/3/search?",
JQL = "jql=project=PPPP AND created >= -365d",
PageSize = 100,
Email = "my email", // Replace with your Atlassian email
APIToken = "Actual API token", // Replace with your API token
// === Function to Get a Page of Issues ===
GetPage = (StartAt as number) =>
let
Url = BaseUrl & JQL & "&startAt=" & Number.ToText(StartAt) & "&maxResults=" & Number.ToText(PageSize),
Source = Json.Document(Web.Contents(Url, [
Headers = [
#"Authorization" = "Basic " & Binary.ToText(Text.ToBinary(Email & ":" & APIToken), BinaryEncoding.Base64),
#"Accept" = "application/json"
]
])),
Issues = Source[issues]
in
Issues,
// === Generate All Pages ===
Pages = List.Generate(
() => [i = 0, data = GetPage(0)],
each List.Count([data]) > 0,
each [i = [i] + PageSize, data = GetPage([i])],
each [data]
),
// === Flatten and Convert to Table ===
Flattened = List.Combine(Pages),
Table = Table.FromList(Flattened, Record.FieldValues, {"Issue"}),
// === Expand Fields ===
Expanded = Table.ExpandRecordColumn(Table, "Issue", {
"key", "fields"
}),
FieldsExpanded = Table.ExpandRecordColumn(Expanded, "fields", {
"summary", "status", "assignee", "created", "updated", "customfield_10007"
}, {
"Summary", "Status", "Assignee", "Created", "Updated", "Sprint"
}),
StatusExpanded = Table.ExpandRecordColumn(FieldsExpanded, "Status", {"name"}, {"Status Name"}),
AssigneeExpanded = Table.ExpandRecordColumn(StatusExpanded, "Assignee", {"displayName"}, {"Assignee Name"}),
FinalTable = AssigneeExpanded
in
FinalTable
Hey @GauravSinghPBI,
Try this: -
let
// === Configuration ===
BaseUrl = "https://natwest.atlassian.net/rest/api/3/search?",
JQL = "jql=project=PPPP AND created >= -365d ORDER BY created ASC",
PageSize = 100,
Email = "my email", // Replace with your Atlassian email
APIToken = "Actual API token", // Replace with your API token
// === Function to Get a Page of Issues ===
GetPage = (StartAt as number) =>
let
Url = BaseUrl & JQL & "&startAt=" & Number.ToText(StartAt) & "&maxResults=" & Number.ToText(PageSize),
// Add error handling for API calls
Source = try Json.Document(Web.Contents(Url, [
Headers = [
#"Authorization" = "Basic " & Binary.ToText(Text.ToBinary(Email & ":" & APIToken), BinaryEncoding.Base64),
#"Accept" = "application/json"
]
])) otherwise [issues = {}, total = 0],
Issues = if Record.HasFields(Source, "issues") then Source[issues] else {},
Total = if Record.HasFields(Source, "total") then Source[total] else 0
in
[issues = Issues, total = Total, startAt = StartAt],
// === Get First Page to Determine Total Count ===
FirstPage = GetPage(0),
TotalRecords = FirstPage[total],
// === Generate All Pages Without Duplication ===
AllPages = List.Generate(
() => [currentStart = 0, pageData = FirstPage],
each [currentStart] < TotalRecords,
each [
currentStart = [currentStart] + PageSize,
pageData = if [currentStart] < TotalRecords then GetPage([currentStart]) else [issues = {}]
],
each [pageData][issues]
),
// === Flatten All Issues ===
AllIssues = List.Combine(AllPages),
// === Process Data Only If Issues Exist ===
FinalResult = if List.Count(AllIssues) > 0 then
let
// === Convert to Table ===
IssuesTable = Table.FromList(AllIssues, Splitter.SplitByNothing(), {"Issue"}),
// === Expand Main Fields ===
ExpandedIssues = Table.ExpandRecordColumn(IssuesTable, "Issue", {"key", "fields"}),
// === Add Derived Columns with Safe Field Access ===
WithKey = Table.AddColumn(ExpandedIssues, "Key", each
if Record.HasFields([fields], "key") then [key] else null, type text),
WithSummary = Table.AddColumn(WithKey, "Summary", each
if Record.HasFields([fields], "summary") then [fields][summary] else null, type text),
WithCreated = Table.AddColumn(WithSummary, "Created", each
if Record.HasFields([fields], "created") then
try DateTime.FromText([fields][created]) otherwise null
else null, type nullable datetime),
WithUpdated = Table.AddColumn(WithCreated, "Updated", each
if Record.HasFields([fields], "updated") then
try DateTime.FromText([fields][updated]) otherwise null
else null, type nullable datetime),
WithStatus = Table.AddColumn(WithUpdated, "Status Name", each
if Record.HasFields([fields], "status") and [fields][status] <> null then
if Record.HasFields([fields][status], "name") then [fields][status][name] else null
else null, type text),
WithAssignee = Table.AddColumn(WithStatus, "Assignee Name", each
if Record.HasFields([fields], "assignee") and [fields][assignee] <> null then
if Record.HasFields([fields][assignee], "displayName") then [fields][assignee][displayName] else null
else null, type text),
WithSprint = Table.AddColumn(WithAssignee, "Sprint", each
if Record.HasFields([fields], "customfield_10007") then
// Sprint field can be complex, handle accordingly
let SprintValue = [fields][customfield_10007]
in if SprintValue <> null then Text.From(SprintValue) else null
else null, type text),
// === Remove Intermediate Columns ===
CleanedTable = Table.RemoveColumns(WithSprint, {"Issue", "fields"})
in
CleanedTable
else
// === Return Empty Table with Correct Schema ===
Table.FromRecords({}, type table [
Key = text,
Summary = text,
Created = nullable datetime,
Updated = nullable datetime,
#"Status Name" = text,
#"Assignee Name" = text,
Sprint = text
])
in
FinalResult
Fixed? ✓ Mark it • Share it • Help others!
Best Regards,
Jainesh Poojara | Power BI Developer
Code is not comipiling
Expression.Error: The column 'Issue' of the table wasn't found.
Details:
Issue
Advance your Data & AI career with 50 days of live learning, contests, hands-on challenges, study groups & certifications and more!
Check out the October 2025 Power BI update to learn about new features.