VectorCompose - Prototype: Technical Guide

Guide for the Vector Compose prototype.

Getting Started - Vector Compose

Intro

This document is a living document as we will update it along the development path. So keep an eye out for when the portal gets updated.

Vector Compose is a module part of the Print Manager. This module has its own API and is responsible for managing new vector based print jobs.

The current setup is an Alpha version and has a high chance of changing in the near future.

This module is not meant for production (yet) and its implementation will change a lot.

When it does change, we will update this document accordingly.

API

For the moment we are releasing the API defined as an OpenAPI contract. This OpenAPI contract is a document which describes what endpoint are available and how they should be addressed.

To interact with the API, you can use the test server: https://server.developer.bergstein.com

For quick testing of the API endpoints you can visit the Swagger page: https://server.developer.bergstein.com/swagger/index.html

Authenticating

To authenticate to a Print Manager server, you must first obtain an access token.

This access token is a JWT-token which must be added to the HTTP 'Authorization' header as a Bearer token.

An access token can be created from this endpoint: [POST] {baseServerUrl}/authentication_module/v1/token/access

In concrete terms, for the test server you can reach out to: https://server.developer.bergstein.com/authentication_module/v1/token/access

Then you can address any endpoint by adding the Bearer token like this:

curl -X 'GET' \
  'https://server.developer.bergstein.com/vectorcomposemanager_module/v1/worker' \
  -H 'accept: application/json' \
  -H 'manager-id: 1' \
  -H 'Authorization: Bearer eyJhbGciOiJodHRwOi...' <ADD TOKEN LIKE THIS>

Be mindful that the access token is valid for only 10 minutes. Before that time you need to either create a new access token, or refresh your current token with the RefreshToken on the refresh endpoint: 'authentication_module/v1/token/access'.

The actual login credentials can be requested at support@bergstein.com.

On to the practical application.

The printing procedure requires several API calls to complete. We will sketch out the workflow as follows under the assumption you are authenticated (i.e. have an access token) already.

Step 1 - Connecting

First up define a 'baseURL'. This is the root address of your PrintManager server.

When using the test server, you can use https://server.developer.bergstein.com/.

This base URL is always the same for all the API's and its endpoints.

To test the connection, its good to try and call the Health endpoint of any module using HTTP GET.

For example the VectorCompose module Health address is https://{baseURL}/vectorcompose_module/v1/health_checks.

Here we will give an example request using cURL, a popular CLI tool for making HTTP requests:

curl -X 'GET' \
  'https://server.developer.bergstein.com/vectorcompose_module/v1/health_checks' \
  -H 'accept: application/json'

The successful reply HTTP message, code 200 OK, is formulated as:

{
  "healthChecks": [
    {
      "name": "VC Manager - Id='1'",
      "status": "HEALTHY",
      "moduleName": "VectorComposeModuleV2"
    }
  ]
}

Step 2 - Determine Print Job

A print job is a special formulated SVG file stored in the Print Manager under a folder.

The format of the document will be {name_of_the_printjob.}{vc/vct}.svg.

A vc denotes a vector compose job, a vct denotes a template vector compose job which the customer uses as a reference to create/duplicate a production job from (with different images).

Only the vc is valid in production. So the file path suffix is always .vc.svg for production.

So eventually in production you will get a file like 1000000002.vc.svg.

This job will probably be stored in such a way its clear for the customer what job belong to what product/batch/process.

So for example you will get:

/Orders/
  |_ /CustomerA/ 
        |_ /Recipro/
            |_ type_ab_1.vct.svg
            |_ 1000000002.vc.svg
            |_ 1000000003.vc.svg
  |_ /CustomerB/ 
        |_ /Recipro/
            |_ type_ab_2.vct.svg
            |_ 1000000008.vc.svg
            |_ 1000000009.vc.svg
        |_ /Luftsagen
            |_ type_ab_3vct.svg
            |_ 1000000015.vc.svg

So when a customer enters/scans a barcode, its presumed we will eventually perform a lookup of the job on the API.

To check the available files you need to address the File Module (V2).

The endpoint to discover what folders and files are stored at a given URI is:

So to check what files are available you can check the test server for the 1000000002.vc.svg file.

We activate the Find method with includeHidden=false to omit some hidden process folders and we add exact=true to force the result to be exactly 1 item. If there is 0 or more than 1 item you will get a 409 with the detail 'Exact find expected one result, but found X."'

