NeuroAgent

Jira API v3 Pagination Fix: Missing startAt, maxResults, total

Fix missing Jira API v3 pagination metadata (startAt, maxResults, total). Learn the difference between /search and /search/jql endpoints and implement proper pagination in your C# application.

Question

Why is the Jira API v3 not returning paging information (startAt, maxResults, total) in the response when querying for issues?

I’m developing a C# application that interacts with the Jira API. When attempting to retrieve newly created Jira issues from the past month using the API v3, the JSON response doesn’t include the expected paging information fields (startAt, maxResults, total). The response directly starts with the issues array.

Without this paging information, I’m unable to implement pagination through the data. I’ve tried including startAt and maxResults parameters in my request URL to force the API to return these fields, but they’re still missing from the response. The URL appears to be well-formed.

It’s worth noting that we recently migrated from a deprecated API version to version 3. Here’s the URL I’m using:

https://bec-sv.atlassian.net/rest/api/3/search/jql?jql=created >%3D -35d&fields=id,key,issuetype,created,customfield_12106,status,reporter,summary,updated,customfield_12111,customfield_11700,customfield_12107,assignee,customfield_12113,customfield_12108,customfield_12134,customfield_12226,customfield_12207,customfield_11902,fixVersions,customfield_10008,customfield_12283,customfield_12326,customfield_12325,customfield_12327,customfield_12321,customfield_12320,customfield_12329,customfield_12330,customfield_12331,customfield_12328,customfield_10007&startAt=0&maxResults=1000

Does anyone have insight into why the paging information might be missing from the response and how to retrieve it?

NeuroAgent

The issue you’re experiencing with missing pagination metadata in the Jira API v3 response is likely due to using the incorrect endpoint. When you use /rest/api/3/search/jql, Jira doesn’t return the standard pagination fields (startAt, maxResults, total) that are available with the /rest/api/3/search endpoint. The newer /search/jql endpoint uses a different pagination approach with nextPageToken instead of the traditional pagination parameters.

Contents

Understanding the Endpoint Difference

The key issue lies in the endpoint you’re using. Jira API v3 has two different search endpoints with distinct behaviors:

  • /rest/api/3/search: This is the traditional endpoint that returns complete pagination metadata including startAt, maxResults, and total fields in the response.

  • /rest/api/3/search/jql: This newer endpoint uses a different pagination mechanism and doesn’t return the traditional pagination metadata. Instead, it relies on nextPageToken for pagination.

According to the Stack Overflow discussion on this topic, “In Jira API v3, the correct endpoint for a JQL search is /rest/api/3/search, not /rest/api/3/search/jql. When you use /search/jql, Jira doesn’t return the paging metadata (startAt, maxResults, total).” [source]


Correct Implementation Using /rest/api/3/search

To get the pagination metadata you need, you should use the /rest/api/3/search endpoint instead. Here’s how to properly structure your request:

csharp
// Correct endpoint URL
string baseUrl = "https://bec-sv.atlassian.net/rest/api/3/search";
string jqlQuery = "created >= -35d";
string fields = "id,key,issuetype,created,customfield_12106,status,reporter,summary,updated,customfield_12111,customfield_11700,customfield_12107,assignee,customfield_12113,customfield_12108,customfield_12134,customfield_12226,customfield_12207,customfield_11902,fixVersions,customfield_10008,customfield_12283,customfield_12326,customfield_12325,customfield_12327,customfield_12321,customfield_12320,customfield_12329,customfield_12330,customfield_12331,customfield_12328,customfield_10007";

var queryParams = new Dictionary<string, string>
{
    { "jql", jqlQuery },
    { "fields", fields },
    { "startAt", "0" },
    { "maxResults", "1000" }
};

var response = await httpClient.GetAsync($"{baseUrl}?{new FormUrlEncodedContent(queryParams).ReadAsStringAsync()}");

With this approach, you’ll get a response that includes the pagination metadata:

json
{
  "expand": "schema,names",
  "startAt": 0,
  "maxResults": 1000,
  "total": 2500,
  "issues": [
    // ... array of issues
  ]
}

The community discussion confirms this approach works: “You can use the pagination parameter ‘startAt’ to specify the starting issue returned in the JQL results, so you will be able to run multiple calls returning 1000 issues sequentially.” [source]


Alternative: Using the Newer /search/jql Endpoint

If you need to use the newer /search/jql endpoint (which may eventually replace the traditional search endpoints), you’ll need to adapt your pagination approach. This endpoint uses nextPageToken instead of the traditional pagination parameters.

Key differences include:

  • No startAt, maxResults, or total fields in the response
  • Response includes nextPageToken for pagination
  • Different response structure altogether

As noted in the Atlassian community discussion: “With the new ‘/rest/api/3/search/jql’ endpoint, the response structure has changed” and pagination should be handled using nextPageToken instead of startAt. [source]

The response from the /search/jql endpoint looks like this:

json
{
  "issues": [
    // ... array of issues
  ],
  "nextPageToken": "next-page-token-here"
}

To implement pagination with this endpoint:

