Open Zaak Documentation¶
Open Zaak is a modern, open-source data- and services-layer to enable zaakgericht werken, a Dutch alternative to case management. Open Zaak offers structured data storage and services that implement the VNG standards for “API’s voor Zaakgericht werken” in line with the Common Ground model.
Getting Started¶
To get you started, you might find some of these links relevant:
New to Open Zaak? Have a look at the Introduction
New to the VNG standards for “API’s voor Zaakgericht werken”? Read up on the API-specifications.
Want to get started with Open Zaak yourself? See Installation.
Want to configure or manage data in Open Zaak? Read the Manual.
Need help with Open Zaak? Contact Support.
Are you a developer? Head over to Development!
Open Zaak is and only uses Open-source.
Introduction¶
Open Zaak is a modern, open-source data- and services-layer to enable zaakgericht werken, a Dutch alternative to case management. Open Zaak offers structured data storage and services that implement the VNG standards for “API’s voor Zaakgericht werken” in line with the Common Ground model.
Open Zaak exposes several API’s to store and retrieve data:
Zaken API (case instances)
Documenten API (documents)
Catalogi API (case types)
Besluiten API (decisions)
Autorisaties API (authorizations)
The Notificaties API is required for Open Zaak to work but is available as a seperate package, Open Notificaties.
Open Zaak is based on the API reference implementations by VNG Realisatie to create a production-grade product that can be used by municipalities.
Architecture¶
Open Zaak is based on the reference implementation of the “API’s voor Zaakgericht werken” made by VNG Realisatie. The overall architecture remains faithful to the Common Ground principles and all API specifications.
The architecture of Open Zaak focusses on excellent performance, optimal stability and to guarantee data integrity.
To that end, Open Zaak combines the “API’s voor Zaakgericht werken” that are essentially tightly coupled, into a single product. This allows for major performance improvements since related objects (like a BESLUIT for a ZAAK) do not need to fetched over the network but can be directly obtained from the database. This also guarantees data integrity on database level, rather than on service (API) level.
In addition, Open Zaak uses caching wherever possible to prevent needless requests over the netwerk to fetch data from external API’s. Data integrity can not be guaranteed on database level when relations are created to external API’s. In this case, data integrity is enforced on service level as much as possible.
The use of external API’s is fully supported in Open Zaak, even for API’s that are also offered by Open Zaak itself. For example, a ZAAK in Open Zaak, available via the Zaken API can have a DOCUMENT that is accessible via an external Documenten API from another vendor. The only requirement is that all API’s adhere to VNG standards for “API’s voor Zaakgericht werken”.
No permanent copies are made of original sources in Open Zaak as dictated by the Common Ground principles.
Overview¶

