Script Webhooks

Updated Aug 26, 2026
DataMagik Automate

Script Webhooks

Every script in the Script Engine has a webhook URL — a single HTTPS endpoint that runs the script when you send it an HTTP POST. Use it to trigger a script from an external application, a scheduled job on another system, a form submission, a Plex automation, or a one-line curl command. Whatever JSON you post becomes the script's input.

Finding the webhook URL

Open a script in the Script Engine editor. Next to the script's ID chip in the header you'll see a Webhook button. Click it to open a popover that shows:

  • the exact callable URL, with a Copy button;
  • a Return mode toggle — see below;
  • a ready-to-paste curl example that tracks the toggle;
  • a reminder of how to authenticate.

The URL follows this pattern, where {id} is the numeric Script ID:

POST https://data-magik.com/api/script-engine/scripts/{id}/execute

Authentication

Webhook calls authenticate with a DataMagik API key. Create one under Your Account > API Keys; keys start with dcp_. Send it as a header:

X-API-Key: dcp_your_api_key_here

An Authorization: Bearer dcp_your_api_key_here header works identically. The key's user must hold the DataMagik - Builder or DataMagik - Viewer permission, and the script runs in that user's company context.

Keep keys secret. An API key acts as the user who created it. Store it securely, rotate it periodically, and prefer a dedicated service account over a personal key for machine-to-machine webhooks.

Sending data to the script

Post any JSON object as the request body — the script receives it verbatim as its context. For example, this request:

curl -X POST https://data-magik.com/api/script-engine/scripts/482/execute \
  -H "X-API-Key: dcp_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{ "orderId": 12345, "notify": true }'

...is read inside the script like this:

function main(context) {
  const id = context.orderId;   // 12345
  if (context.notify) { /* ... */ }
}
Notes on the body: An empty body is allowed — the script simply gets an empty context. The body must be a JSON object; a bare array, string, or number is rejected with a 400 error. You can optionally pin a script version or priority with the X-Script-Version-Id and X-Script-Priority headers.

What the webhook returns

There are two return modes, chosen per request with the wait query parameter. The Webhook popover in the editor has a Return mode toggle for them and rewrites both the URL and the curl example as you switch, so you can copy the one you want rather than editing the URL by hand.

Queue and poll — the default

Leave wait off entirely and nothing changes from how webhooks have always behaved. Short scripts finish inline; longer ones continue in the background so your caller never hangs.

  • Finished in time — HTTP 200. The response includes execution_id, completed: true, and an execution object with the script's output_data, status, any error_message, run time, API-call count, and console logs.
  • Still running — HTTP 202. The response includes the execution_id and a status_url. Poll GET /api/script-engine/executions/{execution_id} (or stream .../executions/{execution_id}/stream) to get the final result.

Wait for the result — ?wait=sync

Add ?wait=sync when the calling system cannot poll — it has no polling loop and no callback endpoint, and needs the answer in the response to the request it just made.

curl -X POST "https://data-magik.com/api/script-engine/scripts/482/execute?wait=sync" \
  -H "X-API-Key: dcp_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{ "orderId": 12345 }'

The request is held until the script finishes, and whatever your script returns is the entire response body — no wrapper, no envelope, no extra keys. You define the response exactly:

Your script returnsThe caller receives
return { invoice: "INV-1042", total: 91.5 }{"invoice":"INV-1042","total":91.5}
return [1, 2, 3][1,2,3]
return "OK""OK"
return { result: 42 }{"result":42}
return (nothing){}

Because the body belongs to you, the run's identity moves to response headers: X-Execution-Id carries the execution id for tracing the run in history, and X-Execution-Time-Ms carries how long the script itself took.

The status codes in this mode:

CodeMeaning
200Finished. The body is your return value.
422The script ran and failed. There is no return value to pass through, so the body is {success, error, error_code, execution_id} instead.
429Your company already has the maximum number of synchronous runs in flight. Retry shortly, or call without ?wait=sync.
503The execution queue is unavailable, so the run never started.
504Ran out of time — see below.

Add &wait_timeout=30 (seconds) to shorten the wait if your own client gives up sooner than we do and you would rather have our 504 than its dead socket. Values above the ceiling are clamped, not rejected.

The ceiling is about 9 minutes, and it comes from the network, not the Script Engine. A script can be configured to run for up to 45 minutes, but no proxy will hold an HTTP request open that long. Past the ceiling you get a 504 with error_code: "SYNC_WAIT_TIMEOUT", the execution_id, and a status_url.

The run is not cancelled. It carries on in the background under its own timeout, and its result still appears in execution history under that execution_id. A 504 here means “we could not hold the line”, not “the work was lost”.

Note this is deliberately a 504 and never a 202: a caller that asked to wait has no polling loop, so any 2xx would read to it as success for a result it will never collect.
If a script routinely runs longer than the ceiling, ?wait=sync is the wrong shape for it. Use the default mode and poll, or have the script deliver its own result — an email, a file drop, an outbound webhook — instead of returning it.

Where runs show up

Every webhook run is recorded in the script's execution history, with its console logs, output, and any errors — the same place scheduled and manual runs appear. If a call fails, check the response body first (auth or bad-JSON errors come back immediately), then the execution history for runtime errors inside the script.

Related: To run a script automatically on a timetable instead of on demand, see Script Schedules. To trigger a script from an incoming email, see Inbound Email.
Was this page helpful?