Chapter 61

Azure AI Foundry Integration: Deployment Configuration, Structured Outputs Beta and Enterprise Entra ID Integration

Chapter 61: n8n/Zapier Integration: Claude Nodes in No-Code Workflows

61.1 The Value of No-Code Automation Platforms

n8n and Zapier represent two forms of workflow automation:

Embedding Claude in either platform allows non-technical business teams to build AI-driven automation: automatically categorizing and replying to customer emails, intelligently extracting form data, generating and distributing reports, and publishing content across multiple channels.

61.2 Configuring Claude HTTP Nodes in n8n

n8n includes a native Anthropic node (since n8n v1.22+), but understanding the HTTP Request node approach gives you deeper insight into the underlying mechanism.

61.2.1 Creating Anthropic API Credentials

In n8n:

  1. Go to Settings โ†’ Credentials โ†’ New Credential
  2. Choose HTTP Header Auth
  3. Set Header Name to x-api-key and Header Value to your Anthropic API key

61.2.2 Configuring the HTTP Request Node for Claude

// n8n HTTP Request node configuration (JSON view)
{
  "method": "POST",
  "url": "https://api.anthropic.com/v1/messages",
  "authentication": "headerAuth",
  "headers": {
    "anthropic-version": "2023-06-01",
    "content-type": "application/json"
  },
  "body": {
    "model": "claude-opus-4-5",
    "max_tokens": 1024,
    "system": "{{ $json.systemPrompt }}",
    "messages": [
      {
        "role": "user",
        "content": "{{ $json.userMessage }}"
      }
    ]
  }
}

Steps in n8n's GUI:

  1. Drag in an HTTP Request node
  2. Method: POST
  3. URL: https://api.anthropic.com/v1/messages
  4. Authentication: select the Header Auth credential created earlier
  5. Headers tab:
    • anthropic-version: 2023-06-01
    • Content-Type: application/json
  6. Body tab โ†’ JSON: paste the body above
  7. Use {{ $json.fieldName }} to reference upstream node data

61.2.3 Extracting Claude Response Content

The Claude API returns this response structure:

{
  "id": "msg_01xxx",
  "type": "message",
  "role": "assistant",
  "content": [
    {
      "type": "text",
      "text": "Here is Claude's response..."
    }
  ],
  "stop_reason": "end_turn",
  "usage": {
    "input_tokens": 42,
    "output_tokens": 128
  }
}

Use a Set node to extract the text:

// Set node expression
{{ $json.content[0].text }}

Or a Code node for more complex processing:

const response = $input.first().json;
const text = response.content[0].text;
const inputTokens = response.usage.input_tokens;
const outputTokens = response.usage.output_tokens;

return [{
  json: {
    claudeResponse: text,
    tokensUsed: inputTokens + outputTokens,
    cost: ((inputTokens * 3 + outputTokens * 15) / 1_000_000).toFixed(6)
  }
}];

61.3 Building Practical n8n Claude Workflows

61.3.1 Workflow 1: Gmail Smart Classification and Auto-Reply

Trigger: Gmail Trigger (new email arrives)
  โ†“
Set Node: Build classification prompt
  โ†“
HTTP Request: Call Claude (classify)
  โ†“
IF Node: Branch based on classification
  โ”œโ”€โ”€ technical_support โ†’ Query knowledge base โ†’ Claude generates reply โ†’ Gmail Reply
  โ”œโ”€โ”€ sales_inquiry โ†’ Notify Slack โ†’ Create CRM record
  โ””โ”€โ”€ complaint โ†’ Mark high priority โ†’ Notify manager โ†’ Human handling

Classification node Claude config:

{
  "model": "claude-haiku-4-5",
  "max_tokens": 64,
  "messages": [
    {
      "role": "user",
      "content": "Classify the following email as: technical_support/sales_inquiry/complaint/general. Output only the classification name, no explanation.\n\nSubject: {{ $json.subject }}\nBody: {{ $json.snippet }}"
    }
  ]
}

Reply generation node:

