Deployment Automation

<< Click to Display Table of Contents >>

Navigation:  Low-code Process Automation > Automation - Test and Production environments > From Studio to Automation Service > Deployment >

Deployment Automation

Overview

The Deployment Automation API allows you to export and import Bizagi deployment packages (.bex files) using REST endpoints instead of performing deployments manually through the Management Console (MC).

 

Using this API, you can integrate Bizagi deployments into automated workflows such as scripts, CI/CD pipelines, or API clients. All deployment operations run asynchronously. When a request is submitted, the API immediately returns an execution identifier that you can use to monitor progress until the operation completes.

 

How it works

The Deployment Automation API exposes endpoints to:

Export a deployment package from a Development environment.

Monitor the export execution and retrieve the download URL for the generated package.

Import a deployment package into a Test or Production environment.

Monitor the import execution status.

 

Each operation is executed asynchronously and tracked using an ExecutionId returned by the API.

 

Generating an API Key

Requests to the Deployment Automation API require an API Key.

 

To generate an API Key in the Management Console:

1.Expand the External Access drop down menu.

2.Select API Key Configuration.

 

DeploymentAutomation01

 

3.Enable the API Key using the Enabled toggle switch.

4.Click the calendar button to select the expiration date.

5.Click Create a new API Key.

 

DeploymentAutomation02

 

6.Confirm the action in the pop up window that appears.

 

DeploymentAutomation03

 

note_pin

The API Key is displayed once. We strongly recommend copying it and storing it securely.

 

Consuming the API

Exporting a deployment package

The Export endpoint generates a .bex deployment package in a Development environment.

 

Key characteristics

Triggered using a POST request.

Requires a JSON request body defining the content to export.

Runs asynchronously.

Returns an ExecutionId used to track progress.

 

Endpoint

POST /api/external/v1/deployment/Export

 

Headers

Authorization: Bearer <API_KEY>

Content-Type: application/json

 

Request Body

JSON object describing the deployment configuration.

The FileName field is required.

The Type field must be either Deployment or MicroDeployment.

 

note_pin

Before calling the API, use Bizagi Studio to obtain the JSON file by following these steps:

 

1.Go to the Export/Import menu.

2.Select Share Processes in the Export section.

 

DeploymentAutomation05

 

3.Configure the export settings by selecting the components you want to include, then click the Download button.

 

DeploymentAutomation06

 

The file content can be used directly as the request body for automated exports.

 

Example:

Request

Response

Notes

{
"Workflows": [
{
"DisplayName": "MyProcess",
"Version": "1.0",
"Id": "uuid"
}
],
"FileName": "MyDeployment",
"Type": "Deployment"
}

{
"ExecutionId": "f1e2d3c4-...",
"Status": "Started",
"Message": "Export package process started successfully"
}

 

When the request is received, Bizagi validates the data and verifies that no other export operation is currently running. If validation succeeds, the export starts asynchronously.

 

Use the returned ExecutionId to monitor the export execution.

 

Monitoring export execution and retrieving the package

The ExportStatus endpoint checks the current state of the export and, once finished, obtains the download URL for the .bex file.

 

Endpoint

GET /api/external/v1/deployment/ExportStatus/{executionId}

 

Headers

Authorization: Bearer <API_KEY>

 

Request body

Not required.

 

Export states

The Export operation can return the following states:

Started: Request accepted.

Running: Export in progress.

Done: Export completed successfully.

Error: Export failed.

 

While the status is Started or Running, continue polling the endpoint until the status changes.

 

Response body (completed export)

{
"Status": "Done",
"SasUrlToken": "https://storage...MyDeployment.bex?...",
"ExpiryTime": "2024-01-15T11:40:00Z"
}

 

note_pin

The SasUrlToken is a temporary download URL that expires automatically. The .bex file is downloaded when the URL is accessed. This URL is used during the Import step.

 

Importing a deployment package

The Import endpoint applies a previously generated .bex package to a Test or Production environment.

 

Key characteristics

Triggered using a POST request.

Requires a JSON request body.

Uses the SAS URL generated during export.

Runs asynchronously.

Returns a new ExecutionId.

 

Endpoint

POST /api/external/v1/deployment/Import

 

Headers

Authorization: Bearer <API_KEY>
Content-Type: application/json

 

Request body

JSON object containing the SAS URL and an optional password.

 

Example:

Request

