n8n

PostTTS for n8n

Automate audio generation in any workflow. Connect PostTTS to 400+ apps with n8n's built-in HTTP Request node — no custom code required.

No-code automation · Works with n8n Cloud or self-hosted · 400+ connectors

Quick Start

1

Get your API key

Create a free account and generate an API key on the Integration page. Copy the ptts_ key — it's only shown once.

2

Add an HTTP Request node

In your n8n workflow, add an HTTP Request node and point it at POST /api/v1/posts/convert with your key in a Bearer header.

3

Chain with any app

Connect the output to any of n8n's 400+ nodes — RSS, Gmail, Slack, Webhooks, Google Sheets, Airtable, S3, Discord, and more.

Why n8n?

A thin HTTP layer unlocks every n8n connector for PostTTS.

Self-host or Cloud

Open-source and free to self-host, or use n8n Cloud for a managed setup.

No custom node needed

Use n8n's built-in HTTP Request node. Install nothing; maintain nothing.

400+ connectors

Chain PostTTS with Slack, Gmail, Google Sheets, Airtable, S3, Discord, and more.

Common Workflow Patterns

Copy a pattern's JSON and paste it onto your n8n canvas — no manual setup required.

RSS → PostTTS → Podcast hosting

Every new RSS item becomes a podcast episode automatically.

RSS Feed Read HTTP Request Your host
{
  "nodes": [
    {
      "parameters": {
        "url": "https://example.com/feed.xml",
        "options": {}
      },
      "id": "rss-trigger",
      "name": "RSS Feed Read",
      "type": "n8n-nodes-base.rssFeedRead",
      "typeVersion": 1,
      "position": [240, 300]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://posttts.com/api/v1/posts/convert",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n  \"site_id\": \"site_01HX...\",\n  \"url\": \"{{ $json.link }}\",\n  \"voice\": \"woman\"\n}",
        "options": {}
      },
      "id": "posttts-convert",
      "name": "PostTTS Convert",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [460, 300]
    }
  ],
  "connections": {
    "RSS Feed Read": {
      "main": [[{ "node": "PostTTS Convert", "type": "main", "index": 0 }]]
    }
  }
}

Webhook → PostTTS → Email

Notify subscribers the moment their audio is ready.

Webhook HTTP Request Gmail
{
  "nodes": [
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "posttts-convert",
        "options": {}
      },
      "id": "webhook-trigger",
      "name": "Webhook",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [240, 300]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://posttts.com/api/v1/posts/convert",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n  \"site_id\": \"site_01HX...\",\n  \"url\": \"{{ $json.body.url }}\",\n  \"voice\": \"woman\"\n}",
        "options": {}
      },
      "id": "posttts-convert",
      "name": "PostTTS Convert",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [460, 300]
    },
    {
      "parameters": {
        "sendTo": "subscriber@example.com",
        "subject": "Your audio is ready",
        "message": "=Listen here: {{ $json.audio_url }}",
        "options": {}
      },
      "id": "gmail-send",
      "name": "Send Gmail",
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2.1,
      "position": [680, 300]
    }
  ],
  "connections": {
    "Webhook": {
      "main": [[{ "node": "PostTTS Convert", "type": "main", "index": 0 }]]
    },
    "PostTTS Convert": {
      "main": [[{ "node": "Send Gmail", "type": "main", "index": 0 }]]
    }
  }
}

Google Sheets → PostTTS → Storage

Bulk-convert a list of URLs on demand.

Google Sheets HTTP Request
{
  "nodes": [
    {
      "parameters": {
        "documentId": "YOUR_GOOGLE_SHEET_ID",
        "sheetName": "Sheet1",
        "options": {}
      },
      "id": "sheets-read",
      "name": "Google Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.2,
      "position": [240, 300]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://posttts.com/api/v1/posts/convert",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n  \"site_id\": \"site_01HX...\",\n  \"url\": \"{{ $json.url }}\",\n  \"voice\": \"woman\"\n}",
        "options": {}
      },
      "id": "posttts-convert",
      "name": "PostTTS Convert",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [460, 300]
    }
  ],
  "connections": {
    "Google Sheets": {
      "main": [[{ "node": "PostTTS Convert", "type": "main", "index": 0 }]]
    }
  }
}

Schedule → PostTTS → Slack

Post a daily audio digest to your team channel.

