Planning 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 Success Manager (CSM).

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 permission to edit the plan. For more information, see Planning Capabilities.

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 Planning 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:

  1. 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 Analytic Model API Reference.
  2. 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.
  3. (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.
  4. 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 (_).

  5. 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.

Copy
Retrieve plan 93668189-8734-4cd8-b340-e9bb9f4a38f0
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.

Copy
{
    "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 the date values in the timePeriods array as values in this column.
  • A column for each id value in the planSegmentLevels object, where the row value is the id of the members in the planSegmentLevelMembers object.
  • A column for each id value in the planItems 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 several date values. In this file, you want to replace data for the date 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. The planSegmentLevels IDs are the column names and the planSegmentLevelMembers 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. Use VALIDATE to find any errors before using STRICT_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.

Copy
Upload plan_data.csv to Visier
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.

Copy
{
    "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 value "Add" to add the specified row to the plan or "Remove" 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 from planSegmentLevelMembers as the row value.

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 for Product > New Organization and another row for Product > 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 corresponding planSegmentLevelMembers. In this example, there are two columns for the Organization Hierarchy and two columns for the Location Hierarchy.
  • Because Platform Product doesn't yet exist in the Product organization, this example uses the display name for the new member. The locations for Platform Product are blank to indicate that it is a new member. If you wanted to add locations to Platform Product, you'd add additional rows in the CSV for each Platform Product location.
  • When removing EMEA from under the Innovation Center, if the plan has additional segments within Product > Innovation Center > EMEA, these rows are removed from the plan as well. For example, a row at Product > 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.

Copy
Upload plan_rows.csv to Visier
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.

Copy
{
    "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 Planning 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 Product > R&D and you want to add Product > R&D > US > San Francisco, your file should have a row to add US and another row to add San Francisco.

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 planId.

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.