Anaplan API 2.0 Python Library

I recently posted a Python library for version 1.3 of our API. With the GA announcement of API 2.0, I'm sharing a new library that works with these endpoints. Like the previous library, this supports certificate authentication as well. Both the public certificate and private key must be in PEM format. Additionally, this library supports the use of Java keystore.

Edit: A recent update to the M2Crypto library caused it to become incompatible on certain systems. As a result, I have migrated to the Cryptography package to handle certificate authentication. Many thanks to @christophe_keom  for your assistance with the migration to Cryptography!

Note: While all of these scripts have been tested and found to be fully functional, due to the vast amount of potential use cases, Anaplan does not explicitly support custom scripts built by our customers. This article is for information only and does not suggest any future product direction. This library is a work in progress and will be updated with new features once they have been tested.

Getting Started

The attached Python library serves as a wrapper for interacting with the Anaplan API. This article will explain how you can use the library to automate many of the requests that are available in our Apiary, which can be found at

This article assumes you have the requests and M2Crypto modules installed as well as the Python 3.7. Please make sure you are installing these modules with Python 3, and not for an older version of Python. For more information on these modules, please see their respective websites:

  • Python 
    (If you are using a Python version older or newer than 3.7 we cannot guarantee the validity of the article) 
  • Requests 
  • Cryptography

Note: Please read the comments at the top of every script before use, as they more thoroughly detail the assumptions that each script makes.

Gathering the Necessary Information

In order to use this library, the following information is required:

  • Anaplan model ID
  • Anaplan workspace ID
  • Anaplan action ID
  • CA certificate key-pair (private key and public certificate), or username and password

There are two ways to obtain the model and workspace IDs:

  1. While the model is open, go Help>About: Help Menu.png
  2. Select the workspace and model IDs from the URL: URL.png


Every API request is required to supply valid authentication. There are two (2) ways to authenticate:

  1. Certificate Authentication
  2. Basic Authentication

For full details about CA certificates, please refer to our Anapedia article.

Basic authentication uses your Anaplan username and password.

To create a connection with this library, define the authentication type and details, and the Anaplan workspace and model IDs:

Certificate Files:

conn = AnaplanConnection(anaplan.generate_authorization("Certificate","<path to private key>", "<path to public certificate>"), "<workspace ID>", "<model ID>")


conn = AnaplanConnection(anaplan.generate_authorization("Basic","<Anaplan username>", "<Anaplan password>"), "<workspace ID>", "<model ID>") 

 Java Keystore:

from anaplan_auth import get_keystore_pair

key_pair=get_keystore_pair('/Users/jessewilson/Documents/Certificates/my_keystore.jks', '<passphrase>', '<key alias>', '<key passphrase>')
#Instantiate AnaplanConnection without workspace or model IDs
conn = AnaplanConnection(anaplan.generate_authorization("Certificate", privKey, pubCert), "", "")

Note: In the above code, you must import the get_keystore_pair method from the anaplan_auth module in order to pull the private key and public certificate details from the keystore.

Getting Anaplan Resource Information

You can use this library to get the necessary file or action IDs. This library builds a Python key-value dictionary, which you can search to obtain the desired information:


list_of_files = anaplan.get_list(conn, "files")
files_dict = anaplan_resource_dictionary.build_id_dict(list_of_files)

This code will build a dictionary, with the file name as the key. The following code will return the ID of the file:

users_file_id = anaplan_resource_dictionary.get_id(files_dict, "file name")

To build a dictionary of other resources, replace "files" with the desired resource: actions, exports, imports, processes. You can use this functionality to easily refer to objects (workspace, model, action, file) by name, rather than ID.


#Fetch the name of the process to run
process=input("Enter name of process to run: ")

start = datetime.utcnow()
with open('/Users/jessewilson/Desktop/Test results.txt', 'w+') as file:
        file.write(anaplan.execute_action(conn, str(ard.get_id(ard.build_id_dict(anaplan.get_list(conn, "processes"), "processes"), process)), 1))
end = datetime.utcnow()

The code above prompts for a process name, queries the Anaplan model for a list of processes, builds a key-value dictionary based on the resource name, then searches that dictionary for the user-provided name, and executes the action, and writes the results to a local file.


You can upload a file of any size and define a chunk size up to 50mb. The library loops through the file or memory buffer, reading chunks of the specified size and uploads to the Anaplan model.
Flat file: 

upload = anaplan.file_upload(conn, "<file ID>", <chunkSize (1-50)>, "<path to file>")

"Streamed" file:

with open('/Users/jessewilson/Documents/countries.csv', "rt") as f:
print(anaplan.stream_upload(conn, "113000000000", buf))
print(anaplan.stream_upload(conn, "113000000000", "", complete=True))

The above code reads a flat file and saves the data to a buffer (this can be replaced with any data source, it does not necessarily need to read from a file). This data is then passed to the "streaming" upload method. This method does not accept the chunk size input. Instead, it simply ensures that the data in the buffer is less than 50mb before uploading. You are responsible for ensuring that the data you've extracted is appropriately split. Once you've finished uploading the data, you must make one final call to mark the file as complete and ready for use by Anaplan actions.

Executing Actions

You can run any Anaplan action with this script and define a number of times to retry the request if there's a problem. In order to execute an Anaplan action, the ID is required. To execute, all that is required is the following:

run_job = execute_action(conn, "<action ID>", "<retryCount>")