Schedule Trigger HTTP Request Slack
{
  "nodes": [
    {
      "parameters": {
        "rule": {
          "interval": [{ "field": "days", "daysInterval": 1, "triggerAtHour": 9 }]
        }
      },
      "id": "schedule-trigger",
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.2,
      "position": [240, 300]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://posttts.com/api/v1/posts/convert",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n  \"site_id\": \"site_01HX...\",\n  \"url\": \"https://yourblog.com/daily-digest\",\n  \"voice\": \"woman\"\n}",
        "options": {}
      },
      "id": "posttts-convert",
      "name": "PostTTS Convert",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [460, 300]
    },
    {
      "parameters": {
        "channel": "#general",
        "text": "=Today's audio: {{ $json.audio_url }}",
        "otherOptions": {}
      },
      "id": "slack-send",
      "name": "Send Slack",
      "type": "n8n-nodes-base.slack",
      "typeVersion": 2.2,
      "position": [680, 300]
    }
  ],
  "connections": {
    "Schedule Trigger": {
      "main": [[{ "node": "PostTTS Convert", "type": "main", "index": 0 }]]
    },
    "PostTTS Convert": {
      "main": [[{ "node": "Send Slack", "type": "main", "index": 0 }]]
    }
  }
}

How to import

In n8n: copy the JSON above, open a new or existing workflow, and paste (Cmd/Ctrl + V) directly onto the canvas. The nodes and their connections appear instantly. Configure the Header Auth credential (Name: Authorization, Value: Bearer ptts_...) on the PostTTS Convert node and swap in your site_id.

HTTP Request Node Configuration

Fill these fields in n8n's HTTP Request node to call PostTTS.

Field Value
Method POST
URL https://posttts.com/api/v1/posts/convert
Authentication Generic Credential Type → Header Auth
Header Name Authorization
Header Value Bearer ptts_xxxxxxxxxxxxxxxxxxxxxxxx
Body Content Type JSON
Specify Body Using JSON (see example below)

Example Request Body

Paste this into the JSON field of the HTTP Request node.

{
  "site_id": "site_01HX...",
  "url": "{{ $json.url }}",
  "voice": "woman"
}

Use n8n expressions like {{ $json.url }} to map data from upstream nodes into the request.

Polling for Async Conversions

For long posts, the initial POST returns 202 Accepted. Build a small poll loop in n8n.

  1. 1Capture id from the POST response into a Set node.
  2. 2Add a Wait node (5 seconds is a sensible start).
  3. 3Add an HTTP Request node: GET /api/v1/posts/{{ $json.id }}/audio.
  4. 4Add an IF node checking status === "ready". If true, continue; if false, loop back to the Wait node.

Poll response shape

{
  "id": "post_01HX...",
  "status": "ready",
  "audio_url": "https://cdn.posttts.com/audio/post_01HX.m4a",
  "voice": "woman",
  "duration_seconds": 184
}

Security Tips

Store your ptts_ key in n8n's Credentials panel (Header Auth type) — never paste it directly into node parameters where it's visible in workflow exports.

Use n8n environment variables (or a Set node at the top of your workflow) for site_id. It makes swapping between dev and prod workflows a one-line change.

Frequently Asked Questions

No. n8n's built-in HTTP Request node handles everything — POST for conversions, GET for polling, DELETE for cleanup. You install nothing and there's no package to keep updated.

Yes, identically. The HTTP Request node, Credentials, Wait, IF, and Set nodes are all in n8n's core. Whichever way you run n8n, the workflow is the same.

Create a new Credential of type "Header Auth" in n8n: Name = Authorization, Value = Bearer ptts_... Then reference that credential in the HTTP Request node. The key is encrypted at rest and never appears in exported workflow JSON.

Add an RSS Feed Trigger node at the top of the workflow, connect it to an HTTP Request node pointing at /api/v1/posts/convert, and map $json.link (the RSS item URL) into the "url" field of the request body. Every new item triggers a conversion.

Split the workflow. Workflow A: POST the conversion and store the returned id in a database or queue. Workflow B: a Schedule-triggered workflow that polls GET /api/v1/posts/:id/audio for any pending ids and fires your notification step once status flips to "ready".

In the HTTP Request node settings, enable "Continue On Fail" and add an IF node downstream checking $json.error or HTTP status codes. For 429 rate limits, branch into a Wait node (5-30s) before retrying. n8n also supports "Retry On Fail" at the node level.

Start automating with PostTTS

Create a free account, grab your API key, and wire up your first n8n workflow in minutes.

Create Free Account

Free plan includes 10 posts/month · No credit card required