Loading
Set Up and Maintain Your Salesforce Organization
Table of Contents
Select Filters

          No results
          No results
          Here are some search tips

          Check the spelling of your keywords.
          Use more general search terms.
          Select fewer filters to broaden your search.

          Search all of Salesforce Help
          Archive SDK Data Query

          Archive SDK Data Query

          The Archive SDK Data Query enables programmatic access to archived data in the Archive app. These data queries automate business processes, support third-party system integrations, create custom views and reports, and cross-reference archived data with active records.

          Archive Widget and Archive Search provide use options for manual data retrieval. The SDK offers advanced capabilities, such as query parameters, filters, and pagination, for direct data access via code.

          SDK Data Query features include:

          • Search archived records by using specified criteria.
          • Use partial matching with an asterisk (*).
          • Return large datasets in batches of up to 1,000 records per page.
          • Apply up to six filters to refine your results.

          These objects are filtered out and aren't searchable via the SDK.

          • Feed
          • HistoryShareFeed
          • Relation
          • Share

          To maintain optimal performance, and verify that only relevant archived data is returned, these objects are excluded from searches.

          Note
          Note Files and Attachments can't be retrieved through the Archive SDK.

          To access archived files, use the Archive Widget or Archive Search.

          Archive SDK Data Query Methods

          To define how you query archived data, set the method provided by the Archive SDK.

          • Accessing Archive Data—The methods within ArchiverAccessor are designed to interact with archived records. Then you can build queries and retrieve data stored in the Archive product.
          • Defining Query Operations—These signatures tell you what kinds of queries you can perform by using the SDK, such as global searches and filtered queries.
          • Guiding Usage—By examining method signatures, developers can understand the inputs and outputs required for their implementations.

          performArchiverGlobalSearch Method

          This method indicates the functionality to perform a global search on archived data.

          Query Parameters

          The Data Query SDK uses several parameters to refine your search. Some parameters are required, while others are optional. Understanding how to configure each parameter helps you get the most accurate and relevant results.

          • Object Name—Specifies the type of Salesforce object to query.

            For example, string sObjectName = 'Account' specifies that the query targets Account records.

            This parameter is mandatory.

            Note
            Note Each query targets a single object. Use separate queries to retrieve data from multiple objects.
          • Search Filters—Filters that narrow search results based on field conditions.
            • Field Name—The field that you want to filter by, such as Name or CreatedDate
            • Value or List of Values—The specific value or values that you want to match

              Example: Single Value Filter

              SF_Archive.SearchFilter filter = new
              SF_Archive.SearchFilter('Name', 'test'); 

              This query returns records where the Name field matches the string "test".

              Example: Multiple Value Filter
              SF_Archive.SearchFilter filter = new
              SF_Archive.SearchFilter('Status', new List<String>{'Open', 'Closed'}); 

              This query returns records where the Status field matches the strings "Open" or "Closed."

              Handling Empty or Null Values—To search for records where a field is empty or null, you can add an empty string ("") to the List of Values.

              Example:

              List<SearchFilter> filters = new List<SearchFilter>();
              filters.add(new SearchFilter('Subject', '')); 
              This query returns Case records where the Subject field is either empty or null.

              Search filter limits:

              • Queries must have at least 1 filter per query.
              • Queries can have up to 6 filters, combined with AND logic, per query.
              • Filters are combined using AND logic by default. OR logic isn't currently supported.
              • A filter's value list can't exceed 1,000 items.

            This parameter is mandatory.

          • Date Filters—If you want to search based on dates, use the DateRange parameter and the mandatory filters. DateRange filters records by fields such as ArchiveDate, CreatedDate, or ModifiedDate.

            Example: Date Filter for Specific Date Query

            Date todayDate = Date.today();
            Date jan1st2024 = Date.newInstance(2024, 1, 1);
            DateRange dateRange = new DateRange('archive_date', jan1st2024, todayDate);

            This query returns records archived between January 1, 2024 and today.

            Example: Date Filter for Multiple Date Range

            List<SF_Archive.SearchFilter> filters = new List<SF_Archive.SearchFilter>();
            SF_Archive.SearchFilter filter = new SF_Archive.SearchFilter('Name', 'test');
            filters.add(filter);
            string sObjectName = 'Account';
            
            Date myDate = Date.newInstance(2024, 1, 11); // January 11, 2024
            Date myDate2 = Date.newInstance(2023, 12, 25); // December 12, 2023
            SF_Archive.dateRange range = new SF_Archive.dateRange('CreatedDate', myDate, myDate);
            SF_Archive.dateRange range2 = new SF_Archive.dateRange('CreatedDate', myDate2, myDate2);
            list<SF_Archive.dateRange> ranges = new list<SF_Archive.dateRange> {range, range2};
            SF_Archive.ArchiverAccessorResponse res = SF_Archive.ArchiverAccessor.performArchiverGlobalSearch(sObjectName, filters, ranges);

            This query returns records archived between December 12, 2023 and January 11, 2024.

            Date filter recommendations:

            • To search based on the Archive Date, add the archive_date date field.
            • Use the Apex date format: MM/DD/YYYY.

            This parameter is optional.

          • Returned Fields—Specify fields to include in the results. If not specified, all fields are returned.

            Example: Return Specific Fields

            List<string> fields = new List<string>{'Name', 'CreatedDate'};

            This query returns only the Name and CreatedDate fields for each record.

            This parameter is optional.

          • Page Size—Sets the number of records per query. The default number of records per query is 25, and the maximum is 1,000.

            Example: Custom Page Size

            SF_Archive.ArchiverAccessorResponse res = 
            SF_Archive.ArchiverAccessor.performArchiverGlobalSearch('Account', 
            filters, 100, fields);

            This query returns 100 records per page.

            Note
            Note Exceeding 1,000 records in your query triggers a run-time error.
            This parameter is optional.
          • Sorting Direction—Sorts results by a field, such as CreatedDate.
            • Ascending (asc): Oldest to newest.
            • Descending (desc): Newest to oldest.

              Example: Sorting Query

              SortingDirection sortingDirection = new SortingDirection('desc');

              This query returns records sorted in descending order based on their CreatedDate.

              This parameter is optional.

          getNextPage Method

          If the results don't all fit on the same page, this method calls the next page.

          ScrollId Parameter

          Use pagination to return large datasets by fetching results in pages of up to 1,000 records.

          To set up the pagination workflow, perform the initial query, use the scrollId from the response to fetch subsequent pages, and continue until scrollId = '-1'..

          Example: Fetch Results with Pagination

          // Perform initial search query
          SF_Archive.ArchiverAccessorResponse res = SF_Archive.ArchiverAccessor.performArchiverGlobalSearch('Account', 
          filters, 100, fields);
                              
          // Get the search response
          SF_Archive.ArchiverAccessorSearchResponse searchResponse = res.getSearchResponseMap();
                              
          // Process first page of results
          system.debug('Total result count: ' + searchResponse.totalResultCount);
          system.debug('Records: ' + searchResponse.records);
                              
          // Fetch next page using the scrollId
          if (searchResponse.scrollId != '-1') {
          SF_Archive.ArchiverAccessorResponse nextPageRes = SF_Archive.ArchiverAccessor.getNextPage(searchResponse.scroll);
          SF_Archive.ArchiverAccessorSearchResponse nextPageResponse = nextPageRes.getSearchResponseMap();
          system.debug('Next Page Records: ' + nextPageResponse.records);
          }

          Access the Methods

          To find the method signatures, go to Apex Classes under Setup. Open the ArchiverAccessor class. Locate all methods listed under the performArchiverGlobalSearch namespace.

          Sample Data Query

          This example retrieves Account records by using these conditions.

          • Fields: Name, CreatedDate
          • Limit: 100 records per page
          • Name: Contains string "test"
          • Sorting: Descending by CreatedDate
          List<SF_Archive.SearchFilter> filters = new List<SF_Archive.SearchFilter>();
          SF_Archive.SearchFilter filter = new SF_Archive.SearchFilter('Name', 'test');
          filters.add(filter);
                          
          List<string> fields = new List<string>{'Name', 'CreatedDate'};
                          
          SortingDirection sortingDirection = new SortingDirection('desc');
                          
          SF_Archive.ArchiverAccessorResponse res = SF_Archive.ArchiverAccessor.performArchiverGlobalSearch('Account', 
          filters, 100, fields, sortingDirection);
                      

          Troubleshoot Common Errors

          Error Code Description Resolution
          INTERNAL_ERROR An unexpected failure occurred. Contact support with error details.
          RESOURCE_LIMIT_ERROR Exceeded pagination or query size limits. Reduce page size or refine search filters.
          VALIDATION_ERROR Missing or invalid search criteria. Make sure that all fields and fields are valid.

          Additional Recommendations

          • Monitor your API usage to avoid hitting limits.
          • To cast the response to an object, serialize it into JSON and then deserialize it back into an object.
          • Verify that fields are enabled and accessible.
          • Double-check all query parameters.
          • For unresolved issues, contact Archive SDK Support with detailed logs.

          For more information, see Archive SDK Testing.

          Archive SDK Data Query—Code Example

          In this code example, a filter, a date range, and an archive search request are validated through the status code in the Archive app.

          A getNextPage call following (scrollId != -1) is included because the size of the results is limited in the performArchiverGlobalSearch call.

          string sObjectName = 'Account';
          list<SF_Archive.SearchFilter>request = new list<SF_Archive.SearchFilter>();
          SF_Archive.SearchFilter filter1 = new SF_Archive.SearchFilter('Name', 'test');
          request.add(filter1);
          SF_Archive.dateRange range = new SF_Archive.dateRange('CreatedDate', system.today()-150, system.today());
          SF_Archive.ArchiverAccessorResponse res = SF_Archive.ArchiverAccessor.performArchiverGlobalSearch(sObjectName, request, range);
          
          if(res.getStatusCode() == 200){
              system.debug('code: ' + res.getStatuscode());
              SF_Archive.ArchiverAccessorSearchResponse searchResponse = res.getSearchResponseMap();
              system.debug('count: '+ searchResponse.totalResultCount);
              system.debug('scrollid: '+ searchResponse.scrollId);
              system.debug('list size: '+ searchResponse.records.size());
              string scrollId = searchResponse.scrollId;
              integer page = 1;
          
              while(scrollId != '-1'){
                  page++;
                  SF_Archive.ArchiverAccessorResponse secondPage =
                  SF_Archive.ArchiverAccessor.getNextPage(searchResponse.scrollId);
                  if(secondPage.getStatusCode() == 200){
                      SF_Archive.ArchiverAccessorSearchResponse searchResponse2 = secondPage.getSearchResponseMap();
                      scrollId = searchResponse2.scrollId;
                      system.debug('count: '+ searchResponse2.totalResultCount);
                      system.debug('scrollid: '+ searchResponse2.scrollId);
                      system.debug('list size: '+ searchResponse2.records.size());
                      system.debug('page number: '+ page);
                  } else{
                      system.debug('response is != 200: '+ secondPage.getStatusCode());
                      system.debug('body: '+ secondPage.getBody());
                      break;
                      } 
                  }
              } else {
                  system.debug('status code erorr|: '+ res.getStatusCode());
                  system.debug('status code message|: '+ res.getErrorMessage()); 
              }

          Archive SDK Data Query—Sample Use Case 1

          This example use case shows how to build and customize a widget that displays High Priority Accounts in the Archive app.

          Use Case

          Your business requires that the Tier 3 Support Team has access to view archived Cases with a high-priority status.

          This example shows how to:

          • Create a customized Lightning Web Component (LWC).
          • Pull archived data by using the data query SDK.
          • Apply the filter (High Priority).
            Note
            Note Other filters can be customized by referring to the code in Archive SDK Data Query — Code Example.

            This example is limited to 25 records. The SDK enables you to set the results at 1,000 per page. The default is 25, with the option of pagination through the results.

          Widget Displaying High-Priority Cases

          Sample SdkUseCaseWidget.js

          In this code example, the parameter is AccountRecordId.

          import { LightningElement, api, track } from 'lwc';
              import getCases from '@salesforce/apex/ArchiveSdk.getCases';
              export default class SampleSdkUseCaseWidget extends LightningElement {
              @api recordId;
              
              columns = [
              { label: 'Case Number', fieldName: 'caseNumber', type: 'text', cellAttributes: {alignment: 'center'}},
              { label: 'Subject', fieldName: 'subject', type: 'text' , cellAttributes: {alignment: 'center'}, },
              { label: 'Priority', fieldName: 'priority', type: 'text', cellAttributes: {alignment: 'center'}, },
              { label: 'Status', fieldName: 'status', type: 'text', cellAttributes: {alignment: 'center'}, }
              ];
              @track records;
              @track data
              @track _loading;
              
              async connectedCallback() {
              this._loading = true;
              try {
              const result = await getCases({parentId: this.recordId})
              this.records = result;
              this._loading = false;
              } catch (error) {
              this._loading = false;
              }}
          }            

          Sample SdkUseCaseWidget.html

          The Apex controller that the LWC uses calls the Data Query SDK.

          SF_Archive.ArchiverAccessor.performArchiverGlobalSearch(sObjectName, request, fields, range);

          This is the call for the Archive SDK. It includes these parameters.

          • sObjectName—Depicts the Search
          • Filters—Used to retrieve the data
          • Fields—The projected fields to return from data.
          • Range—The date range used to query the data.
          <template>
              <template if:true={_loading}>
                  <lightning-spinner></lightning-spinner>
              </template>
              <lightning-datatable
                  key-field="caseNumber"
                  data={records}
                  columns={columns}
                  hide-checkbox-column>
              </lightning-datatable>
          </template>

          ArchiveSdk.cls

          This code block is the Apex controller.

          public with sharing class ArchiveSDK {
                          
              @AuraEnabled
              public static List<CaseTableWrapperExample.CaseRecord> getCases(String parentId) {
              // Create an empty list to hold maps with String keys and Object values
              List<Map<String, Object>> totalRecords = new List<Map<String, Object>>();
              
              // Create a list to store search filter objects
              List<SF_Archive.SearchFilter> request = new List<SF_Archive.SearchFilter>();
              
              // Create a search filter for the 'AccountId' field with a given 'parentId' value
              SF_Archive.SearchFilter filter1 = new SF_Archive.SearchFilter('AccountId', parentId);
              
              // Create a search filter for the 'Priority' field with a given 'High' value
              SF_Archive.SearchFilter filter2 = new SF_Archive.SearchFilter('Priority', 'High');
              
              // Add the filters to the request list
              request.add(filter1);
              request.add(filter2);
              
              // Define the object name as 'Case'
              String sObjectName = 'Case';
              
              // Create a list of Strings representing field names to be retrieved from Archive DB
              List<String> fields = new List<String>{'CaseNumber', 'Subject', 'Priority', 'Status'};
              
              // Create the DateRange based on the created date
              SF_Archive.DateRange range = new SF_Archive.DateRange('CreatedDate', system.today() - 150, system.today());
              
              // Perform an initial global search and store the response
              SF_Archive.ArchiverAccessorResponse res = SF_Archive.ArchiverAccessor.performArchiverGlobalSearch(sObjectName, request, range);
              
              // Check if the HTTP response status code is 200 (success)
              if (res.getStatusCode() == 200) {
                  system.debug('code: ' + res.getStatuscode());
                  
                  // Retrieve the initial search response map
                  SF_Archive.ArchiverAccessorSearchResponse searchResponse = res.getSearchResponseMap();
                  
                  system.debug('count: ' + searchResponse.totalResultCount);
                  system.debug('scrollid: ' + searchResponse.scrollId);
                  system.debug('list size: ' + searchResponse.records.size());
                  
                  // Store the scroll ID for pagination
                  String scrollId = searchResponse.scrollId;
                  
                  // Initialize the page number
                  Integer page = 1;
                  
                  // Add the records from the initial search to the totalRecords list
                  totalRecords.addAll(searchResponse.records);
                  
                  // Continue to fetch additional pages while the scroll ID is not '-1'
                  while (scrollId != '-1') {
                      page++;
                      
                      // Get the next page of search results using the UPDATED scrollId 
                      SF_Archive.ArchiverAccessorResponse nextPageResponse = SF_Archive.ArchiverAccessor.getNextPage(scrollId);
                      
                      // Check if the HTTP response status code is 200 (success)
                      if (nextPageResponse.getStatusCode() == 200) {
                      
                          // Retrieve the search response for the current page
                          SF_Archive.ArchiverAccessorSearchResponse searchResponse2 = nextPageResponse.getSearchResponseMap();
                          
                          // CRITICAL FIX: Update the scrollId with the value from the new response 
                          scrollId = searchResponse2.scrollId;
                          
                          system.debug('count: ' + searchResponse2.totalResultCount);
                          system.debug('scrollid: ' + searchResponse2.scrollId);
                          system.debug('list size: ' + searchResponse2.records.size());
                          system.debug('page number: ' + page); 
                          
                          // Add the records from the current page to the totalRecords list
                          totalRecords.addAll(searchResponse2.records);
                      } else {
                          // Output an error message if the HTTP response status code is not 200
                          system.debug('response is != 200: ' + nextPageResponse.getStatusCode());
                          system.debug('body: ' + nextPageResponse.getBody());
                          
                          // Break out of the loop if there is an error
                          break;
                      }
                  } // End of while loop
              } else {
                  // Handle error from initial search
                  system.debug('status code error: ' + res.getStatusCode());
                  system.debug('status code message: ' + res.getErrorMessage());
              }
              
              // Return the list of total records
              List<CaseTableWrapperExample.CaseRecord> result = new List<CaseTableWrapperExample.CaseRecord>();
              return CaseTableWrapperExample.getCasesTable(totalRecords);
              }
          }

          CaseTableWrapperExample.cls

          Helper class to formulate class from Apex to LWC

          public class CaseTableWrapperExample{
              public static List<caseRecord> getCasesTable(list<map<string,object>> cases){
              List<caseRecord> caseReturnList = new List<caseRecord>();
              for(Map<string,object> caseRecord: cases){
              caseRecord tempCase = new caseRecord();
              tempCase.caseNumber = String.valueOf(caseRecord.get('CaseNumber'));
              tempCase.id = String.valueOf(caseRecord.get('Id'));
              tempCase.origin = String.valueOf(caseRecord.get('Origin'));
              tempCase.status = String.valueOf(caseRecord.get('Status'));
              tempCase.subject = String.valueOf(caseRecord.get('Subject'));
              tempCase.priority = String.valueOf(caseRecord.get('Priority'));
                  
              caseReturnList.add(tempCase);
              }
              return caseReturnList;
              }
              
              public class caseRecord {
              @AuraEnabled public string caseNumber;
              @AuraEnabled public string id;
              @AuraEnabled public string origin;
              @AuraEnabled public string status;
              @AuraEnabled public string priority;
              @AuraEnabled public string subject;
          }}

          The above code describes a sample scenario whereby you can add LWC as a widget to the Lightning page.

          To view the actual Lightning data table, add this code to the sampleSdkUseCaseWidget.js-meta.xml file. Then add the Archive Widget to the Lightning Page.

          <?xml version="1.0" encoding="UTF-8"?>
          <LightningComponentBundle xmlns="<a href='http://soap.sforce.com/2006/04/metadata">;
              <apiVersion>55.0</apiVersion>
              <isExposed>true</isExposed>
              <targets>
              <target>lightning__RecordPage</target>
              <target>lightning__AppPage</target>
              </targets>
              <targetConfigs>
              <targetConfig targets="lightning__RecordPage">
              <supportedFormFactors>
              <supportedFormFactor type="Small" />
              <supportedFormFactor type="Large" />
              </supportedFormFactors>
              </targetConfig>
              <targetConfig targets="lightning__AppPage">
              <supportedFormFactors>
              <supportedFormFactor type="Small" />
              <supportedFormFactor type="Large" />
              </supportedFormFactors>
              </targetConfig>
              </targetConfigs>
          </LightningComponentBundle>

          Archive SDK Data Query—Sample Use Case 2

          This example use case shows how Archive SDK handles tasks without exceeding governor limits, such as CPU limits or Timeout callouts, in the Archive app.

          For more information, see Apex Governor Limits.

          Use Case

          Your business requires that the Tier 3 Support Team has access to view archived Cases with a high-priority status.

          This example shows how to work around an error when the number of archived records retrieved via the SDK is too large. The error reads: SF_Archive.ArchiverAccessor.ArchiverAccessorException: Exceeded time allotted for callout, please contact support.

          Code from these Apex classes creates this use case.

          The ArchiveSecondPageJob class processes paginated data from Archive by using a scroll ID, making callouts as needed. It runs asynchronously via the Queueable interface, tracking the total execution time to avoid exceeding limits and enqueuing itself for continued processing if necessary. The class handles responses, updates the scroll ID, and logs details about each retrieved data page.

          public class ArchiveSecondPageJob implements Queueable,Database.AllowsCallouts {
                                    
                 private String scrollId;
                 private long totalTime;
                 private integer pageNumber;
          
                 public archiveSecondPageJob(String prevScrollId, integer pageNumber) {
                     scrollId = prevScrollId;
                     this.pageNumber = pageNumber;
                 }
          
                 public void execute(QueueableContext context) {
                     system.debug('executing');
                     doExecute();
                 }
                 private void doExecute() {
                         SF_Archive.ArchiverAccessorSearchResponse searchResponse = null;
                         integer page = 1;
                         long totalTime = 0;
            
                                 while(scrollId != '-1')
                                 {       
                                     //avoid 12000 ms limit
                                     if(totalTime > 90000){
                                         system.debug('Creating new task');
                archiveSecondPageJob q = new archiveSecondPageJob(scrollId,this.pageNumber);
                                         System.enqueueJob(q);
                                         return;
                                     }
                                     //Get the next page using the scrollId     
                                     Long startTime = DateTime.now().getTime(); 
                                     SF_Archive.ArchiverAccessorResponse nextPage = SF_Archive.ArchiverAccessor.getNextPage(scrollId); 
                                     Long stopTime = DateTime.now().getTime();
                                     totalTime += stopTime - startTime;
                                     if(nextPage.getStatusCode() == 200){     
                                         this.pageNumber++;
                                         SF_Archive.ArchiverAccessorSearchResponse searchResponse2 =nextPage.getSearchResponseMap();      
                                         scrollId = searchResponse2.scrollId;
                                         system.debug('count: '+ searchResponse2.totalResultCount);    
                                         system.debug('scrollid: '+ searchResponse2.scrollId); 
                                         system.debug('list size: '+ searchResponse2.records.size());  
                                         system.debug('body: '+ searchResponse2.records);  
                                         system.debug('page: '+ pageNumber);  
                                         system.debug('time: '+ totalTime); 
                                     }       
                                     else{           
                                         system.debug('response is != 200: '+ nextPage.getStatusCode());           
                                         system.debug('body: '+ nextPage.getBody());
                                         return;
                                     }           
                                 }
                 }
          }
                      

          The ArchiveSearch class performs a search on the Case object by using specific filters, retrieves the results, and logs details such as the total count and scroll ID. If the search returns a valid scroll ID, indicating more pages of results, it enqueues the archiveSecondPageJob to process the next page asynchronously. This class essentially initiates the search and hands off further processing to the previously defined archiveSecondPageJob.

          Here's the format for the initial search call.

          public class ArchiveSearch {
                              
              public void doSearch(){
                  
                  string sObjectName = 'Case';
                  list<SF_Archive.SearchFilter> request = new list<SF_Archive.SearchFilter>();
              
                  SF_Archive.SearchFilter filter1 = new SF_Archive.SearchFilter('Priority', 'High');
                  request.add(filter1);
                  
             
                  list<string> fields = new list<string>{'CaseNumber', 'Id'};
                  
                  SF_Archive.ArchiverAccessorResponse res = SF_Archive.ArchiverAccessor.performArchiverGlobalSearch(sObjectName, request, fields);   
                  if(res.getStatusCode() == 200){
                     system.debug('code: ' + res.getStatuscode());
                     SF_Archive.ArchiverAccessorSearchResponse searchResponse = res.getSearchResponseMap();
                     system.debug('count: '+ searchResponse.totalResultCount);
                     system.debug('scrollid: '+ searchResponse.scrollId);
                     system.debug('list size: '+ searchResponse.records.size());
                     string scrollId = searchResponse.scrollId;
                     integer page = 1;   
                     if(scrollId != '-1'){
                         system.debug('calling next page');
                         integer pageNumber = 2;
                         archiveSecondPageJob q = new archiveSecondPageJob(scrollId, pageNumber);
                         System.enqueueJob(q);
             }}}}

          For more information, see Salesforce Apex Developer Guide.

           
          Loading
          Salesforce Help | Article