DeepScript

Integration

n8n Integration — self-hosted audio automation

Your n8n + your DeepScript servers = full data sovereignty. No cloud automation, no Schrems II exposure.

n8n is the self-hostable alternative to Zapier and Make — you run the workflow engine yourself, for example on the same Hetzner server as the rest of your infrastructure. Combined with DeepScript (also hosted in Germany), this creates a pipeline where audio, workflow and metadata never touch US cloud providers — ideal for hospitals, law firms and government. An official DeepScript community node is in the works; until then, use n8n's generic HTTP Request node with the `X-API-KEY` header. Below is a full workflow export as JSON that you can import into your n8n instance (`Workflows → Import from File`). Webhooks back to n8n work via the Webhook node, so even long transcriptions (> 30 min) run cleanly without a polling loop.

n8n docs: HTTP Request node

What you can build

  • Fully self-hosted: n8n + DeepScript containers + your reverse proxy = full data sovereignty on a single box.
  • HTTP Request node with `X-API-KEY` header — no extra plugin needed, works out of the box.
  • Webhook node for `transcription.completed` events, clean async flow without polling.
  • Branches, loops, code nodes (JavaScript/Python) — complex logic directly in the workflow.
  • Ideal for government, hospitals and law firms: nothing goes to US clouds, everything stays on your machine.

Code samples

n8n workflow JSON — upload + webhook callbackJSON
{
  "name": "DeepScript: Upload and Process",
  "nodes": [
    {
      "name": "Manual Trigger",
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [240, 300],
      "parameters": {}
    },
    {
      "name": "Read Audio File",
      "type": "n8n-nodes-base.readBinaryFile",
      "typeVersion": 1,
      "position": [440, 300],
      "parameters": { "filePath": "/data/audio/meeting.mp3" }
    },
    {
      "name": "Upload to DeepScript",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4,
      "position": [640, 300],
      "parameters": {
        "method": "POST",
        "url": "https://api.deepscript.com/v1/transcriptions",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            { "name": "X-API-KEY", "value": "={{ $env.DEEPSCRIPT_API_KEY }}" }
          ]
        },
        "sendBody": true,
        "contentType": "multipart-form-data",
        "bodyParameters": {
          "parameters": [
            { "name": "file", "value": "={{ $binary.data }}", "parameterType": "formBinaryData" },
            { "name": "model", "value": "premium" },
            { "name": "language", "value": "de" }
          ]
        }
      }
    },
    {
      "name": "Webhook (transcription.completed)",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 1,
      "position": [840, 300],
      "parameters": {
        "path": "deepscript-completed",
        "responseMode": "responseNode"
      }
    },
    {
      "name": "Get Transcript",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4,
      "position": [1040, 300],
      "parameters": {
        "method": "GET",
        "url": "=https://api.deepscript.com/v1/transcriptions/{{ $json.data.transcriptionId }}",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            { "name": "X-API-KEY", "value": "={{ $env.DEEPSCRIPT_API_KEY }}" }
          ]
        }
      }
    }
  ],
  "connections": {
    "Manual Trigger": { "main": [[{ "node": "Read Audio File", "type": "main", "index": 0 }]] },
    "Read Audio File": { "main": [[{ "node": "Upload to DeepScript", "type": "main", "index": 0 }]] },
    "Webhook (transcription.completed)": { "main": [[{ "node": "Get Transcript", "type": "main", "index": 0 }]] }
  }
}
n8n Code node — verify HMAC signatureJavaScript
// In an n8n Code node placed right after the Webhook node.
// Verifies the X-DeepScript-Signature header against the raw body.
const crypto = require("crypto");

const SIGNING_SECRET = $env.DEEPSCRIPT_WEBHOOK_SECRET; // "whsec_xxx"
const header = $input.first().json.headers["x-deepscript-signature"];
const rawBody = $input.first().json.body;

const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")));
const { t: timestamp, v1: signature } = parts;

if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) {
  throw new Error("Webhook timestamp out of tolerance (>5min)");
}

const signedPayload = `${timestamp}.${JSON.stringify(rawBody)}`;
const expected = crypto
  .createHmac("sha256", SIGNING_SECRET)
  .update(signedPayload)
  .digest("hex");

const valid = crypto.timingSafeEqual(
  Buffer.from(signature, "hex"),
  Buffer.from(expected, "hex")
);
if (!valid) throw new Error("Invalid webhook signature");

return [{ json: { verified: true, event: rawBody } }];

Setup in a few steps

  1. 1

    Install n8n or start the Docker container

    Via Docker: `docker run -d --name n8n -p 5678:5678 -v ~/.n8n:/home/node/.n8n n8nio/n8n`. For production we recommend running n8n behind Caddy or Traefik with Let's Encrypt TLS on the same server as your other infrastructure.

  2. 2

    Store the API key as a credential

    In n8n under Credentials, create a new "Generic Credential Type" with header name `X-API-KEY` and value `ds_live_xxx`. Alternatively: mount the API key as the `DEEPSCRIPT_API_KEY` environment variable and reference it in HTTP nodes via `{{ $env.DEEPSCRIPT_API_KEY }}`.

  3. 3

    Import the workflow

    Copy the JSON export above into a `.json` file, then `Workflows → Import from File`. n8n auto-detects the nodes — you only need to map the DeepScript credential and tweak file paths if necessary.

  4. 4

    Register the webhook in DeepScript

    n8n's Webhook node gives you a URL like `https://your-n8n.example.com/webhook/deepscript-completed`. Register this URL at `POST /v1/webhooks` with the event `transcription.completed`. Store the returned secret in the HMAC verification Code node.

Frequently asked questions

Do I need the community node, or is HTTP Request enough?

HTTP Request is enough for every use case — the API is simple enough. A community node is in progress, but it'll mainly bring convenience features (auto-polling loop, typed outputs). Functionally nothing you can't already do today.

Can I run n8n on the same server as my reverse proxy?

Yes — recommended. Docker Compose with Caddy or Traefik in front of n8n. At several workflows per second the n8n queue mode architecture (workers + Redis) makes sense. For low volumes single-instance mode is enough.

How large can audio files be in the HTTP Request node?

n8n's default body limit is 16 MB. To use DeepScript's 500 MB upload limit, set `N8N_PAYLOAD_SIZE_MAX=512` (in MB) on your n8n instance. Alternative for very large files: upload to S3-compatible storage first and only send the URL to the DeepScript API.

Does any data leave my infrastructure?

Only the audio file plus metadata goes to DeepScript (Hetzner DE). If you run DeepScript on your own hardware too (enterprise setup), even that stays in-house. n8n workflow data, credentials and logs always remain on your server.

Can I version-control workflows in Git?

Yes — since version 1.0 n8n supports native Git integration via Source Control (Enterprise feature). Community edition: export workflows as JSON and commit them manually. The latter is sufficient for most setups.

Ready to ship this to production?

Create an account, generate an API key, ship. Three transcriptions free to try. Full OpenAPI 3.1 docs at api.deepscript.com/docs.

n8n Integration — self-hosted & GDPR-compliant | DeepScript