How to get form id of a start event in a process?

Hi, i’m new to Camunda and doing a POC. I’m trying to figure out how to get the form id of a start event of a process. I noticed that when Tasklist app is doing this, it calls some nice internal API and gets the process definition with startEventFormId, like this:

        "id": "2251799814251693",
        "name": "Address Change",
        "bpmnProcessId": "Process_1hb7f40",
        "sortValues": null,
        "version": 2,
        "startEventFormId": "Form_Address_Change",
        "tenantId": "<default>"

But i don’t know what this internal api is:

Should i be using that? I’m writing my BFF in node if that helps.


@timg There is no official API to return the Form that starts a process at the moment. About you using the internal API, you should list processes from Operate API, but it also would not return the start form for you, unfortunately. Tasklist has some internal endpoints that are used only by the application, you can use them, but be aware that they can be changed by the engineers to adapt to new features on Tasklist. So here you have 2 options:

  • Do the same as Tasklist is doing: the call below should return you the form in case this process is started by one (in case not, it will return 404) - also please bear in mind that because this is an internal endpoint, changes may occur on it without notifications.
curl -X 'GET' \
  'http://localhost:8080/v1/external/process/<process_id>/form' \
  -H 'accept: application/json'

Example of return:

  "id": "subscribeForm",
  "processDefinitionKey": "2251799813685273",
  "title": "subscribeFormProcess",
  "schema": "\n        {\n  \"components\": [\n    {\n      \"text\": \"# Subscribe to newsletter\",\n      \"type\": \"text\",\n      \"layout\": {\n        \"row\": \"Row_0jjnqip\",\n        \"columns\": null\n      },\n      \"id\": \"Field_1xn41dw\"\n    },\n    {\n      \"label\": \"Name\",\n      \"type\": \"textfield\",\n      \"layout\": {\n        \"row\": \"Row_15ghdy6\",\n        \"columns\": null\n      },\n      \"id\": \"Field_0ibsmz4\",\n      \"key\": \"field_1lfayry\"\n    },\n    {\n      \"label\": \"Email\",\n      \"type\": \"textfield\",\n      \"layout\": {\n        \"row\": \"Row_1klibf9\",\n        \"columns\": null\n      },\n      \"id\": \"Field_0msuoi3\",\n      \"key\": \"field_1prtdvl\",\n      \"validate\": {\n        \"required\": true\n      }\n    }\n  ],\n  \"type\": \"default\",\n  \"id\": \"subscribe\",\n  \"executionPlatform\": \"Camunda Cloud\",\n  \"executionPlatformVersion\": \"8.3.0\",\n  \"exporter\": {\n    \"name\": \"Camunda Modeler\",\n    \"version\": \"5.12.0-nightly.20230524\"\n  },\n  \"schemaVersion\": 8\n}\n  ",
  "version": null,
  "tenantId": "<default>",
  "isDeleted": false
  • Another option would be to use exporters/importers and save the process on a storage of your preference, so you could use the xml process to find out what form should start the process.

I’m taking a request to make the start form as part of our official API when listing Processes.

A quick question just out of curiosity, on the POC you are doing are you trying to do the same as Tasklist - that is to display the form and start the process?

Thanks @marcosgvieira . To answer you question, yes we are trying a build a UI that is not tied to the process in any way. This process will be user task heavy (really a case management flow to start).

Example would be an address change for a customer. The process that involves changing the address across many of the customer’s accounts could be complex. Involving user tasks and automated ones. This process will/could change. So I would like to define the process with bpmn and user forms in Camunda and build a UI/api that would not be tightly coupled to any of the processes. It would need to be able to list available process definitions, allow a user to start a process, which would then generate user tasks that we would pick up and display forms for. I can see the form id that comes back with a task, but no form id when starting a process. So how do I start the process (that may require some input variables that a form would enumerate and fill) if I don’t know if the start even requires a form and if so, which one?

I can’t build our app against an API that may change at any moment, so won’t be using the internal one that Tasklist is using (though it returns the perfect payload for my needs). I’m not sure I understand what the export option is, but if I need to persist things I don’t think that’s a viable option.

I must be missing something. How would one know which variables are required to start a process or which form is required to start a process. Is this an unusual need? Is there something in the js sdk that I can use to solve this?

@timg thanks for sharing your requirements!

You can check how exporter/importer works here: Exporters | Camunda 8 Docs and you got it right this would require storing the information that you need in your side.

Unfortunately as we don’t have an official API to support this need right now and you don’t think it’s viable to store information on your side, the best option that I see for you to build something right now would be to use the internal API (it will not change from one day to another - what I mean is that we can take the decision to change this API between stable versions, and as you noticed this API is not documented - for example 8.5 → 8.6 but we also don’t have plans to do any change in this internal API as it only supports the start process feature).

In other hand I can add a feature to backlog to make this a permanent feature exposed in the official APIs.

I assume also that the reason why you are not using Tasklist OOTB is because you are missing some important features (the requirements that you shared are basically what Tasklist OOTB does), so comments or save data, what would be crucial for you to use it?

@marcosgvieira I think we are going to need to build our own UI in the end. We will need functionality like comments, group assignments, document attachment, styling, etc. We will also need embeddable components into our existing UI. We would also build additional user permission control, etc.

I’m trying to see if there is something i can do to work around this. Something like design a process where i hardcode a variable with the id of the form to use at the start. So then I can start a new process instance, fetch the variable with the form id, fetch the form, have the user fill it out, submit all the new variables to the process, let the process continue as normal. This will essential fake the start event form submission. If there is no variable with with start form id, assume none is required in this process.


So after some more pondering, I ended using official SDK/Api to get the start form id. Essentially, I pull all process definitions and then for each one fetch the definition XML, convert to json and extract the start process form id if there is one. Something like this:

const definitionXml = await operate.getProcessDefinitionXML(groupedDefs[id].key);
const definitionJson = parser.parse(definitionXml);
groupedDefs[id].startFormId = definitionJson["bpmn:definitions"]["bpmn:process"]["bpmn:startEvent"]["bpmn:extensionElements"] != null ? 
          definitionJson["bpmn:definitions"]["bpmn:process"]["bpmn:startEvent"]["bpmn:extensionElements"]["zeebe:formDefinition"]["formId"] :

Will probably be very slow with many processes, but no options here. Hopefully API will be expanded in the future as per our convo above.

Hi @timg, thanks for sharing your solution and sorry as I missed this message and just seeing it now.

Your solution is mainly getting the xml of the process and extracting the form, what as you mentioned will work but is not exactly ideal.

We are evaluating how to better approach this in the next iterations, thanks for the thoughts and sharing feedbacks.