.md

Getting started with workflows

Create your first automated workflow in the dcupl Console. This tutorial walks you through building a data processing pipeline using the visual editor.

What you'll build

flowchart LR
  T[Webhook Trigger] --> F[Fetch Products]
  F --> V{Validate}
  V -->|Valid| Tr[Transform]
  V -->|Invalid| L[Log Error]
  Tr --> R[Return Response]

A workflow that:

  1. Receives a webhook request with the number of products to fetch
  2. Fetches those products from a public sample API (dummyjson.com)
  3. Validates them: a product needs a title, a price and at least 50 items in stock
  4. Transforms the valid products
  5. Logs the invalid ones
  6. Returns the transformed products as JSON

Prerequisites

  • A dcupl Console account at console.dcupl.com
  • A project created in the Console, where you are an owner or editor (the Workflows menu isn't shown to viewers)
  • A runner instance available for deployment

Step 1: create a new workflow

  1. Open your project in the Console (the draft version)
  2. Click Workflows in the left sidebar
  3. On the Templates tab, click + (Create a new workflow template)
  4. Fill in the details:
    • Workflow Name: Product Sync
    • Workflow Key: product-sync
    • Description: Fetches and processes product data
    • Template: From Scratch (HTTP)
  5. Click Create Workflow

The workflow editor opens with the template: an HTTP Trigger connected to a Status Response. Click Edit Workflow to start editing.

Step 2: add a webhook trigger

  1. Open the HTTP Trigger node the template created (to add one yourself, drag HTTP Request from the Trigger section of the node palette)
  2. Configure the webhook:
    • Path: /products/sync
    • Methods: Select POST

Changes apply as you edit; you save the whole workflow in Step 8. This creates an endpoint that will trigger your workflow when it receives HTTP requests.

Step 3: add an HTTP Request node

  1. From the Nodes section of the palette, drag an HTTP Request node onto the canvas

  2. Connect the trigger's output port to the request node's input port

  3. Name it "Fetch Products", set Method to GET, and set URL to:

    {{variables.productsApiUrl}}?limit={{request.body.limit}}&select=title,price,stock
Note

{{variables.productsApiUrl}} reads a workflow variable, which you add in Step 7. {{request.body.limit}} reads the limit field of the webhook's JSON body; a run whose body has no limit fails at this node with Unresolved template placeholder {{request.body.limit}}.

Step 4: add validation logic

  1. Drag a Script node onto the canvas
  2. Connect the request node's main output to the script node
  3. Name it "Validate Products"
  4. On the node's Ports & Schema tab, click + Add Output twice to add the output ports valid and invalid
  5. In the script editor, check each product and send it to the matching port:
Validate Products
// The HTTP Request node emits one item: { body, headers, statusCode, ... }.
// The sample API answers { products: [...], total, skip, limit }.
const products = $json.first().body.products || [];
const isValid = (p) => Boolean(p.title) && p.price > 0 && p.stock >= 50;

return _output.route({
  valid: products.filter(isValid),
  invalid: products.filter((p) => !isValid(p)),
});

$json.first() is the first incoming item's data; $json() returns all of them. Returning a plain value or array sends it to the main port instead.

Step 5: add conditional routing

Route valid products

  1. Drag another Script node onto the canvas and name it "Transform Products"
  2. Connect the validation node's valid port to it
  3. Give it this script, which turns each valid product into the shape the response returns:
Transform Products
// One item per valid product arrives here
return $json().map((p) => ({ id: p.id, name: p.title, price: p.price, stock: p.stock }));

Route invalid products

  1. Drag a Script node onto the canvas and name it "Log Errors"
  2. Connect the validation node's invalid port to it
  3. Give it this script:
Log Errors
// One item per invalid product arrives here (none when every product is valid)
$json().forEach((p) => console.log('low stock', p.id, p.title, p.stock));

// End this branch without items, so it does not change what the run answers
return [];

console.log output is recorded when you test with Enable Data Trace (Step 9). A script that returns nothing passes its input on, and a branch that ends with items can become part of the run's answer, so the script returns an empty array.

Your workflow now has two parallel paths from the validation node. Connect every custom port that can receive items: items on an unconnected port go to the node's error port, and the run fails if that isn't connected either.

Watch out

Don't route with edge conditions: the editor lets you add a condition to an edge, but the workflow runner currently ignores it and passes every item through.

Step 6: configure the response

The template's Status Response node returns only the execution status (status, executionId, duration). To return the transformed products instead:

  1. Delete the Status Response node
  2. From the Response section of the palette, drag a Script Response node onto the canvas
  3. Connect the "Transform Products" node's main output to it
  4. Give it this script:
Script Response
// `data` holds the incoming items' JSON: the transformed products
return { count: data.length, products: data };

Return an object: what the script returns is the response body, and an array would arrive as an object with the keys "0", "1", ….

Step 7: add variables

Keep the API's base URL in a workflow variable, so you can point the workflow at another API without editing nodes.

  1. Click the key icon (Project Variables) in the workflow toolbar
  2. In Global Workflow Variables, add the variable:
    • Name: productsApiUrl
    • Value: https://dummyjson.com/products
  3. Click Add Variable

Variable values are masked in the list and encrypted with the runner's key when you deploy, so variables are also where API tokens belong (Bearer {{variables.apiToken}} in a header). Until productsApiUrl exists, Deploy stays disabled and offers Define Variables.

Step 8: save and deploy

Save your workflow

Click Save Changes in the toolbar.

Deploy to runner

  1. Select your target runner in the runner dropdown of the toolbar
  2. Click Deploy
  3. Wait for the runner's status to change to Up to date

Step 9: test your workflow

From the Console

  1. Click Execute in the toolbar — the Test Workflow panel opens on its New Test tab
  2. Enter { "limit": 5 } as the Request Body (JSON), and turn on Enable Data Trace to record the "Log Errors" output
  3. Click Start Test
  4. View the execution results below the form
  5. Open a node on the canvas to see its input and output data, or check the History tab for past runs

Using cURL

curl -X POST \
  'https://<runner-url>/v3/workflow/<project-id>-product-sync/products/sync' \
  -H 'Content-Type: application/json' \
  -d '{ "limit": 5 }'

The runner URL is shown on the Workflows page, and the deployed workflow key is your key prefixed with the project ID. The test panel's Request Preview shows the exact command. If you added API-key authentication to the trigger, also send the key in an api-key header.

Expected result

The run answers with what the Script Response returns. With the sample API's current data, four of the first five products have at least 50 items in stock; the fifth goes to "Log Errors":

Response
{
  "count": 4,
  "products": [
    { "id": 1, "name": "Essence Mascara Lash Princess", "price": 9.99, "stock": 99 },
    { "id": 3, "name": "Powder Canister", "price": 14.99, "stock": 89 },
    { "id": 4, "name": "Red Lipstick", "price": 12.99, "stock": 91 },
    { "id": 5, "name": "Red Nail Polish", "price": 8.99, "stock": 79 }
  ]
}

The sample data belongs to dummyjson.com and may change. The whole workflow as a template file is the example on the template reference.

Troubleshooting

Workflow not triggering

  • Verify the endpoint URL is correct
  • If the trigger has API-key authentication, check the key is sent in the api-key header
  • Ensure the runner status shows Up to date

Script errors

  • Open the failing node on the canvas to see its error and input data
  • Verify $json() returns data
  • Use console.log() in scripts and run the test with Enable Data Trace to capture the logs
  • Scripts time out after 500 ms by default

HTTP request failures

  • Check the target URL is accessible
  • Verify authentication headers are correct
  • Review the error output port for details

Connection issues

  • Ensure all required input ports are connected
  • Check that every output port that receives items is connected
  • Verify the workflow is saved and deployed (status Up to date)