This site is currently undergoing maintenance, so instances of "RelativityOne" may still be present. You may also experience 404 errors, search disruptions, and temporary style changes.

Last date modified: 2026-Oct-07

ARM API (REST) V1 to V3 migration guide - part 2

This guide is for developers integrating with the ARM REST API. It covers migrating the following endpoints from the unversioned Kepler API, V1, or V2 to the public V3 API:

Endpoint Status
POST /relativity-arm/v3/jobs/list Available now
GET /relativity-arm/v3/jobs/{jobId}/status Available now
GET /relativity-arm/v3/jobs/{jobId}/statistics Available now
POST /relativity-arm/v3/restore-jobs/available-archives Available now
GET /relativity-arm/v3/archive-jobs/directories Available now

This is the second part of the migration guide. For the first part covering breaking changes and other endpoints, see ARM API (REST) V1 to V3 migration guide - part 1.

List Jobs

Old approach

Clients queried the JobLocation, JobCaseInformation, Jobs, and JobExecutions tables directly via SQL. Some used the private V2 endpoint:

Copy
GET /relativity-arm-private/v2/jobs-list/view/{search}

New endpoint

Copy
POST /relativity-arm/v3/jobs/list

Request body

All V3 POST and PUT endpoints wrap their body in a top-level Request object.

Copy
{
                "Request": {
                "View": "All",
                "ContinuationToken": null,
                "PageSize": 100
                }
            }
Field Type Required Notes
View string (enum) Yes All, Transient (active/queued), Completed (finished)
ContinuationToken string No Omit on the first request. Pass the token from the previous response to get the next page.
PageSize integer No 1–1000. Defaults to 100 when omitted.

Response

Copy
{
                "Jobs": [
                {
                "JobID": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
                "JobName": "archive-3fa85f64",
                "JobPriority": "Medium",
                "JobState": "InProgress",
                "JobType": "Archive",
                "TimeElapsed": "00:00:11:38",
                "WorkspaceID": 1234567,
                "ActionsHistory": [
                {
                "Date": "2026-08-01T12:01:00",
                "Type": "Run",
                "UserName": "user@example.com"
                }
                ]
                }
                ],
                "JobView": "All",
                "ContinuationToken": "abc123..."
            }

JobState values

Value Meaning
NotStarted Job created but not yet started
InProgress Job is currently running
Paused Job is paused
Cancelling Cancellation in progress
Cancelled Job was cancelled
Errored Job ended with errors
Completed Job finished successfully

JobType values

Value Meaning
Archive Creates a new ARM archive
Restore Restores a workspace from an archive
DatabaseRestore (Deprecated) Restores a workspace from a .BAK file

Fields

Field Type Notes
JobID string Use this as {jobId} in subsequent calls.
JobName string (No note)
JobPriority string (enum) Low, Medium, High. Absent when not set.
JobState string (enum) See JobState values table.
JobType string (enum) See JobType values table.
TimeElapsed string Format: DD:HH:MM:SS. Absent when the job has not started.
WorkspaceID integer Applicable to any job type.
ActionsHistory array Ordered history of user actions on this job.

JobID is an opaque string, not necessarily a UUID/GUID. Jobs created by the legacy application can have a plain numeric-looking value (such as "42"); jobs created by the new application use a UUID. Do not parse or validate its format — treat it as an opaque identifier.

Pagination

Repeat the request with the ContinuationToken from the previous response until ContinuationToken is null or absent — that signals the last page.

What changed

Old behavior V3 behavior
Unlimited single response or SQL table scan Paginated with ContinuationToken. Default page size: 100.
ElapsedTime from SQL TimeElapsed in response as DD:HH:MM:SS string (absent when not started)
workspaceId absent or from SQL join WorkspaceID present on each job record
No action history in list ActionsHistory included

TimeElapsed is absent from the response object (not null) when the job has not yet started. Check for field presence before reading it.

What you must do

  • Replace any private V2 list call or direct SQL query with POST /relativity-arm/v3/jobs/list.
  • Wrap the request body in a top-level Request object (see Request body).
  • Implement pagination: loop until ContinuationToken is absent.
  • If you were filtering by workspace, use WorkspaceID from the response client-side.

Job Status

Old approach

Clients queried JobExecutions, JobState, JobStage, and JobHistory tables directly via SQL. Some used the public V1 endpoint:

Copy
GET /relativity-arm/v1/jobs/{jobID}/status

New endpoint

Copy
GET /relativity-arm/v3/jobs/{jobId}/status

