Plan Data Load API
Use Visier APIs to load data into Visier® Workforce Planning.
Note:
- Available with a subscription to Planning.
- Alpha This API is in alpha. While in alpha, APIs may change in a breaking way without notice; functionality may be removed, and no deprecation notices will be issued. If you are interested in using this API, please contact your Customer/Partner Success Manager.
- To access a sample script that loads data into a plan and scenario using the Plan Data Load API, see Planning Data Load on GitHub.
Who can use this feature?
To use the APIs, you must have a Visier account with a profile that has the API capability. If you don't have an account, contact your administrator. They will create an account for you with permissions that allow you to view data.
In addition to an API profile, your API user must have access to the plan as an editor, co-owner, or owner. For more information, see How to Share Your Plan.
If the plan is a managed plan and you're adding or removing rows, you must have access to all plan items in the plan. For more information, see Set Managed Plan Security.
Not sure if you have this feature or capability? Reach out to your administrator.
Overview
The Plan Data Load API allows a user to modify plan data in an automated manner, inserting new plan segment members, removing segment members, and inserting plan values using CSV files. For more information about plans, see Workforce Planning.
The process to update your plan data using Visier APIs is:
- Retrieve plan ID: Retrieve a list of all accessible plans, and identify the desired plan's ID. For each plan, the API response returns its ID, display name, planning model, scenarios, and currency code. For more information, see "Retrieve a list of plans" in API Reference.
- Retrieve plan schema: With the plan ID, use the plan details endpoint to retrieve the plan schema. The plan's schema informs the segment members and plan items in the CSV file. For more information, see Retrieve a plan's details.
- (Optional) Modify plan members: Update the structure of the plan with a CSV file containing the list of changes to the plan structure. Build a CSV file using the plan segment levels and plan segment level members returned in the plan's details. Send this CSV to Visier before you load data for the plan. For more information, see (Optional) Add or remove plan rows.
- Create data file: Build a CSV file that matches the returned schema of the plan. For more information, see Format your data file.
Note: Filenames can contain letters (A-Z, a-z), numbers (0-9), hyphens (-), periods (.), and underscores (_).
- Send data to Visier: Send the CSV to Visier. For more information, see Upload plan data.
Tip: To troubleshoot errors returned by the API, see Error codes.
Retrieve a plan's details
To load data into a plan, retrieve the plan's schema to understand how to structure your data file. If you don't know the plan's ID, first call GET /v1alpha/planning/model/plans to get a list of all plans. When you have the plan ID, call GET /v1alpha/planning/model/plans/{planId}?withSchema=true to retrieve the plan's schema.
The response returns details about the plan, including the dimensions and time periods for the plan. The data upload CSV file uses the scenario UUIDs, plan items IDs, time period dates, plan segment level IDs, and plan segment level members.
Example: This sample request retrieves a plan's schema.
curl -X GET --url 'https://{vanity_name}.api.visier.io/v1alpha/planning/model/plans/93668189-8734-4cd8-b340-e9bb9f4a38f0?withSchema=true' \
-H 'apikey:{api_key}' \
-H 'Cookie:VisierASIDToken={security_token}'
The response returns the plan's scenarios, currency, plan items, and segments. The following response describes a plan based on the Headcount and Cost Planning (Classic) model. It's segmented by Organization Hierarchy (Levels 2 to 4) and Location (Country and City). For this sample, the response is shortened to show only the members, plan items, and time periods used in the examples in this article.
{
"plan": {
"uuid": "93668189-8734-4cd8-b340-e9bb9f4a38f0",
"displayName": "Workforce Plan FY 2025",
"modelId": "WorkforcePlanModel",
"scenarios": [
{
"uuid": "7af12ba3-6e7a-453e-924e-0585ba22b8c6",
"displayName": "Default"
}
],
"currencyCode": "USD"
},
"schema": {
"planItems": [
{
"id": "Involuntary Turnover",
"displayName": "Annual involuntary turnover rate",
"dataType": "rate"
},
{
"id": "Voluntary Turnover",
"displayName": "Annual resignation rate",
"dataType": "rate"
},
{
"id": "Base Pay Change Rate",
"displayName": "Change in base pay",
"dataType": "rate"
}
],
"timePeriods": [
{
"date": "2024-01-01",
"displayName": "Jan 2024"
},
{
"date": "2024-02-01",
"displayName": "Feb 2024"
},
{
"date": "2024-03-01",
"displayName": "Mar 2024"
}
],
"planSegmentLevels": [
{
"id": "Organization_Hierarchy.Level_1",
"displayName": "Level 1",
"order": 1,
"segmentId": "Organization_Hierarchy",
"segmentDisplayName": "Organization Hierarchy"
},
{
"id": "Organization_Hierarchy.Level_2",
"displayName": "Level 2",
"order": 2,
"segmentId": "Organization_Hierarchy",
"segmentDisplayName": "Organization Hierarchy"
},
{
"id": "Location.Location_1",
"displayName": "Country",
"order": 3,
"segmentId": "Location",
"segmentDisplayName": "Location Hierarchy"
},
{
"id": "Location.Location_3",
"displayName": "City",
"order": 4,
"segmentId": "Location",
"segmentDisplayName": "Location Hierarchy"
}
],
"planSegmentLevelMembers": [
{
"segmentLevelId": "Organization_Hierarchy.Level_1",
"members": [
{
"id": "[Organization_Hierarchy].[-1].[-1]",
"displayName": "Root - Direct reports"
},
{
"id": "[Organization_Hierarchy].[Customer Support]",
"displayName": "Customer Support"
},
{
"id": "[Organization_Hierarchy].[Product]",
"displayName": "Product"
}
],
"segmentId": "Organization_Hierarchy"
},
{
"segmentLevelId": "Organization_Hierarchy.Level_2",
"members": [
{
"id": "[Organization_Hierarchy].[NA Customer Support]",
"displayName": "NA Customer Support",
"parentId": "[Organization_Hierarchy].[Customer Support]"
},
{
"id": "[Organization_Hierarchy].[Asia Customer Support]",
"displayName": "Asia Customer Support",
"parentId": "[Organization_Hierarchy].[Customer Support]"
},
{
"id": "[Organization_Hierarchy].[Product Management]",
"displayName": "Product Management",
"parentId": "[Organization_Hierarchy].[Product]"
},
{
"id": "[Organization_Hierarchy].[Innovation Center]",
"displayName": "Innovation Center",
"parentId": "[Organization_Hierarchy].[Product]"
}
],
"segmentId": "Organization_Hierarchy"
},
{
"segmentLevelId": "Location.Location_1",
"members": [
{
"id": "[Location].[APAC].[Australia]",
"displayName": "Australia",
"parentId": "[Location].[APAC]"
},
{
"id": "[Location].[APAC].[Japan]",
"displayName": "Japan",
"parentId": "[Location].[APAC]"
},
{
"id": "[Location].[EMEA].[Poland]",
"displayName": "Poland",
"parentId": "[Location].[EMEA]"
}
],
"segmentId": "Location"
},
{
"segmentLevelId": "Location.Location_3",
"members": [
{
"id": "[Location].[APAC].[Australia].[Victoria].[Melbourne]",
"displayName": "Melbourne",
"parentId": "[Location].[APAC].[Australia].[Victoria]"
},
{
"id": "[Location].[APAC].[Japan].[Kansai].[Osaka]",
"displayName": "Osaka",
"parentId": "[Location].[APAC].[Japan].[Kansai]"
},
{
"id": "[Location].[EMEA].[Poland].[Masovian].[Warsaw]",
"displayName": "Warsaw",
"parentId": "[Location].[EMEA].[Poland].[Masovian]"
}
],
"segmentId": "Location"
}
]
}
}
Format your data file
Use the plan details to structure your data file. The CSV should contain the entire schema for the plan segments and plan items whose data you want to modify.
The CSV must contain the following columns:
periodId
: From the GET response, use thedate
values in thetimePeriods
array as values in this column.- A column for each
id
value in theplanSegmentLevels
object, where the row value is theid
of themembers
in theplanSegmentLevelMembers
object. - A column for each
id
value in theplanItems
object that you want to modify data for, where the row value is the data value.
Example: This example loads new data into the Involuntary Turnover and Base Pay Change Rate values for NA Customer Support in January 2024 using the details returned in the previous example.
Using the sample response from Retrieve a plan's details, you can note the following plan details to inform the CSV file:
- In the
timePeriods
array, there are severaldate
values. In this file, you want to replace data for thedate
2024-01-01. - In the
planSegmentLevels
array, there are three Organization Hierarchy levels: 2, 3, and 4. To modify data for NA Customer Support, specify both Level 2 and Level 3 of the Organization Hierarchy. Level 1 of the Organization Hierarchy is not required because it is not included in your plan structure. You must include a column for Level 4 with a blank row value because the data change is occurring at a higher level of the plan hierarchy. TheplanSegmentLevels
IDs are the column names and theplanSegmentLevelMembers
member IDs are the row values. - The
planItems
array contains all of the metrics used in the plan. Use the plan item IDs as column names for the metric data you want to modify. The row values are the data values to load into the plan.
With the plan's schema, you can build the following data file to load data for Customer Support's Involuntary Turnover and Base Pay Change Rate plan items.
periodId |
Organization_Hierarchy.Level_1 |
Organization_Hierarchy.Level_2 |
Location.Location_1 | Location.Location_3 |
Involuntary Turnover |
Base Pay Change Rate |
---|---|---|---|---|---|---|
2024-01-01 |
[Organization_Hierarchy].[Customer Support] |
[Organization_Hierarchy].[NA Customer Support] |
0.70 |
0.98 |
Upload plan data
Include the CSV in the API request to load plan data into a specific plan and scenario: PATCH /v1alpha/planning/data/plans/{planId}/scenarios/{scenarioId}. In the request body, include the filename and the path to the file.
Caution: If your plan data includes new plan rows, you must add the rows to the plan before uploading data. For more information, see (Optional) Add or remove plan rows.
Use the calculation
query parameter to specify whether the values roll up to the parent value, distribute among child values, or neither.
ROLLUP
: Roll up loaded data values to parent and ancestor rows. If the data provides a parent value and its child value, this method prioritizes the loaded value for the child and overwrites the parent.DISTRIBUTE
: Distribute loaded data values to their children and descendent rows. If the data provides a parent value and its child value, this method prioritizes the parent values and overrides the loaded child value.NONE
: The loaded values are not rolled up or distributed. This is the default.
During data loading, Visier validates the CSV. The data load request fails if the CSV contains formatting errors, such as duplicate columns or missing required columns like the periodId
column or dimension and level columns. If there are row errors, such as referencing a path that may not exist in the plan like Product > Finance > Japan
, those errors can be skipped with the SKIP_ERRORS
method or fail the request with the STRICT_UPLOAD
method. In the query parameters, set the validation method
:
VALIDATE
: Runs a test load through all the validation steps without putting the data into the plan. UseVALIDATE
to find any errors before usingSTRICT_UPLOAD
to load the data.SKIP_ERRORS
: Loads all data without errors into the plan. Any rows with errors are excluded from the update to the plan.STRICT_UPLOAD
: Loads data into the plan if there are no errors in any row. If there are errors, the load fails. This is the default.
Example: In this sample, the request uploads a CSV with the calculation type ROLLUP
and the validation method SKIP_ERRORS
.
curl --location --request PATCH 'https://{vanity_name}.api.visier.io/v1alpha/planning/data/plans/93668189-8734-4cd8-b340-e9bb9f4a38f0/scenarios/gn2tuq1948hrqb3?calculation=ROLLUP&method=SKIP_ERRORS' \
-H 'apikey: {api_key}' \
-H 'Cookie: VisierASIDToken={security_token}'
--form 'file=@"./plan_data.csv"'
The response returns the following information.
{
"updatedCellsCount": 2,
"changelists": [
{
"planItem": "Involuntary Turnover",
"changes": [
{
"rowMembers": [
"[Organization_Hierarchy].[Customer Support]",
"[Organization_Hierarchy].[NA Customer Support]",
],
"period": "Jan 2024",
"oldValue": 0.40,
"newValue": 0.70
}
]
},
{
"planItem": "Base Pay Change Rate",
"changes": [
{
"rowMembers": [
"[Organization_Hierarchy].[Customer Support]",
"[Organization_Hierarchy].[NA Customer Support]",
],
"period": "Jan 2024",
"oldValue": 0.97,
"newValue": 0.98
}
]
}
]
}
(Optional) Add or remove plan rows
Use the PATCH /v1alpha/planning/data/plans/{planId}/rows endpoint to add or remove plan rows. The request requires a CSV file with the following columns:
Add/Remove
: In the column, use the valueAdd
to add the specified row to the plan orRemove
to remove the specified row from the plan.- A column for each plan segment level using the IDs from
planSegmentLevels
.- To add a row, use the corresponding segment member ID from
planSegmentLevelMembers
. If the member doesn't exist in the schema, provide a display name. The response returns its assigned segment member ID. - To remove a row, use the corresponding
segmentId
as the column name and the segment member ID fromplanSegmentLevelMembers
as the row value.
- To add a row, use the corresponding segment member ID from
Note:
- If a row is added or removed in a plan, Visier modifies all the scenarios in the plan to inherit the new structure.
- If a custom member is created and the plan is a subplan or has subplans as part of a collaboration project, the member is shared across all plans within the project.
- To add multiple levels of new segments, such as a new row and two children beneath it, include a row in the CSV for every segment. To add a new organization to
Product
and a new location under it, include one row forProduct > New Organization
and another row forProduct > New Organization > New Location
.
Example: This example adds one row for a new organization called Platform Product
under the Product
organization, adds an EMEA
location under the new organization, and deletes the EMEA
location from Innovation Center
, which is also under Product
.
Using the sample response from Retrieve a plan's details, you can use the following plan details to create the CSV file.
- The columns for the file are the IDs from the
planSementLevels
array. The row values for each column are the correspondingplanSegmentLevelMembers
. In this example, there are two columns for theOrganization Hierarchy
and two columns for theLocation Hierarchy
. - Because
Platform Product
doesn't yet exist in theProduct
organization, this example uses the display name for the new member. The locations forPlatform Product
are blank to indicate that it is a new member. If you wanted to add locations toPlatform Product
, you'd add additional rows in the CSV for eachPlatform Product
location. - When removing
EMEA
from under theInnovation Center
, if the plan has additional segments withinProduct > Innovation Center > EMEA
, these rows are removed from the plan as well. For example, a row atProduct > Innovation Center > EMEA > Poland
would be deleted.
With the plan's existing schema, you can build the following data file.
Organization_Hierarchy.Level_1 |
Organization_Hierarchy.Level_2 |
Location.Location_1 |
Location.Location_2 |
Add/Remove |
---|---|---|---|---|
[Organization_Hierarchy].[Product] |
Platform Product |
|
|
Add |
[Organization_Hierarchy].[Product] | Platform Product | [Location].[EMEA] | Add | |
[Organization_Hierarchy].[Product] |
[Organization_Hierarchy].[Innovation Center] |
[Location].[EMEA] |
|
Remove |
To send the CSV to Visier, your API request might look like the following sample.
curl --location --request PATCH 'https://{vanity_name}.api.visier.io/v1alpha/planning/data/plans/93668189-8734-4cd8-b340-e9bb9f4a38f0/rows?method=SKIP_ERRORS' \
--header 'apikey: {api_key}' \
--header 'Cookie: VisierASIDToken={security_token}'
--form 'file=@"./plan_rows.csv"'
The response returns the following information. In this example, two rows were removed because the row Product > Innovation Center > EMEA
had a child row below it.
{
"addedRowsCount": 2,
"removedRowsCount": 2,
"customMembers": [
{
"id": "[Organization_Hierarchy].[f47b58ef-0d36-4090-8f50-f27d26f54dbf]",
"displayName": "Platform Product",
"parentId": "[Organization_Hierarchy].[Product]"
}
]
}
Error codes
The following table lists the RCI error codes you might encounter while using the Plan Data Load API and how to resolve them.
RCI |
Description |
Action |
---|---|---|
RCIP980021 |
The provided path does not exist in the plan but can be added to the plan.
|
Use the Add or remove rows endpoint to add the row to the plan.
|
RCIP980022 |
||
RCIP972016 |
The provided path does not exist and more rows need to be added before this row can be added. |
Use the Add or remove rows endpoint to add the row and its ancestor rows to the plan. Usually, the missing rows are intermediary rows. For example, if your plan has |
RCIP972033 |
The plan already contains a custom member with the provided display name. |
If creating a new member, change the member's display name. If referencing an existing member, use its member ID, not the display name. |
RCIP971019 |
You do not have access to modify this row or its children. |
If the row is in an open subplan in the current plan, the row can only be edited in the subplan. To edit the row, you can end the collaboration project or change your API request to modify the subplan using its If you have insufficient access but should be able to access the row, contact your administrator. |
RCIP972030 |
There was an issue with one of the row's ancestor rows.
|
Identify the issue with the ancestor row and fix it. For example, if you doesn't have access to the ancestor row or the ancestor row is missing an intermediary row, you should resolve these issues before trying your request again.
|
RCIP972034 |
||
RCIP972037 |
||
RCIP972004 |
The loaded value is less than the minimum accepted value for the plan item. |
Increase the value being loaded. If the minimum accepted value for the plan item is incorrect, contact your administrator. |
RCIP972005 |
The loaded value is greater than the maximum accepted value for the given plan item. |
Decrease the value being loaded. If the maximum accepted value for the plan item is incorrect, contact your administrator. |
RCIP971023 |
The value provided cannot be interpreted as a number. |
Check that the value in the cell is a valid number. Plans cannot accept infinities. |