DEV Community

Pirate Prentice
Pirate Prentice

Posted on

n8n OpenAI Node: Generate Text, Images, and Chat Completions in Your Workflows (Free Workflow JSON)

n8n OpenAI Node: Generate Text, Images, and Chat Completions in Your Workflows

The n8n OpenAI node connects your workflows to OpenAI's API — GPT-4o, GPT-4, GPT-3.5, DALL·E, Whisper, and more — without writing a single line of HTTP request boilerplate. You define the operation in the UI, wire in your data, and get structured output back as n8n items.

This guide covers every operation, the gotchas that trip people up, three real workflow patterns, and a free downloadable JSON to get you started.


What the OpenAI node can do

Resource Operations
Chat Message (GPT-4o, GPT-4, GPT-3.5-turbo, etc.)
Text Complete (legacy completions API)
Image Generate (DALL·E 3 / DALL·E 2), Analyze
Audio Transcribe (Whisper), Translate (Whisper)
File Upload, Delete, Get, Get Many
Assistant Create, Delete, Get, Get Many, Message (Assistants API v2)

The Chat → Message operation is what you'll use 90% of the time.


Setting up credentials

  1. In n8n, go to Settings → Credentials → New → OpenAI.
  2. Paste your API key from platform.openai.com/api-keys.
  3. (Optional) Set an Organization ID if your key belongs to a multi-org account.

The credential is reusable across all OpenAI nodes in your instance.


Chat → Message operation (the core operation)

Basic setup

Resource: Chat
Operation: Message
Model: gpt-4o (or gpt-4o-mini for cost savings)
Messages: [
  { role: system, content: "You are a helpful assistant." },
  { role: user,   content: "{{ $json.userMessage }}" }
]
Enter fullscreen mode Exit fullscreen mode

Key parameters

Parameter What it does Tip
Model Which GPT model to call Use gpt-4o-mini for bulk/cheap tasks; gpt-4o for quality
Messages Array of role/content pairs Always include a system message to set behavior
Max Tokens Hard cap on response length Leave unset to let the model decide; set if you need predictable costs
Temperature Randomness 0–2 0 = deterministic, 0.7 = balanced, 1.5+ = creative
JSON Response Force JSON output Enable when you need structured data; add "respond in JSON" to system message
Return All Get full API response Useful for finish_reason, usage.total_tokens debugging

Accessing the output

The node returns the completion text as:

{{ $json.message.content }}
Enter fullscreen mode Exit fullscreen mode

If you enabled JSON Response, the content is a JSON string — parse it with:

// In a Code node
const parsed = JSON.parse($input.first().json.message.content);
return [{ json: parsed }];
Enter fullscreen mode Exit fullscreen mode

Image → Generate operation (DALL·E)

Resource: Image
Operation: Generate
Prompt: "{{ $json.imagePrompt }}"
Model: dall-e-3
Size: 1024x1024
Quality: standard
Response Format: URL  (or b64_json for binary)
Enter fullscreen mode Exit fullscreen mode

Output: {{ $json.url }} — a temporary CDN URL (expires ~1 hour). If you need to persist the image, download it immediately with an HTTP Request node and store it in S3/Google Drive.

DALL·E 3 gotcha: Only one image per request (n=1 is hardcoded). For bulk image generation, use a Loop Over Items before the OpenAI node.


Audio → Transcribe operation (Whisper)

Resource: Audio
Operation: Transcribe
Input Data Field Name: data  (the binary property containing your audio file)
Model: whisper-1
Language: en  (optional  auto-detect if omitted)
Enter fullscreen mode Exit fullscreen mode

The node expects binary audio data. Feed it from a:

  • Read/Write Files node (local file)
  • HTTP Request node downloading a URL
  • Telegram/WhatsApp node voice message

Output: {{ $json.text }} — the transcript.


Assistants API operation

Use Assistant → Message when you need:

  • Persistent conversation threads across multiple turns
  • Code Interpreter (run Python, process files)
  • File Search (RAG over your uploaded documents)
  • Custom tool calling with function definitions

The flow: create a Thread → add Messages → create a Run → poll until completed → retrieve Messages.

n8n's built-in Assistant operation handles the run-polling loop for you — you just wire in a Thread ID and get back the assistant's reply.

Gotcha: Thread IDs are stateful on OpenAI's servers. Store them (in a database or n8n static data) if you need multi-session continuity.


Gotchas & common errors

1. Rate limits (429)

OpenAI throttles by tokens-per-minute and requests-per-minute per model tier. For bulk processing:

  • Add a Wait node (1–2s) between batches
  • Use Split in Batches with batch size 5–10
  • Or use a lower-tier model (gpt-4o-mini) that has higher rate limits

