# Retool Apify Integration - Run Actors & Return Data (`produkdigitalali/retool-apify-workflow-bridge`) Actor

Run Apify Actors and saved tasks from Retool, pass dynamic JSON input, wait synchronously or start asynchronously, and return normalized run status and dataset results for tables, forms, dashboards, and workflows.

- **URL**: https://apify.com/produkdigitalali/retool-apify-workflow-bridge.md
- **Developed by:** [ProdukDigitalAli](https://apify.com/produkdigitalali) (community)
- **Categories:**
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 workflow executions

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Retool Apify Integration - Run Actors & Return Data

Trigger Apify Actors or saved tasks from Retool, wait for completion when needed, and return one predictable JSON object that Retool can bind directly to tables, charts, forms, and workflows.

### Why use this Actor?

Retool can call REST APIs directly, but every Apify workflow otherwise needs repeated glue logic for run creation, waiting, status handling, dataset retrieval, errors, and result normalization. This bridge packages that workflow into one reusable Actor.

#### Use cases

- **Run an Apify Actor from a Retool button** and pass form/table values as JSON input.
- **Fill a Retool table with Apify dataset results** after a synchronous run finishes.
- **Start long-running workflows asynchronously** and keep a Retool row ID in `correlationId` for later polling or webhook logic.

### What it returns

Each bridge run emits one `WORKFLOW_RESULT` record and writes the same object to the default key-value store as `OUTPUT`.

Key fields include:

- `status`: `SUCCESS`, `STARTED`, `TARGET_FAILED`, `TIMEOUT`, or `ERROR`
- `targetType`, `targetId`
- `runId`, `runStatus`, `statusMessage`
- `startedAt`, `finishedAt`
- `defaultDatasetId`
- `datasetItemCountReturned`
- `datasetItems` (optional)
- `runConsoleUrl`, `datasetConsoleUrl`
- `correlationId`
- `errorType`, `errorMessage`

### How it works

1. Retool starts this bridge Actor using the Apify API.
2. The bridge launches the requested Actor or task.
3. In `sync` mode it waits for a terminal status, then optionally retrieves the target's default dataset.
4. It normalizes the workflow into one stable JSON object.
5. In `async` mode it returns immediately with the downstream `runId`.

### Minimal input

```json
{
  "targetType": "actor",
  "targetId": "apify~hello-world",
  "targetInput": {},
  "mode": "sync"
}
```

### Advanced input

```json
{
  "targetType": "actor",
  "targetId": "your-user~your-actor",
  "targetInput": {
    "startUrls": [{"url": "https://example.com"}],
    "maxItems": 20
  },
  "mode": "sync",
  "waitTimeoutSeconds": 180,
  "includeDatasetItems": true,
  "datasetLimit": 100,
  "datasetFields": ["title", "url"],
  "cleanDataset": true,
  "correlationId": "retool-row-123"
}
```

### Authentication and permissions

On Apify, the bridge first uses the scoped `APIFY_TOKEN` injected into the run. Limited-permission Actors can call other limited-permission Actors and obtain their results, so many public Actor workflows need no second token.

For a private Actor task or another target that the scoped run token cannot access, you can provide `apifyToken`. It is marked `isSecret: true`, encrypted by Apify, sent only in an Authorization header, and never intentionally written to logs or output.

A downstream full-permission Actor can still require the user's explicit approval in Apify Console.

### Sync vs async

#### Synchronous

Use for short workflows when Retool needs the result immediately. `waitTimeoutSeconds` supports up to 300 seconds; the bridge handles the Apify API's 60-second per-request wait limit internally.

#### Asynchronous

Use for long workflows. The bridge starts the target and returns `STARTED` plus `runId` immediately. `correlationId` can store a Retool row/workflow key.

### Errors are normalized

Common failures are returned as structured `errorType` values such as:

- `AUTH_ERROR`
- `INSUFFICIENT_PERMISSIONS`
- `FULL_PERMISSION_ACTOR_NOT_APPROVED`
- `NOT_FOUND`
- `RATE_LIMITED`
- `NETWORK_ERROR`
- `INVALID_RESPONSE`

The bridge does not charge its custom workflow event if the downstream run was never created.

### Pricing

The source defines one PPE event: `workflow-execution`, charged exactly once after Apify successfully creates the downstream run. Internal retries are never billed twice. Final Store pricing is set in Apify Console.

### Task examples

#### Run an Apify Actor from a Retool button

Use a Retool REST query to start this bridge and pass the current form/table values in `targetInput`.

#### Fill a Retool table with Apify dataset results

Use `mode: sync`, `includeDatasetItems: true`, and bind `OUTPUT.datasetItems` to your Retool table.

#### Start a long Apify workflow from Retool and correlate it later

Use `mode: async` and set `correlationId` to your Retool row or job identifier. The returned `runId` is suitable for later polling/webhook flows.

### Limitations

- This Actor does not create a native Retool plugin; it provides a standardized API workflow that Retool can call.
- Dataset retrieval uses the target Actor's default dataset only.
- In async mode dataset items are not retrieved because the target is still running.
- Private tasks or targets outside the scoped run token may require the optional encrypted token.
- The bridge does not bypass Apify permission approvals or downstream Actor pricing.

### API / MCP friendly

Inputs are bounded and outputs use deterministic field names, making the Actor suitable for Retool REST queries, API clients, automation platforms, and AI agents that need a simple "run -> wait -> retrieve -> normalize" operation.

# Actor input Schema

## `targetType` (type: `string`):

Run an Actor directly or a saved Actor task.

## `targetId` (type: `string`):

Actor ID/name such as apify~hello-world, or an Actor task ID/name when targetType=task.

## `targetInput` (type: `object`):

JSON input forwarded to the downstream Actor or task.

## `mode` (type: `string`):

sync waits for completion and can return dataset items; async returns immediately with the new run ID.

## `waitTimeoutSeconds` (type: `integer`):

Maximum wait in synchronous mode. The bridge polls safely beyond the API's 60-second per-request wait limit.

## `includeDatasetItems` (type: `boolean`):

When a synchronous target succeeds, include items from its default dataset in the normalized result.

## `datasetLimit` (type: `integer`):

Maximum number of downstream dataset items to return. Set 0 to skip dataset retrieval.

## `datasetFields` (type: `array`):

Optional field whitelist. Leave empty to return all fields.

## `cleanDataset` (type: `boolean`):

Skip hidden and empty fields/items when retrieving downstream dataset results.

## `correlationId` (type: `string`):

Optional Retool row/workflow identifier copied to the output for async correlation.

## `apifyToken` (type: `string`):

Usually leave blank: on Apify, the bridge uses the current scoped run token and can call limited-permission Actors. Provide a token only when your private task/target requires it. The value is encrypted and never logged.

## Actor input object example

```json
{
  "targetType": "actor",
  "targetId": "apify~hello-world",
  "targetInput": {
    "greeting": "Hello from Retool"
  },
  "mode": "sync",
  "waitTimeoutSeconds": 60,
  "includeDatasetItems": true,
  "datasetLimit": 100,
  "datasetFields": [],
  "cleanDataset": true,
  "correlationId": ""
}
```

# Actor output Schema

## `results` (type: `string`):

No description

## `summary` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "targetId": "apify~hello-world",
    "targetInput": {
        "greeting": "Hello from Retool"
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("produkdigitalali/retool-apify-workflow-bridge").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "targetId": "apify~hello-world",
    "targetInput": { "greeting": "Hello from Retool" },
}

# Run the Actor and wait for it to finish
run = client.actor("produkdigitalali/retool-apify-workflow-bridge").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "targetId": "apify~hello-world",
  "targetInput": {
    "greeting": "Hello from Retool"
  }
}' |
apify call produkdigitalali/retool-apify-workflow-bridge --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,produkdigitalali/retool-apify-workflow-bridge"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/HVSWKQif9eiTWTgFT/builds/sQug7efHFZk8bhLDf/openapi.json
