# Create Your First Workflow In this guide you will create a two-step approval workflow, save it to the database, and start a process instance - all through the Web API. The workflow models a document that starts in `Draft` and moves to `Approved` when the `Submit` command is executed. A [scheme](https://docs.workflowengine.io/get-started/concepts/scheme/) defines the [activities](https://docs.workflowengine.io/get-started/concepts/activity/), [transitions](https://docs.workflowengine.io/get-started/concepts/transition/), and [commands](https://docs.workflowengine.io/get-started/concepts/command/) of a process. You will write one as an XML file and upload it to the running Web API, which stores schemes in the database and uses them as blueprints when creating [process instances](https://docs.workflowengine.io/get-started/concepts/process-instance/). **Prerequisites:** - [Workflow Engine installed and running](https://docs.workflowengine.io/get-started/install-workflow-engine/) ## Step 1: Define the scheme XML A scheme contains three sections: `` (the triggers), `` (the states), and `` (the movements between states). The scheme below models a document that starts in `Draft` and moves to `Approved` when the `Submit` command is executed. Save this as `Approval.xml`: ![Approval scheme: Draft transitions to Approved via Submit command](https://docs.workflowengine.io/images/get-started/create-your-first-workflow/Approval.png) ```xml filename="Approval.xml" ``` An activity with `IsInitial="true"` is where the process starts. An activity with `IsFinal="true"` ends the process when reached. A trigger with `Type="Command"` fires the transition when the matching command executes. A condition with `Type="Always"` means the transition has no guard - it fires unconditionally. You can also create schemes visually using the standalone Designer. No installation needed - run it via npx: ```bash npx @optimajet/workflow-designer http://localhost:5274/workflow-api/designer Approval ``` This opens a browser tab with the full Designer UI connected to your Web API. You can draw activities and transitions visually and save them, or load an existing XML file through the Designer's menu - the scheme is stored in the database just like the XML approach above. ## Step 2: Upload and save the scheme The Designer API accepts scheme files in two steps: parse the XML into JSON, then save it to the database. Use a temporary file to pass the JSON between the two calls: ```bash # Step 1: Parse the XML file into JSON curl -s -X POST http://localhost:5274/workflow-api/designer \ -F "operation=uploadscheme" \ -F "schemecode=Approval" \ -F "schemeXml=@Approval.xml" > scheme.json # Step 2: Save the parsed scheme to the database curl -s -X POST http://localhost:5274/workflow-api/designer \ -F "operation=save" \ -F "schemecode=Approval" \ -F "data= WorkflowEngine Designer
``` Save this as `process.html` and serve it through a local HTTP server (opening directly from `file://` may not work due to browser security): ```bash npx serve . ``` Then open in your browser. The Designer loads the process instance and highlights its current activity. ## Step 4: Check available commands Before executing a command, you can check which commands are available for the current activity and user: ```bash curl -X POST http://localhost:5274/workflow-api/rpc/get-available-commands \ -H "Content-Type: application/json" \ -d '{ "processId": "a3f5b2c1-4d6e-7f8a-9b0c-1d2e3f4a5b6c", "identityIds": ["user-42"] }' ``` Response: ```json { "availableCommands": [ { "processId": "a3f5b2c1-4d6e-7f8a-9b0c-1d2e3f4a5b6c", "name": "Submit", "localizedName": "Submit", "parameters": [], "validForActivityName": "Draft", "validForStateName": "Draft", "isForSubprocess": false, "classifier": "Direct", "identities": [ "user-42" ] } ] } ``` The runtime returns only the commands whose conditions and rules permit the given identity. In this case, `Submit` is available because the process is at `Draft` and the transition has `Type="Always"` - no restrictions. ## Step 5: Execute a command Advance the process from `Draft` to `Approved` by executing the `Submit` command. The command is valid only while the process is at `Draft`: ```bash curl -X POST http://localhost:5274/workflow-api/rpc/execute-command \ -H "Content-Type: application/json" \ -d '{ "command": { "processId": "a3f5b2c1-4d6e-7f8a-9b0c-1d2e3f4a5b6c", "name": "Submit", "validForActivityName": "Draft" } }' ``` Verify the new state: ```bash curl -X POST http://localhost:5274/workflow-api/rpc/get-process-instance \ -H "Content-Type: application/json" \ -d '{ "processId": "a3f5b2c1-4d6e-7f8a-9b0c-1d2e3f4a5b6c" }' ``` Response: ```json { "processInstance": { "processId": "a3f5b2c1-4d6e-7f8a-9b0c-1d2e3f4a5b6c", "currentActivityName": "Approved", "currentState": "Approved", "schemeCode": "Approval" } } ``` The process moved to `Approved` - the workflow ran to completion. ## Step 6: Set state directly (optional) You can move a process instance to any activity directly, bypassing transitions and conditions. This is useful for error recovery or testing: ```bash curl -X POST http://localhost:5274/workflow-api/rpc/set-state-without-execution \ -H "Content-Type: application/json" \ -d '{ "processId": "a3f5b2c1-4d6e-7f8a-9b0c-1d2e3f4a5b6c", "stateName": "Draft" }' ``` The process is now back at `Draft` without executing any transitions. This can be useful for testing or recovering a process that reached an incorrect state. ## Step 7: Delete the process instance (optional) Delete the process instance and all its data when it is no longer needed: ```bash curl -X POST http://localhost:5274/workflow-api/rpc/delete-instance \ -H "Content-Type: application/json" \ -d '{ "processId": "a3f5b2c1-4d6e-7f8a-9b0c-1d2e3f4a5b6c" }' ``` This removes the process instance and all its subprocesses from the database. ## What you built - Defined a scheme with `Draft` and `Approved` activities, a `Submit` command, and a transition between them. - Uploaded the scheme XML to the Web API and saved it to the database. - Created a process instance and verified it was positioned at `Draft`. - Viewed the process instance in the Designer UI. - Checked which commands are available for a user. - Executed the `Submit` command and the process advanced to `Approved`. - Moved the process back to `Draft` using direct state control. - Deleted the process instance when it was no longer needed. ## Next steps - Web API Setup: Configure base path, connection strings, authentication, and Swagger for the Web API. - Web API Security: Restrict API access with JWT tokens, permissions, and tenant access control. - [Framework-Agnostic Install](https://docs.workflowengine.io/get-started/framework-agnostic-install/): Install Workflow Engine without ASP\.NET Core - for console apps, workers, and custom hosts. - [Core Concepts](https://docs.workflowengine.io/get-started/concepts/workflow-engine-concepts/): Learn schemes, activities, transitions, commands, timers, rules, and actions. ## Frequently asked questions **What is the minimum scheme XML needed to define a workflow?** A minimal scheme needs at least one command, an initial activity, a final activity, and a transition connecting them. The example on this page, a two-activity approval with Draft, Approved, and a single Submit command, is a complete working scheme. **How do I save a scheme through the Web API?** Send the XML file to the `designer` endpoint with `operation=uploadscheme` to parse it into JSON, then send the JSON back with `operation=save` to store it in the database. Both calls use the same endpoint - see Step 2 above for the exact commands. **How do I know my scheme was saved correctly?** Create a process instance through the Web API and check the current activity. If `POST /rpc/get-process-instance` returns the initial activity name in `currentActivityName`, the scheme was saved correctly. **How do I check which commands are available?** Use `POST /rpc/get-available-commands` with the `processId` and `identityIds` array. The runtime evaluates conditions and rules on each outgoing transition and returns only the commands the user is allowed to execute. **How do I advance a process from one activity to another?** Execute a command that triggers a transition. Use `POST /rpc/execute-command` with the command name and the activity where the command is valid. The command must match a `Command` element in the scheme, and the transition must have a trigger referencing that command. **How do I move a process to a specific activity without executing a transition?** Use `POST /rpc/set-state-without-execution` with the process ID and the target state name. The target activity must have `IsForSetState="true"` and a `State` attribute in the scheme. **How do I delete a process instance?** Use `POST /rpc/delete-instance` with the process ID. This removes the instance and all its subprocesses from the database. **Can I view a process instance in the Designer?** Yes. Create an HTML file that loads the WorkflowDesigner and call `designer.load()` with both `schemecode` and `processid` - see the example after Step 3 above. Serve the file through a local HTTP server.