AutomationFlowsSlack & Telegram › Classify Documents and Score Confidence with Easybits Extractor and Slack

Classify Documents and Score Confidence with Easybits Extractor and Slack

ByFelix @easybits on n8n.io

Upload a document (PDF, PNG, or JPEG) via a hosted web form and let the easybits Extractor classify it into one of your defined categories – with a self-reported confidence score on every classification. Low-confidence or unclassifiable documents are routed to Slack for manual…

Event trigger★★★☆☆ complexity12 nodesForm Trigger@Easybits/N8N Nodes ExtractorSlack
Slack & Telegram Trigger: Event Nodes: 12 Complexity: ★★★☆☆ Added:

This workflow corresponds to n8n.io template #15229 — we link there as the canonical source.

This workflow follows the Form Trigger → Slack recipe pattern — see all workflows that pair these two integrations.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "meta": {
    "templateCredsSetupCompleted": false
  },
  "name": "easybits' Extractor Classification Workflow (Community Node Update)",
  "tags": [
    {
      "name": "AI Classification"
    },
    {
      "name": "easybits"
    },
    {
      "name": "Document Processing"
    },
    {
      "name": "AI"
    }
  ],
  "nodes": [
    {
      "id": "8da8cbef-6c27-4780-bf3d-c1429967f0d5",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -208,
        -160
      ],
      "parameters": {
        "color": 7,
        "width": 352,
        "height": 320,
        "content": "## \ud83d\udccb Form Upload\nAccepts a file upload via a **web form**. Supports **PDF, PNG, and JPEG**."
      },
      "typeVersion": 1
    },
    {
      "id": "b7de03db-e825-4a95-9835-eb6355e290da",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1040,
        -592
      ],
      "parameters": {
        "width": 816,
        "height": 1472,
        "content": "# \ud83d\udcc4 easybits' Document Classification & Confidence Scoring\n\n## What This Workflow Does\nUpload a document (PDF, PNG, or JPEG) via a hosted web form and let the **easybits Extractor** classify it into one of your defined categories \u2014 **with a self-reported confidence score** on every classification. Low-confidence or unclassifiable documents are routed to Slack for manual review. Everything else continues through your pipeline.\n\n## Why Confidence Scoring Matters\nClassification without confidence scoring is a black box: you never know whether the model was sure or guessing. By asking the extractor to return both `document_class` and `confidence_score` in a single call, you get a clean signal for routing decisions and a trivial error-handling pattern \u2014 no separate model call, no extra latency, no extra cost.\n\n## How It Works\n1. **Form Upload** \u2013 A user uploads a file through the n8n web form.\n2. **Classify + Score via easybits** \u2013 The file is sent to the easybits Extractor, which returns two fields: `document_class` (e.g. `medical_invoice`, `hotel_invoice`, or `null` if uncertain) and `confidence_score` (a decimal between 0.0 and 1.0).\n3. **Validation** \u2013 An IF node checks whether the class is empty OR the confidence is below 0.5. Either condition routes the document to Slack for manual review. Everything else passes through to the success branch.\n4. **Continue Pipeline** \u2013 From here, extend the workflow however you like: route to Google Drive folders, log to a spreadsheet, trigger type-specific extraction, etc.\n\n## Setup Guide\n\n### 1. Create Your easybits Extractor Pipeline\n1. Go to **extractor.easybits.tech** and create a new pipeline.\n2. Add **two fields** to the mapping:\n   - `document_class` \u2013 for the classification label\n   - `confidence_score` \u2013 for the self-reported confidence\n3. In the description of each field, paste the matching prompt. Use the two prompt sticky notes in this workflow as starting points \u2014 they're production-tested.\n4. Adjust the categories and threshold guidance to fit your use case.\n\n### 2. Install the easybits Extractor Node\n1. The node is **verified** and works on n8n Cloud out of the box \u2014 just search for it in the node panel.\n2. For self-hosted instances: **Settings \u2192 Community Nodes \u2192 Install** `@easybits/n8n-nodes-extractor`.\n\n### 3. Configure the Node\n1. Add the **easybits Extractor** node to your workflow.\n2. Enter your **Pipeline ID** and **API Key** from the pipeline details page.\n\nThe node reads binary data directly from the previous node. No Base64 conversion or manual HTTP configuration needed.\n\n### 4. Tune the Confidence Threshold\nThe default threshold in the IF node is **0.5**. Raise it (e.g. 0.7) if your downstream pipeline is sensitive to misclassification, or lower it if you'd rather catch more edge cases manually. Adjust based on your review capacity.\n\n### 5. Activate & Test\n1. Click **Active** in the top-right corner of n8n.\n2. Open the form URL and upload a test document \u2014 try both a clear-cut case and an ambiguous one.\n3. Check the execution output: you should see your `document_class` and `confidence_score` in the response, and the review branch should fire on the ambiguous document.\n\n## Credentials to Configure\n- **easybits Extractor** \u2013 Pipeline ID + API Key\n- **Slack** \u2013 workspace credentials and the channel/user to receive review alerts"
      },
      "typeVersion": 1
    },
    {
      "id": "98f01f20-cfeb-42f5-9acf-18c6287ca307",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        160,
        -160
      ],
      "parameters": {
        "color": 7,
        "width": 576,
        "height": 320,
        "content": "## \ud83d\ude80 Classify + Score\nSends the uploaded document to the **easybits Extractor**, which returns two fields in a single call: `document_class` (the assigned category or `null`) and `confidence_score` (0.0\u20131.0)."
      },
      "typeVersion": 1
    },
    {
      "id": "005bb615-c5a1-45a2-a3e3-c9ef67f0081a",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        752,
        -288
      ],
      "parameters": {
        "color": 7,
        "width": 480,
        "height": 448,
        "content": "## \u2705 Validation Check\nChecks whether the classification is trustworthy. Uses **OR logic** across two conditions:\n\n- `document_class` is empty \u2192 model could not assign a category\n- `confidence_score` is below **0.5** \u2192 model is unsure about its decision\n\nEither one routes to Slack for manual review. Only high-confidence, clearly classified documents continue through the pipeline."
      },
      "typeVersion": 1
    },
    {
      "id": "04a78b6d-e3a8-4319-b0eb-efd17d52310c",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1248,
        -288
      ],
      "parameters": {
        "color": 7,
        "width": 352,
        "height": 448,
        "content": "## \ud83d\udcac Slack Alert\nPosts a review notification to the finance channel when a document cannot be classified confidently. Includes the assigned class (or `null`), the confidence score, and a timestamp so the reviewer can quickly find and handle the document manually."
      },
      "typeVersion": 1
    },
    {
      "id": "2abe9d70-4f3e-4e73-9bca-2f6ded351e1f",
      "name": "Form Trigger: Upload Document",
      "type": "n8n-nodes-base.formTrigger",
      "position": [
        -80,
        -16
      ],
      "parameters": {
        "options": {},
        "formTitle": "Image Upload",
        "formFields": {
          "values": [
            {
              "fieldType": "file",
              "fieldLabel": "image"
            }
          ]
        }
      },
      "typeVersion": 2.5
    },
    {
      "id": "462ab12e-29e9-44f3-93cd-06bb395c08b4",
      "name": "easybits: Classify & Score",
      "type": "@easybits/n8n-nodes-extractor.easybitsExtractor",
      "position": [
        400,
        -16
      ],
      "parameters": {},
      "credentials": {
        "easybitsExtractorApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2
    },
    {
      "id": "e4b96f52-882c-4a64-828a-080245c51dcd",
      "name": "IF: Empty or Low Confidence",
      "type": "n8n-nodes-base.if",
      "position": [
        944,
        -16
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "or",
          "conditions": [
            {
              "id": "b7761fcc-381a-4d02-baff-21528a6678cc",
              "operator": {
                "type": "string",
                "operation": "empty",
                "singleValue": true
              },
              "leftValue": "={{ $json.data.document_class }}",
              "rightValue": "null"
            },
            {
              "id": "a3df6a9d-67f6-46b1-b61c-31f033b3d16e",
              "operator": {
                "type": "number",
                "operation": "lte"
              },
              "leftValue": "={{ $json.data.confidence_score }}",
              "rightValue": 0.5
            },
            {
              "id": "c734be16-587a-4bee-830b-dbb2e718107a",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.data.document_class }}",
              "rightValue": "null"
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "ac6303cf-edc8-4fe1-ae6d-0d61587dc53d",
      "name": "Slack: Notify \u2013 Needs Review",
      "type": "n8n-nodes-base.slack",
      "position": [
        1376,
        -32
      ],
      "parameters": {
        "text": "=\u26a0\ufe0f Document needs manual review\n\nName: {{ $('Form Trigger: Upload Document').item.json.image[0].filename }}\nClassification: {{ $json.data.document_class || 'null' }}\nConfidence: {{ $json.data.confidence_score }}\n\nThe easybits Extractor either could not assign a category or returned a low-confidence result. Please review the uploaded document manually.\n\nTimestamp: {{ $now.toISO() }}",
        "user": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_SLACK_USER_OR_CHANNEL_ID",
          "cachedResultName": "YOUR_SLACK_USER_OR_CHANNEL_NAME"
        },
        "select": "user",
        "otherOptions": {}
      },
      "credentials": {
        "slackApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.4
    },
    {
      "id": "afc16b16-9464-41cf-9080-4a05d97e92ff",
      "name": "Continue Workflow",
      "type": "n8n-nodes-base.noOp",
      "position": [
        1376,
        256
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "d761b8e5-f137-474c-ab7e-5f53eea80485",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        160,
        176
      ],
      "parameters": {
        "color": 7,
        "width": 272,
        "height": 528,
        "content": "## \ud83d\udcca Classification Prompt\nPaste the full prompt into the description of the `document_class` field in your easybits pipeline.\n\n**What it does:**\nAssigns one of 5 categories \u2013 `medical_invoice`, `restaurant_invoice`, `hotel_invoice`, `trades_invoice`, `telecom_invoice` \u2013 or returns `null` if the document doesn't cleanly fit any category.\n\n\ud83d\udc49 Full prompt: https://github.com/felix-sattler-easybits/n8n-workflows/blob/aa5d2502b3ef0a87e52833a2a3a44b99a297ff82/easybits-document-classification-and-confidence-score/easybits_classification_prompt.md"
      },
      "typeVersion": 1
    },
    {
      "id": "784e6ee0-62e3-4b80-a2fc-c8dcfd4c5566",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        448,
        176
      ],
      "parameters": {
        "color": 7,
        "width": 288,
        "height": 448,
        "content": "## \ud83c\udfaf Confidence Scoring Prompt\nPaste the full prompt into the description of the `confidence_score` field in your easybits pipeline.\n\n**What it does:**\nReturns a decimal between 0.0 and 1.0 representing how certain the model is about its classification decision \u2013 including `null` decisions.\n\n\ud83d\udc49 Full prompt: https://github.com/felix-sattler-easybits/n8n-workflows/blob/aa5d2502b3ef0a87e52833a2a3a44b99a297ff82/easybits-document-classification-and-confidence-score/easybits_confidence_scoring_prompt.md"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "callerPolicy": "workflowsFromSameOwner",
    "timeSavedMode": "fixed",
    "availableInMCP": false,
    "executionOrder": "v1"
  },
  "versionId": "",
  "connections": {
    "easybits: Classify & Score": {
      "main": [
        [
          {
            "node": "IF: Empty or Low Confidence",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF: Empty or Low Confidence": {
      "main": [
        [
          {
            "node": "Slack: Notify \u2013 Needs Review",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Continue Workflow",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Form Trigger: Upload Document": {
      "main": [
        [
          {
            "node": "easybits: Classify & Score",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

Upload a document (PDF, PNG, or JPEG) via a hosted web form and let the easybits Extractor classify it into one of your defined categories – with a self-reported confidence score on every classification. Low-confidence or unclassifiable documents are routed to Slack for manual…

Source: https://n8n.io/workflows/15229/ — original creator credit. Request a take-down →

More Slack & Telegram workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

Slack & Telegram

Upload a document (PDF, PNG, JPEG) via a web form and let easybits Extractor classify it into one of your defined categories. Based on the classification result and a confidence score, the document is

Form Trigger, Google Drive, Slack +1
Slack & Telegram

🧩 Jamf Smart Group Membership to Slack Automatically export Jamf smart group membership to Slack in CSV format. Perfect for IT and security teams who need fast visibility into device grouping—without

HTTP Request, Slack
Slack & Telegram

Upload a document (PDF, PNG, JPEG) via a web form and let easybits Extractor classify it into one of your defined categories. Based on the classification result and a confidence score, the document is

Form Trigger, HTTP Request, Google Drive +1
Slack & Telegram

🚀 Lightning-fast setup - Deploy in under 5 minutes 💡 Zero AI costs - Uses simple math instead of expensive LLM calls 🛡️ 99% spam blocking - Mathematical CAPTCHAs stop bots instantly ⚡ Ultra-efficient

Telegram Trigger, Google Sheets, Telegram +1
Slack & Telegram

The Recap AI - Reverse Engineer Short Form AI Video. Uses formTrigger, httpRequest, slack. Event-driven trigger; 22 nodes.

Form Trigger, HTTP Request, Slack