There are two main entry points to make api calls to the 3Di API V3.0.

The first one is the ThreediApiClient class that will handle the login process for you and then directly can be used on any API endpoint.

The ThreediApiClient needs three settings to make requests to the 3Di API:

  • the host name
  • the username to login with and
  • the user's password

These settings should be stored in environment variables, or in a ".env" file that can be passes to the ThreediApiClient on initialisation.

A sample .env file could look like this



The second entry point is an object that handles the authentication is therefore is called ApiAccess. Actually the ThreediApiClient uses this object itself for the authentication process. Using it directly can be useful if you want to retrieve your auth token for example.

from threedi_api_client import ApiAccess
envf = "<path>/.env"
a = ApiAccess(envf)

If you have an instance of the ThreediApiClient already you can also use the api_access() shortcut


Usage examples

Let's jump right in with an example. To get an instance of the client:

from threedi_api_client import ThreediApiClient
env_file = "<path>/.env"
api_client = ThreediApiClient(env_file)

Now you can easily make use of the api models generated by the openapi client. Let us create a simulation. We will use a Simulation model instance to pass data to the API. Some fields are optional but we do need to specify

  • the unique organisation ID we want to run the simulation for
  • the model schema to use for the simulation by referring to the id of the threedimodel resource
  • datetime (in ISO 8601 (UTC) format) for the simulation start
  • either a end datetime (also in ISO 8601 (UTC) format) or the duration parameter in seconds

If you do not know the unique ID for your organisation you can make use th the OrganisationsApi object grants access to the /organisations/ endpoint

from openapi_client.api import OrganisationsApi

# first get the uuid for the organisation because I just keep forgetting it
from openapi_client.api import OrganisationsApi
organisations_api = OrganisationsApi(api_client)

# I am lazy so I look for an organisation that starts with "nelen", case insensitive 
{'count': 2,
'next': None,
'previous': None,
'results': [{'name': 'Nelen & Schuurmans',
      'unique_id': 'b8f91de705774fe8a4e7cb2d9413bf5c',
      'url': ''},
     {'name': 'Nelen & Schuurmans alleen werknemers',
      'unique_id': 'e82c74c4fb5846b3ae990c0cc69130c6',
      'url': ''}]}        

Now we can create the Simulation model instance.


# start date will be a datetime object
from datetime import datetime

my_extreme_event_simulation = Simulation(
        name="my extreme event",   # (optional)
        threedimodel=1,            # The model schema to use for the simulation by referring to the id of the threedimodel resource
        start_datetime=datetime.utcnow(),  # accepts datetime instance
        duration=7200              # in secs ==> 2 hours 

The SimulationsApi object gives use access to the /simulations/ endpoint.

from openapi_client import SimulationsApi
simulations_api = SimulationsApi(api_client)

{'created': 'now',
'duration': 7200,
'duration_humanized': '2 hours, 0 minutes, 0 seconds',
'end_datetime': '2019-11-04T16:19:46Z',
'id': 631,
'name': 'my extreme event',
'organisation': 'b8f91de705774fe8a4e7cb2d9413bf5c',
'organisation_name': 'Nelen & Schuurmans',
'slug': 'my-extreme-event-378f55a5-06df-4021-8fb6-65bbb70519dc',
'start_datetime': '2019-11-04T14:19:46Z',
'threedimodel': '',
'threedimodel_id': '1',
'url': '',
'user': 'lars.claussen',
'uuid': '378f55a5-06df-4021-8fb6-65bbb70519dc'}

Simulations allow for adding an arbitrary number of events to them like

  • rain events
  • sources and sinks
  • initial conditions
  • laterals
  • saved states
  • structure controls

All of them have their own openapi client model. To add a constant rain event to the simulation you would do the following.

from openapi_client.models import ConstantRain
const_rain = ConstantRain(
    simulation=631,   # the ID we got from our create call above
    offset=60,        # let the rain start after one minute
    duration=5000,    # let the rain last for 5000 secs
    value=0.0006,     # not too extreme after all...;-)
    units="m/s"       # the only unit supported for now
simulations_api.simulations_events_rain_constant_create(631, const_rain)
{'duration': 5000,
'offset': 60,
'simulation': '',
'units': 'm/s',
'url': '',
'value': 0.0006}

If you want to see which events are defined on a given simulation

{'boundaries': None,
'breach': [],
'filerasterrain': [],
'filerastersourcessinks': [],
'filetimeseriesrain': [],
'filetimeseriessourcessinks': [],
'initial_groundwaterlevel': None,
'initial_onedwaterlevel': None,
'initial_onedwaterlevelpredefined': None,
'initial_savedstate': None,
'initial_twodwaterlevel': None,
'laterals': [],
'lizardrasterrain': [],
'lizardrastersourcessinks': [],
'lizardtimeseriesrain': [],
'lizardtimeseriessourcessinks': [],
'savedstates': [],
'timedstructurecontrol': [],
'timeseriesrain': [{'constant': True,
                'duration': 5000,
                'interpolate': False,
                'offset': 60,
                'simulation': '',
                'units': 'm/s',
                'url': '',
                'values': [[0.0, 0.0006], [5000.0, 0.0]]}],
'timeseriessourcessinks': []}

To list all file resources get yourself an instance of the FilesApi class

    files = FilesApi(api_client)
    {'count': 3064,
    'next': '',
    'previous': None,
    'results': [{'bucket': '3di',
            'etag': None,
            'expiry_date': '2019-08-16',
            'filename': '',
            'id': 2,

Advanced usage

Upload example (rain raster upload). You need to install the python requests library to run this example.

import requests
from openapi_client import SimulationsApi

simulation_pk = 1
filename = ''
local_file_path = './data/'

# Use the api_client as created in the code block
# above
sim_api = SimulationsApi(api_client)

# Create rain raster upload resource in API
# returns a 'file_upload' instance containing a
# put_url property which is the URL to the object
# storage object to be uploaded with an HTTP PUT requests.
file_upload = sim_api.simulations_events_rain_rasters_upload(
    filename, simulation_pk)

# Open the local file in binary mode for uploading
with open(local_file_path, 'rb') as f: 
    # Requests automatically streams the file this way
    requests.put(file_upload.put_url, data=f)