Get started with the Processing API
The Processing API supports the automation of your processing workflows. You can programmatically use this API to create and update custodians, data sources, processing sets, and profiles required for processing. It provides an alternative to manually creating them through the Relativity UI. You also can use the Processing API to run inventory, discovery, and publishing jobs.
Use the information on this page to learn about Processing API fundamentals. It includes prerequisites for developing with this API, and code samples for common operations. Additional resources to help you get started with the Processing API include:
- Field Mapping API and Field Mapping service - provides information about the Field Mapping service available through the Relativity Services API and REST API respectively.
- Processing on the Relativity Documentation site - provides general information about how Relativity supports processing.
- Relativity SDK samples - provides information about how to run the code samples provided on this page against your local Relativity instance.
This page contains the following information:
- Processing API fundamentals
- Processing API prerequisites
- Processing Custodian Manager
- Processing Profile Manager
- Processing Data Source Manager
- Processing Set Manager
- Processing Job Manager
See these related pages:
Processing API fundamentals
The Processing application provides system admins with the ability to ingest raw data directly into a workspace for review. When you set up a processing workflow, you create a processing profile. This profile specifies settings that control how the processing engine ingests the data. You create or reference the following items:
- A custodian who is a user associated with the data included in a processing job.
- A data source that contains the path used to specify the location of the files that you want to discover.
You also create a processing set that links a processing profile to one or more data sources. When you run a discovery job, the processing engine discovers files in the data source based on the values specified in the processing set. For more information, see Processing on the Relativity Documentation site
The Processing API provides interfaces and objects that you can use to automate many of the tasks in a processing workflow. It includes the following interfaces that you can use to access services, which interact with custodian, data source, and processing set objects:
- IProcessingCustodianManager - used to access the Processing Custodian Manager service.
- IProcessingDataSourceManager - used to access the Processing Data Source Manager service.
- IProcessingProfileManager - used to access the Processing Profile Manager service.
- IProcessingSetManager - used to access the Processing Set Manager service.
Each of these interfaces provide a ReadAsync() and SaveAsync() method, which you can use to create, update, or retrieve processing objects. The Processing API includes the ProcessingCustodian, ProcessingDatasource, ProcessingProfile, and ProcessingSet classes. You can set or retrieve properties on these classes by calling the ReadAsync() or SaveAsync() method on their respective interfaces. You must call the SaveAsync() method to add any new or modified objects to the database.
Common processing workflows
The Processing API also includes the IProcessingJobManager interface. You can use this interface to access the Processing Job Manager service for running inventory, discovery, and publishing jobs. It includes the following methods:
- SubmitInventoryJobsAsync() method – used for excluding irrelevant files from a data set prior to running a discovery job, such as eliminating NIST file types. The InventoryJob class includes properties for the workspace artifact and processing set IDs required to submit a job.
- SubmitDiscoveryJobsAsync() method – used for submitting data sources to the processing engine for discovery. The DiscoveryJob class includes properties for the workspace artifact and processing set IDs required to submit a job.
- SubmitPublishJobsAsync() method – used to publish the processed data to a workspace after discovery, so that reviewers can access it. The PublishJob class includes properties for the workspace artifact and processing set IDs required to submit a job.
Common workflows for processing include inventorying, discovering, and then publishing data, or just discovering and then publishing data. You can only inventory files that haven’t been discovered. Additionally, you can only publish files after Relativity has completed discovery. For more information, see Processing Job Manager and Processing API services for REST.
In Relativity, you want to enable the auto-publish option on the processing profile, so that the discovered files are automatically added to the workspace. See Relativity environment setup.
Processing API prerequisites
Complete the following prerequisites to begin development with the Processing API:

You can download the SDKs required for automating processing workflows from the Relativity Community. For more information, see Download the SDKs.
After you download the following SDKs, install or extract their contents to folders on your local machine:
- Relativity SDK
- Processing SDK

- Obtain access to an instance of Relativity Server2021 used for development purposes.
Note: You must install the Processing application on this Relativity instance.
- Enable Developer mode in your development instance of Relativity to simplify troubleshooting. For more information, see Set up your development environment.
- In the Relativity UI, ensure that the Auto-publish set field is set to Yes on the processing profile that the processing set references in your code. For more information about this field, see Processing profiles in the Relativity Documentation site.

