This documentation explains how to use the python-workfront package, but you should consult the Workfront API documentation for details on the API itself.

Creating a Session

To interact with Workfront, a Session is needed, and for this session to be useful, it needs to be authenticated using either an API key or a username and password.

When using a username and password, you use the login() method to log in and obtain a session identifier:

>>> from workfront import Session
>>> session = Session('yourdomain')
>>> session.login('youruser', 'yourpassword')
>>> session.session_id

When using this authentication method, the UUID of the logged in user is available on the session:

>>> session.user_id

This can be used to load up your User object, amongst other uses.

The session identifier is then passed with all subsequent requests issued by that session until the logout() method is called:

>>> session.logout()
>>> session.session_id is None
>>> session.user_id is None

When using an API key for authentication, you will first have to obtain an API key. This can be done as described in the Quickstart or by calling get_api_key() directly. Once you have an API key, you can pass it during Session instantiation, it will then be used for all requests issued by that session:

>>> session = Session('yourdomain', api_key='yourapikey')

To instantiate a Session, you only need to provide your Workfront domain name, which is the bit before the first dot in the url you use to access workfront. In this case, the latest version of the Workfront API, known as unsupported, will be used. If you wish to use a different version, this can be specified:

>>> session = Session('yourdomain', api_version='v4.0')

If you wish to use the Workfront Sandbox instead, you can create a session using a different url template:

>>> from workfront.session import SANDBOX_TEMPLATE
>>> session = Session('yourdomain', url_template=SANDBOX_TEMPLATE)

When instantiating a Session, you can also independently specify the protocol or, in extremely circumstances, provide your own url_template that contains the exact base url for the API you wish to use.

Finding objects

Once you have a Session, you will want to obtain objects from Workfront. This can be done using either search() or load().

Objects each have a type that is mapped to a concrete Python class of the same name as used in the API Explorer. These Python classes all subclass Object and can either be imported from the API version module directly, which works better if you are using an IDE, or obtained from the api attribute of the session, which works better if your code has to work with multiple version of the workfront API. For example:

>>> from workfront import Session
>>> from workfront.versions.v40 import Task
>>> session = Session('yourdomain', api_version='v4.0')
>>> api = session.api
>>> api.Task is Task

To search for objects, you pass a particular Object type and a list of search parameters as described in the search documentation:

>>> results =,
...                          name='project name',
...                          name_Mod='cicontains')

When passing field names as search parameters, any of the Workfront name, the Python name, or the Field descriptor itself may be used.

The search results will be a list of instances of the passed type matching the provided search criteria:

>>> results[0]
<Project: ID=u'def789', name=u'The Project Name'>

By default, each object will be loaded with its standard set of fields. If you need more fields, or want to load nested sub-objects, the fields parameter can be passed:

>>> project = results[0]
>>> tasks =,
...              ,
...                        status='CLS', status_Mod='ne',
...                        fields=['resolvables:*'])
>>> tasks
[<Task: ID=u'ghi101', name=u'Something to do', resolvables=[{...}]>]
>>> tasks[0].resolvables
(<Issue: ID=u'jkl112', objCode=u'OPTASK'>,)

If you know the UUID of an object, such as that for a project that you may store in a config file, you can skip the search step and load the object directly:

>>> session.load(api.Project,
<Project: ID=u'def789', name=u'The Project Name'>

You can load multiple objects in one go by passing a sequence of UUIDs. Even if this sequence only contains one element, a sequence of objects will still be returned:

>>> session.load(api.Project, [])
[<Project: ID=u'def789', name=u'The Project Name'>]

Working with objects

In the previous section we saw how to load objects from Workfront. To create new content in Workfront, you instantiate the object, passing in a Session and then save it:

>>> issue = api.Issue(session,
...                   name='something bad', description='details',

To make changes to an object, set the attributes you want to change and then use the save method again:

>>> issue.description += '\nautomatically appended text.'

When saving changes to an existing object, only fields that have actually been modified will be submitted back to Workfront.

Objects loaded from Workfront will, by default, only have a subset of their fields loaded. If you access a field that has not been loaded, a FieldNotLoaded exception will be raised:

>>> issue.previous_status
Traceback (most recent call last):
FieldNotLoaded: previousStatus

Further fields can be retrieved from Workfront using load:

>>> issue.load('previous_status')
>>> issue.previous_status

To delete an object, call its delete method:

>>> issue.delete()

Any references or collections are reflected into the Python model using the Reference and Collection descriptors. Unlike plain fields, accessing these will make the request to Workfront to load the necessary objects rather than raising a FieldNotLoaded exception.

References will return the referenced object or None, if there is no object referenced:

>>> issue.project
<Project: ID=u'def789', name=u'The Project Name', objCode=u'PROJ'>

References cannot be altered or set directly, instead set the matching _id fields:

>>> issue.project_id = 'ghj1234'


When you have set an _id field in this fashion, the referenced object will be stale. If you need it, you should re-load it:

>>> issue.load('project')
>>> issue.project
<Project: ID=u'ghj1234', name=u'Another Project', objCode=u'PROJ'>

Collections will always return an immutable sequence of objects in the collection:

>>> issue.resolvables
(<Task: ID=u'tsk345', objCode=u'TASK'>,)

This will be empty if there is no content in the Workfront collection.

Collections cannot be modified.

Workfront actions are made available as methods on objects:

>>> issue.mark_done(status='CLS')

If they return data, it will be returned from the Python method.

The python-workfront package also adds a few convenience methods to some objects. Please consult the API Reference.

Low-level requests

In the event that the existing object reflection, descriptors and methods do not cover your use case, Session provides lower level methods to perform requests in the form of get, post, put and delete.

They all take a path and an optional dictionary of parameters to pass as part of the request. Requests will include any authentication set up on the session. The methods return any data provided in the response from Workfront:

>>> session = Session('yourdomain', api_version='v4.0', api_key='my key')
>>>'/something/New', params=dict(just='in case'))
[u'result', 42]

The lowest level way of issuing a request to Workfront is to use request directly. This will still include any authentication set up on the Session, but gives you additional control over the method used:

>>> session.request(method='TEST', path='/foo', params=dict(what='now'))
u'some data'