Skip to main content
Version: Version 22

REST API

The Principal Toolbox REST API allows administrators and developers to integrate external systems with the Principal Toolbox programmatically. This article covers authentication, request formatting, all available endpoints, and error handling.


Getting Started​

This section covers the foundational requirements for making API calls: the base URL structure, authentication flow, required headers, error responses, and data formatting rules.

Base URL structure​

All API endpoints follow this URL pattern:

{baseurl}/service/fortesipm/{objecttype}/{crud}/{context}
SegmentDescription
{baseurl}The root URL of your Principal Toolbox instance (e.g. https://client.principaltoolbox.com)
{objecttype}The type of object being targeted (e.g. node, entry, user)
{crud}The operation type: read, create, update, or delete
{context}The specific action or scope (e.g. instance, list, descendants)

Example:

https://client.principaltoolbox.com/service/fortesipm/node/read/descendants

Authentication​

Authentication uses a token-based flow. First obtain a token via login, then include it in all subsequent requests.

Step 1: Obtain a token​

Send a POST request to:

POST {baseurl}/service/fortesipm/login

Request body:

{
"username": "someUsername",
"password": "somePassword"
}

A successful login returns HTTP 200 with the following response body:

{
"status": { "code": 101, "text": "SUCCESSFUL" },
"message": "Successful lease",
"details": {
"loginMessage": "Logged in",
"authToken": "NmZmNDM1YTEt...",
"username": "someUsername",
"userDisplayName": "Display Name",
"userID": 1234,
"administrator": false
}
}

A failed login returns HTTP 403.

Step 2: Use the token​

Include the authToken value in every subsequent request using the following header:

PTB-Rest-Authorization: Basic {TOKEN}

Note: The Principal Toolbox requires a minimum JVM version of 1.7 for 4096-bit SSL connections.


Required headers​

HeaderValueWhen required
Content-TypeApplication/JSON;charset=UTF-8All JSON request bodies
PTB-Rest-AuthorizationBasic {TOKEN}All calls except login

For multipart requests (document upload), omit Content-Type and let the HTTP client set it automatically.


Error handling​

When a request fails, the API returns HTTP 400 with a RestStatus object in the response body:

{
"status": { "code": 102, "text": "FAILURE" },
"message": "This is an error message"
}

Status codes:

CodeTextDescription
101SUCCESSFULThe request completed successfully
102FAILUREA general error occurred
501LEASE SUCCESSFULObject was leased (locked) successfully
502LEASE FAILUREObject is already locked by another user

When a 502 Lease Failure occurs, the response includes additional details:

{
"status": { "code": 502, "text": "LEASE FAILURE" },
"message": "Object is locked",
"details": {
"lockedOn": "2024-01-15T10:30:00",
"lockedBy": "someUsername",
"leaseTime": 300
}
}

Data formats​

TypeFormatExamples
EncodingUTF-8—
DatesYYYY-MM-DD2015-08-04
Numbers[-]#[.##]450, 2031.40, -12.3
JSONRFC7159 compliant—
CSV (import/export)Header row required; no spaces in column names; string and memo values in quotes—

When passing XML inside a JSON parameter, strip all tabs, newlines, and comments from the XML before encoding it as a JSON string value.


Instances​

Instance endpoints read and write individual nodes or collections of nodes within the Principal Toolbox object tree.

Read instance​

Available: 6.0+

Returns the data for a single node by its ID.

GET {baseurl}/service/fortesipm/node/read/instance/{id}
ParameterTypeDescription
idURLThe node ID to retrieve

The response includes the node's nodeTypeName, nodeTypeID, id, and all field values.

Example:

GET {baseurl}/service/fortesipm/node/read/instance/48826857

Read list​

Available: 6.0+

Returns all nodes of a given type, system-wide. This endpoint is not scope-limited to a specific location, making it suitable for retrieving financial categories, skills, and other global node types.

POST {baseurl}/service/fortesipm/node/read/list/{nodeTypeName}
ParameterTypeDescription
nodeTypeNameURLThe node type to list (e.g. P2Project, PlanItem)

POST body parameters (all optional):

ParameterDescription
viewXmlA view definition XML for filtering and layout. If omitted, all fields are returned with no filter.
fieldNamesComma-separated list of field names to return (e.g. "Name,Description,FolderID")
sortFieldsComma-separated field names to sort by
sortDirectionsSort direction per sort field: ASC or DESC

Example with viewXml filter (XML must be on a single line with no tabs or newlines):

{
"viewXml": "<listing id='0'><filter><Name operator='equals' filterValues='Test issue' /></filter><layout><header /><row><cell name='Name' /><cell name='Description' /><cell name='FolderID' /></row></layout></listing>"
}

Example with fieldNames only:

{
"fieldNames": "Name,Description,FolderID"
}

Read descendants​

Available: 7.0+

Returns all nodes of a given type within the scope of a parent location. Results are returned as a flat (non-hierarchical) list.

POST {baseurl}/service/fortesipm/node/read/descendants/{id}/{type}
ParameterTypeDescription
idURLThe parent node ID (defines the scope)
typeURLThe node type name to return

POST body parameters are the same as Read list: viewXml, fieldNames, sortFields, sortDirections. All optional.


Read recursive​

Available: 7.0+

Returns a hierarchical (nested) JSON structure of nodes. Similar to Read descendants, but preserves the tree structure. The root node is always included in the result.

POST {baseurl}/service/fortesipm/node/read/recursive/{id}/{type}/{relation}
ParameterTypeDescription
idURLThe root node ID
typeURLThe node type name
relationURLThe relation type: normal, planning, or breakdown

POST body parameters:

ParameterDescription
fieldNamesComma-separated list of field names to return (optional)

Example:

POST {baseurl}/service/fortesipm/node/read/recursive/1455/PlanItem/planning

Update instance​

Available: 8.5+

Updates one or more fields on an existing node.

POST {baseurl}/service/fortesipm/node/update/instance/{nodeTypeName}/{id}
ParameterTypeDescription
nodeTypeNameURLThe node type name
idURLThe node ID to update

Note: The older endpoint /node/update/instance/{id} (without nodeTypeName) is deprecated since version 8.5.0. Use the form above.

Include only the fields you want to change in the request body:

{
"Remarks": "Remarks on this instance",
"Custom2": "123456"
}

Create instance​

Available: 6.0+

Creates a new node at the specified location. Not every node type can be created at every location.

POST {baseurl}/service/fortesipm/node/create/instance/{parentId}/{type}
ParameterTypeDescription
parentIdURLThe ID of the parent node where the new instance is placed
typeURLThe node type name to create

Provide the field values for the new node in the request body:

{
"Description": "REST call does not respond when connection is lost",
"Remarks": "Remarks on this issue",
"Custom2": "123456"
}

Create instances (system-wide)​

Available: 8.5.3+

Creates a system-wide node, not attached to a specific location. Use this only for node types explicitly designed for system-wide creation, such as CurrencyRate.

POST {baseurl}/service/fortesipm/node/create/instances/{type}
ParameterTypeDescription
typeURLThe node type name (e.g. CurrencyRate)

Example:

{
"Startdate": "2018-01-01",
"Currency": 5678980,
"Rate": 123.456
}

Note: Only use this endpoint when specifically advised to do so. For most node types, use Create instance with a parent location.


Metadata​

Metadata endpoints return field definitions and available values for node types.

Read metadata​

Available: 6.0+

Returns the metadata for a node type: field names, display names, types, editability, and select values for static select fields. Responses are cached.

POST {baseurl}/service/fortesipm/node/read/metadata/{nodeTypeName}
ParameterTypeDescription
nodeTypeNameURLThe node type to retrieve metadata for

No POST body parameters are required.

Example response:

{
"id": 6001,
"name": "Issue",
"displayName": "Issue",
"pluralDisplayName": "Issues",
"fields": {
"Name": {
"displayName": "Name",
"type": "string",
"isEditable": true
},
"Custom2": {
"displayName": "Custom 02",
"type": "int",
"isCustom": true,
"displayWidth": 60,
"isEditable": true
},
"Custom7": {
"displayName": "Custom 07",
"type": "string",
"inputType": "select",
"isCustom": true,
"displayWidth": 100,
"isEditable": true,
"selectvalues": [
{ "value": "1", "displayName": "one" },
{ "value": "2", "displayName": "two" }
]
}
}
}

Read available select values​

Available: 6.0+

Returns the values for a dynamic select field. Dynamic select values are not included in the standard metadata response, so this endpoint is required to retrieve them.

POST {baseurl}/service/fortesipm/node/read/metadata/selectvalues/{id}/{fieldName}/{nodeTypeName}
ParameterTypeDescription
idURLThe ID of the top-level node (e.g. a project) that provides context for the select values
fieldNameURLThe name of the select field
nodeTypeNameURLThe node type the field belongs to

Entries​

Entry endpoints return time and cost entries associated with a location.

Read entry list​

Available: 6.0+

Returns individual entries (hours, costs) for a given location.

POST {baseurl}/service/fortesipm/entry/read/list/{id}
ParameterTypeDescription
idURLThe location node ID

POST body parameters:

ParameterRequiredDescription
viewXmlYesView definition XML with filter and layout

The viewXml supports filter operators, sorting via sortfield and sortdirection attributes on the <filter> element, and a completelist flag.

Example:

{
"viewXml": "<listing id='0'><filter sortfield='Resource,Type,PeriodStartdate' sortdirection='ASC,ASC,ASC' completelist='true'><ValueType operator='in' filterValues='Available,Allocation' /><PeriodStartdate operator='bigger' filterValues='today' /></filter><layout><header /><row><cell name='Resource' /><cell name='Type' /><cell name='PeriodStartdate' /><cell name='Hours' /></row></layout></listing>"
}

Read entry timeline​

Available: 6.0+

Groups entries into time periods. Extend the viewXml with a <timeline> section to define the period structure.

POST {baseurl}/service/fortesipm/entry/read/timeline/{id}
ParameterTypeDescription
idURLThe location node ID

Add a <timeline> section to the viewXml:

<timeline>
<startdate>today</startdate>
<intervals>5</intervals>
<scale>weeks</scale>
</timeline>
scale valueDescription
daysOne column per day
weeksOne column per week
monthsOne column per month

To return pivoted output, add doPivoting='true' to the <layout> element. Pivot columns are returned dynamically as PVT{date} fields in the response.


Documents​

Document endpoints manage file attachments and links associated with nodes.

Add document​

Available: 8.0.3+

Attaches a document, link, or file to a node. The request must use multipart content type. Standard JSON content type is not used for this endpoint.

POST {baseurl}/service/fortesipm/node/create/instance/{id}/Document
ParameterTypeDescription
idURLThe ID of the node to attach the document to

The multipart request body contains two parts:

PartTypeContent
ParameterstextJSON object with FileType, Name, and type-specific fields
FilefileUU-encoded file content (only for actual file uploads)

FileType options:

FileTypePurposeAdditional required fields
internaldocumentLink to an existing document in the toolboxInternalLinkID
externaldocumentlinkLink to an external REST serviceExternalDocumentLink
hyperlinkGeneric URL linkUrl
MIME type (e.g. application/msword)Upload a fileActualFileName

Supported MIME types for file upload:

MIME typeExtension
application/msword.doc
application/vnd.openxmlformats-officedocument.wordprocessingml.document.docx
application/vnd.ms-excel.xls
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.xlsx
application/vnd.ms-powerpoint.ppt
application/vnd.openxmlformats-officedocument.presentationml.presentation.pptx
application/octet-streamOther file types

Example: Add a hyperlink:

{
"FileType": "hyperlink",
"Name": "Example Link",
"Url": "http://www.example.com/link?par1=test"
}

Update document​

Available: 8.0.3+

Updates an existing document attachment. Uses the same multipart structure as Add document.

POST {baseurl}/service/fortesipm/node/update/instance/{id}
ParameterTypeDescription
idURLThe ID of the document node (not the parent location)

Messages​

Send notification message​

Available: 7.0+

Sends a message at the specified location. The authenticated user is automatically added as a mention.

POST {baseurl}/service/fortesipm/message/send/{id}
ParameterTypeDescription
idURLThe location node ID where the message is posted

POST body parameters:

ParameterRequiredDescription
messageYesThe message text. HTML is supported, including <a href> links.
mentionsNoArray of user or resource IDs. The message appears on their homepage.
hashtagsNoArray of folder or node IDs. The message appears at those locations.

Example:

{
"message": "<p>Test message that may contain HTML</p>",
"mentions": ["8129701", "221345"],
"hashtags": ["563655"]
}

Import and export​

Import and export endpoints execute tasks that have been pre-configured in the Principal Toolbox. Administrator rights are required for both endpoints. See Imports & Exports for guidance on configuring tasks.

Execute import task​

Available: 8.0.1+

Executes a configured import task with the provided data. Only CSV format is supported via this endpoint.

POST {baseurl}/service/fortesipm/integration/import/execute/{id}
ParameterTypeDescription
idURLThe ID of the import task to execute

The request body is raw CSV data, not JSON:

"column1";"column2"
"value1a";"value1b"
"value2a";"value2b"

A successful response includes a details.log field with the import result, and errors and warnings boolean flags.


Execute export task​

Available: 8.0.1+

Executes a configured export task and returns the export data directly (typically CSV).

GET {baseurl}/service/fortesipm/integration/export/execute/{id}
ParameterTypeDescription
idURLThe ID of the export task to execute

No POST body parameters are required.


User administration​

User administration endpoints require administrator rights. Passwords cannot be set or changed via the REST API.

Create user​

Available: 8.0.1+

Creates a new user account.

POST {baseurl}/service/fortesipm/user/create/instance

POST body parameters:

ParameterRequiredDescription
UserNameYesLogin username
LastnameYesLast name
EmailYesEmail address
IsGroupNoSet to true to create a user group
InitialsNoUser initials
FirstnameNoFirst name
ResourceFolderIDNoCreates the user from an existing resource
SendEmailNoSet to true to send an invitation email
EmailRemarksNoCustom text to include in the invitation email

Note: The Passwd field is not accepted. To allow a user to log in, use SendEmail: true to trigger an invitation email.


Update user​

Available: 8.0.1+

Updates an existing user account. Include only the fields to change.

Update by user ID:

POST {baseurl}/service/fortesipm/user/update/instance/{id}

Update by field value:

POST {baseurl}/service/fortesipm/user/update/instance/{fieldname}/{fieldvalue}
ParameterTypeDescription
idURLThe user node ID
fieldnameURLThe field to match on (e.g. Custom1)
fieldvalueURLThe value to match

Example: update by custom field:

POST {baseurl}/service/fortesipm/user/update/instance/Custom1/jsmith98

Request body:

{
"Initials": "J.",
"Firstname": "Jeremiah"
}

Note: Ensure the field value used for matching is unique across all users.


Delete user (inactivate)​

Available: 8.0.1+

Inactivates a user account. The user's data is preserved.

Delete by user ID:

GET {baseurl}/service/fortesipm/user/delete/instance/{id}

Delete by field value:

GET {baseurl}/service/fortesipm/user/delete/instance/{fieldname}/{fieldvalue}
ParameterTypeDescription
idURLThe user node ID
fieldnameURLThe field to match on
fieldvalueURLThe value to match

Event triggers​

Event triggers invoke external systems automatically when certain actions occur in the Principal Toolbox. Configuration requires a system setting to be added by a system administrator.

Project creation webhook​

Available: 8.0.1+

Triggers an HTTP POST to a configured URL when a project is created successfully.

Add the following system setting to enable this webhook:

<Setting>
<SettingName>CreateProjectWebhookUrl</SettingName>
<SettingValue>http://mywebhook:8080/something/somethingelse</SettingValue>
</Setting>

When a project is created, the Principal Toolbox sends the following body to the configured URL:

{
"id": 123456
}

Where id is the ID of the newly created project. Use Read instance to retrieve full project details.

The webhook response is ignored but logged on failure. Logs are accessible to system administrators.

Note: HTTPS is only supported for certificates trusted by the JVM/Tomcat. For HTTP basic authentication, include credentials in the URL: http://username:password@host.


External document generation​

Available: 8.0.3+

Triggers an HTTP POST when a user generates an external document from the automated reports section.

Add the following system setting to enable this trigger:

<Setting>
<SettingName>EnableExternalDocumentLinks</SettingName>
<SettingValue>true</SettingValue>
</Setting>

The Principal Toolbox sends the following body to the external service:

{
"id": 123456,
"personID": 123344
}

Where id is the location of the report and personID is the ID of the user who triggered the action.


Node types reference​

The table below lists all available node types with their internal IDs, general display names, and version availability.

NameIDDisplay nameAvailable fromRemoved in
Benefit720Benefit7.0+
BudgetType8215Financial category
CurrencyRate77Currency rates
DependencyRelation5700Dependency
DiscussionLog29Discussion item
Entry100Generic entry6.0+9.5
ExportTask21Export task
History10History log
Idea4901Idea7.0+
ImportTask23Import task
KnowledgeRepository4Documents & knowledge folder
Message8003Message7.0+
NonProjectActivity5502Non project activity
NonProjectActivitySet5500Non project activity set
NonProjectCategory5501Non project category
Order6061Order7.5+
OrganizationalUnit500Organisational unit8.0+
P2Action6041Action
P2Change6031Change
P2Issue6001Issue
P2Lessonlearned6051Lessons learned
P2Product5302Classic project product9.0
P2Program5100Classic MSP programme folder9.0
P2ProgramProject5110Classic MSP programme project9.0
P2ProgramTemplate5111Classic MSP programme model9.0
P2Project5000Project
P2ProjectTemplate5002Project model
P2Quality6021Quality review
P2Risk6011Risk
P2Stage5301Classic project stage9.0
Person3User account
PlanItem5602Plan item
Portfolio701Portfolio
PortfolioDashboard711Custom dashboard
PortfolioModel703Portfolio model
ProgramProject4910Programme8.0+
ProgramProjectModel4911Programme model8.0+
ProjectReport5003Portfolio item
ProjectResource8017Project resource
SavedProjectReport5006Saved portfolio item
Scenario730Saved portfolio scenario
Skill16Skill
TimeRegistrationConfiguration5520Time entry configuration
Timesheet81Time sheet
TimesheetRow84Time sheet row
URLFolder400Link (url)
UserGroup30User group7.5+
Workpackage5303Classic project work package9.0

Node relations​

Relations define how nodes are connected in the object tree. The relation type is used in endpoints such as Read recursive.

Normal relation: used for structural containment:

P2Project → P2Issue, P2Risk, P2Quality, P2Change, P2Action, P2Lessonlearned, Order, KnowledgeRepository → Document, Entry

Planning relation: used for Gantt/plan hierarchy:

P2Project → PlanItem (hierarchical)

Breakdown relation: used for product breakdown structure:

P2Project → PlanItem (hierarchical)

Best practices​

  • Store the authToken securely and reuse it across requests. If the session expires, log in again to obtain a new token.
  • Always set the Content-Type: Application/JSON;charset=UTF-8 header on all JSON requests.
  • Strip XML of tabs, newlines, and comments before embedding it as a value in a JSON parameter.
  • Use fieldNames when you only need specific fields. This reduces response payload size and improves performance.
  • Use the /node/read/metadata/{nodeTypeName} endpoint to discover field names and types before building integrations.
  • When matching users via a custom field, ensure the field value is unique across all users.
  • Test all calls with a tool such as Postman before integrating them into your application.
  • Import and export tasks must be configured manually in the Principal Toolbox before they can be executed via the API. See Imports & Exports.
  • Passwords cannot be set via the REST API. Use SendEmail: true when creating or updating users to trigger an invitation email.
  • Use the newer node/update/instance/{nodeTypeName}/{id} endpoint (available from 8.5) rather than the deprecated form without nodeTypeName.

FAQ​

How do I log in via the REST API? Send a POST to {baseurl}/service/fortesipm/login with {"username": "...", "password": "..."}. A successful response includes an authToken. Pass this token in the PTB-Rest-Authorization: Basic {TOKEN} header on all subsequent calls.

Which HTTP method does each endpoint use? Most endpoints use POST. Read instance and all delete calls use GET. Check the method listed for each endpoint in this article.

What does a 400 response mean? The response body contains a RestStatus object with status.code and message. Code 102 indicates a general failure. Code 502 indicates a lease failure: the object is locked by another user.

How do I filter results in a list call? Use the viewXml POST parameter with a <listing> XML structure containing a <filter> element. Strip all tabs and newlines from the XML before encoding it as a JSON string.

Can I set a password via the REST API? No. The Passwd field is always ignored. Use SendEmail: true when creating or updating a user to send an invitation email.

How do I find the correct field names for a node type? Call /node/read/metadata/{nodeTypeName} to retrieve all field names, types, and display names for a given node type.

Why am I receiving a Lease Failure (502)? Another user has locked the object. The response details object includes lockedBy, lockedOn, and leaseTime to identify who holds the lock.

Which version does my endpoint require? Each endpoint in this article lists its minimum version under "Available". Most endpoints are available from version 6.0 onwards. The node/update/instance/{nodeTypeName}/{id} form requires version 8.5+.

Can I create a node anywhere in the tree? No. Not every node type can be created at every location. Refer to the Node relations section and the node type table to understand valid parent-child relationships.


Need more support?​

Contact your Fortes Change Cloud administrator or reach out to Fortes Support for assistance with API configuration and integration.