n8n-docs-datasets / docs-dataset /remaining_gaps.jsonl
DavidrPatton's picture
Add docs-dataset dataset
4484c0f verified
{"instruction": "List the most common n8n nodes with their operations and authentication methods", "output": "# n8n Node Integration Matrix\n\n## Communication Nodes\n| Node | Operations | Auth Method | Common Use Cases |\n|------|------------|-------------|------------------|\n| Gmail | Send, Reply, Get, Delete, Draft | OAuth2 | Notifications, lead follow-up |\n| Slack | Post, Update, Upload, User Info | OAuth2/API Key | Team alerts, bot automation |\n| Discord | Send, Edit, Delete, Webhook | Webhook/Bot Token | Community notifications |\n| Telegram | Send Message, Edit, Get Updates | Bot Token | Alerts, chatbots |\n| Microsoft Teams | Post, Reply, Channel List | OAuth2 | Enterprise notifications |\n| Twilio | SMS Send, Call, WhatsApp | API Key + Secret | Multi-channel messaging |\n\n## CRM Nodes\n| Node | Operations | Auth Method | Common Use Cases |\n|------|------------|-------------|------------------|\n| HubSpot | Create/Update Contact, Deal, Company | OAuth2/API Key | Lead management |\n| Salesforce | CRUD on any object, SOQL | OAuth2 | Enterprise CRM |\n| Pipedrive | Deals, Persons, Orgs, Activities | API Token | Sales pipeline |\n| Zoho CRM | Leads, Contacts, Deals | OAuth2 | SMB CRM automation |\n| GoHighLevel | Contacts, Opportunities, Messages | API Key | Agency automation |\n\n## Database Nodes\n| Node | Operations | Auth Method | Common Use Cases |\n|------|------------|-------------|------------------|\n| PostgreSQL | Query, Insert, Update, Delete | Connection String | Data warehousing |\n| MySQL | Query, Insert, Update, Delete | Connection String | Legacy systems |\n| MongoDB | Find, Insert, Update, Aggregate | Connection String | NoSQL operations |\n| Supabase | Select, Insert, Upsert, RPC | API Key + URL | Real-time backends |\n| Airtable | List, Get, Create, Update | API Key | Spreadsheet-DB hybrid |\n| Google Sheets | Append, Update, Read, Clear | OAuth2 | Lightweight data storage |\n\n## AI/ML Nodes\n| Node | Operations | Auth Method | Common Use Cases |\n|------|------------|-------------|------------------|\n| OpenAI | Chat, Complete, Embed, Image | API Key | Content generation, chatbots |\n| Anthropic Claude | Message, Complete | API Key | Analysis, writing |\n| Google AI | Generate, Embed | API Key | Multi-modal AI |\n| Hugging Face | Inference | API Token | Custom models |\n\n## Marketing Nodes\n| Node | Operations | Auth Method | Common Use Cases |\n|------|------------|-------------|------------------|\n| Mailchimp | Subscribe, Campaign, Tag | API Key | Email marketing |\n| SendGrid | Send, Template | API Key | Transactional email |\n| Mailgun | Send, Validate | API Key + Domain | High-volume email |\n| ActiveCampaign | Contact, Deal, Automation | API Key | Marketing automation |\n\n## Storage Nodes\n| Node | Operations | Auth Method | Common Use Cases |\n|------|------------|-------------|------------------|\n| AWS S3 | Upload, Download, List, Delete | Access Key + Secret | File storage |\n| Google Drive | Upload, Download, Share | OAuth2 | Document management |\n| Dropbox | Upload, Download, Move | OAuth2 | File sync |\n| FTP/SFTP | Upload, Download, List | Username/Password or Key | Legacy file transfer |", "metadata": {"topic": "integration_matrix", "type": "reference"}}
{"instruction": "What HTTP Request configurations are needed for different API authentication types?", "output": "# HTTP Request Authentication Patterns\n\n## API Key in Header\n```json\n{\n \"name\": \"API Request\",\n \"type\": \"n8n-nodes-base.httpRequest\",\n \"parameters\": {\n \"url\": \"https://api.example.com/endpoint\",\n \"authentication\": \"genericCredentialType\",\n \"genericAuthType\": \"httpHeaderAuth\",\n \"options\": {\n \"headers\": {\n \"X-API-Key\": \"={{ $credentials.apiKey }}\"\n }\n }\n }\n}\n```\n\n## API Key in Query String\n```json\n{\n \"parameters\": {\n \"url\": \"https://api.example.com/endpoint\",\n \"qs\": {\n \"api_key\": \"={{ $credentials.apiKey }}\"\n }\n }\n}\n```\n\n## Bearer Token\n```json\n{\n \"parameters\": {\n \"authentication\": \"genericCredentialType\",\n \"genericAuthType\": \"httpHeaderAuth\",\n \"options\": {\n \"headers\": {\n \"Authorization\": \"Bearer {{ $credentials.token }}\"\n }\n }\n }\n}\n```\n\n## Basic Auth\n```json\n{\n \"parameters\": {\n \"authentication\": \"genericCredentialType\",\n \"genericAuthType\": \"httpBasicAuth\"\n },\n \"credentials\": {\n \"httpBasicAuth\": {\n \"user\": \"username\",\n \"password\": \"password\"\n }\n }\n}\n```\n\n## OAuth 2.0\n```json\n{\n \"parameters\": {\n \"authentication\": \"oAuth2Api\"\n },\n \"credentials\": {\n \"oAuth2Api\": {\n \"accessTokenUrl\": \"https://auth.example.com/oauth/token\",\n \"authorizationUrl\": \"https://auth.example.com/oauth/authorize\",\n \"clientId\": \"{{ $credentials.clientId }}\",\n \"clientSecret\": \"{{ $credentials.clientSecret }}\",\n \"scope\": \"read write\"\n }\n }\n}\n```\n\n## HMAC Signature\n```javascript\n// Code node for HMAC signing\nconst crypto = require('crypto');\nconst timestamp = Date.now().toString();\nconst payload = JSON.stringify($json);\nconst signature = crypto\n .createHmac('sha256', $env.API_SECRET)\n .update(timestamp + payload)\n .digest('hex');\n\nreturn {\n headers: {\n 'X-Timestamp': timestamp,\n 'X-Signature': signature\n },\n body: payload\n};\n```", "metadata": {"topic": "http_auth", "type": "reference"}}
{"instruction": "How do I implement CI/CD pipelines for n8n workflows?", "output": "# n8n CI/CD Pipeline Implementation\n\n## Git-Backed Workflows\n\n### 1. Export Workflows to Git\n```bash\n# Export all workflows\nn8n export:workflow --all --output=./workflows/\n\n# Export specific workflow\nn8n export:workflow --id=123 --output=./workflows/my-workflow.json\n```\n\n### 2. GitHub Actions Pipeline\n```yaml\n# .github/workflows/n8n-deploy.yml\nname: Deploy n8n Workflows\n\non:\n push:\n branches: [main]\n paths:\n - 'workflows/**'\n\njobs:\n validate:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v4\n \n - name: Validate JSON\n run: |\n for file in workflows/*.json; do\n jq empty \"$file\" || exit 1\n done\n \n - name: Check for required nodes\n run: |\n for file in workflows/*.json; do\n if ! jq -e '.nodes | length > 0' \"$file\" > /dev/null; then\n echo \"Error: $file has no nodes\"\n exit 1\n fi\n done\n\n deploy:\n needs: validate\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v4\n \n - name: Deploy to n8n\n env:\n N8N_API_KEY: ${{ secrets.N8N_API_KEY }}\n N8N_HOST: ${{ secrets.N8N_HOST }}\n run: |\n for file in workflows/*.json; do\n WORKFLOW_ID=$(jq -r '.id' \"$file\")\n curl -X PUT \"$N8N_HOST/api/v1/workflows/$WORKFLOW_ID\" \\\n -H \"X-N8N-API-KEY: $N8N_API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -d @\"$file\"\n done\n```\n\n## Testing Workflows\n```yaml\n test:\n runs-on: ubuntu-latest\n services:\n n8n:\n image: n8nio/n8n\n ports:\n - 5678:5678\n env:\n N8N_BASIC_AUTH_ACTIVE: false\n steps:\n - name: Import and test workflow\n run: |\n # Import workflow\n curl -X POST \"http://localhost:5678/api/v1/workflows\" \\\n -H \"Content-Type: application/json\" \\\n -d @workflows/test-workflow.json\n \n # Execute and verify\n RESULT=$(curl -X POST \"http://localhost:5678/webhook-test/test\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\"test\": true}')\n \n echo \"$RESULT\" | jq -e '.success == true'\n```\n\n## Environment Management\n```yaml\n# workflows/config/production.env\nN8N_ENCRYPTION_KEY=prod-key-here\nDATABASE_URL=postgresql://prod-db\nWEBHOOK_URL=https://n8n.example.com\n\n# workflows/config/staging.env\nN8N_ENCRYPTION_KEY=staging-key\nDATABASE_URL=postgresql://staging-db\nWEBHOOK_URL=https://staging.n8n.example.com\n```", "metadata": {"topic": "cicd", "type": "devops"}}
{"instruction": "How do I deploy n8n on Kubernetes with auto-scaling?", "output": "# Kubernetes n8n Deployment with Auto-Scaling\n\n## Deployment Manifest\n```yaml\n# n8n-deployment.yaml\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n name: n8n\n labels:\n app: n8n\nspec:\n replicas: 2\n selector:\n matchLabels:\n app: n8n\n template:\n metadata:\n labels:\n app: n8n\n spec:\n containers:\n - name: n8n\n image: n8nio/n8n:latest\n ports:\n - containerPort: 5678\n env:\n - name: N8N_ENCRYPTION_KEY\n valueFrom:\n secretKeyRef:\n name: n8n-secrets\n key: encryption-key\n - name: DB_TYPE\n value: postgresdb\n - name: DB_POSTGRESDB_HOST\n value: postgres-service\n - name: EXECUTIONS_MODE\n value: queue\n - name: QUEUE_BULL_REDIS_HOST\n value: redis-service\n resources:\n requests:\n memory: \"512Mi\"\n cpu: \"250m\"\n limits:\n memory: \"2Gi\"\n cpu: \"1000m\"\n livenessProbe:\n httpGet:\n path: /healthz\n port: 5678\n initialDelaySeconds: 30\n readinessProbe:\n httpGet:\n path: /healthz\n port: 5678\n---\napiVersion: v1\nkind: Service\nmetadata:\n name: n8n-service\nspec:\n selector:\n app: n8n\n ports:\n - port: 80\n targetPort: 5678\n type: ClusterIP\n```\n\n## Horizontal Pod Autoscaler\n```yaml\n# n8n-hpa.yaml\napiVersion: autoscaling/v2\nkind: HorizontalPodAutoscaler\nmetadata:\n name: n8n-hpa\nspec:\n scaleTargetRef:\n apiVersion: apps/v1\n kind: Deployment\n name: n8n\n minReplicas: 2\n maxReplicas: 10\n metrics:\n - type: Resource\n resource:\n name: cpu\n target:\n type: Utilization\n averageUtilization: 70\n - type: Resource\n resource:\n name: memory\n target:\n type: Utilization\n averageUtilization: 80\n behavior:\n scaleUp:\n stabilizationWindowSeconds: 60\n policies:\n - type: Pods\n value: 2\n periodSeconds: 60\n scaleDown:\n stabilizationWindowSeconds: 300\n```\n\n## Queue Workers (Scaling Execution)\n```yaml\n# n8n-worker.yaml\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n name: n8n-worker\nspec:\n replicas: 3\n template:\n spec:\n containers:\n - name: n8n-worker\n image: n8nio/n8n:latest\n command: [\"n8n\", \"worker\"]\n env:\n - name: EXECUTIONS_MODE\n value: queue\n - name: QUEUE_BULL_REDIS_HOST\n value: redis-service\n```\n\n## Ingress with SSL\n```yaml\napiVersion: networking.k8s.io/v1\nkind: Ingress\nmetadata:\n name: n8n-ingress\n annotations:\n cert-manager.io/cluster-issuer: letsencrypt-prod\nspec:\n tls:\n - hosts:\n - n8n.example.com\n secretName: n8n-tls\n rules:\n - host: n8n.example.com\n http:\n paths:\n - path: /\n pathType: Prefix\n backend:\n service:\n name: n8n-service\n port:\n number: 80\n```", "metadata": {"topic": "kubernetes", "type": "devops"}}
{"instruction": "How do I set up Docker Compose for n8n with PostgreSQL and Redis?", "output": "# n8n Docker Compose Production Setup\n\n## docker-compose.yml\n```yaml\nversion: '3.8'\n\nservices:\n n8n:\n image: n8nio/n8n:latest\n restart: always\n ports:\n - \"5678:5678\"\n environment:\n - N8N_HOST=n8n.example.com\n - N8N_PORT=5678\n - N8N_PROTOCOL=https\n - NODE_ENV=production\n - N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}\n - WEBHOOK_URL=https://n8n.example.com/\n # Database\n - DB_TYPE=postgresdb\n - DB_POSTGRESDB_HOST=postgres\n - DB_POSTGRESDB_PORT=5432\n - DB_POSTGRESDB_DATABASE=n8n\n - DB_POSTGRESDB_USER=n8n\n - DB_POSTGRESDB_PASSWORD=${POSTGRES_PASSWORD}\n # Queue mode for scaling\n - EXECUTIONS_MODE=queue\n - QUEUE_BULL_REDIS_HOST=redis\n - QUEUE_BULL_REDIS_PORT=6379\n # Performance\n - EXECUTIONS_DATA_PRUNE=true\n - EXECUTIONS_DATA_MAX_AGE=168\n - GENERIC_TIMEZONE=America/New_York\n volumes:\n - n8n_data:/home/node/.n8n\n depends_on:\n - postgres\n - redis\n healthcheck:\n test: [\"CMD\", \"wget\", \"-q\", \"--spider\", \"http://localhost:5678/healthz\"]\n interval: 30s\n timeout: 10s\n retries: 3\n\n n8n-worker:\n image: n8nio/n8n:latest\n restart: always\n command: worker\n environment:\n - DB_TYPE=postgresdb\n - DB_POSTGRESDB_HOST=postgres\n - DB_POSTGRESDB_DATABASE=n8n\n - DB_POSTGRESDB_USER=n8n\n - DB_POSTGRESDB_PASSWORD=${POSTGRES_PASSWORD}\n - EXECUTIONS_MODE=queue\n - QUEUE_BULL_REDIS_HOST=redis\n - N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}\n depends_on:\n - postgres\n - redis\n - n8n\n deploy:\n replicas: 2\n\n postgres:\n image: postgres:15-alpine\n restart: always\n environment:\n - POSTGRES_USER=n8n\n - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}\n - POSTGRES_DB=n8n\n volumes:\n - postgres_data:/var/lib/postgresql/data\n healthcheck:\n test: [\"CMD-SHELL\", \"pg_isready -U n8n\"]\n interval: 10s\n timeout: 5s\n retries: 5\n\n redis:\n image: redis:7-alpine\n restart: always\n volumes:\n - redis_data:/data\n healthcheck:\n test: [\"CMD\", \"redis-cli\", \"ping\"]\n interval: 10s\n timeout: 5s\n retries: 5\n\n caddy:\n image: caddy:2-alpine\n restart: always\n ports:\n - \"80:80\"\n - \"443:443\"\n volumes:\n - ./Caddyfile:/etc/caddy/Caddyfile\n - caddy_data:/data\n depends_on:\n - n8n\n\nvolumes:\n n8n_data:\n postgres_data:\n redis_data:\n caddy_data:\n```\n\n## Caddyfile (Reverse Proxy)\n```\nn8n.example.com {\n reverse_proxy n8n:5678\n}\n```\n\n## .env file\n```bash\nN8N_ENCRYPTION_KEY=your-32-char-encryption-key-here\nPOSTGRES_PASSWORD=your-secure-password-here\n```\n\n## Start Commands\n```bash\n# Start all services\ndocker-compose up -d\n\n# Scale workers\ndocker-compose up -d --scale n8n-worker=4\n\n# View logs\ndocker-compose logs -f n8n\n\n# Backup database\ndocker-compose exec postgres pg_dump -U n8n n8n > backup.sql\n```", "metadata": {"topic": "docker", "type": "devops"}}
{"instruction": "How do I build SMS marketing workflows with Twilio in n8n?", "output": "# SMS Marketing Automation with Twilio\n\n## Send SMS Campaign\n```json\n{\n \"nodes\": [\n {\n \"name\": \"Get Subscribers\",\n \"type\": \"n8n-nodes-base.postgres\",\n \"parameters\": {\n \"query\": \"SELECT phone, first_name, segment FROM subscribers WHERE sms_opt_in = true AND segment = '{{ $json.targetSegment }}'\"\n }\n },\n {\n \"name\": \"Personalize Message\",\n \"type\": \"n8n-nodes-base.set\",\n \"parameters\": {\n \"values\": {\n \"string\": [{\n \"name\": \"message\",\n \"value\": \"Hi {{ $json.first_name }}! {{ $json.campaignMessage }} Reply STOP to opt out.\"\n }]\n }\n }\n },\n {\n \"name\": \"Send SMS\",\n \"type\": \"n8n-nodes-base.twilio\",\n \"parameters\": {\n \"operation\": \"send\",\n \"from\": \"={{ $env.TWILIO_PHONE }}\",\n \"to\": \"={{ $json.phone }}\",\n \"message\": \"={{ $json.message }}\"\n }\n },\n {\n \"name\": \"Log Delivery\",\n \"type\": \"n8n-nodes-base.postgres\",\n \"parameters\": {\n \"operation\": \"insert\",\n \"table\": \"sms_log\",\n \"columns\": \"phone, message_sid, status, sent_at\"\n }\n }\n ]\n}\n```\n\n## Handle Inbound SMS (Opt-out)\n```json\n{\n \"nodes\": [\n {\n \"name\": \"Twilio Webhook\",\n \"type\": \"n8n-nodes-base.webhook\",\n \"parameters\": {\"path\": \"twilio-inbound\", \"method\": \"POST\"}\n },\n {\n \"name\": \"Parse Message\",\n \"type\": \"n8n-nodes-base.set\",\n \"parameters\": {\n \"values\": {\n \"string\": [\n {\"name\": \"from\", \"value\": \"={{ $json.From }}\"},\n {\"name\": \"body\", \"value\": \"={{ $json.Body.toLowerCase().trim() }}\"}\n ]\n }\n }\n },\n {\n \"name\": \"Check Opt-Out\",\n \"type\": \"n8n-nodes-base.if\",\n \"parameters\": {\n \"conditions\": {\n \"string\": [{\n \"value1\": \"={{ $json.body }}\",\n \"operation\": \"contains\",\n \"value2\": \"stop\"\n }]\n }\n }\n },\n {\n \"name\": \"Update Opt-Out Status\",\n \"type\": \"n8n-nodes-base.postgres\",\n \"parameters\": {\n \"query\": \"UPDATE subscribers SET sms_opt_in = false WHERE phone = '{{ $json.from }}'\"\n }\n },\n {\n \"name\": \"Confirm Opt-Out\",\n \"type\": \"n8n-nodes-base.twilio\",\n \"parameters\": {\n \"operation\": \"send\",\n \"to\": \"={{ $json.from }}\",\n \"message\": \"You've been unsubscribed. Reply START to resubscribe.\"\n }\n }\n ]\n}\n```\n\n## SMS Drip Campaign\n```javascript\n// Day 0: Welcome SMS\n// Day 3: Value SMS\n// Day 7: Offer SMS\n\nconst campaigns = [\n { day: 0, message: \"Welcome to {brand}! Reply HELP for support.\" },\n { day: 3, message: \"Did you know? {tip}. Learn more: {link}\" },\n { day: 7, message: \"Special offer! Use code {code} for 20% off.\" }\n];\n\nconst daysSinceSignup = Math.floor((Date.now() - new Date($json.signup_date)) / 86400000);\nconst campaign = campaigns.find(c => c.day === daysSinceSignup);\n\nif (campaign) {\n return { send: true, message: campaign.message };\n}\nreturn { send: false };\n```", "metadata": {"topic": "sms_marketing", "type": "workflow"}}
{"instruction": "How do I integrate WhatsApp Business API with n8n?", "output": "# WhatsApp Business API Integration\n\n## Send WhatsApp Message (via Twilio)\n```json\n{\n \"name\": \"Send WhatsApp\",\n \"type\": \"n8n-nodes-base.twilio\",\n \"parameters\": {\n \"operation\": \"send\",\n \"from\": \"whatsapp:+14155238886\",\n \"to\": \"whatsapp:{{ $json.customerPhone }}\",\n \"message\": \"={{ $json.messageContent }}\"\n }\n}\n```\n\n## Send WhatsApp Template Message\n```json\n{\n \"name\": \"Send Template\",\n \"type\": \"n8n-nodes-base.httpRequest\",\n \"parameters\": {\n \"url\": \"https://graph.facebook.com/v18.0/{{ $env.WHATSAPP_PHONE_ID }}/messages\",\n \"method\": \"POST\",\n \"headers\": {\n \"Authorization\": \"Bearer {{ $env.WHATSAPP_TOKEN }}\",\n \"Content-Type\": \"application/json\"\n },\n \"body\": {\n \"messaging_product\": \"whatsapp\",\n \"to\": \"{{ $json.phone }}\",\n \"type\": \"template\",\n \"template\": {\n \"name\": \"order_confirmation\",\n \"language\": {\"code\": \"en\"},\n \"components\": [\n {\n \"type\": \"body\",\n \"parameters\": [\n {\"type\": \"text\", \"text\": \"{{ $json.customerName }}\"},\n {\"type\": \"text\", \"text\": \"{{ $json.orderNumber }}\"}\n ]\n }\n ]\n }\n }\n }\n}\n```\n\n## WhatsApp Webhook Handler\n```json\n{\n \"nodes\": [\n {\n \"name\": \"WhatsApp Webhook\",\n \"type\": \"n8n-nodes-base.webhook\",\n \"parameters\": {\"path\": \"whatsapp\", \"method\": \"POST\"}\n },\n {\n \"name\": \"Extract Message\",\n \"type\": \"n8n-nodes-base.code\",\n \"parameters\": {\n \"jsCode\": \"const entry = $json.entry?.[0];\\nconst change = entry?.changes?.[0];\\nconst message = change?.value?.messages?.[0];\\n\\nif (!message) return { type: 'status_update' };\\n\\nreturn {\\n from: message.from,\\n type: message.type,\\n text: message.text?.body || '',\\n timestamp: message.timestamp\\n};\"\n }\n },\n {\n \"name\": \"Route by Type\",\n \"type\": \"n8n-nodes-base.switch\",\n \"parameters\": {\n \"rules\": [\n {\"value\": \"text\"},\n {\"value\": \"image\"},\n {\"value\": \"location\"}\n ]\n }\n },\n {\n \"name\": \"Process Text\",\n \"type\": \"n8n-nodes-base.openAi\",\n \"parameters\": {\n \"prompt\": \"Customer message: {{ $json.text }}\\n\\nGenerate a helpful response.\"\n }\n },\n {\n \"name\": \"Reply\",\n \"type\": \"n8n-nodes-base.httpRequest\",\n \"parameters\": {\n \"url\": \"https://graph.facebook.com/v18.0/{{ $env.WHATSAPP_PHONE_ID }}/messages\",\n \"method\": \"POST\",\n \"body\": {\n \"messaging_product\": \"whatsapp\",\n \"to\": \"{{ $json.from }}\",\n \"type\": \"text\",\n \"text\": {\"body\": \"{{ $json.response }}\"}\n }\n }\n }\n ]\n}\n```\n\n## Multi-Channel Router\n```javascript\n// Route message to best channel\nconst customer = $json.customer;\nconst channelPriority = ['whatsapp', 'sms', 'email'];\n\nfor (const channel of channelPriority) {\n if (channel === 'whatsapp' && customer.whatsapp_opt_in) {\n return { channel: 'whatsapp', to: `whatsapp:${customer.phone}` };\n }\n if (channel === 'sms' && customer.sms_opt_in) {\n return { channel: 'sms', to: customer.phone };\n }\n if (channel === 'email' && customer.email_opt_in) {\n return { channel: 'email', to: customer.email };\n }\n}\nreturn { channel: 'none', reason: 'No opted-in channel' };\n```", "metadata": {"topic": "whatsapp", "type": "workflow"}}
{"instruction": "How do I build an omnichannel notification system in n8n?", "output": "# Omnichannel Notification System\n\n## Architecture\n```\nEvent \u2192 Determine Best Channel \u2192 Route \u2192 Send \u2192 Log \u2192 Track Delivery\n```\n\n## Main Workflow\n```json\n{\n \"nodes\": [\n {\n \"name\": \"Notification Trigger\",\n \"type\": \"n8n-nodes-base.webhook\",\n \"parameters\": {\"path\": \"notify\"}\n },\n {\n \"name\": \"Get User Preferences\",\n \"type\": \"n8n-nodes-base.postgres\",\n \"parameters\": {\n \"query\": \"SELECT * FROM user_preferences WHERE user_id = '{{ $json.userId }}'\"\n }\n },\n {\n \"name\": \"Select Channel\",\n \"type\": \"n8n-nodes-base.code\",\n \"parameters\": {\n \"jsCode\": \"const prefs = $json;\\nconst priority = $json.priority || 'normal';\\n\\n// Urgent: Try all channels\\nif (priority === 'urgent') {\\n return { channels: ['push', 'sms', 'email'] };\\n}\\n\\n// Normal: Use preferred channel\\nconst preferred = prefs.preferred_channel || 'email';\\nreturn { channels: [preferred] };\"\n }\n },\n {\n \"name\": \"Split Channels\",\n \"type\": \"n8n-nodes-base.splitInBatches\",\n \"parameters\": {\"batchSize\": 1}\n },\n {\n \"name\": \"Route by Channel\",\n \"type\": \"n8n-nodes-base.switch\",\n \"parameters\": {\n \"rules\": [\n {\"value\": \"email\"},\n {\"value\": \"sms\"},\n {\"value\": \"push\"},\n {\"value\": \"whatsapp\"},\n {\"value\": \"slack\"}\n ]\n }\n }\n ]\n}\n```\n\n## Channel Implementations\n\n### Email (SendGrid)\n```json\n{\n \"name\": \"Send Email\",\n \"type\": \"n8n-nodes-base.sendGrid\",\n \"parameters\": {\n \"to\": \"={{ $json.email }}\",\n \"subject\": \"={{ $json.subject }}\",\n \"html\": \"={{ $json.htmlContent }}\"\n }\n}\n```\n\n### SMS (Twilio)\n```json\n{\n \"name\": \"Send SMS\",\n \"type\": \"n8n-nodes-base.twilio\",\n \"parameters\": {\n \"to\": \"={{ $json.phone }}\",\n \"message\": \"={{ $json.smsContent }}\"\n }\n}\n```\n\n### Push (OneSignal)\n```json\n{\n \"name\": \"Send Push\",\n \"type\": \"n8n-nodes-base.httpRequest\",\n \"parameters\": {\n \"url\": \"https://onesignal.com/api/v1/notifications\",\n \"method\": \"POST\",\n \"headers\": {\"Authorization\": \"Basic {{ $env.ONESIGNAL_KEY }}\"},\n \"body\": {\n \"app_id\": \"{{ $env.ONESIGNAL_APP }}\",\n \"include_player_ids\": [\"{{ $json.pushToken }}\"],\n \"contents\": {\"en\": \"{{ $json.pushContent }}\"}\n }\n }\n}\n```\n\n## Delivery Tracking\n```javascript\n// Log all notification attempts\nawait db.insert('notification_log', {\n user_id: $json.userId,\n channel: $json.channel,\n message_id: $json.messageId,\n status: $json.deliveryStatus,\n sent_at: new Date(),\n metadata: JSON.stringify($json.metadata)\n});\n\n// Update user's last contact timestamp\nawait db.update('users')\n .set({ last_contacted: new Date() })\n .where('id', $json.userId);\n```", "metadata": {"topic": "omnichannel_notifications", "type": "workflow"}}
{"instruction": "How do I integrate Airbyte with n8n for ETL pipelines?", "output": "# Airbyte + n8n ETL Integration\n\n## Trigger Airbyte Sync\n```json\n{\n \"name\": \"Trigger Airbyte Sync\",\n \"type\": \"n8n-nodes-base.httpRequest\",\n \"parameters\": {\n \"url\": \"http://airbyte:8000/api/v1/connections/sync\",\n \"method\": \"POST\",\n \"headers\": {\n \"Authorization\": \"Basic {{ Buffer.from('airbyte:password').toString('base64') }}\"\n },\n \"body\": {\n \"connectionId\": \"{{ $json.connectionId }}\"\n }\n }\n}\n```\n\n## Monitor Sync Status\n```json\n{\n \"nodes\": [\n {\n \"name\": \"Trigger Sync\",\n \"type\": \"n8n-nodes-base.httpRequest\"\n },\n {\n \"name\": \"Wait\",\n \"type\": \"n8n-nodes-base.wait\",\n \"parameters\": {\"resume\": \"timeInterval\", \"interval\": 30}\n },\n {\n \"name\": \"Check Status\",\n \"type\": \"n8n-nodes-base.httpRequest\",\n \"parameters\": {\n \"url\": \"http://airbyte:8000/api/v1/jobs/get\",\n \"body\": {\"id\": \"{{ $json.job.id }}\"}\n }\n },\n {\n \"name\": \"Is Complete?\",\n \"type\": \"n8n-nodes-base.if\",\n \"parameters\": {\n \"conditions\": {\n \"string\": [{\n \"value1\": \"={{ $json.job.status }}\",\n \"value2\": \"succeeded\"\n }]\n }\n }\n },\n {\n \"name\": \"Loop Back\",\n \"type\": \"n8n-nodes-base.noOp\"\n }\n ]\n}\n```\n\n## Post-Sync Processing\n```javascript\n// After Airbyte sync completes, process the data\nconst syncStats = $json.job.attempts[0].attempt.totalStats;\n\nreturn {\n recordsSynced: syncStats.recordsEmitted,\n bytesEmitted: syncStats.bytesEmitted,\n status: 'completed',\n nextSteps: ['transform', 'validate', 'notify']\n};\n```\n\n## Orchestration Pattern\n```\nSchedule \u2192 Trigger Airbyte \u2192 Wait for Completion \u2192 \nTransform in n8n \u2192 Load to Destination \u2192 Notify Team\n```", "metadata": {"topic": "airbyte", "type": "etl"}}
{"instruction": "How do I implement Change Data Capture with Debezium and n8n?", "output": "# Debezium CDC with n8n\n\n## Kafka Consumer for CDC Events\n```json\n{\n \"nodes\": [\n {\n \"name\": \"Kafka Trigger\",\n \"type\": \"n8n-nodes-base.kafkaTrigger\",\n \"parameters\": {\n \"topic\": \"dbserver1.inventory.customers\",\n \"groupId\": \"n8n-cdc-consumer\",\n \"options\": {\n \"fromBeginning\": false,\n \"jsonParse\": true\n }\n }\n },\n {\n \"name\": \"Parse CDC Event\",\n \"type\": \"n8n-nodes-base.code\",\n \"parameters\": {\n \"jsCode\": \"const event = $json;\\nreturn {\\n operation: event.op, // c=create, u=update, d=delete\\n before: event.before,\\n after: event.after,\\n source: {\\n table: event.source.table,\\n db: event.source.db,\\n ts_ms: event.ts_ms\\n }\\n};\"\n }\n },\n {\n \"name\": \"Route by Operation\",\n \"type\": \"n8n-nodes-base.switch\",\n \"parameters\": {\n \"rules\": [\n {\"value\": \"c\", \"label\": \"Insert\"},\n {\"value\": \"u\", \"label\": \"Update\"},\n {\"value\": \"d\", \"label\": \"Delete\"}\n ]\n }\n }\n ]\n}\n```\n\n## Handle Insert Events\n```javascript\n// New customer created\nconst customer = $json.after;\n\n// Sync to CRM\nawait triggerWorkflow('crm-sync', {\n action: 'create',\n data: customer\n});\n\n// Send welcome email\nawait triggerWorkflow('welcome-email', {\n email: customer.email,\n name: customer.name\n});\n\nreturn { processed: true, customerId: customer.id };\n```\n\n## Handle Update Events\n```javascript\n// Customer updated - detect what changed\nconst before = $json.before;\nconst after = $json.after;\n\nconst changes = {};\nfor (const key of Object.keys(after)) {\n if (before[key] !== after[key]) {\n changes[key] = { old: before[key], new: after[key] };\n }\n}\n\n// Special handling for email change\nif (changes.email) {\n await triggerWorkflow('email-verification', {\n customerId: after.id,\n newEmail: after.email\n });\n}\n\nreturn { changes, customerId: after.id };\n```\n\n## Debezium Connector Config\n```json\n{\n \"name\": \"postgres-connector\",\n \"config\": {\n \"connector.class\": \"io.debezium.connector.postgresql.PostgresConnector\",\n \"database.hostname\": \"postgres\",\n \"database.port\": \"5432\",\n \"database.user\": \"debezium\",\n \"database.password\": \"debezium\",\n \"database.dbname\": \"app\",\n \"database.server.name\": \"dbserver1\",\n \"table.include.list\": \"public.customers,public.orders\",\n \"plugin.name\": \"pgoutput\",\n \"slot.name\": \"debezium\",\n \"publication.name\": \"dbz_publication\"\n }\n}\n```", "metadata": {"topic": "debezium_cdc", "type": "etl"}}
{"instruction": "How do I write automated tests for n8n workflows?", "output": "# Automated Testing for n8n Workflows\n\n## Test Framework Setup\n```javascript\n// tests/workflow-tests.js\nconst axios = require('axios');\n\nconst N8N_URL = process.env.N8N_URL || 'http://localhost:5678';\nconst API_KEY = process.env.N8N_API_KEY;\n\nasync function testWorkflow(workflowId, testData, expectedOutput) {\n // Execute workflow\n const response = await axios.post(\n `${N8N_URL}/api/v1/workflows/${workflowId}/execute`,\n { data: testData },\n { headers: { 'X-N8N-API-KEY': API_KEY } }\n );\n \n // Wait for completion\n const executionId = response.data.executionId;\n let execution;\n do {\n await new Promise(r => setTimeout(r, 1000));\n execution = await axios.get(\n `${N8N_URL}/api/v1/executions/${executionId}`,\n { headers: { 'X-N8N-API-KEY': API_KEY } }\n );\n } while (execution.data.status === 'running');\n \n // Validate output\n const output = execution.data.data.resultData.lastNodeExecutionStack;\n return validateOutput(output, expectedOutput);\n}\n```\n\n## Test Cases\n```javascript\ndescribe('Lead Processing Workflow', () => {\n test('should score high-value lead correctly', async () => {\n const testData = {\n email: 'test@enterprise.com',\n company_size: 500,\n budget: 50000\n };\n \n const result = await testWorkflow('lead-scoring', testData);\n \n expect(result.score).toBeGreaterThan(70);\n expect(result.segment).toBe('enterprise');\n });\n \n test('should reject invalid email', async () => {\n const testData = {\n email: 'invalid-email',\n company_size: 10\n };\n \n const result = await testWorkflow('lead-scoring', testData);\n \n expect(result.error).toBe('Invalid email format');\n });\n \n test('should handle timeout gracefully', async () => {\n const testData = {\n email: 'slow@test.com',\n simulate_delay: true\n };\n \n const result = await testWorkflow('lead-scoring', testData, { timeout: 5000 });\n \n expect(result.fallback_used).toBe(true);\n });\n});\n```\n\n## Webhook Testing\n```javascript\nasync function testWebhook(webhookPath, payload, expectedStatus = 200) {\n const response = await axios.post(\n `${N8N_URL}/webhook/${webhookPath}`,\n payload,\n { validateStatus: () => true }\n );\n \n return {\n status: response.status,\n data: response.data,\n passed: response.status === expectedStatus\n };\n}\n\n// Test examples\nawait testWebhook('order-received', { orderId: '123', items: [] }, 400); // Should fail validation\nawait testWebhook('order-received', { orderId: '123', items: [{sku: 'A1', qty: 2}] }, 200);\n```\n\n## CI Integration\n```yaml\n# .github/workflows/test.yml\njobs:\n test:\n runs-on: ubuntu-latest\n services:\n n8n:\n image: n8nio/n8n\n ports: ['5678:5678']\n steps:\n - uses: actions/checkout@v4\n - run: npm install\n - run: npm test\n env:\n N8N_URL: http://localhost:5678\n```", "metadata": {"topic": "testing", "type": "devops"}}