Response

Note

{
"SasUrlToken": "<SAS_URL_FROM_EXPORT>",
"Password": "optional"
}

{
"ExecutionId": "a9b8c7d6-...",
"Status": "Started",
"Message": "Import package process started successfully"
}

When the request is submitted, Bizagi downloads the .bex file using the provided URL, validates the package, and starts the deployment asynchronously.

 

Monitoring import execution

The ImportStatus endpoint allows you to monitor the progress of an import operation until it completes or fails.

 

Endpoint

GET /api/external/v1/deployment/ImportStatus/{executionId}

 

Headers

Authorization: Bearer <API_KEY>

 

Import states

The Import operation can return the following states:

Started: Request accepted.

Running: Deployment in progress.

Done: Deployment completed successfully.

Error: Deployment failed. If the deployment fails, the response includes a message explaining the reason.

 

Interacting with the API using an external tool

When using an API client (such as Bruno):

1.Create a request using the appropriate HTTP method and endpoint URL.

2.Add the request body for your Import or Export operation.

 

DeploymentAutomation07

 

3.Add the Authorization header with your API Key.

 

DeploymentAutomation08

 

4.Send the request to obtain the ExecutionId.

 

DeploymentAutomation09

 

5.Create a second request (ExportStatus or ImportStatus) to poll the execution progress.

6.Pass the ExecutionId as a path parameter.

 

DeploymentAutomation10

 

7.Send the request.

 

DeploymentAutomation11

 

Automation examples

The following examples show how the Deployment Automation API can be used as part of automated workflows, such as scripts or CI/CD pipelines.

 

These examples are provided for reference purposes.

 

PowerShell

# Configuration
$devApiKey = $env:BIZAGI_DEV_API_KEY
$testApiKey = $env:BIZAGI_TEST_API_KEY
$devBaseUrl = "https://dev.mybizagi.com/api/external/v1/deployment"
$testBaseUrl = "https://test.mybizagi.com/api/external/v1/deployment"
 
# Headers
$devHeaders = @{
   "Authorization" = "Bearer $devApiKey"
   "Content-Type" = "application/json"
}
 
$testHeaders = @{
   "Authorization" = "Bearer $testApiKey"
   "Content-Type" = "application/json"
}
 
# 1. Start Export
Write-Host "Starting export..."
$exportConfig = Get-Content -Path "export-config.json" -Raw
$exportResponse = Invoke-RestMethod -Uri "$devBaseUrl/Export" -Method Post -Headers $devHeaders -Body $exportConfig
$exportExecutionId = $exportResponse.ExecutionId
 
Write-Host "Export started. ExecutionId: $exportExecutionId"
 
# 2. Monitor Export
do {
   Start-Sleep -Seconds 5
   $exportStatus = Invoke-RestMethod -Uri "$devBaseUrl/ExportStatus/$exportExecutionId" -Method Get -Headers $devHeaders
   Write-Host "Export status: $($exportStatus.Status) - $($exportStatus.Message)"
} while ($exportStatus.Status -eq "Started" -or $exportStatus.Status -eq "Running")
 
if ($exportStatus.Status -ne "Done") {
   Write-Error "Export failed: $($exportStatus.Message)"
   exit 1
}
 
$sasUrl = $exportStatus.SasUrlToken
Write-Host "Export completed. SAS URL obtained."
 
# 3. Start Import
Write-Host "Starting import into Test environment..."
$importConfig = @{
   SasUrlToken = $sasUrl
   Password = "SecurePass123"
} | ConvertTo-Json
 
$importResponse = Invoke-RestMethod -Uri "$testBaseUrl/Import" -Method Post -Headers $testHeaders -Body $importConfig
$importExecutionId = $importResponse.ExecutionId
 
Write-Host "Import started. ExecutionId: $importExecutionId"
 
# 4. Monitor Import
do {
   Start-Sleep -Seconds 10
   $importStatus = Invoke-RestMethod -Uri "$testBaseUrl/ImportStatus/$importExecutionId" -Method Get -Headers $testHeaders
   Write-Host "Import status: $($importStatus.Status) - $($importStatus.Message)"
} while ($importStatus.Status -eq "Started" -or $importStatus.Status -eq "Running")
 
if ($importStatus.Status -ne "Done") {
   Write-Error "Import failed: $($importStatus.Message)"
   exit 1
}
 