{
  "model": "claude-opus-4-5",
  "max_tokens": 512,
  "system": "You are the company's technical support specialist. Generate professional, friendly reply emails based on knowledge base content (if provided). Reply in the same language as the incoming email.",
  "messages": [
    {
      "role": "user",
      "content": "Customer email:\n{{ $json.emailBody }}\n\nKnowledge base reference:\n{{ $json.knowledgeBaseResult }}\n\nGenerate a reply email body (no headers or signature):"
    }
  ]
}

61.3.2 Workflow 2: Webhook-triggered Document Processing Pipeline

Trigger: Webhook (POST request with document URL)
  โ†“
HTTP Request: Download document content
  โ†“
Code Node: Preprocess text (strip HTML, truncate to 50000 chars)
  โ†“
HTTP Request: Claude extracts structured information
  โ†“
Set Node: Parse Claude's JSON output
  โ†“
Google Sheets: Write extracted data
  โ†“
Webhook Response: Return processing result

Claude extraction node config:

{
  "model": "claude-opus-4-5",
  "max_tokens": 1024,
  "messages": [
    {
      "role": "user",
      "content": "Extract key information from the following document. Output strictly as JSON with no other text:\n\nDocument:\n{{ $json.documentText }}\n\nFields to extract:\n- company_name\n- contact_person\n- phone\n- email\n- products_mentioned (array)\n- key_requirements (max 3, array)\n- urgency (high/medium/low)\n\nExample: {\"company_name\": \"...\", ...}"
    }
  ]
}

Code node to parse JSON output:

const claudeText = $input.first().json.content[0].text;

const jsonMatch = claudeText.match(/\{[\s\S]*\}/);
if (!jsonMatch) {
  throw new Error(`Claude did not return valid JSON: ${claudeText}`);
}

const extracted = JSON.parse(jsonMatch[0]);
return [{ json: extracted }];

61.3.3 Workflow 3: Scheduled Content Generation and Multi-Channel Publishing

Trigger: Schedule (daily at 9:00 AM)
  โ†“
HTTP Request: Fetch today's trending topics (RSS/API)
  โ†“
HTTP Request: Claude generates multi-format content
  โ†“
Code Node: Parse different format content
  โ†“
Parallel execution:
  โ”œโ”€โ”€ Twitter API: Publish short version (280 chars)
  โ”œโ”€โ”€ LinkedIn API: Publish professional version
  โ””โ”€โ”€ Notion API: Archive full version

Claude multi-format generation node:

{
  "model": "claude-opus-4-5",
  "max_tokens": 2048,
  "messages": [
    {
      "role": "user",
      "content": "Based on the following topic, generate content in three formats. Output strictly as JSON.\n\nTopic: {{ $json.topic }}\nBackground: {{ $json.background }}\n\nOutput format:\n{\n  \"twitter\": \"Twitter post (max 280 chars, can include hashtags)\",\n  \"linkedin\": \"LinkedIn article (300-500 words, professional tone)\",\n  \"full_article\": \"Full article (800-1200 words, with title, intro, body, conclusion)\"\n}"
    }
  ]
}

61.4 Integrating Claude in Zapier

Zapier calls the Claude API via Webhooks by Zapier or the HTTP action (requires Zapier Premium).

61.4.1 Using Webhooks by Zapier

Zap structure:

Trigger: Your app (e.g., Typeform new form submission)
  โ†“
Action: Webhooks by Zapier - Custom Request
  โ†“
Action: Code by Zapier (parse Claude response)
  โ†“
Action: Downstream app (Gmail/Slack/Google Sheets, etc.)

Webhooks by Zapier node config:

Code by Zapier to extract response:

const responseBody = JSON.parse(inputData.webhookBody);
const claudeText = responseBody.content[0].text;

return {
  claudeResponse: claudeText,
  inputTokens: responseBody.usage.input_tokens,
  outputTokens: responseBody.usage.output_tokens
};

61.4.2 Zapier Example: Typeform โ†’ Claude Analysis โ†’ Google Sheets

Trigger: Typeform - New Entry (customer survey submission)
  โ†“
Action: Webhooks by Zapier (POST to Claude API)
  - Analyze survey answers, extract pain points and priorities
  โ†“
Action: Code by Zapier (parse Claude JSON output)
  โ†“