{jobId} is the JobID value from the list or create-job response.

Response

Copy
{
                "JobId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
                "JobState": "InProgress",
                "TimeElapsed": "00:00:11:38",
                "CurrentPhase": {
                "Phase": "Executing",
                "Status": "InProgress",
                "Progress": 0.42
                }
            }

Fields

Field Type Notes
JobId string Echo of the path parameter. Opaque string — not necessarily a UUID. See note in List Jobs.
JobState string (enum) Same values as in the list endpoint
TimeElapsed string (TimeSpan) Absent when the job has not started yet
CurrentPhase object Absent when the job has not started yet

Phase and Stage model

ARM introduced Phases as a higher-level grouping above the legacy Stage concept. A Phase represents a piece of work that must happen in sequence relative to other Phases. For example, Validating always completes before Executing begins. Within a single Phase, multiple Stages may run in parallel. The CurrentPhase object reflects the active Phase and its aggregate progress across all of its concurrent Stages.

CurrentPhase fields

Field Type Notes
Phase string (enum) Validating, Executing, Reporting
Status string (enum) NotStarted, Queued, InProgress, Completed, Errored
Progress float Completion fraction 0–1 (mean of the phase's stage progress)

What changed versus legacy SQL

Legacy SQL field V3 status endpoint
CurrentStageStartTime Removed permanently — no replacement
JobElapsedTime Available as TimeElapsed
ArchiveFile / ArchivePath Not in status — fetch once from the job detail endpoint
JobName Not in status — fetch once from the job detail endpoint

What you must do

  • Replace direct SQL polling with GET /relativity-arm/v3/jobs/{jobId}/status.
  • Remove all code reading CurrentStageStartTime — permanently gone.
  • TimeElapsed and CurrentPhase are absent (not null) when the job has not started. Guard against missing fields.
  • For JobName or ArchivePath, make a one-time call to the archive or restore job detail endpoint; these fields do not change during execution.

Job Statistics

Old approach

Clients queried ArchiveComposition (archive jobs) or CompositionValidation (restore jobs) directly via SQL. Some used the private V1 endpoint with a jobExecutionId (an internal integer):

Copy
GET /v1/jobs/{jobExecutionId}/statistics

New endpoint

Copy
GET /relativity-arm/v3/jobs/{jobId}/statistics

Takes the JobID from the list or create-job response. No need to look up an execution ID.

Response

Copy
{
                "JobID": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
                "Migrators": [
                {
                "DisplayName": "Document Repository Files",
                "SourceItemsCount": 48320,
                "DestinationItemsCount": 48318,
                "MissingItemsCount": 2
                },
                {
                "DisplayName": "Non-Repository Files",
                "SourceItemsCount": 5102,
                "DestinationItemsCount": 48318,
                "MissingItemsCount": null
                }
                ]
            }

Migrators entry fields

Field Type Notes
DisplayName string Human-readable content type name. Use directly for display.
SourceItemsCount integer Items in source workspace or archive before the job ran. Absent when not tracked.
DestinationItemsCount integer Items that reached the destination, counted after the job finished. Absent when not tracked by this migrator.
MissingItemsCount integer Items present in source but not found on disk. Absent when not tracked by this migrator.

What changed versus V1 private

Old V1 behavior V3 behavior
Called with jobExecutionId (integer) — required a separate lookup step Called with JobID — no lookup step needed
Single endpoint for archive and restore Same — one endpoint covers both
All migrators returned including those that did not run Only migrators that produced statistics are included
ItemTypeName string required client-side mapping DisplayName is human-readable, provided directly

Error responses

Status When
404 Not Found Job does not exist or has been deleted
400 Bad Request Job exists but has not yet completed — statistics are not available until the job finishes

What you must do

  • Replace the V1 private call and SQL queries with GET /relativity-arm/v3/jobs/{jobId}/statistics.
  • Remove the intermediate call to resolve jobExecutionId — pass the JobID directly.
  • MissingItemsCount may be absent (not null) for migrators that do not track missing items — guard before reading.
  • 400 is returned while the job is still running. Show a "not yet available" state rather than an error.

Available Archives for Restore

Old approach

Copy
POST /Relativity.REST/api/Relativity.ARM/Configuration/AvailableArchives  (unversioned Kepler)
            GET  /relativity-arm-private/v2/restore-archive/available-archives         (private V2)

New endpoint

Copy
POST /relativity-arm/v3/restore-jobs/available-archives

Request body

All V3 POST and PUT endpoints wrap their body in a top-level Request object.

Copy
{
                "Request": {
                "ContinuationToken": null,
                "PageSize": 25
                }
            }
Parameter Type Default Notes
continuationToken string null Opaque token returned by the previous page; omit on the first request
pageSize integer 25 Items per page. If omitted, the default value of 25 is used.

Response shape

Copy
{
                "Items": [
                {
                "FormattedName": "WorkspaceName (1000001 - 26-06-25 12:22:35)",
                "FullPath": "\\\\server\\ARM\\1000001_WorkspaceName_20260625122235",
                "ArchiveInUse": false
                }
                ],
                "ContinuationToken": "opaque-token-for-next-page"
            }

What you must do

  • Replace the Kepler unversioned call or private V2 call with POST /relativity-arm/v3/restore-jobs/available-archives.
  • Wrap the request body in a top-level Request object (see Request body).
  • If migrating from the unversioned Kepler endpoint: switch from session-token auth to bearer token.
  • Paging is now cursor-based: pass the ContinuationToken from the previous response as continuationToken on the next request. An empty or absent ContinuationToken in the response means there are no more results.

Archive Storage Path Directories

Old approach

Copy
GET /relativity-arm-private/v3/archive-directories/archive

New endpoint

Copy
GET /relativity-arm/v3/archive-jobs/directories

Response shape

Copy
{
                "Roots": [
                {
                "DisplayPath": "\\\\server\\ARM",
                "DisplayName": "ARM",
                "Children": [
                {
                "DisplayPath": "\\\\server\\ARM\\subfolder",
                "DisplayName": "subfolder"
                }
                ]
                }
                ]
            }

What you must do

  • Replace the private endpoint URL with /relativity-arm/v3/archive-jobs/directories.
  • Response structure (Roots, DisplayPath, DisplayName, Children) is unchanged. Each child has DisplayPath and DisplayName only — only root and one level of depth are supported.
  • This endpoint takes no parameters and returns the full directory tree in one response — there is no pagination.

Error responses (all endpoints)

Status Meaning
400 Bad Request Invalid request (such as missing required field, out-of-range PageSize)
401 Unauthorized Missing or invalid bearer token
403 Forbidden Valid token but caller does not have access to the requested workspace
404 Not Found Resource does not exist

Part 2 migration checklist

Check that you have completed the following:

  • Replace all job-list calls (private V2 / SQL) with POST /relativity-arm/v3/jobs/list.
  • Wrap all POST request bodies (/relativity-arm/v3/jobs/list, /relativity-arm/v3/restore-jobs/available-archives) in a top-level Request object.
  • Implement pagination: loop until ContinuationToken is absent.
  • Update status polling to GET /relativity-arm/v3/jobs/{jobId}/status.
  • Remove all references to CurrentStageStartTime — no replacement.
  • Guard against absent (not null) TimeElapsed and CurrentPhase when job not yet started.
  • Guard against absent TimeElapsed in list response when job not yet started.
  • Move JobName and ArchivePath fetch to the job detail endpoint.
  • Replace V1 statistics call with GET /relativity-arm/v3/jobs/{jobId}/statistics; switched from jobExecutionId (integer) to JobID (opaque string).
  • Remove intermediate jobExecutionId lookup step for statistics.
  • Replace unversioned / private V2 AvailableArchives call with POST /relativity-arm/v3/restore-jobs/available-archives.
  • Replace private archive-directories call with GET /relativity-arm/v3/archive-jobs/directories.
  • Remove all direct SQL access to ARM tables (JobLocation, ArchiveComposition, CompositionValidation).
  • Switch all authentication to bearer token.

In addition, check that you have completed the steps in ARM API (REST) V1 to V3 migration guide - part 1.

Additional resources

  • OpenAPI Specification: See ARM REST API Reference V3 for complete API documentation.
  • V3 Interface Definitions: Located in Relativity.ARM.Services.Interfaces.V3 namespace.
  • Model Definitions: Located in Relativity.ARM.Services.Interfaces.V3.Models namespace.

Getting help

If you encounter issues during migration or require functionality that is not available in V3:

  1. Review both migration guides:
    1. ARM API (REST) V1 to V3 migration guide - part 1
    2. ARM API (REST) V1 to V3 migration guide - part 2
  2. Check ARM REST API Reference V3 for detailed endpoint and model documentation.
  3. Contact Relativity Support for assistance. Select "Developer Services" as the topic of the ticket.
Feedback