csharp
string baseUrl = "https://bec-sv.atlassian.net/rest/api/3/search/jql";
string jqlQuery = "created >= -35d";
string fields = "id,key,issuetype,created,customfield_12106,status,reporter,summary,updated,customfield_12111,customfield_11700,customfield_12107,assignee,customfield_12113,customfield_12108,customfield_12134,customfield_12226,customfield_12207,customfield_11902,fixVersions,customfield_10008,customfield_12283,customfield_12326,customfield_12325,customfield_12327,customfield_12321,customfield_12320,customfield_12329,customfield_12330,customfield_12331,customfield_12328,customfield_10007";

var queryParams = new Dictionary<string, string>
{
    { "jql", jqlQuery },
    { "fields", fields }
};

// First request
var response = await httpClient.GetAsync($"{baseUrl}?{new FormUrlEncodedContent(queryParams).ReadAsStringAsync()}");
var data = await response.Content.ReadFromJsonAsync<JiraSearchJqlResponse>();

// Subsequent requests using nextPageToken
if (!string.IsNullOrEmpty(data.NextPageToken))
{
    queryParams.Add("nextPageToken", data.NextPageToken);
    response = await httpClient.GetAsync($"{baseUrl}?{new FormUrlEncodedContent(queryParams).ReadAsStringAsync()}");
}

Pagination Best Practices

When implementing pagination with Jira API v3, consider these best practices:

For Traditional /rest/api/3/search Endpoint:

  • Use reasonable maxValues: The maximum value for maxResults is typically 1000. As noted in the Atlassian documentation, “You can only retrieve ‘pages’ of max 1000 issues using the paging query parameters startAt and maxResults.” [source]
  • Calculate total iterations: Use the total field to determine how many pages you need to retrieve: Math.Ceil(total / maxResults)
  • Sequential pagination: Add the value of maxResults to startAt for each subsequent request to move through the results [source]

For Newer /search/jql Endpoint:

  • Use nextPageToken: This token is used for pagination instead of offset-based pagination
  • Token expires: nextPageToken has an expiration time, so you should process results promptly
  • No total count: Unlike the traditional endpoint, you won’t know the total number of results upfront

The Atlassian documentation recommends: “REST API clients systematically confirm maxResults value when making the requests to prevent disruptions whenever these limits change.” [source]


Migration Considerations

It’s important to note that Atlassian has announced deprecation timelines for the traditional search endpoints. According to the community discussion, “the /rest/api/2/search and /rest/api/3/search endpoints will be removed on May 1st, 2025.” [source]

This means you have a few options:

  1. Immediate Migration: Switch to /search/jql now and adapt your pagination logic
  2. Gradual Migration: Continue using /rest/api/3/search until the deprecation date
  3. Hybrid Approach: Use both endpoints depending on your specific needs

The Atlassian documentation notes: “Most of the existing response handling remains the same, but the request structure must be adjusted to align with the new API. Additionally, pagination should be handled using nextPageToken instead of startAt.” [source]


Troubleshooting Steps

If you’re still not getting pagination metadata after switching to the correct endpoint, try these troubleshooting steps:

  1. Verify endpoint URL: Ensure you’re using /rest/api/3/search not /rest/api/3/search/jql
  2. Check response format: Look for the presence of startAt, maxResults, and total fields
  3. Test with minimal parameters: Try a simple query first to isolate the issue
  4. Review API permissions: Ensure your application has the necessary permissions to view all issues
  5. Check for rate limiting: Jira may throttle responses for large result sets

One community member noted: “In this case, even though you are setting maxResults to 1000, the API itself has a hard limit of 100 results per request. To solve this problem, you will need to implement pagination in your API requests.” [source]

If you’re working with more than 50 records, be prepared to send multiple requests: “If you have more than 50 records, you will need to send a request multiple times. In the first response, you will get the value of total that represent the total records from the JQL.” [source]


Conclusion

The missing pagination metadata in your Jira API v3 response is most likely due to using the /search/jql endpoint instead of the traditional /rest/api/3/search endpoint. Here are the key takeaways:

  1. Use the correct endpoint: Switch from /rest/api/3/search/jql to /rest/api/3/search to get the startAt, maxResults, and total fields in your response
  2. Plan for migration: Be aware that the traditional search endpoints will be deprecated on May 1st, 2025, and start planning your migration to the new pagination approach
  3. Implement proper pagination: Calculate the number of pages needed using the total field and iterate through results by incrementing startAt by maxResults
  4. Test both approaches: Consider maintaining both endpoints during the transition period to ensure compatibility

By using the correct endpoint and implementing proper pagination logic, you’ll be able to retrieve all your Jira issues efficiently while maintaining compatibility with both current and future API versions.

Sources

  1. Problem Getting Paging Info from Jira API - Stack Overflow
  2. JIRA Cloud REST API pagination - Same issues returned on different pages - Atlassian Community
  3. How to use the maxResults API parameter for Jira Issue Search REST API - Atlassian
  4. Jira Atlassian API Pagination - Stack Overflow
  5. Why can’t I query more than 1000 results for JIRA? - Stack Overflow
  6. Solved: Rest API maxResults Problem - Atlassian Community
  7. Solved: JIRA API code to resolve pagination for issue search - Atlassian Community
  8. JIRA Cloud REST API v3 /search/jql: Slower Fetching with nextPageToken & No totalIssues – Any Workarounds? - Atlassian Developer Community
  9. When are JQL search endpoints /rest/api/2/search and /rest/api/3/search really being removed? - Atlassian Community
  10. Atlassian REST API Search Endpoints Deprecation - Adaptavist