So we make a call like this;

curl -X 'GET' \
  'https://server.developer.bergstein.com/file_module/v2/explore/find?searchTerm=1000000002.vc.svg&includeHidden=false&exact=true' \
  -H 'accept: application/json' \
  -H 'Authorization: Bearer eyJhbGciOiJodHRwOi8vd3d3Lncz...

Then you will get a reply like this:

{
  "uris": [
    "/Orders/Bahco/Recipro/1000000002/1000000002.vc.svg"
  ]
}

Here you can see there is one production ready file located at "/Orders/Bahco/Recipro/1000000002/1000000002.vc.svg".

Step 3 - Start a Print Job

With this full job name in hand, e.g. filepath "/Orders/Bahco/Recipro/1000000002/1000000002.vc.svg" (and you need the exact path!), you will activate the HTTP POST API endpoint on URL: https://server.developer.bergstein.com/vectorcomposemanager_module/v1/start_load_worker;

For example a request can be:

curl -X 'POST' \
  'https://server.developer.bergstein.com/vectorcomposemanager_module/v1/start_load_worker' \
  -H 'accept: application/json' \
  -H 'manager-id: 1' \
  -H 'Authorization: Bearer eyJhbGciOiJodHRwOi8vd3d3Lnc...' \
  -H 'Content-Type: application/json' \
  -d '{
  "referenceId": "1d92d6f0-00dd-49d9-b204-b8d7d3bc299f",
  "svgUrl": "/examples/test2.vc.svg"
}'

If the endpoint succeeds you will get a response message like this:

{
  "success": true
}

Now you've started a worker with your provided id (e.g. 1d92d6f0-00dd-49d9-b204-b8d7d3bc299f) with a certain job (e.g. "/examples/test2.vc.svg").

To view all running workers you can address endpoint /vectorcomposemanager_module/v1/worker like this:

curl -X 'GET' \
  'https://server.developer.bergstein.com/vectorcomposemanager_module/v1/worker' \
  -H 'accept: application/json' \
  -H 'manager-id: 1' \
  -H 'Authorization: Bearer eyJhbGciOiJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzA0L3htbGRzaWctbW

Then you will get a response like:

{
  "workers": [
    {
      "referenceId": "1d92d6f0-00dd-49d9-b204-b8d7d3bc299f",
      "createdDateTimeUtc": "2026-06-22T10:25:02Z",
      "inputPath": "/.workers/1d92d6f0-00dd-49d9-b204-b8d7d3bc299f/input/",
      "outputPath": "/.workers/1d92d6f0-00dd-49d9-b204-b8d7d3bc299f/output/"
    },
    {
      "referenceId": "a9509052-65ae-4d4d-84c4-ab596cac2a47",
      "createdDateTimeUtc": "2026-06-22T09:22:56Z",
      "inputPath": "/.workers/a9509052-65ae-4d4d-84c4-ab596cac2a47/input/",
      "outputPath": "/.workers/a9509052-65ae-4d4d-84c4-ab596cac2a47/output/"
    }
  ]
}

Step 4 - Getting metadata

During production, some extra job related data may be required. When a Job(Template) is created, the user/operator can add and fill-out Variables which are embedded in the Job file.

To read out the Variable value you can activate the plugin action of the VariablesPlugin by doing a HTTP POST on endpoint https://{baseURL}/vectorcomposeworker_module/v1/plugin/actions.

Keep in mind that you have to add headers to specific the VectorCompose-Manager and the Worker instance in question by appending HTTP header like worker-id=1d92d6f0-00dd-49d9-b204-b8d7d3bc299f and manager-id=1.

The request body to get a certain Variable, for example product_length, like this.

{
  "pluginActions": [
    {
      "pluginName": "VariablesPlugin",
      "parameters": [
        {
          "name": "actionName",
          "value": "getVariable"
        },
        {
          "name": "id",
          "value": "product_length"
        }
      ]
    }
  ]
}

But if you need multiple variables, instead of chaining single calls, you can make one call like this:

{
  "pluginActions": [
    {
      "pluginName": "VariablesPlugin",
      "parameters": [
        { "name": "actionName", "value": "getVariables" },
        {
          "name": "names",
          "value": "[\"order_number\",\"job_name\",\"product_type\",\"product_name\",\"product_length\",\"product_width\",\"layout_type\",\"mask_type\",\"camera_program_type\"]"
        }
      ]
    }
  ]
}