Who’s behind Open Zaak?¶
The Open Zaak project was initiated shortly before the 1.0 release of the VNG standards for “API’s voor Zaakgericht werken”, on August 1, 2019, by 9 municipalities:
Amsterdam
Rotterdam
Utrecht
Tilburg
Arnhem
Haarlem
‘s-Hertogenbosch
Delft
Hoorn
Using Dimpact as a legal entity, they formed a project to develop a modern, open-source data- and services-layer to enable zaakgericht werken, in line with the Common Ground model.
Open-source¶
Open Zaak is open-source and available under the EUPL license.
In addition, this project makes use of various open-source Python libraries and npm packages under the hood.
API-specifications¶
Open Zaak adheres to the API-specifications as described by the VNG standards for “API’s voor Zaakgericht werken”. The interaction between these API’s can be found there as well.
Supported API versions¶
The following API’s are available in Open Zaak:
API |
Specification version(s) |
---|---|
In addition, Open Zaak requires access to a Notificaties API. Open Zaak uses Open Notificaties by default.
Installation¶
There are several ways to install Open Zaak. A scalable solution is to use Kubernetes. You can also run the Docker containers on a single machine.
Before you begin¶
Check the minimum system requirements for the target machine(s).
Make sure the target machine(s) have access to the Internet.
The target machine(s) should be reachable via at least a local DNS entry:
Open Zaak:
open-zaak.<organization.local>
Open Notificaties:
open-notificaties.<organization.local>
The machine(s) do not need to be publically accessible and do not need a public DNS entry. In some cases, you might want this but it’s not recommended. The same machine can be used for both Open Zaak and Open Notificaties.
If you want to use NLX, make sure you have a publicaly available domain name, for example
nlx.<organization.com>
, where your NLX-inway is accessible to the outside world.
Guides¶
Hardware requirements¶
Based on our initial performance tests in both a Kubernetes environment and single machine setups, we can indicate some minimum system requirements to reach a certain performance.
A Kubernetes setup will scale more easy while being a little more expensive.
Determine what you need¶
Municipalities
For municipality users, we made a small table of to quickly look up how many users we expect to access the system concurrently based on the number of inhabitants. You can also directly look at the concurrent users in the performance table below if this is not applicable or you have a good idea of the number of concurrent users yourself.
Inhabitants |
Expected concurrent users |
10.000 |
100 |
50.000 |
250 |
100.000 |
500 |
500.000 |
1.000 |
1.000.000 |
2.000 |
Performance
Based on functional performance test scenario’s and requirements, we made a translation to technical performance requirements (requests per second). We used the following numbers to make the translation:
Average number of requests per functional scenario: 7 (higher means more requests per second)
Average waiting time between functional scenario’s: 5 minutes (lower means more requests per second)
Concurrent users |
Expected requests per second |
100 |
3 |
250 |
6 |
500 |
12 |
1.000 |
24 |
2.000 |
47 |
The above number for requests per second depends greatly on the the actual usage of the API. We used theoretical scenarios to give some indication, so it’s best to use a higher number when looking for the minimum system requirements below.
Minimum system requirements¶
Platform: 64-bit
Processor(s): 4 - 16 CPUs (see below) at 2.0 GHz
RAM: 8 - 32 GB (see below)
Hard disk space: 20 GB (excluding storage for documents)
Based on the number of requests per second you need, you can see what kind of hardware you need to achieve this.
Requests per second |
CPUs |
Memory (GB) |
25 |
4 |
8 |
50 |
6 |
12 |
100 |
12 |
24 |
150 |
14 |
28 |
200 |
16 |
32 |
With these specifications you can run everything on a single machine or divided over several instances.
Use a seperate database server with roughly a third of the CPUs and memory as the main server. The database is usually the limiting factor.
Preferably use 2 load balancer (like Traefik) replica’s.
Use as many replica’s as available CPU’s taking into account you need to have a few replica’s for your load balancer, and possibly other services.
Deploying on Kubernetes¶
Kubernetes is an open-source system for automating deployment, scaling, and management of containerized applications.
—kubernetes.io
Kubernetes (K8s) is one of the main supported targets for deployment. We provide a fully automated deployment toolset suitable for DevOps engineers and/or system administrators.
This documentation will sketch out the architecture, document the initial requirements and teach you how to deploy on K8s.
This setup is tested against a Google Cloud Kubernetes cluster with 4vCPU and
15G of memory - two n2-standard-2
nodes. See the documentation for the
available machine types. Please see Hardware requirements to
determine your hardware requirements.
Assumed/required knowledge level of Kubernetes¶
Kubernetes is a complex infrastructure with a lot of moving parts and a steep learning curve.
We assume you have some familiarity with the following concepts:
Additionally, familiarity with the kubectl command line tool is a big advantage.
You should be able to save a kube-config
file and optionally specify its
location via the KUBECONFIG
environment variable.
This guide is written and tested against a Kubernetes cluster on Google Cloud.
Google cloud resources can be managed with the gcloud command line tool, or alternatively in the cloud console via point and click.
We have collected a number of example commands to spin up an environment.
Creating a cluster
See the documentation to create a cluster and the prerequisites. We assume
a Google Cloud project name of gemeente
.
[user@host]$ gcloud container --project "gemeente" clusters create "test-cluster" \
--zone "europe-west4-b" \
--cluster-version "1.14.8-gke.12" \
--machine-type "n2-standard-2" \
--num-nodes "2"
Creating a database
From the documentation to create an SQL instance:
[user@host]$ gcloud sql instances create test \
--assign-ip \
--region europe-west4 \
--zone europe-west4-b \
--database-version POSTGRES_11 \
--root-password letmein \
--cpu 2 \
--memory 7GiB
In your Google Cloud console you can then configure the remote networks that are allowed to access this instance. You should at least include the network from where you are deploying.
Additionally, it’s recommended to set up a private IP so connections from the Kubernetes cluster are allowed.
Application architecture¶
Typically, your K8s cluster provider will set up a load balancer in front of your cluster, directing all the traffic to services in the cluster.
DNS is set up so that your domain name(s) point to the IP address of the load balancer.
The load balancer will then pass the traffic to an Ingress in the cluster, which will route the traffic to the backend services.
All applications make use of caching via Redis cache databases.
Traffic from the ingress will enter Open Zaak at one or multiple NGINX reverse proxies. NGINX will performs one of two possible tasks:
pass the request to the Open Zaak application or
send the binary data of uploaded files to the client
NGINX exists to serve uploaded files in a secure and performant way, reducing load on the Open Zaak application.
All other requests are passed to the Open Zaak application.
Traffic from the ingress is directly passed to the Open Notificaties application. Open Notificaties then communicates with async workers (using RabbitMQ) to distribute the notifications to all the relevant subscribers.
Environment requirements¶
Before you begin, you will need:
a kubernetes cluster that you can access, this means you need a valid
~/.kube/config
file. You can override which kube config to use by setting theKUBECONFIG
environment variable if you manage multiple clusters.If you are dealing with jump/bastion hosts, complicated firewalls… Please contact your provider on how you can access your cluster from your local machine.
a PostgreSQL (10 or 11) database server with credentials:
a database hostname that you can reach from your local machine
a database hostname that can be reached from your K8s cluster (possibly the same as above)
the username of a superuser (typically
postgres
)a password for the superuser
credentials for the Open Zaak database and Open Notificaties database
A persistent-volume storage class supporting
ReadWriteMany
. Contact your provider to see if they offer it. If this is not an option, you can use aReadWriteOnce
storage class and set up an NFS-server around it, but this will likely have slower performance.On Google Cloud, you can use:
[user@host]$ gcloud compute disks create --size=10GB --zone=europe-west4-b gce-nfs-disk
Deployment requirements¶
Fully automated deployment is implemented with Ansible. Ansible runs on your local machine (control host) and connects to the required services to realize the desired state.
For example, to create the application database, it will create a database
connection and execute the necessary queries. To manage kubernetes objects,
it will use the Kubernetes API via your KUBECONFIG
.
Ansible is a Python tool and has a number of dependencies. The deployment is tested on Python 3.7.
You can either clone the https://github.com/open-zaak/open-zaak repository, or download and extract the latest ZIP: https://github.com/open-zaak/open-zaak/archive/master.zip
Check your operation system packages and make sure you have installed a recent enough Python version. We recommend using Python 3.7.
Virtual environments isolate dependencies between environments. It gives us close control over the exact required versions.
Create a virtualenv:
[user@host]$ python3.7 -m venv env
This creates a virtualenv named env
. Next, activate the virtualenv. You
need to do this every time you want to use the deployment tooling.
[user@host]$ source env/bin/activate
First, navigate to the correct directory. In the folder where you placed the
copy of the repository, change into the deployment
directory:
(env) [user@host]$ cd /path/to/open-zaak/deployment/
To install the required dependencies, we use the Python package manager pip
:
(env) [user@host]$ pip install -r requirements.txt
(env) [user@host]$ ansible-galaxy collection install -r requirements.yml
Roughly said, this installs Ansible and the modules to talk to the PostgreSQL database and Kubernetes API.
Deploying (automated or manual)¶
Ansible has the concept of playbooks - a predefined set of tasks to execute, logically grouped.
Open Zaak ships with two playbooks:
provision.yml
:finishes the configuration of your Kubernetes cluster (if needed)
initializes the application databases
apps.yml
:installs Open Zaak
installs Open Notificaties
You can run the Ansible-playbooks as-is (with some configuration through variables), or use them an inspiration for manual deployment.
Below you find some guidance to modify the provisioning specifically to your needs.
Set the variable needs_ingress
in provision.yml
to no
. Otherwise,
Traefik 2.0 is set up as Ingress controller.
ReadWriteMany
storage solution¶Set the variable needs_nfs
in provision.yml
to no
. Otherwise,
a NFS-server is deployed to use as ReadWriteMany
solution.
Todo
streamline nfs/RWX solution!
The playbook will set up the application database user(s) with the correct,
minimal permissions and will set up the databases for the applications. To be
able to do this, you need superuser access. See the
vars/db_credentials.example.yml
file for the example configuration.
Both Open Zaak and Open Notificaties require database configuration to be
defined in the vars/openzaak.yml
and vars/opennotificaties.yml
variable files:
openzaak_db_name: openzaak # name of the database to create
openzaak_db_host: postgres.gemeente.nl # hostname or IP address of the database server
openzaak_db_port: "5432" # database server port, default is 5432
openzaak_db_username: openzaak # username of the application database user
openzaak_db_password: secret # password of the application database user
For Open Notificaties, the prefix is opennotificaties
instead of openzaak
.
Run the provision.yml
playbook using:
(env) [user@host]$ ./deploy.sh provision.yml
The apps.yml
playbook sets up the Open Zaak and Open Notificaties
installations.
Todo
opt-out of the Traefik CRD and provide an alternative Ingress resource
To deploy Open Zaak, some variables need to be set (in vars/openzaak.yml
):
domain
: the domain name, e.g.open-zaak.gemeente.nl
openzaak_secret_key
: generate a key via https://miniwebtool.com/django-secret-key-generator/. Make sure to put the value between single quotes!
See roles/openzaak/defaults/main.yml
for other possible variables to
override.
To deploy Open Notificaties, some variables need to be set (in vars/opennotificaties.yml
):
opennotificaties
: the domain name, e.g.open-notificaties.gemeente.nl
opennotificaties_secret_key
: generate a key via https://miniwebtool.com/django-secret-key-generator/. Make sure to put the value between single quotes!
See roles/opennotificaties/defaults/main.yml
for other possible variables to
override.
If you want to use NLX, you need to create NLX certificate. See https://docs.nlx.io/try-nlx/retrieve-a-demo-certificate.
The key and certificate need to be set in vars/nlx.yml
:
nlx_inway_key
: private keynlx_inway_cert
: certificate
Run the apps.yml
playbook using:
(env) [user@host]$ ./deploy.sh apps.yml
Next steps¶
You may want to customize the logging setup. The default setup should be sufficient to get started though.
To be able to work with Open Zaak, a couple of things have to be configured first, see Open Zaak configuration for more details.
Updating an Open Zaak installation¶
Make sure you have the deployment tooling installed - see Deployment requirements for more details.
If you have an existing environment (from the installation), make sure to update it:
# fetch the updates from Github
[user@host]$ git fetch origin
# checkout the tag of the version you wish to update to, e.g. 1.0.0
[user@host]$ git checkout X.Y.z
# activate the virtualenv
[user@host]$ source env/bin/activate
# ensure all (correct versions of the) dependencies are installed
(env) [user@host]$ pip install -r requirements.txt
Open Zaak deployment code defines variables to specify the Docker image tag to use. This is synchronized with the git tag you’re checking out.
Warning
Make sure you are aware of possible breaking changes or manual interventions by reading the Changelog!
Next, to perform the upgrade, you run the apps.yml
playbook just like with the
installation:
(env) [user@host]$ ./deploy.sh apps.yml
Note
In the Kubernetes deployment setup, Open Zaak makes use of multiple replicas by default, and is set up to perform rolling releases. This means that the old version stays live until all new versions are running without errors.
We make use of health checks and liveness probes to achieve this.
This does mean that there’s a brief window where clients may hit the old or new version at the same time - usually this shouldn’t pose a problem though.
Deploying on a single server¶
Open Zaak can be deployed on a single machine - either a dedicated server (DDS) or virtual private server (VPS). The required hardware can be rented from a hosting provider or be provided in your environment. Please see Hardware requirements to determine the hardware requirements.
This documentation describes the architecture, prerequisites and how to deploy Open Zaak on a server. Additionally, it documents the possible configuration options.
Note
The default settings allow Open Zaak to be deployed to the same machine as Open Notificaties.
Architecture¶
The application is deployed as Docker containers, of which the images are available on docker hub. Traffic is routed to the server, where the web server (nginx) handles SSL termination and proxies the requests to the application containers.
Data is stored in a PostgreSQL database. By default, the database is installed on the same machine (running on the host), but you can make use of a hosted database (Google Cloud, AWS, Azure…). See the Configuration parameters for more information.
Prerequisites¶
Before you can deploy, you need:
Ensure you have a server with root
privileges. We assume you can directly
ssh to the machine as root
user. If that’s not the case, a user with
sudo
will also work. Python 3 must be available on the server. Debian 9/10
are officially supported operating systems, though it is likely the
installation also works on Ubuntu. CentOS/RedHat might work.
You can either clone the https://github.com/open-zaak/open-zaak repository, or download and extract the latest ZIP: https://github.com/open-zaak/open-zaak/archive/master.zip
You will need to have at least Python 3.5 installed on your system. In the examples, we assume you have Python 3.6.
Create a virtualenv with:
[user@laptop]$ python3.6 -m venv env/
[user@laptop]$ source env/bin/activate
Make sure to install the deployment tooling. In your virtualenv, install the dependencies:
(env) [user@laptop]$ pip install -r deployment/requirements.txt
(env) [user@laptop]$ ansible-galaxy collection install -r requirements.yml
(env) [user@laptop]$ ansible-galaxy role install -r requirements.yml
Deployment¶
Deployment is done with an Ansible playbook, performing the following steps:
Install and configure PostgreSQL database server
Install the Docker runtime
Install the SSL certificate with Let’s Encrypt
Setup Open Zaak with Docker
Install and configure nginx as reverse proxy
Make sure the virtualenv is activated:
[user@laptop]$ source env/bin/activate
Navigate to the correct deployment directory:
(env) [user@laptop]$ cd deployment/single-server
Create the vars/open-zaak.yml
file - you can find an example in
vars/open-zaak.yml.example
. Generate a secret key using the
django secret key generator and put the value between single
quotes.
Configure the host by creating the hosts
file from the example:
(env) [user@laptop]$ cp hosts.example hosts
Edit the open-zaak.gemeente.nl
to point to your actual domain name. You must
make sure that the DNS entry for this domain points to the IP address of your
server.
Warning
It’s important to use the correct domain name, as the SSL certificate
will be generated for this domain and only this domain will be whitelisted
by Open Zaak! If you are using a private DNS name, then no SSL certificate
can be created via Letsencrypt - make sure to disable it by setting
certbot_create_if_missing=false
or openzaak_ssl=false
if you don’t
plan on using HTTPS at all.
Execute the playbook by running:
(env) [user@laptop]$ ansible-playbook open-zaak.yml
Hint
If you have your secrets Ansible vault encrypted, make sure you have either:
set the
ANSIBLE_VAULT_PASSWORD_FILE
environment variable, orpass
--ask-vault-pass
flag toansible-playbook
.
If you need to override any deployment variables (see Configuration parameters), you can pass variables to
ansible-playbook
using the syntax:--extra-vars "some_var=some_value other_var=other_value"
.If you want to run the deployment from the same machine as where it will run (ie. install to itself), you can pass
--connection local
toansible-playbook
.If you cannot connect as
root
to the target machine, you can pass--user <user> --become --become-method=sudo --ask-become-pass
which will connect as user<user>
that needssudo
-rights on the target machine to install the requirements.
A full example might look like this:
(env) [user@laptop]$ ansible-playbook open-zaak.yml \
--user admin
--inventory my-hosts \ # Use inventory file ``my-hosts`` instead of ``hosts``.
--limit open-zaak.gemeente.nl \ # Only pick open-zaak.gemeente.nl from the inventory file.
--extra-vars "openzaak_ssl=false app_db_name=openzaak-test app_db_user=openzaak-test" \
--connection local \
--become \
--become-method=sudo \
--ask-become-pass
Note
You can run the deployment multiple times, it will not affect the final outcome. If you decide to change configuration parameters, you do not have to start from scratch.
Changing environment variables
The Open Zaak configuration is templated out to /home/openzaak/.env
on the host
machine. It’s possible to modify environment variables here, but doing so will not
become effective immediately - you need to restart the containers:
[root@host]# docker restart openzaak-0 openzaak-1 openzaak-2
Make sure to do this for every replica - you can see what’s running with docker ps
.
Warning
If you modify the .env
file and then apply the Ansible playbook again,
this will overwrite your changes!
After the initial deployment, some initial configuration is required. This configuration is stored in the database and is only needed once.
Create a superuser
A superuser allows you to perform all administrative tasks.
Log in to the server:
[user@laptop]$ ssh root@open-zaak.gemeente.nl
Create the superuser (interactive on the shell). Note that the password you type in will not be visible - not even with asterisks. This is normal.
[root@open-zaak.gemeente.nl]# docker exec -it openzaak-0 src/manage.py createsuperuser Gebruikersnaam: demo E-mailadres: admin@open-zaak.gemeente.nl Password: Password (again): Superuser created successfully.
Configure Open Zaak Admin
See the Open Zaak configuration on how to configure Open Zaak post-installation.
Configuration parameters¶
At deployment time, you can configure a number of parts of the deployment by
overriding variables. You can override variables on the command line (using the
-e "..."
syntax) or by overriding them in vars/secrets.yml
.
Note
Tweaking configuration parameters is considered advanced usage.
certbot_admin_email
: e-mail address to use to accept the Let’s Encrypt terms and conditions.openzaak_ssl
: whether to use Let’s Encrypt to create an SSL certificate for your domain. Set tofalse
if you want to use an existing certificate.
The default values can be found in roles/openzaak/defaults/main.yml
.
openzaak_db_port
: database port. If you are running multiple PostgreSQL versions on the same machine, you’ll have to point to the correct port.openzaak_db_host
: specify the hostname if you’re using a cloud database or a database on a different server.openzaak_db_name
: specify a different database name.openzaak_secret_key
: A Django secret key. Used for cryptographic operations - this may NOT leak, ever. If it does leak, change it.
Scaling
The openzaak_replicas
variable controls scaling on backend services. If
your hardware allows it, you can create more replicas. By default, 3 replicas
are running.
The format of each replica is:
name: openzaak-i
port: 800i
The port number must be available on the host - i.e. you may not have other services already listening on that port.
Next steps¶
You may want to customize the logging setup. The default setup should be sufficient to get started though.
To be able to work with Open Zaak, a couple of things have to be configured first, see Open Zaak configuration for more details.
Updating an Open Zaak installation¶
Make sure you have the deployment tooling installed - see the installation steps for more details.
If you have an existing environment (from the installation), make sure to update it:
# fetch the updates from Github
[user@host]$ git fetch origin
# checkout the tag of the version you wish to update to, e.g. 1.0.0
[user@host]$ git checkout X.Y.z
# activate the virtualenv
[user@host]$ source env/bin/activate
# ensure all (correct versions of the) dependencies are installed
(env) [user@host]$ pip install -r requirements.txt
(env) [user@host]$ ansible-galaxy install -r requirements.yml
Open Zaak deployment code defines variables to specify the Docker image tag to use. This is synchronized with the git tag you’re checking out.
Warning
Make sure you are aware of possible breaking changes or manual interventions by reading the Changelog!
Next, to perform the upgrade, you run the open-zaak.yml
playbook just like with the
installation in Running the deployment:
(env) [user@laptop]$ ansible-playbook open-zaak.yml
Note
This will instruct the docker containers to restart using a new image. You may notice some brief downtime (order of seconds to minutes) while the new image is being downloaded and containers are being restarted.
Updating an Open Zaak installation¶
Software receives new features and bugfixes all the time, and Open Zaak is no different. At some point, you’ll want to update to a newer version of Open Zaak - be it a patch version with bugfixes or a feature release to upgrade to.
Before you actually upgrade, we strongly advise you to take a look at the Changelog to spot any breaking changes or required manual interventions.
Note
We always recommend you to have taken and tested your backups in case something goes wrong, BEFORE performing any updates.
Note
We encourage having multiple environments such as staging and production, completely isolated from each other. This allows you to test out the update on a staging environment to check if anything goes wrong, without affecting production.
The update instructions are split per target environment.
Updating on Kubernetes¶
See Updating an Open Zaak installation for the update instructions on Kubernetes.
Updating a single server installation¶
See the steps on how to update a single server installation.
Open Zaak configuration¶
Before you can work with Open Zaak after installation, a few settings need to be configured first.
Setting the domain¶
In the admin, under Configuration > Websites, make sure to change the existing
Site
to the domain under which Open Zaak will be deployed (see
the manual for more information).
Configure Notifications API¶
Next, the Notifications for Open Zaak must be configured. Navigate to
Configuration > Notificatiescomponentconfiguratie and fill out the correct API root
URL for the Notifications API, for example: https://notificaties.gemeente.local/api/v1/
.
You must configure the credentials for this API too:
Make sure you have a
client ID
andsecret
pair for this API.Navigate to API Autorisaties > Externe API credentials
Click Externe API credential toevoegen in the top right
Enter the same API root URL in the API-root field, e.g.
https://notificaties.gemeente.local/api/v1/
and give a human readable label, for example: Notifications API.Enter the
Client ID
andsecret
from step 1Provide a User ID - for example
open-zaak-backend
. This is only used for (audit trail) logging.Provide a human readable User represenation, such as
Open Zaak backend
. This is also used only for (audit trail) logging.
Currently, Open Zaak does not require any webhook subscriptions. It will however send notifications on various API actions.
Create an API token¶
By creating an API token, we can perform an API test call to verify the succesful installation.
Navigate to API Autorisaties > Applicaties and click on Applicatie toevoegen in the top right.
Give the application a label, such as test
or demo
, and fill out a demo
client ID
and secret
. Next, click on Opslaan en opnieuw bewerken in the
bottom right. The application will be saved and you will see the same page again. Now,
click on Beheer autorisaties in the bottom right, which brings you to the
authorization management for this application.
Select Catalogi API for the Component field
Check the
catalogi.lezen
checkboxClick Opslaan in the bottom right
On the application detail page, you can now select and copy the JSON Web Token (JWT) shown under Client credentials, which is required to make an API call.
Warning
The JWT displayed here expires after a short time (1 hour by default) and should not
be used in real applications. Applictions should use the client ID
and secret
pair to generate JWT’s on the fly.
Making an API call¶
We can now make an HTTP request to one of the APIs of Open Zaak. For this example, we have used Postman to make the request.
Make sure to set the value of the Authorization header to the JWT that was copied in the previous step.
Then perform a GET request to the list display of ZaakTypen
(Catalogi API) - this
endpoint is accessible at {{base_url}}/catalogi/api/v1/zaaktypen
(where
{{base_url}}
is set to the domain configured in
Setting the domain).

