Problem/Motivation

This feature enhances the pagination capabilities of the Search API Decoupled module by adding support for an explicit offset query parameter in API requests.
It allows clients to skip an arbitrary number of results, enabling more flexible data fetching and integration with frontend applications that use infinite scrolling or custom pagination strategies.

Currently, the prepareQuery() method in SearchApiEndpointController calculates result offsets based solely on the page parameter:

'offset' => $request->get('page') !== NULL ? $request->get('page') * $limit : 0,

This works well for traditional pagination (page=0,1,2...), but doesn’t support skipping a specific number of items independent of pages — a common need for:

  • Infinite scrolling UIs (React, Vue, Next.js, etc.)
  • Mobile apps requesting partial data loads
  • Data exports or analytics queries requiring custom start points

By introducing an offset parameter, developers can now control the exact starting point of search results without depending on page calculations.

Proposed resolution

In SearchApiEndpointController::prepareQuery(), replace the existing pagination logic with this improved version:

// Determine pagination and offset.
$page = $request->get('page');
$offset_param = $request->get('offset');
$offset = 0;

// If both 'page' and 'offset' are present, combine them.
if ($page !== NULL && is_numeric($page)) {
  $offset = (int) $page * $limit;
  if ($offset_param !== NULL && is_numeric($offset_param)) {
    $offset += (int) $offset_param;
  }
}
// If only 'offset' is provided, use it directly.
elseif ($offset_param !== NULL && is_numeric($offset_param)) {
  $offset = (int) $offset_param;
}

// Prevent negative offset values.
$offset = max(0, $offset);

// Build query with computed limit and offset.
$query = $search_api_index->query([
  'limit' => $limit,
  'offset' => $offset,
]);

Example Responses

✅ Example Request 1:
GET /api/search/experiences?offset=4

Effect: Returns results starting from the 5th item.

✅ Example Request 2:
GET /api/search/experiences?page=1&offset=2

Effect: Returns results starting from the 7th item (assuming a limit of 4 → 1 * 4 + 2 = 6 → item #7).

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

sourav_paul created an issue. See original summary.

sourav_paul’s picture

Status: Active » Needs review
a.dmitriiev’s picture

Status: Needs review » Needs work
sourav_paul’s picture

Status: Needs work » Needs review
a.dmitriiev’s picture

Status: Needs review » Needs work

Thank you for the adjustments. I believe there is a small problem now as some lines were deleted that should not be deleted.

a.dmitriiev’s picture

Status: Needs work » Fixed

I fixed those lines myself and merged

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.

sourav_paul’s picture

Thank you so much @a.dmitriiev, This feature would help a lot of people to tackle such scenarios.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.