Write-Host "Automated deployment completed successfully!"
``

 

Python

import os
import time
import json
import requests
from typing import Optional
 
# Configuration
DEV_API_KEY = os.getenv('BIZAGI_DEV_API_KEY')
TEST_API_KEY = os.getenv('BIZAGI_TEST_API_KEY')
DEV_BASE_URL = 'https://dev.mybizagi.com/api/external/v1/deployment'
TEST_BASE_URL = 'https://test.mybizagi.com/api/external/v1/deployment'
 
 
def get_headers(api_key: str) -> dict:
   return {
       'Authorization': f'Bearer {api_key}',
       'Content-Type': 'application/json'
   }
 
 
def start_export(base_url: str, api_key: str, config: dict) -> str:
   """Starts an export operation and returns the ExecutionId"""
   print('Starting export...')
   response = requests.post(
       f'{base_url}/Export',
       headers=get_headers(api_key),
       json=config
   )
   response.raise_for_status()
   execution_id = response.json()['ExecutionId']
   print(f'Export started. ExecutionId: {execution_id}')
   return execution_id
 
 
def poll_export_status(base_url: str, api_key: str, execution_id: str) -> str:
   """Polls the export until completion and returns the SAS URL"""
  while True:
       time.sleep(5)
       response = requests.get(
           f'{base_url}/ExportStatus/{execution_id}',
           headers=get_headers(api_key)
       )
       response.raise_for_status()
       status = response.json()
 
       print(f"Export status: {status['Status']} - {status['Message']}")
 
      if status['Status'] == 'Done':
           return status['SasUrlToken']
       elif status['Status'] == 'Error':
          raise Exception(f"Export failed: {status['Message']}")
 
 
def start_import(
   base_url: str,
   api_key: str,
   sas_url: str,
   password: Optional[str] = None
) -> str:
   """Starts an import operation and returns the ExecutionId"""
   print('Starting import...')
   config = {'SasUrlToken': sas_url}
  if password:
       config['Password'] = password
 
   response = requests.post(
       f'{base_url}/Import',
       headers=get_headers(api_key),
       json=config
   )
   response.raise_for_status()
   execution_id = response.json()['ExecutionId']
   print(f'Import started. ExecutionId: {execution_id}')
   return execution_id
 
 
def poll_import_status(base_url: str, api_key: str, execution_id: str):
   """Polls the import until completion"""
  while True:
       time.sleep(10)
       response = requests.get(
           f'{base_url}/ImportStatus/{execution_id}',
           headers=get_headers(api_key)
       )
 
      if response.status_code == 404:
          raise Exception('Import execution not found')
 
       response.raise_for_status()
       status = response.json()
 
       print(f"Import status: {status['Status']} - {status['Message']}")
 
      if status['Status'] == 'Done':
           return
       elif status['Status'] == 'Error':
          raise Exception(f"Import failed: {status['Message']}")
 
 
def main():
   # 1. Load export configuration
  with open('export-config.json', 'r') as f:
       export_config = json.load(f)
 
   # 2. Execute export
   export_execution_id = start_export(
       DEV_BASE_URL,
       DEV_API_KEY,
       export_config
   )
   sas_url = poll_export_status(
       DEV_BASE_URL,
       DEV_API_KEY,
       export_execution_id
   )
   print('Export completed. SAS URL obtained.')
 
   # 3. Execute import
   import_execution_id = start_import(
       TEST_BASE_URL,
       TEST_API_KEY,
       sas_url,
       'SecurePass123'
   )
   poll_import_status(
       TEST_BASE_URL,
       TEST_API_KEY,
       import_execution_id
   )
 
   print('Automated deployment completed successfully!')
 
 
if __name__ == '__main__':
   main()

 

Bash (using curl)

#!/bin/bash
set -e
 
# Configuration
DEV_API_KEY="${BIZAGI_DEV_API_KEY}"
TEST_API_KEY="${BIZAGI_TEST_API_KEY}"
DEV_BASE_URL="https://dev.mybizagi.com/api/external/v1/deployment"
TEST_BASE_URL="https://test.mybizagi.com/api/external/v1/deployment"
 
# Function to start export
start_export() {
   echo "Starting export..."
   response=$(curl -s -X POST "${DEV_BASE_URL}/Export" \
       -H "Authorization: Bearer ${DEV_API_KEY}" \
       -H "Content-Type: application/json" \
       -d @export-config.json)
 
   execution_id=$(echo $response | jq -r '.ExecutionId')
   echo "Export started. ExecutionId: ${execution_id}"
   echo $execution_id
}
 
