Getting Started with ZenBPM
This tutorial will guide you through the basics of ZenBPM, helping you set up your first BPMN process and execute it.
What You'll Learn
- How to install and run ZenBPM
- How to create a simple BPMN process
- How to deploy the process to ZenBPM
- How to start a process instance
- How to monitor the process execution
Prerequisites
- Basic understanding of what BPMN is
- Docker installed on your machine
Step 1: Install and Run ZenBPM
The easiest way to get started with ZenBPM is to use Docker.
- Pull the ZenBPM Docker image:
docker pull ghcr.io/pbinitiative/zenbpm:latest
:::
- Run the ZenBPM container:
docker run -d -p 8080:8080 -p 9090:9090 --name zenbpm ghcr.io/pbinitiative/zenbpm:latest
:::
This will start ZenBPM with:
- REST API available at localhost:8080
- gRPC API available at localhost:9090
Step 2: Create a Simple BPMN Process
For this tutorial, we'll create a simple "Hello World" process with a start event, a message throw event, and an end event.
- Create a file named
hello-world.bpmnwith the following content:
<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" id="Definitions_0tl6ily" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="5.35.0">
<bpmn:process id="Process_0iehjhs" isExecutable="true">
<bpmn:startEvent id="StartEvent_1" name="Start Process">
<bpmn:outgoing>Flow_1l01xu9</bpmn:outgoing>
</bpmn:startEvent>
<bpmn:sequenceFlow id="Flow_1l01xu9" sourceRef="StartEvent_1" targetRef="Event_1" />
<bpmn:endEvent id="Event_End" name="End Process">
<bpmn:incoming>Flow_02ezsew</bpmn:incoming>
</bpmn:endEvent>
<bpmn:sequenceFlow id="Flow_02ezsew" sourceRef="Event_1" targetRef="Event_End" />
<bpmn:intermediateThrowEvent id="Event_1" name="Throw Event">
<bpmn:incoming>Flow_1l01xu9</bpmn:incoming>
<bpmn:outgoing>Flow_02ezsew</bpmn:outgoing>
<bpmn:messageEventDefinition id="MessageEventDefinition_02xi10c" messageRef="Message_36nekaq" />
</bpmn:intermediateThrowEvent>
</bpmn:process>
<bpmn:message id="Message_36nekaq" name="Message_1" />
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_0iehjhs">
<bpmndi:BPMNShape id="StartEvent_1_di" bpmnElement="StartEvent_1">
<dc:Bounds x="182" y="102" width="36" height="36" />
<bpmndi:BPMNLabel>
<dc:Bounds x="167" y="145" width="67" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Event_0b5zljm_di" bpmnElement="Event_End">
<dc:Bounds x="342" y="102" width="36" height="36" />
<bpmndi:BPMNLabel>
<dc:Bounds x="329" y="145" width="63" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Event_0xpjar9_di" bpmnElement="Event_1">
<dc:Bounds x="262" y="102" width="36" height="36" />
<bpmndi:BPMNLabel>
<dc:Bounds x="251" y="145" width="62" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="Flow_1l01xu9_di" bpmnElement="Flow_1l01xu9">
<di:waypoint x="218" y="120" />
<di:waypoint x="262" y="120" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_02ezsew_di" bpmnElement="Flow_02ezsew">
<di:waypoint x="298" y="120" />
<di:waypoint x="342" y="120" />
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>
This BPMN file defines a simple process with:
- A start event
- A Message intermediate throw event
- An end event
Step 3: Deploy the Process to ZenBPM
Now that we have our BPMN process, let's deploy it to ZenBPM:
Deploy a new process definition
Request Body schema: multipart/form-datarequired
| resource required | string <binary> BPMN process definition file (.bpmn format only, max 4MB) |
Responses
Response samples
- 201
- 400
- 409
- 502
{- "processDefinitionKey": 4503599627370498
}You should receive a response with details about the deployed process definition, including a processDefinitionKey that uniquely identifies it.
Step 4: Start a Process Instance
With the process definition deployed, we can now start a process instance:
Create a new process instance
Request Body schema: application/jsonrequired
| processDefinitionKey required | integer <int64> |
| variables | object |
| historyTimeToLive | string Duration for which process instance data are kept in storage after the process instance ends. If omitted the default will be picked up from engine configuration. (1d8h, 1M5d8h) |
| businessKey | string Business key of the process instance used mainly for correlating process instance to the business entity. |
Responses
Request samples
- Payload
{- "processDefinitionKey": 4503599627370498,
- "variables": {
- "customerId": "customer-456",
- "amount": 1000,
- "applicationDate": "2025-08-22"
}
}Response samples
- 201
- 400
- 500
- 502
{- "key": "4503599627370501",
- "processDefinitionKey": "4503599627370498",
- "createdAt": "2025-08-22T14:30:25Z",
- "state": "active",
- "variables": {
- "customerId": "customer-456",
- "amount": 1000,
- "applicationDate": "2025-08-22"
}
}This will start a new instance of our "Hello World" process. The response will include a processInstanceKey that uniquely identifies this instance.
Step 5: Monitor the Process Execution
Let's check the status of our process instance:
Get state of a process instance selected by processInstanceKey
path Parameters
| processInstanceKey required | integer <int64> Example: 4503599627370501 |
Responses
Response samples
- 200
- 400
- 500
- 502
{- "key": "4503599627370501",
- "processDefinitionKey": "4503599627370498",
- "createdAt": "2025-08-22T14:30:25Z",
- "state": "active",
- "variables": {
- "customerId": "customer-456",
- "amount": 1000,
- "applicationDate": "2025-08-22",
- "taskAssignee": "john.doe",
- "currentStatus": "Application review"
}
}Replace {processInstanceKey} with the actual key from the previous step.
You should see details about the process instance, including its current state. Since our process is very simple, it might have already completed by the time you check.
Step 6: View Process history
this feature is not implemented yet
To see what activities were executed in our process:
Get list of visited flow elements for a process instance
path Parameters
| processInstanceKey required | integer <int64> Example: 4503599627370501 |
query Parameters
| page | integer <int32> >= 1 Default: 1 Example: page=1 Page number (1-based indexing) |
| size | integer <int32> [ 1 .. 100 ] Default: 10 Example: size=10 Number of items per page (max 100) |
Responses
Response samples
- 200
- 400
- 502
{- "items": [
- {
- "key": "4503599627370525",
- "elementId": "StartEvent_1",
- "processInstanceKey": "4503599627370501",
- "createdAt": "2025-08-22T14:30:26Z"
}, - {
- "key": "4503599627370526",
- "elementId": "Flow_1",
- "processInstanceKey": "4503599627370501",
- "createdAt": "2025-08-22T14:30:26Z"
}, - {
- "key": "4503599627370527",
- "elementId": "Task_CheckApplication",
- "processInstanceKey": "4503599627370501",
- "createdAt": "2025-08-22T14:30:27Z"
}
], - "page": 1,
- "size": 10,
- "count": 3,
- "totalCount": 3
}This will show you all the activities that were executed as part of the process instance, including the message throw event.
Conclusion
Congratulations! You've successfully:
- Set up ZenBPM
- Created a simple BPMN process
- Deployed the process to ZenBPM
- Started a process instance
- Monitored the process execution
Next Steps
Now that you've completed this basic tutorial, you might want to:
- Learn how to create more complex BPMN processes
TODO - Explore user tasks and forms
TODO - Understand message events and correlation
TODO - Set up process monitoring and observability
TODO