Action: Google Sheets - Create Row
  - Write structured extracted data
  โ†“
Action: Slack - Send Channel Message
  - Notify product team of new high-priority feedback

61.5 Webhook Triggers: Letting External Events Drive Claude

n8n's Webhook Trigger allows external systems to proactively trigger Claude processing.

61.5.1 n8n Webhook + Claude Processing

// Workflow: HTTP POST โ†’ Claude analysis โ†’ Return result

POST https://your-n8n.com/webhook/analyze-text
Content-Type: application/json

{
  "text": "Text content to analyze",
  "analysis_type": "sentiment|summary|extraction",
  "language": "en"
}

n8n workflow nodes:

  1. Webhook Trigger: Listen for POST request
  2. Switch Node: Branch on analysis_type
  3. HTTP Request (Claude): Use different prompts for each analysis type
  4. Set Node: Format output
  5. Webhook Response Node: Return result to caller
// Webhook Response content (Set node config)
{
  "success": true,
  "result": "{{ $json.claudeResponse }}",
  "tokens_used": "{{ $json.tokensUsed }}",
  "processing_time_ms": "{{ $json.processingTime }}"
}

61.6 Error Handling and Reliability

61.6.1 n8n Error Handling Nodes

HTTP Request (Claude)
  โ†“ Success
Set Node (process result)
  โ†“ Failure (Error Trigger)
  โ†“
IF Node: Check error type
  โ”œโ”€โ”€ 429 Rate Limit โ†’ Wait Node (60s) โ†’ Retry
  โ”œโ”€โ”€ 500 Server Error โ†’ Alert to Slack
  โ””โ”€โ”€ Other โ†’ Log โ†’ Skip

Rate Limit handling Code node:

const statusCode = $input.first().json.statusCode;
const retryAfter = $input.first().json.headers?.['retry-after'];

if (statusCode === 429) {
  const waitSeconds = retryAfter ? parseInt(retryAfter) : 60;
  return [{
    json: {
      shouldRetry: true,
      waitMs: waitSeconds * 1000,
      message: `Rate limited, waiting ${waitSeconds}s`
    }
  }];
}

return [{ json: { shouldRetry: false, error: $input.first().json } }];

61.6.2 Cost Control: Model Selection by Task

const taskType = $input.first().json.taskType;
const textLength = $input.first().json.text?.length || 0;

let model = "claude-haiku-4-5";  // Default to cheapest model

if (taskType === "complex_analysis" || textLength > 10000) {
  model = "claude-opus-4-5";
} else if (taskType === "summarization" || taskType === "translation") {
  model = "claude-sonnet-4-5";
}

return [{ json: { ...$input.first().json, selectedModel: model } }];

61.7 Best Practices

Prompt Management

Store system prompts in environment variables rather than hardcoding them in each node:

// n8n environment variables (Settings โ†’ Environment Variables)
// CLAUDE_SYSTEM_PROMPT_SUPPORT = "You are..."
const systemPrompt = $env.CLAUDE_SYSTEM_PROMPT_SUPPORT;

Output Validation

function safeParseClaudeJson(text) {
  try {
    return JSON.parse(text);
  } catch (e) {}
  
  const jsonMatch = text.match(/```json\n?([\s\S]*?)\n?```/) ||
                    text.match(/\{[\s\S]*\}/);
  if (jsonMatch) {
    try {
      return JSON.parse(jsonMatch[1] || jsonMatch[0]);
    } catch (e) {}
  }
  
  throw new Error(`Could not parse Claude output as JSON: ${text.substring(0, 200)}`);
}

Summary

n8n and Zapier integrate the Claude API through HTTP Request nodes into visual workflows. Key configuration elements include: Header Auth credentials (x-api-key), the anthropic-version request header, and expressions ({{ $json.field }} in n8n, __field__ in Zapier) to dynamically inject context. Practical workflow scenarios include automated email classification and reply, document structured extraction, and multi-format content generation. Production considerations are: rate limit retries, routing to models by task complexity, safe JSON parsing of Claude output, and centralized system prompt management.

Rate this chapter
4.7  / 5  (3 ratings)

๐Ÿ’ฌ Comments