Skip to main content

SDK API

The VIKTOR SDK API can be accessed using the api_v1 module and is built on top of the REST API. It provides access to many of the relevant requests through an even developer-friendlier Python interface and takes care of more complicated parts such as 'pagination', 'filtering by reference', and 'object serialization'. We therefore strongly recommend using the SDK API wherever possible.

The following resources are available in the SDK API:

  • Workspaces
  • Entity types
  • Entities
  • Revisions
  • Current user

It is possible to use the SDK API in 3 scenarios:

Within a workspace

If you want to use the SDK API module from within the context of a workspace, it is as simple as instantiating the API class using VIKTOR's api_v1 module:

from viktor.api_v1 import API

api = API()
...
entity = api.get_entity(1) # the current workspace is automatically selected

Current workspace and entity

The workspace_id of the current workspace, and entity_id and entity_name of the current entity are sent along within all view-methods and callback-functions. The workspace_id / entity_id can be used to construct the current workspace/entity object, from which you can, for example, navigate to relatives within a view-method:

from viktor.api_v1 import API

@DataView("Data", duration_guess=1)
def calculate_view(self, params, entity_id, entity_name, workspace_id, **kwargs):
current_entity = API().get_entity(entity_id)
parent = current_entity.parent()
parent_params = parent.last_saved_params
# do something with parent_params
return DataResult(...)

Or a callback-function in the parametrization:

from viktor.api_v1 import API
from viktor.parametrization import ViktorParametrization, OptionField


def get_options(params, entity_id, entity_name, workspace_id, **kwargs):
current_entity = API().get_entity(entity_id)
parent = current_entity.parent()
parent_params = parent.last_saved_params
# do something with parent_params
return [...]


class Parametrization(ViktorParametrization):
field = OptionField(..., options=get_options)

Performance

Within a single job (see VIKTOR's call flow for the possible triggers of a job) the results of API calls are temporarily stored (memoized). This means that multiple calls to the same entity only require a single request in the background. This is particularly handy for option functions:

from viktor.api_v1 import API

def get_options1_from_parent(params, entity_id, workspace_id, **kwargs):
parent = API().get_entity(entity_id).parent()
parent_params = parent.last_saved_params
# get options1 from parent_params
...

def get_options2_from_parent(params, entity_id, workspace_id, **kwargs):
parent = API().get_entity(entity_id).parent()
parent_params = parent.last_saved_params
# get options2 from parent_params
...

class Parametrization(ViktorParametrization):
option1 = OptionField('Option 1', options=get_options1_from_parent)
option2 = OptionField('Option 2', options=get_options2_from_parent)

Bypassing user access restrictions

caution

If not used properly, (confidential) information which SHOULD NOT be accessible to a user may leak (e.g. by including confidential data in a view, the data is visible to users with access to that view). Please consider the following when using this flag:

  • Make sure the app's admin is aware that the code circumvents certain permissions at specific places.
  • Make sure to test the implementation thoroughly, to ensure no confidential data is leaked.

Some applications have user restrictions that limit access to certain entities or entity types. For example, if a user does not have permission to read some entity data, the code will also NOT be able to reach this data through an API call when run by the same user.

In some cases it is desirable to restrict user access to a certain entity but have access within the code nonetheless. An example is the case of a global settings entity that consists of confidential pricing data, which should be inaccessible for users but accessible for the code to calculate costs. For these cases a privileged flag can be used:

  1. Configure viktor.config.toml to make use of the privileged api. This serves as an additional layer of security/awareness.

    enable_privileged_api = true
  2. Use the privileged flag on the relevant API call.

    settings_entity = api.get_root_entities(entity_type_names=['Settings'], privileged=True)[0]

Cross-workspace

If you want to use the SDK API module from one workspace to access data from a different workspace, you can instantiate the API class using VIKTOR's api_v1 module and include your Personal Access Token:

from viktor.api_v1 import API

api = API(token=os.environ["TOKEN"])
...
workspace = api.get_workspace(4)
entity = workspace.get_entity(1)

From an external script

If you want to use the SDK API from an external python script (e.g. Jupyter Notebook), make sure to first install the VIKTOR SDK using pip:

pip install viktor

In your python script, you can now instantiate the API class using VIKTOR's api_v1 module. You will need to provide some additional authentication-related information:

  • Your VIKTOR environment url (the location where your data is stored, e.g. cloud.viktor.ai or company.us1.viktor.ai)
  • Your Personal Access Token
from viktor.api_v1 import API

api = API(token=os.environ["TOKEN"], environment="cloud.us1.viktor.ai")
...
workspace = api.get_workspace(3)
entity = workspace.get_entity(1)