2. Token budget exceeded

Long conversation histories compound fast. Trim the messages array to the last N turns, or summarize history with a separate lightweight call before the main call.

3. JSON mode hallucinating keys

Even with JSON Response enabled, GPT sometimes generates keys you didn't ask for. Use a Code node to validate/strip the output before passing it downstream.

4. Image URL expiry

DALL·E URLs expire in ~1 hour. Always download + store immediately if you need persistence.

5. Model not found

Model names are case-sensitive and change over time. Use the exact string from platform.openai.com/docs/models. gpt-4 is different from gpt-4-turbo.

6. Binary field name mismatch (Whisper)

Whisper expects binary data in a specific field. Make sure the field name in Input Data Field Name exactly matches the binary property name from your upstream node (often data from HTTP Request, or the filename from Read Files).


3 workflow patterns

Pattern 1: AI customer support triage

Webhook
  → OpenAI Chat (classify ticket: billing/technical/refund + urgency 1-5)
  → Switch node (route by category)
  → Gmail / Slack / Spreadsheet (log + notify)
Enter fullscreen mode Exit fullscreen mode

System prompt: "Classify the support ticket. Return JSON: {category: string, urgency: number, summary: string}". Enable JSON Response.

This pattern handles hundreds of tickets unattended, routing each to the right queue.

Pattern 2: Weekly content summarizer

Schedule Trigger (every Monday 08:00)
  → HTTP Request (fetch RSS feed or API)
  → Item Lists (aggregate all items)
  → OpenAI Chat (summarize + extract 5 key takeaways)
  → Gmail / Slack (send digest)
Enter fullscreen mode Exit fullscreen mode

Keep total tokens under the model's context window by summarizing in batches if the feed is large.

Pattern 3: Voice-to-task pipeline

Telegram Trigger (voice message)
  → OpenAI Audio Transcribe (Whisper → text)
  → OpenAI Chat (extract action items as JSON array)
  → Google Tasks / Notion / Airtable (create tasks)
  → Telegram (reply confirmation)
Enter fullscreen mode Exit fullscreen mode

A practical zero-UI task capture system — speak your to-dos and they appear in your task manager.


Free workflow JSON

Here's a starter workflow wiring a Webhook trigger to GPT-4o-mini with JSON response mode, then routing the parsed output:

{
  "name": "OpenAI Chat Starter",
  "nodes": [
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "openai-chat",
        "responseMode": "responseNode"
      },
      "name": "Webhook",
      "type": "n8n-nodes-base.webhook",
      "position": [240, 300]
    },
    {
      "parameters": {
        "resource": "chat",
        "operation": "message",
        "model": { "__rl": true, "value": "gpt-4o-mini", "mode": "list" },
        "messages": {
          "values": [
            { "role": "system", "content": "You are a helpful assistant. Respond in JSON: {answer: string, confidence: number}" },
            { "role": "user",   "content": "={{ $json.body.question }}" }
          ]
        },
        "jsonOutput": true
      },
      "name": "OpenAI",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "position": [460, 300]
    },
    {
      "parameters": {
        "jsCode": "const raw = $input.first().json.message.content;\nconst parsed = JSON.parse(raw);\nreturn [{ json: parsed }];"
      },
      "name": "Parse JSON",
      "type": "n8n-nodes-base.code",
      "position": [680, 300]
    },
    {
      "parameters": { "respondWith": "json", "responseBody": "={{ $json }}" },
      "name": "Respond",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [900, 300]
    }
  ],
  "connections": {
    "Webhook":    { "main": [[{ "node": "OpenAI",     "type": "main", "index": 0 }]] },
    "OpenAI":     { "main": [[{ "node": "Parse JSON", "type": "main", "index": 0 }]] },
    "Parse JSON": { "main": [[{ "node": "Respond",    "type": "main", "index": 0 }]] }
  }
}
Enter fullscreen mode Exit fullscreen mode

Import this in Settings → Import from URL/Clipboard.


When to use the OpenAI node vs the AI Agent node

Scenario Use
Single-turn generation (summarize, classify, extract) OpenAI node
Multi-turn chat with tool use / function calling AI Agent node
Persistent assistant with file search / code interpreter Assistant operation (OpenAI node)
Cheap bulk processing OpenAI node with gpt-4o-mini
RAG over your own documents AI Agent + vector store, or Assistant + file search

Next steps


What are you building with the OpenAI node? Drop your use case in the comments.

Top comments (0)