# Run the workflow as a background process

**You’ll build a simple integration where a workflow is executed entirely in the background, without any user interface.** &#x20;

The example includes server-side code and shows how to create a workflow execution and run it programmatically in the background. The workflow executes asynchronously without rendering a user interface, and results can be retrieved via webhooks or API polling—making it easy to integrate into automated backend flows.

This approach is perfect for back-office processes like verifying business data, enriching records, or executing decision logic based on existing inputs—without interrupting the user journey or exposing a UI.

**Use this approach when:**

* No user input is needed to complete the workflow
* You're enriching existing records or verifying external data
* You want to automate internal or compliance-driven processes
* You're building batch jobs or backend workflows triggered by events

***

{% stepper %}
{% step %}

## Set up the server

### **Create a Workflow Execution**

**Add an endpoint on your server that creates a Workflow Execution**

{% hint style="danger" %}
We recommend creating a new execution each time a user starts a workflow, to ensure that the flow is fresh and state is isolated for every attempt.
{% endhint %}

{% tabs %}
{% tab title="JavaScript" %}
{% code lineNumbers="true" %}

```javascript
const express = require('express');
const axios = require('axios');
const { v4: uuidv4 } = require('uuid');

const app = express();
app.use(express.json());

async function getAccessToken() {

   const response = await axios.post("/authorize" .....)
   return response; 
   
}

app.post('/create-workflow-embedded', async (req, res) => {

  const executionPayload = {
    recordId: uuidv4(),
    workflowDefinitionId: uuidv4(),
  };

  const execution = await axios.post(
    'https://api.transactionlink.io/token',
    executionPayload,
    {
      headers: {
        Authorization: `Bearer ${response.data.accessToken}`,
        'Content-Type': 'application/json',
      },
    }
  );

  res.send({
    token: execution.data.token,
  });
});


app.get('/workflow-status', async (req, res) => {
  const executionId = req.query.execution_id;

  const workflow = await axios.get(
    `https://api.transactionlink.io/workflows/${executionId}`,
    {
      headers: {
        Authorization: `Bearer ${ACCESS_TOKEN}`,
      },
    }
  );

  res.send({
    status: workflow.data.status,
    executionId: execution.data.id,
  });
});

app.listen(8080, () => console.log('Running on port 8080'));
```

{% endcode %}
{% endtab %}
{% endtabs %}
{% endstep %}

{% step %}

## Get notified about workflow status

There are two ways to notify your backend when something happens in the workflow

#### 1. Webhook Task

You can add a **Webhook Task** directly in your workflow. This lets you send a custom HTTP POST request to your server at **any point** during the flow — with a payload you fully control.

Use it when:

* You want to notify your backend during a specific step in the process
* You need to trigger external logic or update another system
* You want to send dynamic data collected earlier in the flow
* You want to notify your server when the process is completed — with your own payload

{% hint style="info" %}
**Tip:** Place a Webhook Task at the end of the workflow to send a custom completion signal, including any relevant context or identifiers.
{% endhint %}

Both options can be used together or independently — depending on your use case.

#### 2. Polling the API (Long polling)

As an alternative, you can implement **long polling** from your backend. This involves periodically calling the TransactionLink API to check the status of a specific workflow execution.

While not real-time, long polling can be useful when:

* You cannot expose a public webhook endpoint
* Your infrastructure requires strict control over incoming connections
* You need fallback logic when webhooks are unavailable or blocked

{% hint style="danger" %}
Keep in mind: Webhooks (automatic or via task) are the recommended approach for real-time and scalable integration.
{% endhint %}
{% endstep %}

{% step %}

## Congratulations!

You’ve successfully set up a basic TransactionLink integration.

Now, learn how to **customize your workflow experience** — from styling the hosted page to configuring dynamic logic and automating data collection using workflow tasks and parameters.

{% endstep %}
{% endstepper %}
