> ## Documentation Index
> Fetch the complete documentation index at: https://docs.royaltyport.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Code

> Run custom Node.js or Python scripts in your automation workflows

## Overview

The Code step lets you run custom scripts with full programming flexibility. Use it when you need logic that goes beyond what the Transformer or Validator can do — custom calculations, calling external APIs with complex auth flows, parsing files, or any operation you'd write in a script.

Scripts run in an isolated sandbox with a **60-second timeout**. Each execution gets a clean environment, so there is no shared state between runs.

## Runtimes

| Runtime     | Version | Async Support                                                                |
| ----------- | ------- | ---------------------------------------------------------------------------- |
| **Node.js** | v22     | Top-level `await` works out of the box (scripts run inside an async wrapper) |
| **Python**  | 3.13    | Standard `async`/`await` with asyncio                                        |

## The `input` Object

Your script has access to a global `input` object that contains the full execution context:

* **Trigger data** — the event or manual payload that started the workflow
* **Previous step outputs** — results from all steps that ran before this one
* **Database records** — data from connected automation databases

```js theme={null}
// Node.js — access previous step output
const apiResponse = input.steps["fetch-data"].output.body;
const contractId = input.trigger.contract_id;
respond({ contractId, data: apiResponse });
```

```python theme={null}
# Python — access previous step output
api_response = input["steps"]["fetch-data"]["output"]["body"]
contract_id = input["trigger"]["contract_id"]
respond({"contract_id": contract_id, "data": api_response})
```

## Configuration

| Field       | Description                                            |
| ----------- | ------------------------------------------------------ |
| **Runtime** | Node.js or Python                                      |
| **Script**  | Your code in the built-in editor                       |
| **Auth**    | Optional JSON credentials secret for the script to use |

### Returning Output

Your script must call `respond(data)` to return output to the workflow. If the script completes without calling `respond()`, the step will fail.

```js theme={null}
// Node.js — return a result
const result = { processed: true, count: 42 };
respond(result);
```

```python theme={null}
# Python — return a result
result = {"processed": True, "count": 42}
respond(result)
```

To signal an error, pass a second argument:

```js theme={null}
respond(null, "Something went wrong");
```

### JSON Credentials

When you select **JSON Credentials** as the auth type and attach a secret, the credential file is written into the sandbox. Access the file path via the `CREDENTIALS_PATH` environment variable:

```js theme={null}
// Node.js — use JSON credentials
import { readFileSync } from "fs";

const creds = JSON.parse(readFileSync(process.env.CREDENTIALS_PATH, "utf8"));
// Use creds to authenticate with an external service
```

```python theme={null}
# Python — use JSON credentials
import json, os

with open(os.environ["CREDENTIALS_PATH"]) as f:
    creds = json.load(f)
# Use creds to authenticate with an external service
```

### Editor Features

The script editor includes:

* **Expand** — open the editor in a fullscreen dialog for more space
* **Generate with AI** — click the sparkle icon to have AI generate a script from a natural language description
* **Syntax highlighting** — JavaScript or Python highlighting based on the selected runtime

### Using Libraries

The script editor has built-in [library](/automations/libraries) integration. Click **Library** above the editor to load a saved script, or click **Save** to store the current script as a reusable library item. This is useful when the same logic is shared across multiple automations.

## Output

| Field     | Type    | Description                               |
| --------- | ------- | ----------------------------------------- |
| `data`    | any     | The data passed to `respond()`            |
| `success` | boolean | Whether the script completed successfully |
| `error`   | string  | Error message if the script failed        |