This will return something like:

{
  "results": [
    {
      "pluginName": "VariablesPlugin",
      "action": "getVariables",
      "parameters": [],
      "result": "{\"order_number\":\"1000000002\",\"job_name\":\"Recipro-3021_225#Bahco\",\"product_type\":\"Recipro\",\"product_name\":\"Recipro-3021_225\",\"product_length\":\"229\",\"product_width\":\"19\",\"layout_type\":\"3x2\",\"mask_type\":\"4x4\",\"camera_program_type\":\"CameraProgTestBahco\"}",
      "success": true
    }
  ]
}

Step 5 - Updating positions and rotations

To update/interact with a given Job Instance you should activate the same HTTP POST endpoint https://{baseURL}/vectorcomposeworker_module/v1/plugin/actions.

To make sure you are correctly addressing the worker, you need to add an HTTP header called worker-id with the value of the referenceId which you've set using the previous step.

So you will append an HTTP header like worker-id=1d92d6f0-00dd-49d9-b204-b8d7d3bc299f.

Also don't forget to set the manager-id to 1 to indicate what manager app to use (for now this is always 1).

Finally in the request body you provide the actions which you want to perform on this job instance/worker.

Again setting variables can be done one-by-one;

{
  "pluginActions": [
    {
      "pluginName": "VariablesPlugin",
      "parameters": [
        {
          "name": "actionName",
          "value": "setVariable"
        },
        {
          "name": "id",
          "value": "p1_transform"
        },
        {
          "name": "value",
          "value": "translate(100,50) rotate(5)"
        }
      ]
    },
    {
      "pluginName": "VariablesPlugin",
      "parameters": [
        {
          "name": "actionName",
          "value": "setVariable"
        },
        {
          "name": "id",
          "value": "p1_disable"
        },
        {
          "name": "value",
          "value": "false"
        }
      ]
    },
    {
      "pluginName": "VariablesPlugin",
      "parameters": [
        {
          "name": "actionName",
          "value": "setVariable"
        },
        {
          "name": "id",
          "value": "p2_transform"
        },
        {
          "name": "value",
          "value": "translate(150,150) rotate(-10.4)"
        }
      ]
    },
        {
      "pluginName": "VariablesPlugin",
      "parameters": [
        {
          "name": "actionName",
          "value": "setVariable"
        },
        {
          "name": "id",
          "value": "p2_disable"
        },
        {
          "name": "value",
          "value": "false"
        }
      ]
    }
  ]
}

Then you will receive an response like:

{
  "results": [
    {
      "pluginName": "VariablesPlugin",
      "action": "setVariable",
      "parameters": [],
      "result": "",
      "success": true
    },
    {
      "pluginName": "VariablesPlugin",
      "action": "setVariable",
      "parameters": [],
      "result": "",
      "success": true
    },
    {
      "pluginName": "VariablesPlugin",
      "action": "setVariable",
      "parameters": [],
      "result": "",
      "success": true
    },
    {
      "pluginName": "VariablesPlugin",
      "action": "setVariable",
      "parameters": [],
      "result": "",
      "success": true
    }
  ]
}

Or you can update many at once with the setVariables action like this;

{
  "pluginActions": [
    {
      "pluginName": "VariablesPlugin",
      "parameters": [
        { "name": "actionName", "value": "setVariables" },
        {
          "name": "variables",
          "value": "{\"p1_transform\":\"translate(46,1.75) rotate(5)\",\"p1_disable\":\"false\",\"p2_transform\":\"translate(86,1.75) rotate(-2.1)\",\"p2_disable\":\"false\"}"
        }
      ]
    }
  ]
}

With a success response like:

{
  "results": [
    {
      "pluginName": "VariablesPlugin",
      "action": "setVariables",
      "parameters": [],
      "result": "true",
      "success": true
    }
  ]
}

As you can see we are setting the value of product 1 (P1) and product 2 (P2) to have a certain translate and movement value.

The translate values are in millimeters. A . is used to denote a fractional value. The first value in the translate() is the X-axis and the second the Y-axis. The coordinate system is screen space coordinates. So the 0,0 point is to the top left, going positive to the right (X+) and positive down (Y+).

So for example translate(100,50) means, move the image 100mm to the right and 50mm down.

The rotation value is oriented on the top left using the same coordinate system. A positive angle moves the image from quadrant 1 to quadrant 4 (Clockwise). A negative angle moves the image from quadrant 1 to quadrant 2 (Counter-clockwise).

