Documentation Index Fetch the complete documentation index at: https://docs.tryfltr.com/llms.txt
Use this file to discover all available pages before exploring further.
n8n Integration
n8n is an open-source workflow automation tool that you can self-host or use in the cloud. Perfect for developers who want full control over their automation workflows.
Why n8n?
Self-Hosted Deploy on your own infrastructure for complete control
Open Source Inspect, modify, and extend the platform
Developer-Friendly Code nodes, JavaScript expressions, and custom nodes
Fair Pricing Free self-hosted or affordable cloud plans
Installation
n8n Cloud
Fastest way to get started:
Sign up at n8n.cloud
Create your first workflow
No setup required
Self-Hosted (Docker)
# Using Docker
docker run -it --rm \
--name n8n \
-p 5678:5678 \
-v ~/.n8n:/home/node/.n8n \
n8nio/n8n
# Access at http://localhost:5678
Self-Hosted (npm)
npm install n8n -g
n8n start
Quick Start: FLTR Search Workflow
Step 1: Create New Workflow
Open n8n interface
Click New workflow
Name it “FLTR Knowledge Search”
Step 2: Add HTTP Request Node
Click + to add node
Search for HTTP Request
Configure:
Method: POST
URL: https://api.fltr.com/v1/mcp/query
Authentication: Generic Credential Type → Header Auth
Name: Authorization
Value: Bearer YOUR_API_KEY
Body Parameters (JSON):
{
"query" : "{{ $json.query }}" ,
"dataset_id" : "ds_abc123" ,
"limit" : 5
}
Step 3: Test the Node
Click Execute Node
View results in the output panel
Inspect the JSON response
Step 4: Process Results
Add a Code node to transform results:
// Access FLTR results
const results = $input . first (). json . results ;
// Format for output
const formatted = results . map ( result => ({
title: result . metadata ?. title || 'Untitled' ,
content: result . content ,
score: Math . round ( result . score * 100 ),
chunk_id: result . chunk_id
}));
return formatted . map ( item => ({ json: item }));
Common Workflows
1. Email to Knowledge Base Search
Nodes:
Email Trigger (IMAP) - Watch inbox
HTTP Request - FLTR Query
Code - Format results
Send Email - Reply with results
FLTR HTTP Request:
{
"query" : "{{ $json.subject }} {{ $json.text }}" ,
"dataset_id" : "ds_support_kb" ,
"limit" : 3 ,
"rerank" : true
}
Code Node (Format Response):
const results = $input . first (). json . results ;
const response = `
Hi,
Based on your email, here are some helpful resources:
${ results . map (( r , i ) => `
${ i + 1 } . ${ r . metadata . title } ( ${ Math . round ( r . score * 100 ) } % match)
${ r . content . substring ( 0 , 200 ) } ...
` ). join ( ' \n ' ) }
Hope this helps!
` ;
return [{ json: { response , to: $ ( 'Email Trigger' ). first (). json . from } }];
2. Slack Q&A Bot
Nodes:
Slack Trigger - New message in channel
IF - Check if question
HTTP Request - FLTR Query
Slack - Post reply
IF Condition:
{{ $json.text.includes('?') }}
FLTR Query:
{
"query" : "{{ $json.text }}" ,
"dataset_id" : "ds_company_kb" ,
"limit" : 1
}
Slack Reply:
{{ $json.results[0].content }}
_Source: {{ $json.results[0].metadata.title }}_
_Confidence: {{ Math.round($json.results[0].score * 100) }}%_
3. Document Indexer Pipeline
Nodes:
Webhook - Receive document
Code - Extract metadata
HTTP Request - Upload to FLTR
Slack - Send notification
Code Node (Extract Metadata):
const doc = $input . first (). json ;
return [{
json: {
content: doc . text ,
metadata: {
title: doc . title ,
author: doc . author ,
source: 'API Upload' ,
created_at: new Date (). toISOString (),
tags: doc . tags || []
}
}
}];
HTTP Request (Upload):
Method: POST
URL: https://api.fltr.com/v1/datasets/ds_abc123/documents
Body:
{
"content": "{{ $json.content }}",
"metadata": {{ JSON.stringify($json.metadata) }}
}
4. Customer Support Automation
Nodes:
Webhook Trigger - New support ticket
HTTP Request - FLTR Query
Switch - Route by confidence
Multiple endpoints - Different actions per route
Switch Routes:
Route 1: {{ $json.results[0].score >= 0.8 }}
→ Auto-respond with answer
Route 2: {{ $json.results[0].score >= 0.5 && $json.results[0].score < 0.8 }}
→ Create ticket with suggestions
Route 3: {{ $json.results[0].score < 0.5 }}
→ Escalate to human
Advanced Techniques
Using Code Nodes
n8n’s Code node supports full JavaScript:
Example: Filter and rank results
// Get FLTR results
const results = $input . first (). json . results ;
// Filter by score threshold
const filtered = results . filter ( r => r . score >= 0.7 );
// Sort by score (descending)
const sorted = filtered . sort (( a , b ) => b . score - a . score );
// Add ranking
const ranked = sorted . map (( r , i ) => ({
... r ,
rank: i + 1 ,
score_percent: Math . round ( r . score * 100 )
}));
return ranked . map ( item => ({ json: item }));
Example: Combine multiple queries
// Run multiple FLTR queries and combine results
const query1 = $ ( 'HTTP Request 1' ). first (). json . results ;
const query2 = $ ( 'HTTP Request 2' ). first (). json . results ;
// Merge and deduplicate by chunk_id
const allResults = [ ... query1 , ... query2 ];
const unique = allResults . reduce (( acc , curr ) => {
if ( ! acc . find ( r => r . chunk_id === curr . chunk_id )) {
acc . push ( curr );
}
return acc ;
}, []);
// Sort by score
const sorted = unique . sort (( a , b ) => b . score - a . score );
return sorted . map ( item => ({ json: item }));
Loop Over Results
Use Split in Batches to process each result:
Add Split in Batches after FLTR query
Set batch size to 1
Connect to action node
Each result processed individually
Example: Create Notion page for each result
Input: {{ $json.results }}
Batch size: 1
Notion node:
Title: {{ $json.metadata.title }}
Content: {{ $json.content }}
Tags: {{ $json.metadata.category }}
Error Handling
Add error workflows:
On any node, click Settings (gear icon)
Enable Continue On Fail
Add IF node to check for errors
Route failures to error handler
Error Check:
{{ $json . error !== undefined }}
Error Notification:
⚠️ Workflow Error
Node: {{ $node.name }}
Error: {{ $json.error }}
Input: {{ JSON.stringify($json) }}
Scheduling Workflows
Add Schedule Trigger for recurring tasks:
Example: Daily document sync
Trigger: Cron - 0 2 * * * (2 AM daily)
Action: Fetch new documents from source
Upload to FLTR
Send summary email
Using Credentials
Store API keys securely:
Go to Credentials → New
Select Header Auth
Name: FLTR API Key
Header name: Authorization
Header value: Bearer YOUR_API_KEY
Use in HTTP Request nodes:
Authentication: FLTR API Key
All FLTR Endpoints
Query Dataset
Node: HTTP Request
Method: POST
URL: https://api.fltr.com/v1/mcp/query
Authentication: Header Auth
Header: Authorization
Value: Bearer YOUR_API_KEY
Body (JSON):
{
"query": "{{ $json.query }}",
"dataset_id": "ds_abc123",
"limit": 5,
"rerank": false
}
Batch Query
URL: https://api.fltr.com/v1/mcp/batch-query
Body:
{
"queries": {{ JSON.stringify($json.queries) }},
"dataset_id": "ds_abc123",
"limit": 3
}
Upload Document
URL: https://api.fltr.com/v1/datasets/DATASET_ID/documents
Body:
{
"content": "{{ $json.content }}",
"metadata": {{ JSON.stringify($json.metadata) }}
}
Create Dataset
URL: https://api.fltr.com/v1/datasets
Body:
{
"name": "{{ $json.name }}",
"description": "{{ $json.description }}",
"is_public": false
}
List Datasets
Method: GET
URL: https://api.fltr.com/v1/datasets
Authentication: Header Auth
Expressions and Functions
Accessing Data
// Current node data
{{ $json . field }}
// Previous node data
{{ $ ( 'Node Name' ). first (). json . field }}
// All items from previous node
{{ $ ( 'Node Name' ). all () }}
// Item by index
{{ $ ( 'Node Name' ). item . json . field }}
String Operations
// Substring
{{ $json . content . substring ( 0 , 100 ) }}
// Uppercase/lowercase
{{ $json . title . toUpperCase () }}
// Replace
{{ $json . text . replace ( 'old' , 'new' ) }}
// Includes
{{ $json . text . includes ( 'keyword' ) }}
Array Operations
// Map
{{ $json . results . map ( r => r . title ) }}
// Filter
{{ $json . results . filter ( r => r . score > 0.7 ) }}
// Join
{{ $json . tags . join ( ', ' ) }}
// Length
{{ $json . results . length }}
Math Functions
// Round
{{ Math . round ( $json . score * 100 ) }}
// Max/Min
{{ Math . max ( ... $json . scores ) }}
// Random
{{ Math . random () }}
Rate Limiting
Handle FLTR’s rate limits in n8n:
Method 1: Wait Node
Add Wait node between iterations:
Method 2: Code Node Delay
// Add delay before returning
await new Promise ( resolve => setTimeout ( resolve , 1000 ));
return $input . all ();
Method 3: Error Handling
// In error workflow
if ( $json . error ?. includes ( 'rate limit' )) {
// Wait 1 hour
await new Promise ( resolve => setTimeout ( resolve , 3600000 ));
// Retry
return [{ json: { retry: true } }];
}
Webhook Workflows
Create Webhook Endpoint
Add Webhook node
Set HTTP Method: POST
Copy webhook URL
Configure response
Webhook Response:
{
"status" : "success" ,
"results" : { { JSON.stringify($('HTTP Request').first().json.results) }}
}
Secure Webhooks
Validate incoming requests:
Add IF node after webhook
Check secret header:
{{ $json.headers.authorization === 'Bearer YOUR_SECRET' }}
Route invalid requests to error response
Production Best Practices
1. Use Environments
Set environment variables:
# In docker-compose.yml
environment:
- N8N_ENCRYPTION_KEY=your-key
- FLTR_API_KEY=your-api-key
- FLTR_DATASET_ID=ds_abc123
Access in workflows:
2. Enable Execution Data
Keep execution history:
Settings → Workflow Settings:
Save execution progress: Yes
Save manual executions: Yes
Save error executions: Yes
3. Add Monitoring
Create monitoring workflow:
Trigger: Schedule (every 5 minutes)
Check: Last execution status
Alert: Send notification if failed
Use Merge nodes to combine data
Enable Continue On Fail for non-critical nodes
Use Split in Batches for large datasets
Cache results with Set node
Complete Example: Support Ticket System
Here’s a production-ready workflow:
Node 1: Webhook
HTTP Method: POST
Path: support-ticket
Response Mode: When Last Node Finishes
Node 2: Validate Input
// Code node
const required = [ 'email' , 'subject' , 'description' ];
const missing = required . filter ( f => ! $json [ f ]);
if ( missing . length > 0 ) {
throw new Error ( `Missing fields: ${ missing . join ( ', ' ) } ` );
}
return [ $input . first ()];
Node 3: FLTR Query
{
"query" : "{{ $json.subject }} {{ $json.description }}" ,
"dataset_id" : "{{ $env.FLTR_SUPPORT_KB }}" ,
"limit" : 5 ,
"rerank" : true
}
Node 4: Switch (Route by Confidence)
Route 1: {{ $json.results[0].score >= 0.8 }}
Route 2: {{ $json.results[0].score >= 0.5 }}
Route 3: {{ $json.results[0].score < 0.5 }}
Node 5a: Auto-Response Email
To: {{ $('Webhook').first().json.email }}
Subject: Re: {{ $('Webhook').first().json.subject }}
Hi,
{{ $json.results[0].content }}
Source: {{ $json.results[0].metadata.title }}
If this doesn't help, our team will follow up.
Node 5b: Create Zendesk Ticket
{
"subject" : "{{ $('Webhook').first().json.subject }}" ,
"description" : "{{ $('Webhook').first().json.description }}" ,
"requester" : "{{ $('Webhook').first().json.email }}" ,
"tags" : [ "fltr-suggested" ],
"comment" : {
"body" : "Suggested docs: \n {{ $json.results.map(r => r.metadata.title).join(' \n ') }}"
}
}
Node 5c: Slack Alert
⚠️ Low-confidence ticket
From: {{ $('Webhook').first().json.email }}
Score: {{ Math.round($json.results[0].score * 100) }}%
Subject: {{ $('Webhook').first().json.subject }}
Node 6: Webhook Response
{
"status" : "processed" ,
"confidence" : { { $('FLTR Query').first().json.results[0].score }},
"action" : "{{ $runIndex === 0 ? 'auto-responded' : $runIndex === 1 ? 'ticket-created' : 'escalated' }}"
}
Resources
n8n Documentation Official n8n docs
FLTR API Reference Complete API documentation
n8n Community Get help from the community
Deployment Guide Self-host n8n in production
Next Steps