You need to obtain the Artifact IDs of several items that the classes in the Processing API reference. Use these steps to obtain this information from the workspace database:
- Log in to Relativity.
- On the Workspace tab, locate the workspace that you want to use for automating a processing workflow. Note the Case Artifact ID for the workspace.
- On your database server for Relativity, open Microsoft SQL Server Management Studio.
- In the Object Explorer, expand Databases.
- Use the Case Artifact ID with the prefix EDDS to find the database for your workspace, such as EDDS1014823.
- Expand your workspace to display a list of tables. Reference these tables to obtain the required Artifact IDs:
- EDDSDBO.Folder – Locate the Artifact ID for the destination folder that you want your data source to reference. See Create a ProcessingDataSource object.
- EDDSDBO.ProcessingProfile – Locate the Artifact ID for the processing profile that you want your processing set to reference. See Create a ProcessingSet object.
- EDDSDBO.RelativityTimeZone – Locate the Artifact ID for the time zone that you want your data source to reference. See Create a ProcessingDataSource object.
Note: You must install the Processing application in your Relativity environment in order to view the table for time zones and processing profiles.
Development guidelines for the Processing API
Use these guidelines when automating workflows with the Processing API:
- Add the following DLL references to your Visual Studio project. For additional information, see Prerequisites for Processing API development.
- Relativity.Processing.Services.Interfaces.dll (in the Processing API SDK)
- kCura.Relativity.Client.dll (in the Relativity SDK)
- Relativity.Kepler.dll (in the Relativity SDK)
- Use the Relativity API helpers to establish a connection with the Processing API and set the context used for your code execution. All code samples on this page illustrate how to use the helper classes to connect with the Processing API. For more information, see Using Relativity API Helpers.
- Call the SaveAsync() method on any processing object that you create or modify. Your changes won't be added to the database until you make this call.
- Use a try-catch block around your code for creating, updating, and reading objects. Also, use it when submitting jobs. Catch any ServiceExceptions raised by your code as exemplified in the following code samples.
- Use logging to help troubleshoot your code as exemplified in the following code samples.
Processing Custodian Manager
The Processing Custodian Manager service supports read and save operations on custodian objects. The ProcessingCustodian class represents a custodian associated with the files that you want to process. For more information, see Entity object on the Relativity Documentation site.
Create a ProcessingCustodian
To create a ProcessingCustodian instance, invoke the constructor and then initialize the following properties:
- ArtifactID – set this property to 0, indicating that you are creating a new instance.
- DocumentNumberingPrefix – set this property to a prefix that you want applied to files when the processing engine publishes them to a workspace. The default value is REL.
- FirstName – set this property to the custodian's first name.
- LastName – set this property to the custodian's last name.
Next, call the SaveAsync() method on the proxy created with the IProcessingCustodianManager interface to access the service. You must then pass this method the initialized ProcessingCustodian instance and the workspace Artifact ID.
public async Task<bool> ProcessingCustodianManager_Create_SaveAsync(IHelper helper) { bool success = false; //Get a connection to the API using the Relativity API Helper classes, available on event handlers, //agents, and custom Pages. They are mocked in these samples. //This sample code executes under the context of the current user. using (IProcessingCustodianManager proxy = helper.GetServicesManager().CreateProxy<IProcessingCustodianManager>(ExecutionIdentity.User)) { try { //Build the ProcessingCustodian object. ProcessingCustodian processingCustodian = new ProcessingCustodian { ArtifactID = 0, // Indicates a new ProcessingCustodian object. DocumentNumberingPrefix = "REL", FirstName = "John", LastName = "Smith" }; //Create the ProcessingCustodian object. The service returns the Artifact ID of the object. int artifactId = await proxy.SaveAsync(processingCustodian, WorkspaceId); if (artifactId != 0) { success = true; } else { Logger.LogMessage(LogLevel.Error, nameof(ProcessingCustodianManager_Create_SaveAsync), "Create failed", this.GetType().Name); } } catch (Exception exception) { //The service returns exceptions of type ServiceException. Logger.LogMessage(LogLevel.Error, nameof(ProcessingCustodianManager_Create_SaveAsync), exception.Message, this.GetType().Name); } } return success; }
Read a ProcessingCustodian
Read the values for the properties on a ProcessingCustodian object by calling the ReadAsync() method on the proxy created with IProcessingCustodianManager interface. The ReadAsync() method requires that you pass the Artifact IDs of the ProcessingCustodian object and the workspace as arguments.
public async Task<bool> ProcessingCustodianManager_ReadAsync(IHelper helper, int processingCustodianArtifactId) { bool success = false; //Get a connection to the API using the Relativity API Helper classes, available on event handlers, //agents, and custom Pages. They are mocked in these samples. //This sample code executes under the context of the current user. using (IProcessingCustodianManager proxy = helper.GetServicesManager().CreateProxy<IProcessingCustodianManager>(ExecutionIdentity.User)) { try { //Read the ProcessingCustodian object. ProcessingCustodian processingCustodian = await proxy.ReadAsync(processingCustodianArtifactId, WorkspaceId); //Display the last and first name of the custodian. string fullName = $"{processingCustodian.LastName}, {processingCustodian.FirstName}"; Logger.LogMessage(LogLevel.Debug, nameof(ProcessingCustodianManager_ReadAsync), fullName, this.GetType().Name); success = true; } catch (Exception exception) { //The service returns exceptions of type ServiceException. Logger.LogMessage(LogLevel.Error, nameof(ProcessingCustodianManager_ReadAsync), exception.Message, this.GetType().Name); } } return success; }
Update a ProcessingCustodian
When updating a ProcessingCustodian instance, you call the AsyncRead() method on the proxy created with the IProcessingCustodianManager interface. Next, set the properties on the instance to their new values, and then call the SaveAsync() method. You must call the SaveAsync() method in order for your changes to be added to the database.
public async Task<bool> ProcessingCustodianManager_Update_SaveAsync(IHelper helper, int processingCustodianArtifactId) { bool success = false; //Get a connection to the API using the Relativity API Helper classes, available on event handlers, //agents, and custom Pages. They are mocked in these samples. //This sample code executes under the context of the current user. using (IProcessingCustodianManager proxy = helper.GetServicesManager().CreateProxy<IProcessingCustodianManager>(ExecutionIdentity.User)) { try { //Read the ProcessingCustodian object. ProcessingCustodian processingCustodian = await proxy.ReadAsync(processingCustodianArtifactId, WorkspaceId); //Modify the document numbering prefix and first name. processingCustodian.DocumentNumberingPrefix = "ECA"; processingCustodian.FirstName = "Sam"; processingCustodian.Name = $"{processingCustodian.LastName}, {processingCustodian.FirstName}"; //Update the ProcessingCustodian object. The service returns the Artifact ID of the object. int artifactId = await proxy.SaveAsync(processingCustodian, WorkspaceId); if (artifactId != 0) { success = true; } else { Logger.LogMessage(LogLevel.Error, nameof(ProcessingCustodianManager_Update_SaveAsync), "Update failed", this.GetType().Name); } } catch (Exception exception) { //The service returns exceptions of type ServiceException. Logger.LogMessage(LogLevel.Error, nameof(ProcessingCustodianManager_Update_SaveAsync), exception.Message, this.GetType().Name); } } return success; }
Processing Profile Manager
The Processing Profile Manager service includes the SaveAsync() method for creating and updating a profile, the ReadAsync() method for retrieving a profile, and the DeleteAsync() method for removing a profile from Relativity. The ProcessingProfile class represents a collection of settings used to process documents. Processing profiles are associated with processing sets, so you must provide the Artifact ID of a processing profile when creating or updating a processing set. See Processing Set Manager.
Sample ProcessingProfile object
The ProcessingProfile class has multiple properties for specifying numbering, deNISTing, extraction, and deduplication settings. Many of these properties reference other classes and enumerations. For example, the ProcessingProfile class contains a property that references the DeduplicationSettings class, which has a property that is set with values from the DeduplicationMethod enumeration.
You can find more information about processing profile fields on the following pages:
- Processing profiles in the Relativity Documentation site.
- Processing API on the Relativity API reference page
The BuildBasicProfile class provides an example of how to set the properties on a ProcessingProfile object. It is referenced in the other code samples in this section.
private ProcessingProfile BuildBasicProfile(int timeZoneId) { ProcessingProfile profile = new ProcessingProfile(); profile.Name = "testProf"; profile.NumberingSettings = new NumberingSettings(); profile.NumberingSettings.DefaultDocumentNumberingPrefix = "abc"; profile.NumberingSettings.NumberOfDigits = NumberOfDigits.NumberOfDigits4; profile.NumberingSettings.NumberingType = NumberingType.AutoNumber; profile.NumberingSettings.ParentChildNumbering = ParentChildNumbering.ContinuousAlways; profile.DeduplicationSettings = new DeduplicationSettings(); profile.DeduplicationSettings.DeduplicationMethod = DeduplicationMethod.None; profile.ExtractionSettings = new ExtractionSettings(); profile.ExtractionSettings.Extractchildren = false; profile.ExtractionSettings.EmailOutput = EmailOutput.MSG; profile.ExtractionSettings.ExcelTextExtractionMethod = ExcelTextExtractionMethod.Native; profile.ExtractionSettings.ExcelHeaderFooterExtraction = ExcelHeaderFooterExtraction.DoNotExtract; profile.ExtractionSettings.PowerPointTextExtractionMethod = PowerPointTextExtractionMethod.Native; profile.ExtractionSettings.WordTextExtractionMethod = WordTextExtractionMethod.Native; profile.ExtractionSettings.OCR = false; profile.InventoryDiscoverSettings = new InventoryDiscoverSettings(); profile.InventoryDiscoverSettings.DeNIST = false; profile.InventoryDiscoverSettings.DefaultTimeZoneID = timeZoneId; profile.InventoryDiscoverSettings.DefaultOCRlanguages = new HashSet<OcrLanguage> { OcrLanguage.English }; profile.PublishSettings = new PublishSettings(); profile.PublishSettings.AutopublishSet = false; profile.PublishSettings.DefaultDestinationFolder = new Services.Folder.FolderRef { ArtifactID = NewFolderId }; profile.PublishSettings.UseSourceFolderStructure = true; return profile; }
Create a ProcessingProfile
To create a processing profile in a workspace, instantiate a ProcessingProfile object, and set the required fields as illustrated in Sample ProcessingProfile object. Call the SaveAsync() method by passing it the new ProcessingProfile instance and the Artificat ID of a Workspace object. See the following code:
public async Task<int> ProcessingProfileManager_Create_SaveAsync(IHelper helper, int timeZoneId) { int profileId = 0; //Get a connection to the API using the Relativity API Helper classes, available on event handlers, //agents, and custom Pages. They are mocked in these samples. //This sample code executes under the context of the current user. using (IProcessingProfileManager proxy = helper.GetServicesManager().CreateProxy<IProcessingProfileManager>(ExecutionIdentity.User)) { try { //Build the ProcessingProfile object. ProcessingProfile profile = BuildBasicProfile(timeZoneId); //Build the ProcessingProfileSaveRequest. ProcessingProfileSaveRequest saveRequest = new ProcessingProfileSaveRequest { ProcessingProfile = profile, WorkspaceId = WorkspaceId }; //Create the ProcessingProfile object. The service returns a ProcessingProfileSaveResponse object. ProcessingProfileSaveResponse saveResponse = await proxy.SaveAsync(saveRequest); profileId = saveResponse.ProcessingProfileId; if (profileId == 0) { Logger.LogMessage(LogLevel.Error, nameof(ProcessingProfileManager_Create_SaveAsync), "Create failed", this.GetType().Name); } } catch (ServiceException exception) { //The service returns exceptions of type ServiceException. Logger.LogMessage(LogLevel.Error, nameof(ProcessingProfileManager_Create_SaveAsync), exception.Message, this.GetType().Name); } } return profileId; }
Read a ProcessingProfile
Use the ReadAsync() method to retrieve a processing profile from Relativity. Pass this method a ProcessingProfileReadRequest object, which contains the Artifact ID of the ProcessingProfile object, and Artifact ID of an associated Workspace object. See the following sample code:
public async Task<ProcessingProfile> ProcessingProfileManager_ReadAsync(IHelper helper, int processingProfileArtifactId) { ProcessingProfile readProfile = new ProcessingProfile(); readProfile.ArtifactID = 0; //Get a connection to the API using the Relativity API Helper classes, available on event handlers, //agents, and custom Pages. They are mocked in these samples. //This sample code executes under the context of the current user. using (IProcessingProfileManager proxy = helper.GetServicesManager().CreateProxy<IProcessingProfileManager>(ExecutionIdentity.User)) { try { // Build the ProcessingProfileReadRequest object. ProcessingProfileReadRequest readRequest = new ProcessingProfileReadRequest { ProcessingProfileId = processingProfileArtifactId, WorkspaceId = WorkspaceId }; //Read the ProcessingProfile object. ProcessingProfileReadResponse readResponse = await proxy.ReadAsync(readRequest).ConfigureAwait(false); //Display the Artifact ID of the processing profile. string profileId = $"{readResponse.ProcessingProfile.ArtifactID}"; Logger.LogMessage(LogLevel.Debug, nameof(ProcessingProfileManager_ReadAsync), profileId, this.GetType().Name); readProfile = readResponse.ProcessingProfile; } catch (ServiceException exception) { //The service returns exceptions of type ServiceException. Logger.LogMessage(LogLevel.Error, nameof(ProcessingProfileManager_ReadAsync), exception.Message, this.GetType().Name); } } return readProfile; }
Update a ProcessingProfile
To update a processing profile, modify the profile fields as necessary, instantiate a ProcessingProfileSaveRequest object, and then pass this object to the SaveAsync() method. The ProcessingProfileSaveRequest object contains the Artifact ID of the ProcessingProfile object, and Artifact ID of an associated Workspace object. See the following sample code:
public async Task<int> ProcessingProfileManager_Update_SaveAsync(IHelper helper, int processingProfileId) { int profileId = 0; //Get a connection to the API using the Relativity API Helper classes, available on event handlers, //agents, and custom Pages. They are mocked in these samples. //This sample code executes under the context of the current user. using (IProcessingProfileManager proxy = helper.GetServicesManager().CreateProxy<IProcessingProfileManager>(ExecutionIdentity.User)) { try { // Build the ProcessingProfileReadRequest object. ProcessingProfileReadRequest readRequest = new ProcessingProfileReadRequest { ProcessingProfileId = processingProfileId, WorkspaceId = WorkspaceId }; //Read the ProcessingProfileReadResponse object and grab the profile. ProcessingProfileReadResponse readResponse = await proxy.ReadAsync(readRequest).ConfigureAwait(false); ProcessingProfile profile = readResponse.ProcessingProfile; //Modify the list of OCR languages and the name of the processing profile. profile.Name = "The profile has been updated"; profile.InventoryDiscoverSettings.DefaultOCRlanguages = new HashSet<OcrLanguage> { OcrLanguage.English, OcrLanguage.Spanish }; //Build the ProcessingProfileSaveRequest. ProcessingProfileSaveRequest saveRequest = new ProcessingProfileSaveRequest { ProcessingProfile = profile, WorkspaceId = WorkspaceId }; //Update the ProcessingProfile object.The service returns a ProcessingProfileSaveResponse. ProcessingProfileSaveResponse saveResponse = await proxy.SaveAsync(saveRequest).ConfigureAwait(false); profileId = saveResponse.ProcessingProfileId; if (profileId == 0) { Logger.LogMessage(LogLevel.Error, nameof(ProcessingProfileManager_Update_SaveAsync), "Update failed", this.GetType().Name); } } catch (ServiceException exception) { //The service returns exceptions of type ServiceException. Logger.LogMessage(LogLevel.Error, nameof(ProcessingProfileManager_Update_SaveAsync), exception.Message, this.GetType().Name); } } return profileId; }
Delete a ProcessingProfile
Use the DeleteAsync() method to remove a processing profile from Relativity. Pass this method a ProcessingProfileDeleteRequest object, which contains the Artifact ID of the ProcessingProfile object, and Artifact ID of an associated Workspace object. See the following sample code:
public async Task<bool> ProcessingProfileManager_DeleteAsync(IHelper helper, int processingProfileId) { bool success = false; //Get a connection to the API using the Relativity API Helper classes, available on event handlers, //agents, and custom Pages. They are mocked in these samples. //This sample code executes under the context of the current user. using (IProcessingProfileManager proxy = helper.GetServicesManager().CreateProxy<IProcessingProfileManager>(ExecutionIdentity.User)) { try { // Create the ProcessingProfileDeleteRequest object. ProcessingProfileDeleteRequest deleteRequest = new ProcessingProfileDeleteRequest { ProcessingProfileId = processingProfileId, WorkspaceId = WorkspaceId }; ProcessingProfileDeleteResponse deleteResponse = await proxy.DeleteAsync(deleteRequest).ConfigureAwait(false); if (deleteResponse.Deleted) { success = true; } else { Logger.LogMessage(LogLevel.Error, nameof(ProcessingProfileManager_DeleteAsync), "Deletion failed", this.GetType().Name); } } catch (ServiceException exception) { //The service returns exceptions of type ServiceException. Logger.LogMessage(LogLevel.Error, nameof(ProcessingProfileManager_DeleteAsync), exception.Message, this.GetType().Name); } } return success; }
Processing Data Source Manager
The Processing Data Source Manager service supports read and save operations on data source objects. The ProcessingDataSource class represents a data source that contains the location of the files for discovery during processing. For more information, see Processing sets on the Relativity Documentation site.
Create a ProcessingDataSource
To create a ProcessingDataSource instance, invoke the constructor and initialize the following properties:
- ArtifactID – set this property to 0, indicating that you are creating a new instance.
- Custodian – set this property to the Artifact ID associated with this data source.
- TimeZone – set this property to the Artifact ID that you obtained from the workspace database. See Required Artifact IDs.
- DestinationFolder – set this property to the Artifact ID that you obtained from the workspace database. See Required Artifact IDs.
- StartNumber – set this property to the value used to begin numbering a sequence of documents published from a specific data source.
Note: You can set this property to null. When it is null, Relativity uses auto-numbering. For more information about numbering type options, see Processing sets on the Relativity Documentation site.
- IsStartNumberVisible – determines whether Relativity UI displays the Start Number field in the Data Source layout.
- Other properties – set them to their required values. The following code sample uses the default values.
Call the SaveAsync() method on the proxy created with the IProcessingDataSourceManager interface. You must then pass this method the initialized ProcessingDataSource instance and the workspace Artifact ID as illustrated in the following code.
public async Task<bool> ProcessingDataSourceManager_Create_SaveAsync(IHelper helper, int custodianArtifactId, int destinationFolderArtifactId, int timeZoneArtifactId) { bool success = false; //Get a connection to the API using the Relativity API Helper classes, available on event handlers, //agents, and custom Pages. They are mocked in these samples. //This sample code executes under the context of the current user. using (IProcessingDataSourceManager proxy = helper.GetServicesManager().CreateProxy<IProcessingDataSourceManager>(ExecutionIdentity.User)) { try { //Build the processing ProcessingDataSource object. ProcessingDataSource processingDataSource = new ProcessingDataSource { ArtifactID = 0, // Indicates a new ProcessingDataSource object. ProcessingSet = new ProcessingSetRef { ArtifactID = ProcessingSetId }, Custodian = custodianArtifactId, DestinationFolder = destinationFolderArtifactId, DocumentNumberingPrefix = "REL", InputPath = "@Some/Path", Name = "Data Source 1", OcrLanguages = new[] { OcrLanguage.English }, Order = 200, TimeZone = timeZoneArtifactId, StartNumber = 8, IsStartNumberVisible = true, }; //Create the ProcessingDataSource object. The service returns the Artifact ID for the object. int artifactId = await proxy.SaveAsync(processingDataSource, WorkspaceId); if (artifactId != 0) { success = true; } else { Logger.LogMessage(LogLevel.Error, nameof(ProcessingDataSourceManager_Create_SaveAsync), "Create failed", this.GetType().Name); } } catch (ServiceException exception) { //The service returns exceptions of type ServiceException. Logger.LogMessage(LogLevel.Error, nameof(ProcessingDataSourceManager_Create_SaveAsync), exception.Message, this.GetType().Name); } } return success; }
Read a ProcessingDataSource
Read the values for the properties on a ProcessingDataSource object by calling the ReadAsync() method on the proxy created with the IProcessingDataSourceManager interface. The ReadAsync() method requires that you pass the Artifact IDs of the ProcessingDataSource object and the workspace as arguments.
public async Task<bool> ProcessingDataSourceManager_ReadAsync(IHelper helper, int processingDataSourceArtifactId) { bool success = false; //Get a connection to the API using the Relativity API Helper classes, available on event handlers, //agents, and custom Pages. They are mocked in these samples. //This sample code executes under the context of the current user. using (IProcessingDataSourceManager proxy = helper.GetServicesManager().CreateProxy<IProcessingDataSourceManager>(ExecutionIdentity.User)) { try { //Read the ProcessingSet object. ProcessingDataSource processingDataSource = await proxy.ReadAsync(processingDataSourceArtifactId, WorkspaceId); //Display the input path. Logger.LogMessage(LogLevel.Debug, nameof(ProcessingDataSourceManager_ReadAsync), processingDataSource.InputPath, this.GetType().Name); success = true; } catch (ServiceException exception) { //The service returns exceptions of type ServiceException. Logger.LogMessage(LogLevel.Error, nameof(ProcessingDataSourceManager_ReadAsync), exception.Message, this.GetType().Name); } } return success; }
Update a ProcessingDataSource
When updating a ProcessingDataSource instance, you call the AsyncRead() method on the proxy created with the IProcessingDataSourceManager interface. Next, set the properties on the instance to their new values, and then call the SaveAsync() method. You must call the SaveAsync() method in order for your changes to be added to the database.
public async Task<bool> ProcessingDataSourceManager_Update_SaveAsync(IHelper helper, int processingDataSourceArtifactId) { bool success = false; //Get a connection to the API using the Relativity API Helper classes, available on event handlers, //agents, and custom Pages. They are mocked in these samples. //This sample code executes under the context of the current user. using (IProcessingDataSourceManager proxy = helper.GetServicesManager().CreateProxy<IProcessingDataSourceManager>(ExecutionIdentity.User)) { try { //Read the ProcessingDataSource object. ProcessingDataSource processingDataSource = await proxy.ReadAsync(processingDataSourceArtifactId, WorkspaceId); //Modify the input path and destination folder. processingDataSource.InputPath = "@Some/Other/Path"; processingDataSource.DestinationFolder = 99; // Artifact Id of the destination folder //Update the processing data source object. The service returns the Artifact ID of the object. int artifactId = await proxy.SaveAsync(processingDataSource, WorkspaceId); if (artifactId != 0) { success = true; } else { Logger.LogMessage(LogLevel.Error, nameof(ProcessingDataSourceManager_Update_SaveAsync), "Update failed", this.GetType().Name); } } catch (ServiceException exception) { //The service returns exceptions of type ServiceException. Logger.LogMessage(LogLevel.Error, nameof(ProcessingDataSourceManager_Update_SaveAsync), exception.Message, this.GetType().Name); } } return success; }
Processing Set Manager
The Processing Set Manager service supports read and save operations on processing set objects. The ProcessingSet class represents a processing set object that links a processing profile to one or more data sources. For more information, see Processing sets on the Relativity Documentation site.
Create a ProcessingSet
To create a ProcessingSet instance, invoke the constructor and then initialize the following properties:
- ArtifactID – set this property to 0, indicating that you are creating a new instance.
- EmailNotificationRecipients – set this optional property to an array of email addresses.
- Name – set this property to the name of the processing set.
- Profile – set this property to the Artifact ID of the processing profile that you obtained from your workspace database table. See Required Artifact IDs.
Call the SaveAsync() method on the proxy created with the IProcessingSetManager interface. You must then pass the initialized ProcessingSet object and workspace Artifact ID to this method.
public async Task<bool> ProcessingSetManager_Create_SaveAsync(IHelper helper, int processingProfileArtifactId) { bool success = false; //Get a connection to the API using the Relativity API Helper classes, available on event handlers, //agents, and custom Pages. They are mocked in these samples. //This sample code executes under the context of the current user. using (IProcessingSetManager proxy = helper.GetServicesManager().CreateProxy<IProcessingSetManager>(ExecutionIdentity.User)) { try { //Build the ProcessingSet object. ProcessingSet processingSet = new ProcessingSet { ArtifactID = 0, // Indicates a new ProcessingSet object. EmailNotificationRecipients = new[] { "johnSmith@domain.com", "adamJohnson@domain.com" }, Name = "Test Set", Profile = new ProcessingProfileRef(processingProfileArtifactId) // The Artifact ID of the processing profile. }; //Create the ProcessingSet object. The service returns the Artifact ID of the object. int artifactId = await proxy.SaveAsync(processingSet, WorkspaceId); if (artifactId != 0) { success = true; } else { Logger.LogMessage(LogLevel.Error, nameof(ProcessingSetManager_Create_SaveAsync), "Create failed", this.GetType().Name); } } catch (ServiceException exception) { //The service returns exceptions of type ServiceException. Logger.LogMessage(LogLevel.Error, nameof(ProcessingSetManager_Create_SaveAsync), exception.Message, this.GetType().Name); } } return success; }
Read a ProcessingSet
Read the values for the properties on a ProcessingSet object by calling the ReadAsync() method on the IProcessingSetManager. The ReadAsync() method requires that you pass the Artifact IDs of the ProcessingSet object and the workspace as arguments.
public async Task<bool> ProcessingSetManager_ReadAsync(IHelper helper, int processingSetArtifactId) { bool success = false; //Get a connection to the API using the Relativity API Helper classes, available on event handlers, //agents, and custom Pages. They are mocked in these samples. //This sample code executes under the context of the current user. using (IProcessingSetManager proxy = helper.GetServicesManager().CreateProxy<IProcessingSetManager>(ExecutionIdentity.User)) { try { //Read the ProcessingSet object. ProcessingSet processingSet = await proxy.ReadAsync(processingSetArtifactId, WorkspaceId); //Display the Artifact ID of the processing profile. string profileId = $"{processingSet.Profile.ArtifactID}"; Logger.LogMessage(LogLevel.Debug, nameof(ProcessingSetManager_ReadAsync), profileId, this.GetType().Name); success = true; } catch (ServiceException exception) { //The service returns exceptions of type ServiceException. Logger.LogMessage(LogLevel.Error, nameof(ProcessingSetManager_ReadAsync), exception.Message, this.GetType().Name); } } return success; }
Update a ProcessingSet
When updating a ProcessingSet instance, you call the AsyncRead() method on the proxy created with the IProcessingSetManager interface. Next, set the properties on the instance to their new values, and then call the SaveAsync() method. You must call the SaveAsync() method in order for your changes to be added to the database.
public async Task<bool> ProcessingSetManager_Update_SaveAsync(IHelper helper, int processingSetArtifactId) { bool success = false; //Get a connection to the API using the Relativity API Helper classes, available on event handlers, //agents, and custom Pages. They are mocked in these samples. //This sample code executes under the context of the current user. using (IProcessingSetManager proxy = helper.GetServicesManager().CreateProxy<IProcessingSetManager>(ExecutionIdentity.User)) { try { //Read the ProcessingSet object. ProcessingSet processingSet = await proxy.ReadAsync(processingSetArtifactId, WorkspaceId); //Modify the list of email recipients list and the name of the processing set. processingSet.EmailNotificationRecipients = new[] { "johnSmith@domain.com" }; processingSet.Name = "Test Set"; //Update the ProcessingSet object. The service returns the Artifact ID of the object. int artifactId = await proxy.SaveAsync(processingSet, WorkspaceId); if (artifactId != 0) { success = true; } else { Logger.LogMessage(LogLevel.Error, nameof(ProcessingSetManager_Update_SaveAsync), "Update failed", this.GetType().Name); } } catch (ServiceException exception) { //The service returns exceptions of type ServiceException. Logger.LogMessage(LogLevel.Error, nameof(ProcessingSetManager_Update_SaveAsync), exception.Message, this.GetType().Name); } } return success; }
Retrieve a list of processing sets and related aggregate information
You can use the GetDocumentAggregates() method to retrieve document totals and other information about processing sets in a specific workspace. To retrieve this information, the process sets must have the statuses of Completed or Completed with errors. If you wanted to create a custom dashboard for reporting purposes, use this method to populate it with information about completed processing sets. For example, Relativity uses the GetDocumentAggregates() method to populate the Early Case Assessment dashboard with processing set data.
Use the following classes in conjunction with the GetDocumentAggregates() method. For additional reference information, see Processing API.

When calling the GetDocumentAggregates() method, pass a GetDocumentAggregatesRequest object as an argument. The GetDocumentAggregatesRequest class is a request object. It contains criteria for retrieving processing sets available in a specific workspace. It has the following properties:
- WorkspaceArtifactId – the Artifact ID of the workspace containing processing sets for retrieval.
- PageSize – the number of processing sets returned per page in the results set. The Relativity UI uses this property to support paging and to display results. It determines the number of processing sets returned for each page.
- Page – indicates the number used to identify a specific page of processing sets that you want returned in the results set. This optional property is set to the first page (0) by default.
- SortColumnName – the name of column used for sorting results. You can set the sort column property to one of the following options:
- "PublishedDocumentCount"
- "PublishedDocumentSizeInBytes"
- "ProcessingSetDateCreated"
- "ProcessingSetName" - the name used by default.
Note: The following code sample uses "ProcessingSetName" as the setting for SortColumnName property.
- SortDescending – indicates the sort order for the results. This optional property is set to ascending by default. Set this property to true for descending order, and to false or null for ascending order. When this property is null, it uses the ascending sort order based on sort column name.

The GetDocumentAggregates() method returns a ProcessingSetDocumentInfoSummary object, which contains information about processing sets retrieved from a specific workspace. This class has the following properties:
- ProcessingSetDocumentInfo – represents an object that contains information about specific processing sets within a workspace. For additional reference information, see Processing API or Retrieve aggregate information for processing sets for the REST API.
- TotalProcessingSets – the total number of processing sets with the status of Completed or Complete with errors in a workspace. Use this information in conjunction with paging available through the Relativity UI.
- TotalPublishedDocuments – the total number of documents from all processing sets with the status of Completed or Complete with errors published to a workspace.
- TotalPublishedDocumentSizeInBytes – the total number of bytes for documents from all processing sets with the status of Completed or Complete with errors published to a workspace.
public async Task<ProcessingSetDocumentInfoSummary> ProcessingSetManager_GetDocumentAggregatesAsync(IHelper helper, int workspaceArtifactId) { // Get a connection to the API using the Relativity API Helper classes, available on event handlers, // agents, and custom Pages. They are mocked in these samples. // This sample code executes under the context of the current user. using (IProcessingSetManager proxy = helper.GetServicesManager().CreateProxy<IProcessingSetManager>(ExecutionIdentity.User)) { try { // Build the GetDocumentAggregatesRequest object. GetDocumentAggregatesRequest request = new GetDocumentAggregatesRequest { Page = 0, PageSize = 15, SortColumnName = "ProcessingSetName", SortDescending = true, WorkspaceArtifactId = workspaceArtifactId }; // Submit the request. The service returns information for all 'Completed' and 'Completed with Errors' // Processing Sets in the given workspace. ProcessingSetDocumentInfoSummary processingSetDocumentInfoSummary = await proxy.GetDocumentAggregates(request); return processingSetDocumentInfoSummary; } catch (ServiceException serviceException) { Logger.LogMessage(LogLevel.Error, nameof(ProcessingSetManager_GetDocumentAggregatesAsync), serviceException.Message, this.GetType().Name); throw; } } }
Processing Job Manager
The Processing Job Manager service includes methods for executing inventory, discovery, and publishing jobs. It also includes a method for canceling any of these jobs for a processing set. This service is available through the IProcessingJobManager interface. For more information, see Common processing workflows.
Inventory jobs
The following code illustrates how to run an inventory job by calling the SubmitInventoryJobsAsync() method on the proxy created with the IProcessingJobManager interface. You must pass an initialized InventoryJob instance to this method. This instance has the Artifact ID of the processing set that you want to use for the job, and the Artifact ID of the workspace where it resides.
If you want to use filtering on your inventory job, apply filters through Relativity after you programmatically run your inventory job. For more information, see Inventory on the Relativity Documentation site.
public async Task<bool> ProcessingJobManager_InventoryAsync(IHelper helper, int processingSetArtifactId) { bool success = false; //Get a connection to the API using the Relativity API Helper classes, available on event handlers, //agents, and custom Pages. They are mocked in these samples. //This sample code executes under the context of the current user. using (IProcessingJobManager proxy = helper.GetServicesManager().CreateProxy<IProcessingJobManager>(ExecutionIdentity.User)) { try { //Create an inventory job object. InventoryJob inventoryJob = new InventoryJob { ProcessingSetId = processingSetArtifactId, WorkspaceArtifactId = WorkspaceId }; //Submit the job for inventory. await proxy.SubmitInventoryJobsAsync(inventoryJob); success = true; } catch (ServiceException exception) { //The service returns exceptions of type ServiceException. Logger.LogMessage(LogLevel.Error, nameof(ProcessingJobManager_InventoryAsync), exception.Message, this.GetType().Name); } } return success; }
Discovery jobs
The following code illustrates how to run a discovery job by calling the SubmitDiscoveryJobsAsync() method on the proxy created with the IProcessingJobManager interface. You must pass an initialized DiscoveryJob instance to this method. The DiscoveryJob instance represents a processing job that you want to run. This instance has the Artifact ID of the processing set that you want to use for the job, and the Artifact ID of the workspace where it resides. For more information, see Processing on the Relativity Documentation site
public async Task<bool> ProcessingJobManager_DiscoveryAsync(IHelper helper, int processingSetArtifactId) { bool success = false; //Get a connection to the API using the Relativity API Helper classes, available on event handlers, //agents, and custom Pages. They are mocked in these samples. //This sample code executes under the context of the current user. For more information, see the documentation for Relativity API Helpers. using (IProcessingJobManager proxy = helper.GetServicesManager().CreateProxy<IProcessingJobManager>(ExecutionIdentity.User)) { try { //Create a discovery job object. DiscoveryJob discoveryJob = new DiscoveryJob { ProcessingSetId = processingSetArtifactId, WorkspaceArtifactId = WorkspaceId }; //Submit the job for discovery. await proxy.SubmitDiscoveryJobsAsync(discoveryJob); success = true; } catch (ServiceException exception) { //The service returns exceptions of type ServiceException. Logger.LogMessage(LogLevel.Error, nameof(ProcessingJobManager_DiscoveryAsync), exception.Message, this.GetType().Name); } } return success; }
Publishing jobs
The following code illustrates how to execute a publishing job by calling the SubmitPublishJobsAsync() method on the proxy created with the IProcessingJobManager interface. You must pass an initialized PublishJob instance to this method. This instance has the Artifact ID of the processing set that you want to use for the job, and the Artifact ID of the workspace where it resides.
Similar to the Relativity UI, you can resubmit a publishing job with processing errors by calling the SubmitPublishJobsAsync() method again. For more information, see
public async Task<bool> ProcessingJobManager_PublishAsync(IHelper helper, int processingSetArtifactId) { bool success = false; //Get a connection to the API using the Relativity API Helper classes, available on event handlers, //agents, and custom Pages. They are mocked in these samples. //This sample code executes under the context of the current user. using (IProcessingJobManager proxy = helper.GetServicesManager().CreateProxy<IProcessingJobManager>(ExecutionIdentity.User)) { try { //Create a publish job object. PublishJob publishJob = new PublishJob { ProcessingSetId = processingSetArtifactId, WorkspaceArtifactId = WorkspaceId }; //Submit the job for discovery. await proxy.SubmitPublishJobsAsync(publishJob); success = true; } catch (ServiceException exception) { //The service returns exceptions of type ServiceException. Logger.LogMessage(LogLevel.Error, nameof(ProcessingJobManager_PublishAsync), exception.Message, this.GetType().Name); } } return success; }
Cancel jobs
You can use the SubmitCancelJobAsync() method to cancel inventory, discovery, and publishing jobs for a specific processing set. The following code illustrates how to execute a cancel job by calling this method on the proxy created with the IProcessingJobManager interface. You must pass an initialized CancelJob instance to this method. This instance has the Artifact ID of the processing set associated with the job that you want to cancel, and the Artifact ID of the workspace where it resides.
This sample code returns a Boolean value called success after the cancel job has been successfully submitted. However, this return value doesn't indicate that the job has been canceled. Multiple factors influence when a worker picks up a cancel job and how long the job takes to execute. For example, the amount of data and system state can affect this outcome.
Note: The submission of cancel job returns successfully when the job associated with a processing set has already been canceled.
public async Task<bool> ProcessingJobManager_CancelAsync(IHelper helper, int processingSetArtifactId) { bool success = false; //Get a connection to the API using the Relativity API Helper classes, available on event handlers, //agents, and custom Pages. They are mocked in these samples. //This sample code executes under the context of the current user. using (IProcessingJobManager proxy = helper.GetServicesManager().CreateProxy<IProcessingJobManager>(ExecutionIdentity.User)) { try { //Create a cancel job object. CancelJob cancelJob = new CancelJob { ProcessingSetId = processingSetArtifactId, WorkspaceArtifactId = WorkspaceId }; //Submit a job to cancel a processing set. await proxy.SubmitCancelJobAsync(cancelJob); success = true; } catch (Exception exception) { //The service returns exceptions of type ServiceException. Logger.LogMessage(LogLevel.Error, nameof(ProcessingJobManager_CancelAsync), exception.Message, this.GetType().Name); } } return success; }