This will run the desired action, loop until complete, then print the results to the screen. If failure dump(s) exits, this will also be returned.

Example output:

Process action 112000000082 completed. Failure: True
Process action 112000000079 completed. Failure: True

Worker Report

Failure dump(s):
Error dump for 112000000082
"E","Test User 2","All employees","","101.1a","1.0","2","Error parsing key for this row; no values"
"W","Jesse Wilson","All employees","a004100000HnINpAAN","","0.0","3","Invalid parent"
"W","Alec","All employees","a004100000HnINzAAN","","0.0","4","Invalid parent"
"E","Alec 2","All employees","","","0.0","5","Error parsing key for this row; no values"
"W","Test 2","All employees","a004100000HnIO9AAN","","0.0","6","Invalid parent"
"E","Jesse Wilson - To Delete","All employees","","","0.0","7","Error parsing key for this row; no values"
"W","#1725","All employees","69001","","0.0","8","Invalid parent"
"W","#2156","All employees","21001","","0.0","439","Invalid parent"
"E","All employees","","","","","440","Error parsing key for this row; no values"
Error dump for 112000000079
"Worker Report","Code","Value 1","_Line_","_Error_1_"
"Jesse Wilson","a004100000HnINpAAN","0","434","Item not located in Worker Report list: Jesse Wilson"
"Alec","a004100000HnINzAAN","0","435","Item not located in Worker Report list: Alec"
"Test 2","a004100000HnIO9AAN","0","436","Item not located in Worker Report list: Test 2

Downloading a File

If the above code is used to execute an export action, the fill will not be downloaded automatically. To get this file, use the following:

download = get_file(conn, "<file ID>", "<path to local file>")

This will save the file to the desired location on the local machine (or mounted network share folder) and alert you once the download is complete, or warn you if there is an error.

Get Available Workspaces and Models

API 2.0 introduced a new means of fetching the workspaces and models available to a given user. You can use this library to build a key-value dictionary (as above) for these resources.

#Instantiate AnaplanConnection without workspace or model IDs
conn = AnaplanConnection(anaplan.generate_authorization("Certificate", privKey, pubCert), "", "")
#Setting session variables
uid = anaplan.get_user_id(conn)
#Fetch models and workspaces the account may access
workspaces = ard.build_id_dict(anaplan.get_workspaces(conn, uid), "workspaces")
models = ard.build_id_dict(anaplan.get_models(conn, uid), "models")
#Select workspace and model to use
while True:
        workspace_name=input("Enter workspace name to use (Enter ? to list available workspaces): ")
        if workspace_name == '?':
            for key in workspaces:
while True:
        model_name=input("Enter model name to use (Enter ? to list available models): ")
        if model_name == '?':
            for key in models:
#Extract workspace and model IDs from dictionaries
workspace_id = ard.get_id(workspaces, workspace_name)
model_id = ard.get_id(models, model_name)
#Updating AnaplanConnection object

The above code will create an AnaplanConnection instance with only the user authentication defined. It queries the API to return the ID of the user in question, then queries for the available workspaces and models and builds a dictionary with these results. You can then enter the name of the workspace and model you wish to use (or print to screen all available), then finally update the AnaplanConnection instance to be used in all future requests.

The content in this article has not been evaluated for all Anaplan implementations and may not be recommended for your specific situation.
Please consult your internal administrators prior to applying any of the ideas or steps in this article.

Thanks for the library! For the get_file function, we are struggling when the export contains a comma. The function uses the results of the get .text to parse this out, but it is done by comma separated values. Is there a way to add a text qualifier? Thanks



Sorry, I can't reproduce this. Whether the comma occurs in a text field or number, the payload of my file is correct (both CSV and TXT). A text delimiter is added to text fields that contain commas, and the commas is dropped from numeric fields (commas as decimal point are converted to period). 

Hello, We have found an issue in the get_file function. The URL needs to be inside the while loop that grabs each chunk and the file needs to be appended with each chunk of data. New code: 

# This function downloads a file from Anaplan to a string.
def get_file(conn, fileId):
:param conn: AnaplanConnection object which contains authorization string, workspace ID, and model ID
:param fileId: ID of the Anaplan file to download

chunk = 0
details = get_file_details(conn, fileId)
chunk_count = details[0]
file_name = details[1]

authorization = conn.authorization
workspaceGuid = conn.workspaceGuid
modelGuid = conn.modelGuid

get_header = {
"Authorization": authorization,
file = ""
print("Fetching file " + fileId + "...")

while int(chunk) < int(chunk_count):
url = __base_url__ + "/" + workspaceGuid + "/models/" + modelGuid + "/files/" + fileId + "/chunks/" + str(chunk)
file_contents = requests.get(url, headers=get_header)
except HTTPError as e:
raise HTTPError(e)
if file_contents.ok:
file = file + file_contents.text
return "There was a problem fetching the file: " + file_name
chunk = str(int(chunk) + 1)

if int(chunk) == int(chunk_count):
print("File download complete!")

return file

@CommunityMember81209  I am also struggling with comma separated values.  I can usually fix it using parsing code in python, but it's not very efficient, and also very troublesome. 


What else do I need to do for file_contents.text to not include commas in the content?

Version history
Last update:
‎09-07-2021 09:21 AM
Updated by:
About the Author
  • 3 year veteran of Anaplan, working in Professional Services, formerly Customer Care. Subject matter expert in data integrations, with emphasis on API.

Labels (1)