Helix Core is now P4. Product user interfaces will be updated soon. Learn more >>

P4 CLI Documentation | 2026.1

# P4 REST API 2026.1 breaking changes

The P4 Server REST API is in Technology Preview and under active development. If you used P4 REST API 2025.2, review the following changes and required actions to make sure your application is not impacted when upgrading to P4 REST API 2026.1.

Features offered in Technology Preview are experimental and not guaranteed to always work as expected. If you have feedback and functionality suggestions, email techpreview@perforce.com.

## Endpoint changes

The following `GET` endpoints have been renamed:

Previous endpoint | New endpoint
--- | ---
`./v0/file/metadata` | `./v0/file/revisions`
`./v0/changelist/{changelistNum}/files` | `./v0/changelist/{changelistNum}/revisions`

These endpoints were renamed to better reflect the data they return, which is a list of file revisions.

The response structure is consistent with `/file/revisions`. However, for `GET ./v0/changelist/{changelistNum}/revisions`, the `digest` and `fileSize` fields are no longer included.

If required, `fileSize` can be retrieved using `GET ./v0/file/revisions` with the `output=fileSize` parameter.

## Boolean value changes

Boolean values in `GET ./v0/changelist/{changelistNum}` are now returned as proper JSON booleans. Previously, these values were returned as string representations (`"0"` or `"1"`).

For example:

Value entered: | Interpreted as:
--- | ---
`isPromoted: "1"` | `isPromoted: true`
`isUnsubmitted: "0"` | `isUnsubmitted: false`

This is a breaking change for clients that perform string comparisons.

Action: Update any logic that checks for `"0"` or `"1"` to use boolean values (`true` or `false`) instead.

## Request parameter changes

The way file specifications are passed in requests has changed. The previous `fileSpecs` parameter used a comma-separated list, which caused ambiguity because file specifications can contain commas. This made it difficult to reliably parse the input.

Using multiple `fileSpec` parameters removes this ambiguity and ensures all file specifications are handled correctly.

### Example

Previously, multiple file specifications were passed as a single comma-separated parameter:

    ?fileSpecs=//depot/file1.txt,//depot/file2.txt

With this release, each file specification is now passed as a separate parameter:

    ?fileSpec=//depot/file1.txt&fileSpec=//depot/file2.txt

## Response data changes

Response formats have been standardized to improve consistency and usability.

### Error responses

Error responses now use a consistent, JSON-compliant structure. Previously, errors returned from different layers used different formats, and some responses used numbered properties instead of arrays.

All errors are now returned as a standard JSON object with an array of messages.

Copy

    {
      "errors": [
        {
          "code": 822150148,
          "format": "Invalid option: -%option%.",
          "message": "Invalid option: -a.",
          "statusCode": 400
        }
      ],
      "parameters": { "option": "a" }
    }

### Structure simplification

Some response structures have been simplified:

Arrays now use standard JSON arrays instead of objects with numbered keys

Certain nested objects have been flattened (for example, `jobs` is now an array of strings).

### Property naming

Response property names have been standardized to use camelCase. Previously, naming conventions varied across endpoints.

#### `GET ./changelist/{changelistNum}`

For `GET ./changelist/{changelistNum}`, the properties now use camelCase and `jobs` is a flat array of strings instead of a compound object.

Previous property | New property
--- | ---
`Change` | `change`
`Date` | `date`
`Client` | `client`
`User` | `user`
`Status` | `status`
`Type` | `type`
`Description` | `description`
`ImportedBy` | `importedBy`
`Identity` | `identity`
`Jobs` | `jobs`

#### `GET ./server/info`

For `GET ./server/info`, the property names have been standardized to camelCase.

Previous property | New property
--- | ---
`ServerID` | `serverID`
`lbr.replication` | `lbrReplication`
`serverLicense-ip` | `serverLicenseIP`
`tzoffset` | `tzOffset`

#### `GET ./depot`

For `GET ./depot`, the property names have been updated for consistency with future endpoints.

Previous property | New property
--- | ---
`name` | `depot`
`desc` | `description`
`time` | `date`

Also, for `GET ./depot`, the `extra` field is no longer returned. It has been replaced with type-specific fields (`suffix` for `spec` depots and `address` for `remote` depots) to align with depot specification naming.

Depot type | Previous field | New field
--- | --- | ---
`spec` | `extra` | `suffix`
`remote` | `extra` | `address`
Other depot types | Not applicable | No change

These changes align the response with the corresponding depot specification fields.

## Array response changes

Some responses previously represented arrays using numbered property names (for example, `field0`, `field1`) instead of standard JSON arrays.

This pattern has been removed. All such responses now return proper JSON arrays of objects.

Previous behavior

In some cases, repeated data (such as multiple users with a file open) was returned as a flat set of numbered properties:

Copy

    {
      "otherAction0": "edit",
      "otherAction1": "edit",
      "otherChange0": "default",
      "otherChange1": "default",
      "otherOpen": "2",
      "otherOpen0": "bruno@bruno_ws",
      "otherOpen1": "gale@gale_ws"
    }

New behavior

The same data is now returned as a structured array of objects:

Copy

    {
      "otherOpen": [
        {
          "otherOpen": "bruno@bruno_ws",
          "otherAction": "edit",
          "otherChange": "default"
        },
        {
          "otherOpen": "gale@gale_ws",
          "otherAction": "edit",
          "otherChange": "default"
        }
      ]
    }

This means:

- Numbered properties (for example, `field0`, `field1`) are no longer returned.

- Data is now grouped logically into arrays of objects.

- This applies to all endpoints that previously returned pseudo-arrays.

Action: Update any code that reads values from numbered fields (`otherOpen0`, `otherOpen1`) or combines numbered fields into a list manually to instead read from standard JSON arrays (for example, iterate over the `otherOpen` array).

Your search for returned results