The angle value is in degrees. The value is formatted the same way as the translate does.

So for example rotate(-10.4) means rotate the image 10,4 degrees upward.

If you want to check resulting the file you can dump the SVG using the SaveLoadPlugin action like this:

curl -X 'POST' \
  'https://server.developer.bergstein.com/vectorcomposeworker_module/v1/plugin/actions' \
  -H 'accept: application/json' \
  -H 'worker-id: 1d92d6f0-00dd-49d9-b204-b8d7d3bc299f' \
  -H 'manager-id: 1' \
  -H 'Authorization: Bearer eyJhbGciOiJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzA0L...' \
  -H 'Content-Type: application/json' \
  -d '{
  "pluginActions": [
    {
      "pluginName": "SaveLoadPlugin",
      "parameters": [
        {
          "name": "actionName",
          "value": "saveSvg"
        }
      ]
    }
  ]
}'

Then a document.svg is exported on the worker folder which you can retrieve by doing a file download on that folder for that file. The folder structure is setup like /.workers/{workerid}/output/document.svg.

So initiating a download request like this:

curl -X 'POST' \
  'https://server.developer.bergstein.com/file_module/v2/files/download' \
  -H 'accept: application/json' \
  -H 'Authorization: Bearer eyJhbGciOiJodHRwOi8vd3d3LnczLm9...' \
  -H 'Content-Type: application/json' \
  -d '{
  "downloadBytes": {
    "uri": "/.workers/1d92d6f0-00dd-49d9-b204-b8d7d3bc299f/output/document.svg"
  }
}'

Will result in a file response (base64 encoded) like this:

{
  "metadata": {
    "audit": {
      "CreatedByUserName": "Admin",
      "CreatedDateTimeUtc": "2026-06-22T11:11:56Z",
      "UpdatedByUserName": "Admin",
      "UpdatedDateTimeUtc": "2026-06-22T11:11:56Z"
    },
    "id": "44ae9a74-35de-48c5-b016-140b3704a8ef",
    "name": "document.svg",
    "uri": "/.workers/1d92d6f0-00dd-49d9-b204-b8d7d3bc299f/output/document.svg",
    "nodeType": "NODE_TYPE_FILE",
    "permissions": [],
    "size": 4080343,
    "contentType": "application/octet-stream",
    "hashType": "MD5",
    "hashValue": "974B950DB6F989AC71D10A86FE9EF1FA",
    "etag": "974B950DB6F989AC71D10A86FE9EF1FA"
  },
  "fileData": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB4bWxucz0iaHR0cD..."
}

When you put the base64 fileData into a file, it should reconstitute the SVG.

Step 6 - Sending job to printer

When the load action of the products into the printer starts, you can call the send action on the appropriate job/worker instance.

You call the same HTTP POST endpoint https://{baseURL}/vectorcomposeworker_module/v1/plugin/actions.

But the request body changes to:

{
  "pluginActions": [
    {
      "pluginName": "DigiGen3Plugin",
      "parameters": [
        {
          "name": "actionName",
          "value": "createAndSendDjob"
        }
      ]
    }
  ]
}

If all went well you should get a response like this:

{
  "results": [
    {
      "pluginName": "DigiGen3Plugin",
      "action": "createAndSendDjob",
      "parameters": [],
      "result": "",
      "success": true
    }
  ]
}

Now the Job is loaded into the printer and it will queue it for printing.

Step 7 - Cleanup

After sending the Job Instance/worker will remain alive for up to 1 hour. However this will consume resources on the Print Manager server.

Therefore its recommended to stop the Job Instance/Worker after you've send the job.

To do so you call the HTTP POST endpoint https://{baseURL}/vectorcomposemanager_module/v1/stop_worker.

Like doing:

curl -X 'POST' \
  'https://server.developer.bergstein.com/vectorcomposemanager_module/v1/stop_worker' \
  -H 'accept: application/json' \
  -H 'worker-id: 1d92d6f0-00dd-49d9-b204-b8d7d3bc299f' \
  -H 'manager-id: 1' \
  -H 'Authorization: Bearer eyJhbGciOiJodHRwOi8vd3d3LnczLm9yZy8...' \
  -H 'Content-Type: application/json' \
  -d '{}'

That will yield:

{
  "success": true
}

Closing thoughts

We will keep you posted. If you need help please let us know!

Back to documents