PM3OpenAPI
PM3OpenAPI is a REST API that provides programmatic access to your PM3 project management data. It is designed for developers and system integrators who need to read plan information or create new plans within PM3 from external systems or custom applications.
PM3OpenAPI returns data exclusively in JSON format, making it straightforward to consume from any modern programming language, integration platform, or API tool such as Postman.
Access requires an API token issued by your organisation's PM3 administrator. All requests are authenticated and rate-limited to ensure fair use and stability of the service.
Getting Started
Obtaining an API Token
Before making any requests to PM3OpenAPI, you will need a valid API token. Tokens are issued by your PM3 administrator and can be generated from the Admin General page within the PM3 front-end application. Only users with Admin access to PM3 can generate tokens — contact your administrator to request one.
Note: Your API token grants access to your PM3 data. Please treat it as confidential and do not share it with anyone who should not have access to the system. If you believe your token has been compromised, contact your PM3 administrator to have it replaced.
Base URL
All PM3OpenAPI endpoints are accessed via your organisation's existing PM3 URL, with the path prefix /api/<endpoint>. For example, if your PM3 system is hosted at https://yourcompany.mypm3.com, your API base URL is:
https://yourcompany.mypm3.com/api/
Authentication
Every request must include your API token as a Bearer token in the Authorization HTTP header. Requests without a valid token will be rejected.
Authorization: Bearer <your-api-token>
For example, using cURL:
curl -H "Authorization: Bearer abc123" https://yourcompany.mypm3.com/api/plans
The same header can be configured in Postman under the Authorization tab by selecting Bearer Token and entering your token.
Response Format
All PM3OpenAPI responses are returned in JSON format. You do not need to pass any additional parameters to request JSON — it is the only format the API returns.
Rate Limiting
PM3OpenAPI enforces rate limits per API token across four time windows:
| Window | Request Limit |
|---|---|
| Per Second | 2 |
| Per Minute | 30 |
| Per Hour | 500 |
| Per Day | 5,000 |
If you exceed any limit, the API responds with HTTP 429 Too Many Requests. The response body will indicate how long to wait before retrying, for example:
{ "message": "Rate limit exceeded. Please try again in 30 seconds." }
Your integration should handle 429 responses gracefully by reading the retry guidance from the response body and pausing before re-attempting the request.
Endpoints
The following endpoints are currently available. All are prefixed with /api/.
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/plans |
Returns all plans in the system. |
| POST | /api/plans/basic |
Creates a new plan. |
| GET | /api/location |
Returns all Location lookup values. |
| GET | /api/department |
Returns all Department lookup values. |
| GET | /api/costcentre |
Returns all Cost Centre lookup values. |
| GET | /api/organisation |
Returns all Organisation lookup values. |
| GET | /api/gatewayset |
Returns all Gateway Set lookup values. |
Plans Endpoints
GET /api/plans
Returns a JSON array containing all plans in your PM3 instance. Each object in the array represents a single plan.
GET https://yourcompany.mypm3.com/api/plans
Authorization: Bearer <your-api-token>
A successful response returns HTTP 200 with a JSON array of plan objects.
POST /api/plans/basic
Creates a new plan within PM3. The request body must be a JSON object. Required fields are marked below.
POST https://yourcompany.mypm3.com/api/plans/basic
Authorization: Bearer <your-api-token>
Content-Type: application/json
{
"portfolioID": 1,
"level": 2,
"planName": "My New Project",
"keyCode": "MN"
}
On success the API returns HTTP 201 Created with the new plan's ID and a confirmation message:
{
"planId": 123,
"message": "Plan created successfully."
}
If required fields are missing or validation fails, the API returns HTTP 400 Bad Request with details of the errors.
Request Body Parameters
| Parameter | Required | Description |
|---|---|---|
portfolioID |
Yes | The ID of the portfolio to place the new plan in. |
level |
Yes | The plan level (numeric). Determines the plan's position in the hierarchy. |
planName |
Yes | The name of the plan. Maximum 48 characters. |
keyCode |
Yes | A 2-character alphanumeric code to identify the plan. Must be exactly 2 characters. |
gatewaySetID |
No | ID of the gateway set. Use GET /api/gatewayset to find valid values. |
managerPersonID |
No | ID of the person to assign as plan manager. Defaults to the Baseline User if not provided. |
planDesc |
No | A free-text description of the plan. No length restriction. |
wbsID |
No | WBS (Work Breakdown Structure) identifier. |
parentPlanID |
No | ID of the parent plan, if this plan is a child plan. |
isGatewayWks |
No | Whether to use a gateway workstream. Accepts "Y" or "N". Defaults to "N". |
workstreamOrder |
No | Numeric ordering for the workstream. |
addGatewayWks |
No | If true, a gateway workstream will be added. Defaults to false. |
addDefaultWks |
No | If true, a default workstream will be added. Defaults to false. |
yourRef |
No | An optional external reference code. Maximum 16 characters. |
sponsor |
No | The name of the plan's sponsor. Maximum 72 characters. |
locationID |
No | ID of the location. Use GET /api/location to find valid values. |
deptID |
No | ID of the department. Use GET /api/department to find valid values. |
costCentreID |
No | ID of the cost centre. Use GET /api/costcentre to find valid values. |
orgID |
No | ID of the organisation. Use GET /api/organisation to find valid values. |
plannedStartDate |
No | Planned start date in ISO 8601 format, e.g. 2025-04-01T00:00:00. |
plannedEndDate |
No | Planned end date in ISO 8601 format, e.g. 2026-03-31T00:00:00. |
Lookup Endpoints
Several parameters in POST /api/plans/basic require a numeric ID rather than a name — for example, locationID, deptID, costCentreID, orgID, and gatewaySetID. These values appear as human-readable names within the PM3 front end, but the API requires their corresponding IDs.
The lookup endpoints exist specifically to support this. Each one returns the full list of configured values for a given field, including both the display name and the numeric ID. You can use these to find the correct ID before making a create request.
For example, if a plan should be assigned to the location named London, call GET /api/location, find London in the results, and pass its ID as locationID in your POST /api/plans/basic request.
All lookup endpoints use GET, require no parameters, and return a JSON array.
GET /api/location
Returns all Location values. Use the returned id as locationID on a new plan.
GET https://yourcompany.mypm3.com/api/location
Authorization: Bearer <your-api-token>
GET /api/department
Returns all Department values. Use the returned id as deptID on a new plan.
GET https://yourcompany.mypm3.com/api/department
Authorization: Bearer <your-api-token>
GET /api/costcentre
Returns all Cost Centre values. Use the returned id as costCentreID on a new plan.
GET https://yourcompany.mypm3.com/api/costcentre
Authorization: Bearer <your-api-token>
GET /api/organisation
Returns all Organisation values. Use the returned id as orgID on a new plan.
GET https://yourcompany.mypm3.com/api/organisation
Authorization: Bearer <your-api-token>
GET /api/gatewayset
Returns all Gateway Set values. Use the returned id as gatewaySetID on a new plan.
GET https://yourcompany.mypm3.com/api/gatewayset
Authorization: Bearer <your-api-token>
HTTP Status Codes
| Status Code | Meaning |
|---|---|
200 OK |
The request was successful. The response body contains the requested data. |
201 Created |
A new resource was successfully created. The response body contains the new resource details. |
400 Bad Request |
The request was invalid — typically missing required fields or a failed validation. The response body will contain details. |
401 Unauthorized |
The API token is missing or invalid. Ensure your Authorization header is correctly formatted. |
404 Not Found |
The requested resource does not exist. Check that the endpoint path is correct. |
429 Too Many Requests |
You have exceeded the rate limit. Wait for the period indicated in the response body before retrying. |
500 Internal Server Error |
An unexpected error occurred on the server. Contact Bestoutcome support if this persists. |
Best Practices
- Handle rate limiting gracefully. Build retry logic into your integration that reads the retry guidance from 429 responses and waits before re-sending. Avoid tight retry loops that could cause repeated limit breaches.
- Cache lookup data. Lookup endpoint data changes infrequently. Cache it locally and refresh periodically rather than fetching it on every request.
- Use lookup endpoints to resolve IDs. Fields such as
locationID,deptID,costCentreID,orgID, andgatewaySetIDrequire numeric IDs. Always call the corresponding lookup endpoint to find the correct ID for the name your user has provided, rather than hardcoding values which may differ between PM3 instances. - Validate before posting. Before calling
POST /api/plans/basic, ensure all required fields are present and that string lengths conform to the limits described in this guide. This reduces unnecessary 400 errors. - Observe the daily limit. With a limit of 5,000 requests per day, plan your integration to stay comfortably within this threshold. If you require a higher limit, contact your account manager.
Support: For technical support or to report issues with PM3OpenAPI, please contact Bestoutcome support through your usual account manager or support channel.