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

# Transform webhook payloads with custom JavaScript

> Use the customScript input to normalize, enrich, or redact webhook payloads with an inline JavaScript snippet before the event is stored.

The `customScript` input lets you run an inline JavaScript snippet against every captured event before it is written to storage. Use it to normalize payloads from different providers, strip PII, inject debug metadata, or remap fields — all without modifying the sender or adding a separate processing step.

## How scripts run

Each script executes inside a sandboxed worker thread. The worker is shared for the lifetime of the actor run, so the sandbox is persistent but isolated from the main server process. The runtime enforces a bounded execution timeout and memory ceiling so a runaway script cannot block request handling or exhaust host resources.

If a script fails or times out, the error is logged and the webhook capture continues normally — the event is still stored and the sender still receives the configured response.

## Script context

Your script receives four injected values:

| Name          | Type   | Description                                                                                      |
| ------------- | ------ | ------------------------------------------------------------------------------------------------ |
| `event`       | object | The mutable captured event. Mutate this object to change what gets stored.                       |
| `req`         | object | A read-only snapshot of the incoming request. Changes to this object have no effect.             |
| `console`     | object | A safe `console` with `log`, `warn`, `error`, and `debug` methods. Output goes to the actor log. |
| `HTTP_STATUS` | object | A map of named HTTP status codes for readable comparisons (e.g., `HTTP_STATUS.OK === 200`).      |

### The `event` object

These fields on `event` are writable and affect what is stored:

| Field         | Type             | Description                                                                                    |
| ------------- | ---------------- | ---------------------------------------------------------------------------------------------- |
| `body`        | string \| object | The request body. Replace or mutate this to change the stored payload.                         |
| `headers`     | object           | The request headers as a key-value map. Add, remove, or overwrite individual headers.          |
| `contentType` | string           | The `Content-Type` value from the request.                                                     |
| `statusCode`  | integer          | The HTTP status code the actor will return to the sender. You can override this from a script. |

### The `req` object

`req` is a reduced, read-only snapshot of the incoming request — not the live request object. It gives your script access to query parameters, the original URL, and the remote IP for use in transformation logic. You cannot call methods on `req` or modify it; changes have no effect.

## What scripts cannot do

Scripts run in a restricted sandbox. The following are not available:

* `process` — no access to the Node.js process object or environment variables
* `require` / `import` — no module loading
* Filesystem APIs — no `fs`, `path`, or similar
* Network APIs — no `fetch`, `http`, `https`, or `XMLHttpRequest`
* `eval()` and `Function()` — code generation from strings is disabled

<Warning>
  Scripts that attempt to access restricted globals will throw a `ReferenceError` at runtime. The error is logged and the capture continues, but the transformation will not be applied.
</Warning>

## Common use cases

### 1. Parse and normalize a JSON body

When `enableJSONParsing` is off or the body arrives as a raw string, parse it yourself and add a debug flag:

```js theme={null}
if (event.contentType === 'application/json') {
  const body = typeof event.body === 'string' ? JSON.parse(event.body) : event.body;
  event.body = { ...body, normalized: true, source: 'webhook-debugger' };
}
```

### 2. Strip PII before storage

Remove sensitive fields from the payload so they are never written to the dataset:

```js theme={null}
if (event.body && typeof event.body === 'object') {
  const { email, phone, ssn, ...safe } = event.body;
  event.body = safe;
}
```

### 3. Add debug metadata

Inject custom fields for easier filtering in `/logs` queries:

```js theme={null}
const provider = event.headers['x-webhook-provider'] || 'unknown';
event.body = {
  ...event.body,
  _debug: {
    capturedAt: new Date().toISOString(),
    provider,
    remoteIp: req.ip,
  },
};
```

### 4. Remap fields for a downstream schema

Flatten or rename fields before the event is forwarded or stored:

```js theme={null}
if (event.body && event.body.data && event.body.data.object) {
  const obj = event.body.data.object;
  event.body = {
    id: obj.id,
    type: event.body.type,
    amount: obj.amount,
    currency: obj.currency,
    created: obj.created,
  };
}
```

## Adjusting worker memory

If your scripts process large payloads and hit memory limits, you can raise the worker heap ceilings with two environment variables:

| Variable                                       | Range  | Default | Description                                               |
| ---------------------------------------------- | ------ | ------- | --------------------------------------------------------- |
| `CUSTOM_SCRIPT_WORKER_MAX_OLD_GENERATION_MB`   | 16–256 | 32      | Old-generation heap ceiling for the script worker, in MB. |
| `CUSTOM_SCRIPT_WORKER_MAX_YOUNG_GENERATION_MB` | 8–128  | 16      | Young-generation (semi-space) heap ceiling, in MB.        |

See [Environment variables](/configuration/environment-variables) for how to set these in a local `.env` or Docker run command.

<Warning>
  Scripts share a single worker sandbox for the lifetime of the actor run. Complex scripts or scripts that retain references to large objects can cause memory pressure over time. Test new scripts against low traffic first before deploying to a high-volume endpoint.
</Warning>

<Tip>
  Use `console.log()` inside your script to debug transformation logic. Output appears in the actor log alongside normal request processing messages.
</Tip>