# Function to monitor export
wait_for_export() {
   local execution_id=$1
   local status="Started"
 
   while [[ "$status" == "Started" || "$status" == "Running" ]]; do
       sleep 5
       response=$(curl -s -X GET "${DEV_BASE_URL}/ExportStatus/${execution_id}" \
           -H "Authorization: Bearer ${DEV_API_KEY}")
 
       status=$(echo $response | jq -r '.Status')
      message=$(echo $response | jq -r '.Message')
       echo "Export status: ${status} - ${message}"
   done
 
  if [[ "$status" != "Done" ]]; then
       echo "Export failed: ${message}"
       exit 1
   fi
 
   sas_url=$(echo $response | jq -r '.SasUrlToken')
   echo $sas_url
}
 
# Function to start import
start_import() {
   local sas_url=$1
   echo "Starting import into Test environment..."
 
   response=$(curl -s -X POST "${TEST_BASE_URL}/Import" \
       -H "Authorization: Bearer ${TEST_API_KEY}" \
       -H "Content-Type: application/json" \
       -d "{\"SasUrlToken\": \"${sas_url}\", \"Password\": \"SecurePass123\"}")
 
   execution_id=$(echo $response | jq -r '.ExecutionId')
   echo "Import started. ExecutionId: ${execution_id}"
   echo $execution_id
}
 
# Function to monitor import
wait_for_import() {
   local execution_id=$1
   local status="Started"
 
   while [[ "$status" == "Started" || "$status" == "Running" ]]; do
       sleep 10
       response=$(curl -s -X GET "${TEST_BASE_URL}/ImportStatus/${execution_id}" \
           -H "Authorization: Bearer ${TEST_API_KEY}")
 
       status=$(echo $response | jq -r '.Status')
      message=$(echo $response | jq -r '.Message')
       echo "Import status: ${status} - ${message}"
   done
 
  if [[ "$status" != "Done" ]]; then
       echo "Import failed: ${message}"
       exit 1
   fi
}
 
# Main script
main() {
   # 1. Export
   export_execution_id=$(start_export)
   sas_url=$(wait_for_export "$export_execution_id")
   echo "Export completed. SAS URL obtained."
 
   # 2. Import
   import_execution_id=$(start_import "$sas_url")
   wait_for_import "$import_execution_id"
 
   echo "Automated deployment completed successfully!"
}
 
main

 

CI/CD integration (Azure DevOps)

# azure-pipelines.yml
trigger:
 branches:
   include:
     - main
 
variables:
 # Variable group containing DEV_API_KEY and TEST_API_KEY
 - group: bizagi-api-keys
 
stages:
 - stage: Export
   displayName: 'Export from Development'
   jobs:
     - job: ExportPackage
       displayName: 'Export Deployment Package'
       pool:
         vmImage: 'ubuntu-latest'
       steps:
         - task: PowerShell@2
           displayName: 'Export and Monitor'
           inputs:
             targetType: 'inline'
             script: |
               $headers = @{

 

Export configuration file (export-config.json)

{
 "Workflows": [
   {
     "DisplayName": "MyProcess",
     "Version": "1.0",
     "Id": "4e2ce804-9c19-4e29-966c-142663906715"
   }
 ],
 "ExperienceObjects": [],
 "Options": {
   "SubProcess": true,
   "EnvironmentParamsValue": true,
   "Business configuration": true,
   "Holidays": false,
   "Dimensions": false,
   "Themes": true,
   "Usergroups": true,
   "Workcalendar": true,
   "Custom job": true,
   "User Properties": false,
   "AuthOption": false,
   "Assemblies": false,
   "Oauth2 configuration": false,
   "Organization": false,
   "Org Tables": {
     "Position": false,
     "Skills": false,
     "Location": false,
     "Area": false,
     "Role": false,
     "Organization": false
   }
 },
 "Trigger": [],
 "Description": "Automated deployment from CI/CD",
{

 

Important considerations

Only one Export and one Import operation can run at a time per environment.

Download URLs must be accessed before their expiration time.

Importing files from external public links is not allowed.

Data synchronization is not included in the deployment process.


Last Updated 7/19/2026 6:54:25 PM