A GET request to the Catalogi API using Postman¶
Logging¶
Logging is a valuable tool to discover and debug issues happening when using Open Zaak.
Issues can be of different nature, and a different logging approach is suitable to those. For example, the following types of events are logged in some form or another:
unexpected application errors, as a result of programming mistakes (bugs) - these logs are technical in nature and should be accessible for Open Zaak developers.
application server logs - startup and access logs of the server running Open Zaak. Useful to see if client requests actually reach the ‘backend’
webserver logs - Open Zaak uses a complex set-up to serve user-uploaded files securily. Things can go wrong here too.
container logs - the docker container itself may have problems that need to be investigated.
This guide walks you through the various options on how to access and configure the logs.
Sentry¶
Sentry focuses on tracking down errors in software, i.e. the Open Zaak application. We strongly recommend setting up this integration.
Open Zaak has support to itegrate with Sentry error monitoring. Whenever a bug occurs in Open Zaak, the client will receive an error response and the technical details of the error are sent to the Sentry project, with context.
Note
Sentry integration makes sure to strip sensitive context from technical details. Passwords and/or other credentials are not sent to Sentry, if they happen to be in the request context.
For documentation on how to set up a project in Sentry, please refer to the official documentation (make sure to follow the instructions for the platform Python > Django).
After setting up the project, you will receive a DSN, which is the URL to which exceptions will be sent (e.g. https://e95a42137e6042c59d19376e566f027a@sentry.openzaak.nl/104).
The created Sentry project can be linked to Open Zaak by setting the environment
variable SENTRY_DSN
equal to this DSN.
Viewing nginx logs¶
Nginx is the webserver sitting between the client and the Open Zaak backend. It mostly proxies requests to the backend, but it takes care of serving Documenten API files after the authorization checks are performed.
Many Kubernetes providers provide a graphical interface to view logs, for example on Google Cloud:
Navigate to your Kubernetes cluster
Via Workloads, find the deployment nginx
Find and click the Container logs link
Or, via the CLI tool kubectl
:
# for convenience, set up the k8s namespace
[user@host]$ kubectl config set-context --current --namespace=openzaak-test
# fetch the logs
[user@host]$ kubectl logs -l app.kubernetes.io/name=nginx
# or for a single pod:
[user@host]$ kubectl get pods
NAME READY STATUS RESTARTS AGE
cache-79455b996-62llx 1/1 Running 0 68d
nginx-8579d9dfbd-8dn5m 1/1 Running 0 7h3m
nginx-8579d9dfbd-h4tc4 1/1 Running 0 7h3m
openzaak-59df44f556-7znvg 1/1 Running 0 7h2m
openzaak-59df44f556-gb4lq 1/1 Running 0 7h3m
openzaak-59df44f556-nqtr2 1/1 Running 0 7h3m
[user@host]$ kubectl logs --since=24h nginx-8579d9dfbd-8dn5m
On a single-server setup, nginx is not containerized and the log files can be found in
/var/log/nginx
:
/var/log/nginx/error.log
contains errors encountered by nginx/var/log/nginx/access.log
is the access log of all the client requests
Application server, application and container logs¶
The application server, the application and the container itself write logs (together they make up the ‘backend’).
When the container starts up, it performs some checks before it proceeds with the application server startup.
Then, the application server starts up and writes some status information.
Every request that is received by the application server is logged as well - this is the access log.
Finally, the application itself detects potential problematic situations or writes other informational messages to the logging output.
All of these logs are logged to the container logs.
As with the nginx logs on Kubernetes, you can make use of your provider’s graphical interface if available.
Otherwise, you can use the CLI tool:
# for convenience, set up the k8s namespace
[user@host]$ kubectl config set-context --current --namespace=openzaak-test
# fetch the logs
[user@host]$ kubectl logs -l app.kubernetes.io/name=django
# or for a single pod:
[user@host]$ kubectl get pods
NAME READY STATUS RESTARTS AGE
cache-79455b996-62llx 1/1 Running 0 68d
nginx-8579d9dfbd-8dn5m 1/1 Running 0 7h3m
nginx-8579d9dfbd-h4tc4 1/1 Running 0 7h3m
openzaak-59df44f556-7znvg 1/1 Running 0 7h2m
openzaak-59df44f556-gb4lq 1/1 Running 0 7h3m
openzaak-59df44f556-nqtr2 1/1 Running 0 7h3m
[user@host]$ kubectl logs --since=24h openzaak-59df44f556-gb4lq
Unfortunately, docker does not seem to be able to aggregate logs from different containers. This means that if you are running multiple replicas of Open Zaak (which is the default), you may have to dig around a bit before you find what you are looking for.
To view the logs of a particular replica:
# first replica
[root@server]# docker logs openzaak-0
# second replica
[root@server]# docker logs openzaak-1
Check the Docker documentation for more information about logs in Docker.
Customizing the log output¶
By default, we configure Open Zaak to log to stdout in containers by setting the
environment variable LOG_STDOUT=1
.
You may wish to log to files instead, by using persistent volumes. If you decide to do this, then:
Make sure to mount the volume on
/app/log
- this is where log files are written to.When multiple replicas are used, the volume must be
ReadWriteMany
on Kubernetes.Set the environment variable
LOG_STDOUT=0
to fall back to file-based logging.
Note
Log files are by default rotated - once a log file reaches 10MB, a new file is created and once 10 files exist, the oldest is deleted.
Post-install checklist¶
After Open Zaak has been installed successfully, go through the following checklist to see if the software works as expected:
Check configuration
Check the configuration page for Open Zaak, accessible at the url https://open-zaak.gemeente.nl/view-config/
.
This page will indicate whether certain settings are properly configured:
Run check management commands
If Sentry was set up for Open Zaak, make sure to run the following command to ensure that logging to Sentry will work as expected:
python src/manage.py raven test
Furthermore, to verify that notifications can be received by the URL as defined in the configuration, send a test notification using the following command:
python src/manage.py send_test_notification
Note
The notification is sent to the test
channel - make sure it exists in the
Notificaties API you’re using!
Run the Postman collection
Finally, run a simple Postman collection on the new install of Open Zaak:
Create an
Applicatie
with superuser permissions via the adminA simple Postman collection has been published here, click on the
Run in Postman
button in the top right.Once the collection is loaded into Postman, click the icon in the top right to manage environments:
Then click
Add
, enter the correct environment variables, then clickUpdate
:
Click on the
Runner
button in the top left of the screen, then select the imported collection and the created environment and clickRun
If Open Zaak is properly configured, the tests will pass
Manual¶
Note
The manual is currently only available in the Dutch language!
Once Open Zaak is installed, it needs to be configured to make all API’s accessible and allow inter-communication.
In addition, you can manage the data that is exposed in the Catalogi API directly in the management interface.
Algemene onderwerpen¶
De algemene onderwerpen beschrijven acties voor medewerkers met toegang tot de beheerinterface van Open Zaak (hierna de admin genoemd).
In deze handleiding nemen we aan dat Open Zaak geïnstalleerd is en beschikbaar op het adres https://open-zaak.gemeente.nl.
Inloggen¶
Om in te loggen in de admin kan je navigeren naar de startpagina https://open-zaak.gemeente.nl. Klik vervolgens op Beheer:

Vul je gebruikersnaam en wachtwoord in op het loginscherm:

Na het aanmelden zie je het dashboard. Afhankelijk van je gebruikersrechten zie je meer of minder items op het dashboard.
Wachtwoord wijzigen¶
Eenmaal ingelogd, kan je je wachtwoord wijzigen via de link rechtsboven:

Vul vervolgens je huidige wachtwoord in, je nieuwe wachtwoord en je nieuwe wachtwoord ter bevestiging.
Klik rechtsonderin op Mijn wachtwoord wijzigen om je nieuwe wachtwoord in te stellen.
Note
Merk op dat er bepaalde regels gelden om een voldoende sterk wachtwoord in te stellen. We raden aan om een password manager te gebruiken om een voldoende sterk wachtwoord in te stellen.
Dashboard¶
De gegevens die in de admin beheerd kunnen worden, zijn gegroepeerd op het dashboard. Deze groepen worden hier verder beschreven. Merk op dat het mogelijk is dat je bepaalde groepen niet ziet omdat je onvoldoende rechten hebt.
Accounts¶
Gebruikers zijn de personen die in kunnen loggen in de admin. Aan gebruikers worden rechten toegekend die bepalen wat ze precies kunnen inzien en/of beheren. Gebruikers kunnen gedeactiveerd worden, waardoor ze niet langer in kunnen loggen. Ga naar Een gebruiker aanmaken (en aan een groep toevoegen) om te leren hoe je een gebruiker toevoegt en configureert.
Groepen definiëren een set van permissies die een gebruiker toelaten om gegevens in te zien en/of beheren. Een gebruiker kan tot één of meerdere groepen behoren. Lees meer over groepen beheren.
API Autorisaties¶
De API’s voor zaakgericht werken zijn niet toegankelijk zonder autorisatie. Dit betekent dat elke applicatie die gegevens ophaalt of registreert in Open Zaak hiervoor moet geautoriseerd zijn. We spreken van taakapplicaties.
Via Applicaties wordt elke taakapplicatie geconfigureerd om de toegang in te regelen. Zie Een Applicatie registreren voor hoe je dit doet.
Daarnaast maakt Open Zaak zelf gebruik van andere API’s - bijvoorbeeld de Notificaties API, maar ook externe catalogi, Zaken API’s… zijn mogelijk. Via Externe API credentials kan je instellen hoe Open Zaak zichzelf bij deze API’s autoriseert.
Gegevens¶
De groep gegevens laat je toe om gevens in te kijken die via de Open Zaak API’s aangemaakt en/of gewijzigd worden.
Besluiten toont de besluiten die ontsloten worden via de Besluiten API.
Catalogi laat je toe om de (zaaktype)catalogi te beheren. Hoe je dit doet, is uitgebreid gedocumenteerd in Catalogusbeheer. De gegevens worden ontsloten met de Catalogi API.
Documenten laat je toe om informatieobjecten en gerelateerde objecten in te kijken en beheren. Deze worden via de Documenten API aangemaakt en gewijzigd.
Zaken bevat alle informatie die de Zaken API ontsluit. Hier kan je volledige zaakdossiers inkijken.
Configuratie¶
Het configuratiegedeelte dient om de Open Zaak-installatie te configureren. Typisch wordt dit initieel bij installatie geconfigureerd.
Via Access attempts en Access logs kan je de inlogpogingen en sessies in de admin van gebruikers bekijken. Deze worden gelogd om brute-forcing tegen te kunnen gaan en inzicht te verschaffen in wie op welk moment toegang had tot het systeem.
In de Notificatiescomponentconfiguratie kan je instellen van welke Notificaties API je gebruik maakt. Je moet een geldige configuratie instellen, anders worden er door Open Zaak geen notificaties verstuurd.
Webhook subscriptions bevat de abonnementen die Open Zaak afneemt bij de
Notificaties API. Indien je geen gebruik maakt van de Autorisaties API van
Open Zaak, maar een externe API, dan moet je een abonnement afnemen op het
autorisaties
kanaal.
Websites bevat gegevens over waar Open Zaak gehost wordt. Zorg ervoor dat
de standaard website het juiste domein ingesteld heeft (en dus niet
example.com
).
Logs¶
Er worden vaak informatieve logberichten weggeschreven die kunnen wijzen op een probleem in de Open Zaak applicatie. Deze worden via de logs inzichtelijk gemaakt.
Failed notifications toont de notificaties die Open Zaak probeerde te versturen, maar om één of andere reden niet slaagden. Je kan hier manueel notificaties opnieuw versturen of verder onderzoeken waarom de notificatie niet kon verstuurd worden.
Logging bevat generieke logberichten die meer informatie kunnen verschaffen over mogelijke foutsituaties.
Lijst- en detailweergaves¶
De structuur van de admin volgt voor het grootste deel hetzelfde patroon:
Vertrek vanaf het dashboard
Klik een onderwerp aan binnen een groep, bijvoorbeeld Zaken
Vervolgens zie je een lijst van gegevens
Na het doorklikken op één item op de lijst zie je een detailweergave
We gaan nu dieper in op wat je kan in lijst- en detailweergaves.
Lijstweergave¶
Als voorbeeld zie je de lijstweergave van Zaken:

De meeste lijstweergaves hebben een zoekveld waarmee je de lijst van gegevens kan doorzoeken. Vaak zoeken deze op identificatie, UUID of een ander karakteristiek attribuut.
Aan de rechterzijde is er meestal een set aan filters beschikbaar. Deze laten je toe om snel de resultaatset te reduceren. Filters kunnen gecombineerd worden (combinaties werken als EN-filter). Filteren op
startdatum: vandaag
envertrouwelijkheidaanduiding: openbaar
toont je alle zaken die vandaag gestart zijn EN de vertrouwelijkheidaanduiding “openbaar” hebben.Kolommen zijn sorteerbaar - klik op het kolomhoofd om oplopend te sorteren. Klik een tweede keer om aflopend te sorteren. Je kan sorteren op meerdere kolommen - er verschijnt dan een nummer die aangeeft op welke kolommen er in welke volgorde gesorteerd wordt.
In de lijstweergave zijn bulk acties beschikbaar. Selecteer de objecten waarop je de bulk actie wil toepassen door het vinkje links aan te vinken. Kies vervolgens in de dropdown te actie die je uit wil voeren.
Warning
Merk op dat het verwijderen van objecten deze objecten ook echt permanent verwijdert! Het is zelden nodig om objecten te verwijderen.
Typisch is de eerste kolom in een lijstweergave een klikbare link. Door deze aan te klikken ga je naar de Detailweergave van dat object.
Rechtsboven heb je typisch een knop om nieuwe objecten toe te voegen. Deze opent een formulier om de objectgegevens in te vullen.
Detailweergave¶
In de detailweergave zie je de gegevens/attributen van één enkel object, al dan niet aangevuld met de gerelateerde objecten.
Als voorbeeld zie je (een deel van) de detailweergave van een zaak:

De attributen van de zaak worden opgelijst als bewerkbare velden. Sommige attributen zullen niet bewerkbaar zijn, en als je geen bewerkrechten hebt zie je alles als alleen-lezen. Verplichte velden worden in het vet gedrukt, terwijl optionele velden normaal gedrukt zijn. Indien beschikbaar, dan wordt onder het veld een extra helptekst getoond die meer context geeft over de betekenis van een veld.
Gerelateerde objecten worden vaak via een vergrootglas ingesteld. Wanneer je het icoon aanklikt, dan wordt er een lijstscherm geladen waarin je het gerelateerde object kan selecteren. Na selectie staat het database-ID ingevuld in het veld.
Gerelateerde objecten worden inline getoond. Zo zul je bij een zaak een aantal inlines zien: statussen, zaakobjecten, zaakinformatieobjecten… Dit zijn allemaal relaties aan deze specifieke zaak.
Je kan de geschiedenis inkijken van een specifiek object. Dit toont de wijzigingen aangebracht via de admin interface en door wie en de audit log van wijzigingen die via de API gebeurd zijn.
Wanneer je helemaal naar beneden scrollt (en de juiste rechten hebt), dan zie je links onderin ook een knop Verwijderen. Hierop klikken brengt je naar een bevestigingsscherm. In dit scherm worden alle gerelateerde objecten getoond die mee zullen verwijderd worden.
Warning
Verwijderen van objecten is permanent! Eenmaal je de verwijdering bevestigt kan dit niet meer teruggedraaid worden.
Catalogusbeheer¶
Note
Om catalogussen te kunnen beheren moet je tot de Catalogi admin groep behoren of equivalente permissies hebben. Zie Groepen voor groepenbeheer.
Catalogus aanmaken¶
Om aan de gang te kunnen met catalogusbeheer moet er eerst een catalogus aangemaakt worden, klik bij de beginpagina van de admin op Catalogi onder het kopje Gegevens en klik vervolgens op de knop Catalogus toevoegen rechtsbovenin.

Vul op de volgende pagina minimaal alle dikgedrukte velden in en klik daarna op de OPSLAAN knop rechtsonderin de pagina.
Zaaktype aanmaken¶
Voeg na het toevoegen van de catalogus een Zaaktype toe aan deze catalogus door te klikken op Toon Zaaktypen onder het kopje ACTIES.

Klik vervolgens op de Zaaktype toevoegen knop rechtsbovenin. Op de volgende pagina is het aan te maken zaaktype al gekoppeld aan de juiste catalogus, vul de overige verplichte informatie in en sla het zaaktype op door te klikken op de knop Opslaan en opnieuw bewerken, onderaan de pagina.

Zaaktype publiceren¶
Het zojuist aangemaakt zaaktype is nog een concept, wat inhoudt dat dit zaaktype niet gebruikt kan worden buiten de Catalogi API zelf (er kunnen bijvoorbeeld nog geen Zaken aangemaakt worden met dit zaaktype). Klik op de Publiceren knop onderaan de detail pagina van het zaaktype om het zaaktype te publiceren.

Note
Als je op de detailpagina van het zaaktype aanpassingen maakt en vervolgens het zaaktype publiceert, dan worden deze aanpassingen ook opgeslagen.
Een nieuwe versie van een zaaktype aanmaken¶
Om een nieuwe versie van een zaaktype toe te voegen, moet eerst de datum einde geldigheid van het zaaktype ingevuld worden.

Klik zodra deze datum ingevuld is op de Nieuwe versie toevoegen knop om een nieuwe versie van het zaaktype aan te maken.

Navigeer vervolgens naar de zaaktypen van de aangemaakte catalogus om de nieuwe versie te zien. De nieuwe versie zal eerst gepubliceerd moeten worden voor gebruik buiten de Catalogi API.

Exporteren/importeren van een catalogus¶
Een catalogus kan samen met alle typen die erin zitten (Zaaktypen, Informatieobjecttype, etc.) geëxporteerd worden naar een .zip archief, dat vervolgens weer gebruikt kan worden om de catalogus in een andere Catalogi API te importeren.
Om dit te doen in OpenZaak, klik op de te exporteren catalogus onder Gegevens > Catalogi en klik vervolgens op de Exporteren knop onderaan de pagina. Download daarna de export als .zip-bestand.

Om de importfunctionaliteit te demonstreren is de zojuist geëxporteerde catalogus verwijderd uit de OpenZaak admin. Klik hiervoor op de Verwijderen knop linksonderin de detailpagina van de catalogus.

Importeer de catalogus door op de catalogus lijstweergave te klikken op de Importeer catalogus knop rechtsbovenin. Upload op de volgende pagine het .zip-bestand en kies of er voor de objecten nieuwe UUIDs gegenereerd moeten worden, of dat de bestaande UUIDs uit de import gebruikt moeten worden.

Warning
LET OP: alle Zaaktypen, Informatieobjecttypen en Besluittypen worden geïmporteerd als concept.
Exporteren/importeren van een zaaktype¶
In sommige gevallen hoeft niet een gehele catalogus geïmporteerd te worden, maar alleen een enkel zaaktype uit die catalogus, dit is ook mogelijk in de OpenZaak admin.
Om te demonstreren hoe het importeren werkt als er Informatieobjecttypen en Besluittypen gerelateerd zijn aan het Zaaktype, worden deze voor deze tutorial eerst toegevoegd aan het zaaktype. Navigeer hiervoor naar de catalogi lijstweergave, klik op Toon alle besluittypen, klik daarna op Besluittype toevoegen, vul de verplichte informatie in en leg een relatie met het te exporteren zaaktype (hetzelfde geldt voor Informatieobjecttypen).
Exporteer het zaaktype door te klikken op Export onderaan de pagina van het zaaktype en download het .zip-bestand. Om hierna het importeren te demonstreren, wordt dit zaaktype verwijderd door te klikken op Verwijderen linksonderin de zaaktype pagina.

Klik vervolgens de catalogus aan waarin het zaaktype terecht moet komen en druk op de Import ZaakType knop.

Upload op de volgende pagina het .zip-bestand met de export van het zaaktype

Omdat er in de .zip ook Besluittypen en Informatieobjecttypen zitten, moet er bepaald worden of deze ook geïmporteerd moeten worden, of dat deze vervangen kunnen worden door bestaande Besluittypen en Informatieobjecttypen. Aangezien het Besluittype en Informatieobjecttype in deze tutorial niet zijn verwijderd, wordt er hier voor gekozen om de bestaande typen te gebruiken. Klik tot slot op Select om de import uit te voeren.

Gebruikerstoegang¶
Note
Om gebruikers te kunnen beheren moet je tot de User admin groep behoren of equivalente permissies hebben. Zie Groepen voor groepenbeheer.
Groepen¶
Een groep is een set van permissies. Een permissie laat een gebruiker toe om iets te doen. Typisch zijn er vier soorten permissies voor een soort van gegeven:
objecten lezen
objecten aanmaken
objecten aanpassen
objecten verwijderen
Een gebruiker kan tot meerdere groepen behoren - de permissies vullen elkaar dan aan, d.w.z. dat je de gecombineerde set van permissies krijgt van elke groep.
Een standaard Open Zaak installatie komt met een aantal standaardgroepen:
- Admin
Een beheerder die alles kan. Ga hier erg zorgvuldig mee om!
- API admin
Leden van deze groep kunnen taakapplicaties en hun API-toegang instellen, en Open Zaak configureren om andere API’s te consumeren.
- Autorisaties admin
Leden van deze groep kunnen taakapplicaties en hun API-toegang instellen, en Open Zaak configureren om andere API’s te consumeren.
- Autorisaties lezen
Leden van deze groep kunnen zien welke applicaties toegang hebben tot de Open Zaak API’s, maar deze niet bewerken.
- Besluiten admin
Leden van de groep kunnen de resources ontsloten via de Besluiten API lezen, aanmaken en bewerken:
Besluiten
Relaties tussen besluiten en documenten
- Besluiten lezen
Leden van de groep kunnen de resources ontsloten via de Besluiten API lezen.
- Catalogi admin
Leden van de groep kunnen de resources ontsloten via de Catalogi API lezen, aanmaken en bewerken:
Catalogi
Zaaktypen
Statustypen
Resultaattypen
Eigenschappen
Roltypen
Informatieobjecttypen
Besluittypen
Zaaktype-informatieobjecttypen
- Catalogi lezen
Leden van de groep kunnen de resources ontsloten via de Catalogi API lezen.
- Documenten admin
Leden van de groep kunnen de resources ontsloten via de Documenten API lezen, aanmaken en bewerken:
Enkelvoudige informatieobjecten (= documenten) met versiehistorie
Gebruiksrechten van documenten
Relaties tussen documenten en andere objecten
- Documenten lezen
Leden van de groep kunnen de resources ontsloten via de Documenten API lezen.
- Zaken admin
Leden van de groep kunnen de resources ontsloten via de Zaken API lezen, aanmaken en bewerken:
Zaken
Statussen van zaken
Resultaat van zaken
Eigenschappen van zaken
Documenten bij zaken
Andere objecten bij zaken
Klantcontacten van zaken
Betrokkenen bij zaken
Relevante zaak-relaties
- Zaken lezen
Leden van de groep kunnen de resources ontsloten via de Zaken API lezen.
Een gebruiker aanmaken (en aan een groep toevoegen)¶
Vertrek vanaf de startpagina en vind de groep Accounts. Klik vervolgens op Toevoegen naast de titel Gebruikers:

Vul vervolgens een gebruikersnaam in en een wachtwoord. Vergeet niet om het wachtwoord te bevestigen. Merk op dat er wachtwoordsterkte-regels gelden!
Note
Gebruikersnamen zijn hoofdlettergevoelig!
Klik vervolgens op Opslaan en opnieuw bewerken:

In het volgende scherm kan je vervolgens de rechten voor deze gebruiker instellen.

Het vinkje Stafstatus bepaalt of de gebruiker in kan loggen op de admin-omgeving.
Het vinkje Supergebruikerstatus geeft aan of de gebruiker altijd alle permissies heeft. We raden sterk aan om hier conservatief mee om te gaan.
De beschikbare groepen staan opgelijst in de linkerkolom. Om een gebruiker aan een groep toe te wijzen selecteer je de groep door deze aan te klikken en op de pijl naar rechts (4) te klikken. Je kan meerdere groepen in één keer toekennen door de
CTRL
-toets ingedrukt te houden tijdens het aanklikken. Je kan ook dubbelklikken om een groep toe te kennen.
Klik rechtsonder op Opslaan om de wijzigingen door te voeren.
API-toegang beheer¶
Open Zaak biedt API’s aan voor zaakgericht werken. Deze API’s zijn niet toegankelijk zonder authenticatie en autorisatie - gegevens worden namelijk correct beveiligd. Eindgebruikers maken gebruik van (taak)applicaties, en het zijn deze applicaties die gebruik maken van de API’s voor zaakgericht werken.
Voordat een applicatie dus gegevens kan opvragen, opvoeren, bewerken of vernietigen, moet deze applicatie hiervoor bekend zijn en geautoriseerd zijn.
Elke applicatie die aangesloten wordt op Open Zaak krijgt authenticatiegegevens. Tegelijkertijd worden autorisaties ingesteld per applicatie. Autorisatiebeheerders dienen vervolgens de applicatie-authenticatiegegevens te communiceren naar de beheerder(s) van de (taak)applicatie.
Warning
De applicaties/authenticatiegegevens die hier beheerd worden, zijn niet geschikt voor eindgebruikers, maar enkel voor server-to-server communicatie.
Note
Om API-toegang te kunnen beheren moet je tot de API admin groep behoren of equivalente permissies hebben. Zie Groepen voor groepenbeheer.
Een Applicatie registreren¶
Klik op het dashboard onder de groep API Autorisaties op de link Toevoegen naast de kop Applicaties:

Vul vervolgens het formulier in:

Het label is een vriendelijke naam voor de applicatie waarmee je kan herkennen om welke applicatie binnen je organisatie het gaat. Je kan dit vrij kiezen.
Het vinkje Heeft alle autorisaties laat je toe om snel een applicatie alle mogelijke rechten te geven. Merk op dat dit bijna altijd betekent dat een applicatie meer mag dan nodig is!
Zorg ervoor dat je minstens één combinatie van Client ID en Secret genereert. De applicatie heeft deze gegevens nodig om tokens te kunnen genereren - communiceer deze dus op een veilige manier naar de beheerder van de (taak)applicatie.
Klik tot slot op Opslaan en opnieuw bewerken, waarna je de autorisaties in kan stellen.
Instellen van de API-toegang voor een Applicatie¶
Je kan de applicatie waarvan je autorisaties wenst in te stellen bereiken via het lijstoverzicht of vlak na het registreren van een nieuwe applicatie.
Klik rechtsonderin op Beheer autorisaties om de autorisaties van een applicatie in te stellen.

Autorisaties zijn van toepassing op een bepaalde API-component. Eén applicatie kan zonder problemen autorisaties hebben op een set van componenten.
Componentkeuze¶
Kies in de eerste stap voor welke component je autorisaties wil instellen:

Afhankelijk van de keuze van de component gebeuren nu een aantal dingen:
de relevante scopes worden nu getoond
eventuele extra keuzeparameters zijn beschikbaar

Keuze scopes¶
Scopes bepalen welke acties een applicatie via de API kan uitvoeren. Het is een groepering van rechten.
De betekenis van de scopes is gedocumenteerd per component:
Typisch zal een leverancier van de applicatie je vertellen welke scopes er precies nodig zijn. Selecteer de relevante scopes door de checkboxes aan te vinken.
Keuze relevante typen¶
Voor de Zaken API, Documenten API en Besluiten API worden de autorisaties ingericht per type - Zaaktype, Informatieobjecttype en Besluittype respectievelijk.
De type-selectie heeft drie mogelijke opties:
- Alle huidige *typen:
Dit selecteert alle huidige typen, ook de typen die nog niet gepubliceerd zijn. Voor de Zaken API gelden de autorisaties dan voor alle zaaktypen uit alle catalogi in Open Zaak.
- Alle huidige en toekomstige *typen:
Dit is dezelfde situatie als
Alle huidige *typen
, met het verschil dat *typen die aangemaakt worden na het instellen van de autorisaties hier ook binnen vallen.- Selecteer handmatig:
Bij handmatige selectie worden alle *typen per catalogus opgelijst. Kies de relevante *typen aan door het vinkje aan te zetten.

Keuze vertrouwelijkheidaanduiding¶
Tot slot kan je limiteren tot welke vertrouwelijkheidaanduiding een applicatie toegang heeft. Documenten en Zaken worden aangemaakt met een bepaalde vertrouwelijkheidaanduiding. Een applicatie heeft enkel toegang tot deze documenten en zaken waarvan de vertrouwelijkheidaanduiding meer publiek of gelijk-aan de ingestelde autorisatie-vertrouwelijkheidaanduiding is.
Voor de applicatie lijkt het alsof Documenten en Zaken die meer vertrouwelijk zijn niet bestaan.
Note
Merk op dat de ingestelde vertrouwelijkheidaanduiding van toepassing is op de geselecteerde zaaktypen of informatieobjecttypen. Je kan dus een verschillende maximale vertrouwelijkheidaanduiding instellen per zaaktype of informatieobjecttype.
Toevoegen extra autorisaties¶
Linksonderin vind je een link Nog Autorisaties toevoegen. Zodra je hierop klikt, ga je opnieuw door hetzelfde proces om een autorisatie in te stellen. Je kan zoveel autorisaties instellen als je wenst.
Warning
Let op dat je geen conflicterende autorisaties instelt. Eenmaal een autorisatie voor (een groep van) zaaktypen, informatieobjecttypen of besluittypen is ingesteld mag je geen extra autorisaties voor diezelfde (groep van) zaaktypen, informatieobjecttypen of besluittypen meer instellen.
Opslaan wijzigingen¶
Wanneer je klaar bent, vergeet dan niet om rechtsonderin op Opslaan te klikken om de autorisaties te bewaren.
Support¶
Development is done separately from any support or service that you might need to install, use, implement or integrate Open Zaak.
What kind of support do you need?
Need help with the installation? Contact a service provider!
Found a bug? Please create an issue on Github!
Want to contribute? See Development!
Development¶
Open Zaak is open-source software. We’d love to have you contribute!
Changelog¶
1.0.0 (2020-02-06)¶
🎉 First release of Open Zaak.
Features:
Zaken API implementation
Documenten API implementation
Catalogi API implementation
Besluiten API implementation
Autorisaties API implementation
Support for external APIs
Admin interface to manage Catalogi
Admin interface to manage Applicaties and Autorisaties
Admin interface to view data created via the APIs
NLX ready (can be used with NLX)
Documentation on https://open-zaak.readthedocs.io/
Deployable on Kubernetes, single server and as VMware appliance
Automated test suite
Automated deployment
Getting started¶
The project is developed in Python using the Django framework. There are 3 sections below, focussing on developers, running the project using Docker and hints for running the project in production.
Installation¶
Prerequisites¶
You need the following libraries and/or programs:
Python 3.7 or above
Python Virtualenv and Pip
PostgreSQL 10 or above, with the PostGIS-extension
Getting started¶
Developers can follow the following steps to set up the project on their local development machine.
Navigate to the location where you want to place your project.
Get the code:
$ git clone git@github.com:open-zaak/open-zaak.git $ cd open-zaak
Install all required libraries:
$ virtualenv env $ source env/bin/activate $ pip install -r requirements/dev.txt
Install the front-end CLI tool gulp if you’ve never installed them before and install the frontend libraries:
$ npm install $ npm run build
Activate your virtual environment and create the statics and database:
$ source env/bin/activate $ python src/manage.py migrate
Create a superuser to access the management interface:
$ python src/manage.py createsuperuser
You can now run your installation and point your browser to the address given by this command:
$ python src/manage.py runserver
Note: If you are making local, machine specific, changes, add them to
src/openzaak/conf/includes/local.py
. You can also set certain common
variables in a local .env
file. You can base these files on the
example files included in the same directory.
Note: You can run watch-tasks to compile Sass to CSS and ECMA to JS
using npm run watch
. By default this will compile the files if they change.
Update installation¶
When updating an existing installation:
Activate the virtual environment:
$ cd open-zaak $ source env/bin/activate
Update the code and libraries:
$ git pull $ pip install -r requirements/dev.txt $ npm install $ npm run build
Update the statics and database:
$ python src/manage.py migrate
Configuration via environment variables¶
A number of common settings/configurations can be modified by setting
environment variables, add them to your .env
file or persist them in
src/openzaak/conf/includes/local.py
.
SECRET_KEY
: the secret key to use. A default is set indev.py
DB_NAME
: name of the database for the project. Defaults toopen-zaak
.DB_USER
: username to connect to the database with. Defaults toopen-zaak
.DB_PASSWORD
: password to use to connect to the database. Defaults toopen-zaak
.DB_HOST
: database host. Defaults tolocalhost
DB_PORT
: database port. Defaults to5432
.SENTRY_DSN
: the DSN of the project in Sentry. If set, enabled Sentry SDK as logger and will send errors/logging to Sentry. If unset, Sentry SDK will be disabled.
Settings¶
All settings for the project can be found in
src/openzaak/conf
.
The file includes/local.py
overwrites settings from the base configuration,
and is only loaded for the dev settings.
Release process¶
Open Zaak makes use of quite a bit of Continuous Integration tooling to set up a full release process, all driven by the Git repository.
Travis CI¶
Our pipeline is mostly implemented on Travis:
Merges to the master
branch are built on Travis, where:
Tests are run
Code quality checks are run
Compatibility with the API’s voor zaakgericht werken standard spec is tested
The Docker image is built and published
If the build is for a Git tag on the master
branch, then the image is built and
publish with that version tag to Docker Hub.
Releasing a new version¶
Releasing a new version can only be done by people with merge permissions to the master branch belonging to the Open Zaak organisation on Github.
Assuming a current version of 0.9.0
:
Create a release branch
git checkout -b release/1.0.0
Update the changelog
Update CHANGELOG.rst
in the root of the project, and make sure to commit the
changes.
Bump the version
bumpversion minor
and commit:
git commit -am ":bookmark: Bump version to 1.0.0"
Push the changes and make a pull request.
Tag the release
Once the PR is merged to master, check out the master
branch and tag it:
git checkout master
git pull
git tag 1.0.0
Tagging will ensure that a Docker image openzaak/open-zaak:1.0.0
is published.
Performance¶
Performance is measured using different types of scenarios.
Measuring performance¶
Goal¶
The purpose of performance measurements is to gain insight into the relationships between system requirements, number of users and response times of the API’s. From these relationships we can draw up the minimum system requirements, depending on the number of users, on which the API’s still perform acceptable.
A standardized performance measurement also provides insight into which effect various optimizations have.
Technical test scenarios¶
The performance of some often used API-calls (requests) is measured to gain insights in the technical performance.
Zaken API
Retrieve ZAAKen (
GET /api/v1/zaken
)Retrieve ZAAK (
GET /api/v1/zaken/d4d..2e8
)Create ZAAK (
POST /api/v1/zaken
)
Catalogi API
Retrieve ZAAKTYPEn (
GET /api/v1/zaaktypen
)Retrieve ZAAKTYPE (
GET /api/v1/zaaktypen/d4d..2e8
)Create ZAAKTYPE (
POST /api/v1/zaaktypen
)
Besluiten API
Retrieve BESLUITen (
GET /api/v1/besluit
)Retrieve BESLUIT (
GET /api/v1/besluit/d4d..2e8
)Create BESLUIT (
POST /api/v1/besluit
)
Documenten API
Retrieve ENKELVOUDIGINFORMATIEOBJECTen (
GET /api/v1/enkelvoudiginformatieobjecten
)Retrieve ENKELVOUDIGINFORMATIEOBJECT (
GET /api/v1/enkelvoudiginformatieobjecten/d4d..2e8
)Create ENKELVOUDIGINFORMATIEOBJECT (
POST /api/v1/enkelvoudiginformatieobjecten
)
A scenario in this test specification is equal to an API-call (request). Each API resource is continuously without any delay, or waiting time, between each request. This way, we can determine the maximum number of requests per second and average response times.
We test with an increasing number of virtual users, from 1 to 100, that concurrently execute the test scenarios. A virtual user is technically a script that executes the different scenarios one after another. This way, we see the number of virtual users that concurrently access the API’s and its impact on performance.
The testset that is present in the database:
1.000.000 Zaken in the Zaken API
1.000.000 Documenten in the Documenten API
1.000.000 Besluiten in the Besluiten API
1 Catalogus with 100 Zaaktypen in the Catalogi API
Functional test scenarios¶
Performance testing is done by accessing the APIs as if they were being used by an application, or a virtual system. Some typical functional scenarios have been observed in similar systems:
Retrieve Zaken overview
Retrieve Zaken overview for a specific Zaaktype
Search Zaken by location
Search Zaken by person
Retrieve Zaak details
Retrieve history
Create Zaak
Add Status
Add Betrokkene
Add Document
Add Besluit
Add Resultaat
All functional scenarios have been translated into API requests. The number of API requests, the exact query parameters for filtering and/or sorting lists, and the data sent for creating objects are all very dynamic in practice. For each functional scenario, one or more specific API requests are prepared that fill in the scenario as well as possible.
A number of API requests have been placed out of scope because they are not part of the APIs voor Zaakgericht werken but are most likely required to build a functional user interface.
Retrieve an unfiltered list of Zaken, along with their Zaaktype and Statustype.
Zaken API
1x ZAAKen retrieve (
GET /api/v1/zaken
)1x STATUSsen retrieve (
GET /api/v1/statussen
)
Catalogi API
1x ZAAKTYPEn retrieve (
GET /api/v1/zaaktypen
)1x STATUSTYPEn retrieve (
GET /api/v1/statustypen
)
Retrieve an unfiltered list of Zaken, along with their Zaaktype and Statustype. Each Status is requested, filtered on their matching Statustype for the appropriate Zaaktype.
Zaken API
1x ZAAKen retrieve (
GET /api/v1/zaken?zaaktype=/api/v1/zaaktypen/011..3c1
)3x STATUSsen retrieve (
GET /api/v1/statussen?statustype=/api/v1/statustypen/f82..396
)
Catalogi API
1x ZAAKTYPEn retrieve (
GET /api/v1/zaaktypen/011..3c1
)1x STATUSTYPEn retrieve (
GET /api/v1/statustypen?zaaktype=/api/v1/zaaktypen/011..3c1
)
Retrieve a list of Zaken that match a specific geographical area (polygon).
Zaken API
1x ZAAKen zoeken (
POST /api/v1/zaken/_zoek
)
Retrieve a list of Zaken that match a specific person (Betrokkene).
1x Betrokkene zoeken (buiten scope)
Zaken API
1x ZAAKen filteren
GET /api/v1/rollen?betrokkene=https://personen/api/v1/a66c38
Retrieve a complete Zaak, with its Resultaat, Besluit, 3 Documenten, 2 Zaakobjecten and 3 Betrokkenen.
3x Betrokkenen retrieve via ROLlen-resultaat (buiten scope)
2x Objecten retrieve via ZAAKOBJECTen-resultaat (buiten scope)
Zaken API
1x ZAAK retrieve (
GET /api/v1/zaken/d4d..2e8
)1x STATUSsen retrieve (
GET /api/v1/statussen?zaak=/api/v1/zaken/d4d..2e8
)1x RESULTAAT retrieve (
GET /api/v1/resultaten/f84..e9e
)1x ROLlen retrieve (
GET /api/v1/rollen?zaak=/api/v1/zaken/d4d..2e8
)1x ZAAKOBJECTen retrieve (
GET /api/v1/zaakobjecten?zaak=/api/v1/zaken/d4d..2e8
)
Catalogi API
1x ZAAKTYPE retrieve (
GET /api/v1/zaaktypen/011..3c1
)1x STATUSTYPEn retrieve (
GET /api/v1/statustypen?zaaktype=/api/v1/zaaktypen/011..3c1
)1x BESLUITTYPE retrieve (
GET /api/v1/besluittypen?zaaktype=/api/v1/zaaktypen/011..3c1
)1x RESULTAATTYPE retrieve (
GET /api/v1/resultaattypen/712..a7c?zaaktype=/api/v1/zaaktypen/011..3c1
)
Documenten API
1x OBJECTINFORMATIEOBJECTen retrieve (
GET /api/v1/objectinformatieobjecten?object=/api/v1/zaken/d4d..2e8
)3x ENKELVOUDIGINFORMATIEOBJECT retrieve (
GET /api/v1/enkelvoudiginformatieobjecten/cd6..d90
)
Besluiten API
1x BESLUITen retrieve (
GET /api/v1/besluiten?zaak=/api/v1/zaken/d4d..2e8
)
Retrieve the combined audit trails of a Zaak, Besluit and 3 Documenten from their respective API’s.
Zaken API
1x AUDITTRAIL retrieve (
GET /api/v1/zaken/d4d..2e8/audittrail
)
Documenten API
3x AUDITTRAIL retrieve (
GET /api/v1/enkelvoudiginformatieobjecten/cd6..d90/audittrail
)
Besluiten API
1x AUDITTRAIL retrieve (
GET /api/v1/besluiten/a28..6d3/audittrail
)
Create a Zaak with its initial Status and a Rol with the person that initiated the Zaak.
Zaken API
1x ZAAK create (
POST /api/v1/zaken
)1x STATUS create (
POST /api/v1/status
)1x ROL create (
POST /api/v1/rollen
)
Create a Document and make a relation to a Zaak.
Zaken API
1x ZAAK-INFORMATIEOBJECT create (
POST /api/v1/zaakinformatieobjecten
)
Documenten API
1x ENKELVOUDIGINFORMATIEOBJECT create (
POST /api/v1/enkelvoudiginformatieobjecten
)
Not every scenario is executed as often. For example, a Zaak is requested more often than it is created. In the table below, for every 20 x “Retrieve Zaak details” scenario, 10x “Create Zaak” is executed. This was then converted to a percentage, assuming that all scenarios represent 100%. We call this the weight.
To simulate a user perspective, a specific waiting time is introduced after each scenario. The waiting time represents, for example, the time a user needs to enter data into the user interface or the time it takes to interpret the data. In the table below, after executing “Create Zaak”, the script waits between 0 and 10 minutes (5 minutes on average).
Finally, the number of API-calls is shown for each scenario.
# |
Scenario |
Weight |
Wait time (m) |
API-calls |
||
---|---|---|---|---|---|---|
. |
. |
Abs. |
% |
Avg. |
Range |
. |
1 |
Retrieve Zaken overview |
20 |
20% |
2 |
0 - 4 |
4 |
2 |
… for a specific Zaaktype |
10 |
10% |
2 |
0 - 4 |
6 |
3 |
Search Zaken by location |
1 |
1% |
1 |
0 - 2 |
1 |
4 |
Search Zaken by person |
10 |
10% |
1 |
0 - 2 |
1 |
5 |
Retrieve Zaak details |
8 |
8% |
2 |
0 - 4 |
14 |
6 |
Retrieve history |
2 |
2% |
3 |
0 - 6 |
5 |
7 |
Create Zaak |
10 |
10% |
5 |
0 - 10 |
3 |
8 |
Add Status |
20 |
20% |
2 |
0 - 4 |
1 |
9 |
Add Betrokkene |
3 |
3% |
3 |
0 - 6 |
1 |
10 |
Add Document |
12 |
12% |
4 |
0 - 8 |
2 |
11 |
Add Besluit |
2 |
2% |
3 |
0 - 6 |
1 |
12 |
Add Resultaat |
2 |
2% |
3 |
0 - 6 |
1 |
. |
Total |
100 |
100% |
31 |
40 |
If taken the weight into account, the overall average waiting time is 5 minutes and the average number of requests per scenario is 7.
We test with an increasing number of virtual users, from 1 to 100, that concurrently execute the test scenarios. A virtual user is technically a script that executes the different scenarios one after another, in the distribution and with the associated waiting time as shown in the table above.
The testset that is present in the database:
1.000.000 Zaken in the Zaken API
1.000.000 Documenten in the Documenten API
1.000.000 Besluiten in the Besluiten API
1 Catalogus with 100 Zaaktypen in the Catalogi API
Apache Benchmark stress test¶
Apache Bench is a good tool to measure raw HTTP performance. It is not indicative for application performance, but rather aimed at testing your infrastructure.
This document describes the configuration to run ab
to make meaningful
comparisons and see which changes have which effect.
Running ab
¶
ab -n 1000 -c 100 https://test.openzaak.nl/zaken/api/v1/
The most interesting statistic is the number of requests per second, which you want to be as high as possible.
Philosophy¶
We run a total of 1000 requests to measure performance, using up to 100 concurrent users. Playing around with the concurrency level can reveal hot spots or ideal numbers.
We test and API endpoint that has no IO and is inexpensive to generate. We don’t want to stress the application with queries or complicated template rendering, which is why we pick an API root that generates very little JSON.
Note that if you are running the tests directly against other services, that
you may have to specify the Host
header: -H 'Host: localhost'
, otherwise
Django will generate an HTTP 400 because of the InvalidHostHeader
, which
is very fast but not representative.
Also note that you want to run ab
from a fast client machine. Aim for a
server in a different data center. We’ve seen cases where our client is limited
in requests per second because of a slow home network.
Parameters to vary¶
Traefik/Ingress: SSL termination happens here. We’ve seen Traefik CPU spikes with large private keys (4096 bits), and performance did improve a bit by changing to EC 256 bits at the cost of a worse SSL rating (A+ to A).
Number of nginx replicas - more replicas can handle more traffic from Traefik
Number of Open Zaak replicas - by default each container can handle 4 concurrent requests (2 process * 2 threads per process)
Number of Open Zaak processes/threads in a container
CPU/memory resource requests/limits in Kubernetes. Assigning more CPU/memory power will probably give better results. This applies for the Traefik, nginx and Open Zaak containers.