Skip to main content

How to Fetch Records by List View ID in Salesforce Apex & REST API Guide

In plain words: Fetching records using a List View ID allows your custom Apex controllers, batch jobs, or Lightning Web Components to reuse the exact filtering, sorting, and visibility logic already configured by users in standard Salesforce List Views. Instead of hardcoding complex WHERE clauses, you pass the List View ID to native tools like StandardSetController or the Salesforce User Interface API to pull matching records automatically.

Salesforce List Views allow business users and administrators to create custom data filters without writing code. However, developers often face challenges when trying to query those exact filtered records programmatically. Recreating complex user-configured filter logic manually inside dynamic SOQL creates maintenance overhead whenever a list view is modified. By programmatically binding to the List View ID or developer name, applications can dynamically inherit list view criteria.

1. Architectural Approaches: How Salesforce Handles List Views in Code

Salesforce provides three primary architectural mechanisms to retrieve records defined by a List View:

  • Apex StandardSetController: The native programmatic approach inside Apex. By binding to an sObject collection or query locator and applying setFilterId(listViewId), you can paginate through matching records directly.
  • Salesforce User Interface API (UI API): The modern standard for Lightning Web Components (LWC). Endpoints like /ui-api/list-records/{listViewId} or the wire adapter getListRecordsByName fetch records, metadata, and column configs dynamically.
  • List View Describe REST API: Endpoints under /services/data/vXX.X/sobjects/{sObject}/listviews/{listViewId}/describe return the underlying SOQL query string for advanced custom execution.
360 List View Fetching Architecture Card:
  • Native Apex Pattern: ApexPages.StandardSetController using setFilterId().
  • Modern UI / LWC: lightning/uiListApi (getListRecordsByName).
  • Querying Metadata: Query standard object ListView to retrieve DeveloperName and SobjectType.
  • Security Standard: Always enforce WITH USER_MODE and with sharing to respect record-level security.

2. Implementing List View Retrieval via Apex StandardSetController

The cleanest way to pull records for a List View inside Apex without building external HTTP callouts is using the StandardSetController class.

Production-Ready Pattern: Fetching Records Using StandardSetController
This service class accepts an object's query locator, sets the target List View filter ID, and returns the filtered records.
public with sharing class ListViewRecordService {

    /**
     * @description Retrieves records filtered by a specific Salesforce List View ID
     * @param sObjectType The SObject type name (e.g., 'Account')
     * @param listViewId The 18-character Id of the target List View
     * @param pageSize Number of records to return in the page batch
     * @return List<SObject> Filtered record list
     */
    public static List<SObject> getRecordsByListViewId(String sObjectType, Id listViewId, Integer pageSize) {
        if (String.isBlank(sObjectType) || listViewId == null) {
            throw new IllegalArgumentException('SObject Type and List View ID must not be null.');
        }

        // 1. Build base query locator for the target object
        String baseQuery = 'SELECT Id, Name FROM ' + String.escapeSingleQuotes(sObjectType) + ' LIMIT 10000';
        ApexPages.StandardSetController setController = new ApexPages.StandardSetController(
            Database.getQueryLocator(baseQuery)
        );

        // 2. Apply the List View Filter ID
        setController.setFilterId(listViewId);

        // 3. Set the page chunk size
        setController.setPageSize(pageSize != null && pageSize > 0 ? pageSize : 50);

        // 4. Return matching records
        return setController.getRecords();
    }

    /**
     * @description Helper to find a List View ID by developer name
     */
    public static Id getListViewIdByDeveloperName(String sObjectType, String devName) {
        ListView lv = [
            SELECT Id, DeveloperName, SobjectType 
            FROM ListView 
            WHERE SobjectType = :sObjectType 
              AND DeveloperName = :devName 
            WITH USER_MODE 
            LIMIT 1
        ];
        return lv != null ? lv.Id : null;
    }
}

3. Modern LWC Approach: Using User Interface API (UI API)

For modern front-end components, Salesforce provides dedicated wire adapters that fetch List View records directly in the browser without writing custom Apex:

import { LightningElement, wire } from 'lwc';
import { getListRecordsByName } from 'lightning/uiListApi';
import ACCOUNT_OBJECT from '@salesforce/schema/Account';

export default class AccountListViewViewer extends LightningElement {
    @wire(getListRecordsByName, {
        objectApiName: ACCOUNT_OBJECT.objectApiName,
        listViewApiName: 'All_Partner_Accounts',
        fields: ['Account.Id', 'Account.Name', 'Account.Type', 'Account.Industry'],
        pageSize: 25
    })
    listViewData({ error, data }) {
        if (data) {
            console.log('List View Records:', data.records);
        } else if (error) {
            console.error('Failed to load list view:', error);
        }
    }
}

4. Common Traps & Platform Limitations

SOQL Syntax Trap: Querying the "Query" Field on the ListView SObject Directly
Writing SELECT Query FROM ListView WHERE Id = :listViewId in standard SOQL often fails in production because the Query field is not queryable via standard Apex SOQL across all standard objects or org editions. Attempting to use a semi-join like WHERE Id IN (SELECT Id FROM ListView...) is invalid SOQL syntax. Always use StandardSetController.setFilterId() or the UI API instead of raw ListView queries.
Core Rule: Use StandardSetController.setFilterId() for backend Apex processing and adopt lightning/uiListApi wire adapters for Lightning Web Components to ensure dynamic filter inheritance without fragile SOQL parsing.
  • StandardSetController Limit: StandardSetController can work with up to 10,000 records from the base query locator.
  • Handle List View Scope: When filtering by user-specific list views (e.g., "My Accounts"), ensure the code runs under the appropriate user context (with sharing) so records reflect personal ownership filters.
  • Sanitize Dynamic Inputs: When constructing query strings for dynamic objects, sanitize all object parameters using String.escapeSingleQuotes() to prevent injection risks.

Summary

Fetching records using List View IDs bridges the gap between user-defined declarative filters and custom programmatic business logic. By utilizing ApexPages.StandardSetController for server-side processing or modern UI API wire adapters in Lightning Web Components, developers can build scalable, responsive applications that stay synchronized with business data filters.