AutomationFlowsSlack & Telegram › Import Research Papers From Telegram to Zotero with AI Abstract Summaries

Import Research Papers From Telegram to Zotero with AI Abstract Summaries

ByBudi SJ @budisj on n8n.io

This workflow allows you to automatically import research papers into your Zotero library by simply sending a DOI link through Telegram. It fetches metadata from reliable sources such as Crossref, DataCite, and Unpaywall, enriches the bibliographic details, attaches the best…

Event trigger★★★★☆ complexityAI-powered25 nodesTelegram TriggerHTTP RequestChain LlmOpenRouter ChatTelegram
Slack & Telegram Trigger: Event Nodes: 25 Complexity: ★★★★☆ AI nodes: yes Added:

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

This workflow follows the Chainllm → HTTP Request 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
{
  "id": "njoCDW50H4hQEGIY",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Automatically Import Research Papers using DOI URL from Telegram to Zotero",
  "tags": [],
  "nodes": [
    {
      "id": "474334ec-ff15-4a12-a200-50eb928f11db",
      "name": "Telegram Trigger",
      "type": "n8n-nodes-base.telegramTrigger",
      "position": [
        9.007782644689968,
        0
      ],
      "parameters": {
        "updates": [
          "message"
        ],
        "additionalFields": {}
      },
      "typeVersion": 1.2
    },
    {
      "id": "80605785-8fd8-4d86-893d-e33d9cff315e",
      "name": "Code",
      "type": "n8n-nodes-base.code",
      "position": [
        220,
        0
      ],
      "parameters": {
        "jsCode": "// Node: Code (Parse DOI)\nconst txt = $json.message?.text?.trim() || \"\";\n\nfunction extractDOI(s) {\n  // 1) doi.org/...\n  let m = s.match(/doi\\.org\\/(10\\.\\d{4,9}\\/\\S+)/i);\n  if (m) return m[1].replace(/[)\\].,;]*$/, \"\");\n  // 2) raw DOI\n  m = s.match(/(10\\.\\d{4,9}\\/\\S+)/i);\n  if (m) return m[1].replace(/[)\\].,;]*$/, \"\");\n  // 3) arXiv link\n  m = s.match(/arxiv\\.org\\/abs\\/([\\w\\-.]+)/i);\n  if (m) return `10.48550/arXiv.${m[1]}`;\n  return null;\n}\n\nconst doi = extractDOI(txt);\nif (!doi) {\n  return [{ error: true, message: \"DOI not found. Please send a DOI or arXiv/doi.org link.\" }];\n}\n\nreturn [{ doi }];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "7e96135b-4bfb-4a05-a7fe-4936f771e7e5",
      "name": "HTTP Request2",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueRegularOutput",
      "position": [
        960,
        0
      ],
      "parameters": {
        "url": "=https://api.datacite.org/dois/{{ $('Code').item.json.doi }}",
        "options": {}
      },
      "typeVersion": 4.2
    },
    {
      "id": "6562fd43-ad5a-4172-bf40-e627adec9b65",
      "name": "HTTP Request3",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueRegularOutput",
      "position": [
        960,
        -260
      ],
      "parameters": {
        "url": "=https://api.crossref.org/works/{{ $('Code').item.json.doi }}",
        "options": {}
      },
      "typeVersion": 4.2,
      "alwaysOutputData": false
    },
    {
      "id": "44f8af5d-d0c5-4fbc-9717-9bdcc80f6389",
      "name": "HTTP Request4",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueRegularOutput",
      "position": [
        960,
        260
      ],
      "parameters": {
        "url": "=https://api.unpaywall.org/v2/{{ $('Code').item.json.doi }}?email=your-email@example.com",
        "options": {}
      },
      "typeVersion": 4.2
    },
    {
      "id": "b63893ad-f200-4c1b-ba07-7f429f38f2ff",
      "name": "HTTP Request",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        640,
        0
      ],
      "parameters": {
        "url": "=https://api.zotero.org/keys/{{ $json['Zotero API Key'] }}",
        "options": {},
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Zotero-API-Key",
              "value": "={{ $json['Zotero API Key'] }}"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "9f834057-efc6-4f75-b114-4db5d39bd498",
      "name": "Edit Fields",
      "type": "n8n-nodes-base.set",
      "position": [
        420,
        0
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "2530066f-becf-4a83-b96c-a91ddd4aceb1",
              "name": "Zotero API Key",
              "type": "string",
              "value": "={{ $credentials.zoteroApi.key }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "d7b1e0b4-dee1-4359-8da6-b9f3df1854f6",
      "name": "Code4",
      "type": "n8n-nodes-base.code",
      "position": [
        1680,
        0
      ],
      "parameters": {
        "jsCode": "// Code4 \u2014 Build Zotero parent metadata + pick best PDF URL\n// Input from Merge: $json.crossref, $json.datacite, $json.unpay, and $json.doi\n\nconst doi = $json.doi;\n\n// Unwrap API results if not error\nconst crossrefBody = ($json.crossref && !$json.crossref.error) ? $json.crossref.message : null;\nconst dataciteAttr = ($json.datacite && !$json.datacite.error) ? $json.datacite.data?.attributes : null;\nconst unpayBody    = ($json.unpay && !$json.unpay.error) ? $json.unpay : null;\n\nconst pick = (...vals) => vals.find(v => {\n  if (v === undefined || v === null) return false;\n  if (typeof v === 'string') return v.trim().length > 0;\n  return true;\n}) ?? null;\n\n/* ---------- PDF pickers ---------- */\nfunction fromCrossref(m) {\n  if (!m) return null;\n  const links = m.link || [];\n  for (const l of links) {\n    const ct  = (l['content-type'] || '').toLowerCase();\n    const url = l.URL || '';\n    if (ct.includes('pdf') || /\\.pdf(\\?|$)/i.test(url)) return url;\n  }\n  return null;\n}\n\nfunction fromDataCite(attr) {\n  if (!attr) return null;\n  // try identifiers -> arXiv\n  const ids = attr.identifiers || [];\n  const arxiv = ids.find(i => /arxiv/i.test(i.identifierType || ''))?.identifier;\n  if (arxiv) {\n    const id = String(arxiv).replace(/^arXiv:/i,'');\n    return `https://arxiv.org/pdf/${id}.pdf`;\n  }\n  return null;\n}\n\nfunction fromUnpay(u) {\n  if (!u) return null;\n  if (u.best_oa_location?.url_for_pdf) return u.best_oa_location.url_for_pdf;\n  if (/\\.pdf(\\?|$)/i.test(u.best_oa_location?.url || '')) return u.best_oa_location.url;\n  for (const loc of (u.oa_locations || [])) {\n    if (loc.url_for_pdf) return loc.url_for_pdf;\n    if (/\\.pdf(\\?|$)/i.test(loc.url || '')) return loc.url;\n  }\n  return null;\n}\n\n// Priority: Crossref \u2192 Unpaywall \u2192 DataCite \u2192 arXiv fallback (from DOI)\nlet pdfUrl = fromCrossref(crossrefBody);\nif (!pdfUrl) pdfUrl = fromUnpay(unpayBody);\nif (!pdfUrl) pdfUrl = fromDataCite(dataciteAttr);\nif (!pdfUrl && /^10\\.48550\\/arxiv\\./i.test(doi || '')) {\n  const arxivId = doi.replace(/^10\\.48550\\/arxiv\\./i, '');\n  pdfUrl = `https://arxiv.org/pdf/${arxivId}.pdf`;\n}\n\n/* ---------- Parent metadata (Zotero item) ---------- */\n// Title\nconst title = pick(\n  crossrefBody?.title?.[0],\n  dataciteAttr?.titles?.[0]?.title,\n  doi\n);\n\n// Date (YYYY, YYYY-MM, or YYYY-MM-DD)\nconst issued = crossrefBody?.issued?.['date-parts']?.[0] || [];\nconst dateStr = issued.length\n  ? issued.join('-')\n  : pick(\n      dataciteAttr?.published,\n      dataciteAttr?.publishedOnline,\n      dataciteAttr?.publishedPrint,\n      dataciteAttr?.created\n    ) || \"\";\n\n// Journal / container\nconst publicationTitle = pick(\n  crossrefBody?.['container-title']?.[0],\n  dataciteAttr?.container?.title\n) || \"\";\n\n// Landing page (not PDF)\nconst landingFromCR = crossrefBody?.URL;\nconst landingFromUP = unpayBody?.best_oa_location?.url || unpayBody?.oa_locations?.[0]?.url;\nconst landingFromDC = dataciteAttr?.url;\nconst url = pick(landingFromCR, landingFromUP, landingFromDC) || \"\";\n\n// Abstract\nlet abstractNote = \"\";\nif (Array.isArray(dataciteAttr?.descriptions) && dataciteAttr.descriptions.length) {\n  const absExact = dataciteAttr.descriptions.find(d => /abstract/i.test(d.descriptionType || ''));\n  abstractNote = pick(absExact?.description, dataciteAttr.descriptions[0]?.description) || \"\";\n}\n\n// Creators\nlet creators = [];\nif (Array.isArray(crossrefBody?.author)) {\n  creators = crossrefBody.author.map(a => ({\n    creatorType: \"author\",\n    firstName: a.given || \"\",\n    lastName:  a.family || (a.name || \"\")\n  }));\n} else if (Array.isArray(dataciteAttr?.creators)) {\n  creators = dataciteAttr.creators.map(c => ({\n    creatorType: \"author\",\n    firstName: c.givenName || \"\",\n    lastName:  c.familyName || (c.name || \"\")\n  }));\n}\n\n// Tags\nconst tags = [];\nif (Array.isArray(crossrefBody?.subject)) {\n  for (const s of crossrefBody.subject.slice(0, 5)) tags.push({ tag: String(s) });\n}\ntags.push({ tag: \"from-telegram\" });\n\n// Item type heuristic\nconst itemType = publicationTitle ? \"journalArticle\" : \"preprint\";\n\n// Build meta object for POST /items (parent)\nconst meta = {\n  itemType,\n  title,\n  DOI: doi || \"\",\n  url,\n  date: dateStr,\n  publicationTitle,\n  abstractNote,\n  creators,\n  tags\n};\n\n// Unified output for next step:\n// - meta: used for \"Zotero - Create Parent\"\n// - pdfUrl + hasPdf: for IF & attachment creation (linked_url)\nreturn [{\n  doi,\n  title,\n  meta,\n  pdfUrl,\n  hasPdf: Boolean(pdfUrl)\n}];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "c7aa9f0e-d58a-48d8-8353-f2c60feb42fc",
      "name": "Merge",
      "type": "n8n-nodes-base.merge",
      "position": [
        1520,
        0
      ],
      "parameters": {
        "mode": "combine",
        "options": {},
        "combineBy": "combineByPosition",
        "numberInputs": 3
      },
      "executeOnce": true,
      "typeVersion": 3.2
    },
    {
      "id": "5f26c1c8-f21f-4aca-b4ae-84ff86c970f4",
      "name": "If3",
      "type": "n8n-nodes-base.if",
      "position": [
        1920,
        0
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "520e9b80-afa5-45e1-b572-88a855298b2c",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ $json.hasPdf }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "987447af-6fc0-4ef7-afa6-cf43066fd476",
      "name": "HTTP Request9",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        2160,
        0
      ],
      "parameters": {
        "url": "=https://api.zotero.org/users/{{ $('HTTP Request').item.json.userID }}/items",
        "method": "POST",
        "options": {},
        "jsonBody": "={{ [ $('Code4').item.json.meta ] }}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "headerParameters": {
          "parameters": [
            {
              "name": "ZOTERO-API-KEY",
              "value": "={{ $('HTTP Request').item.json.key }}"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "d9369d30-23f6-4425-8064-160a40189650",
      "name": "Edit Fields1",
      "type": "n8n-nodes-base.set",
      "position": [
        1180,
        -260
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "0df8889d-a22d-4512-a2dc-3e4700f37fe4",
              "name": "crossref",
              "type": "object",
              "value": "={{ $json }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "a50771b9-b2a1-4ed4-8c7e-1b0b1d629285",
      "name": "Edit Fields2",
      "type": "n8n-nodes-base.set",
      "position": [
        1180,
        0
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "0df8889d-a22d-4512-a2dc-3e4700f37fe4",
              "name": "datacite",
              "type": "object",
              "value": "={{ $json }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "dd594610-4115-4035-af02-bec335a10212",
      "name": "Edit Fields3",
      "type": "n8n-nodes-base.set",
      "position": [
        1180,
        260
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "0df8889d-a22d-4512-a2dc-3e4700f37fe4",
              "name": "unpay",
              "type": "object",
              "value": "={{ $json }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "0dfa6558-08a4-4a7a-94a2-3d02371aa938",
      "name": "HTTP Request1",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        2380,
        0
      ],
      "parameters": {
        "url": "=https://api.zotero.org/users/{{ $('HTTP Request').item.json.userID }}/items",
        "method": "POST",
        "options": {},
        "jsonBody": "={{ [\n  {\n    itemType: \"attachment\",\n    parentItem: $json.successful['0'].key,\n    linkMode: \"linked_url\",\n    title: \"Fulltext PDF\",\n    url: $('If3').item.json.pdfUrl,\n    contentType: \"application/pdf\"\n  }\n] }}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "headerParameters": {
          "parameters": [
            {
              "name": "Zotero-API-Key",
              "value": "={{ $('HTTP Request').item.json.key }}"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "594c9d30-853d-4447-a42d-c3eb4068287f",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -580,
        -440
      ],
      "parameters": {
        "width": 540,
        "height": 1120,
        "content": "# Automatically Import Research Papers using DOI URL from Telegram to Zotero\n\nThis workflow allows you to automatically import research papers into your Zotero library by simply sending a DOI link through Telegram. It fetches metadata from reliable sources such as Crossref, DataCite, and Unpaywall, enriches the bibliographic details, attaches the best available full-text PDF when possible, and generates a concise summary of the abstract using an LLM before sending it back to Telegram.  \n\n## \u2728 Key Features  \n- **Telegram Integration** \u2013 Send a DOI link via Telegram bot to trigger the workflow.  \n- **DOI Parsing** \u2013 Automatically detects and extracts DOI or arXiv identifiers from user messages.  \n- **Metadata Fetching** \u2013 Retrieves bibliographic information from **Crossref**, **DataCite**, and **Unpaywall**.  \n- **Smart PDF Finder** \u2013 Locates the best available PDF (publisher link, open access, or arXiv).  \n- **Zotero Integration** \u2013 Creates a Zotero parent item with complete metadata and attaches the PDF link when available.  \n- **Abstract Summarization** \u2013 Uses a basic LLM chain to generate a short and clear summary of the abstract.  \n- **Telegram Feedback** \u2013 Sends the title, URL, and abstract summary back to the user in Telegram.  \n\n\n## \ud83d\udd11 Required Credentials  \n- **Telegram API** \u2013 To connect the workflow with your Telegram bot.  \n- **Zotero API Key** \u2013 To create and update items in your Zotero library.  \n- **OpenRouter API Key** \u2013 To enable the LLM for generating abstract summaries.  \n- *(Optional)* Email for **Unpaywall API** requests (recommended for stable access).  \n\n## \ud83d\udca1 Benefits  \n- Save time by automating manual research paper imports.  \n- Ensure high-quality metadata by combining multiple sources (Crossref, DataCite, Unpaywall).  \n- Get instant summaries of abstracts directly in Telegram for quick understanding.  \n- Keep your Zotero library organized with accurate titles, abstracts, authors, and tags.  \n- Quickly attach available full-text PDFs without manual searching.  \n- Improve your academic workflow by managing references and summaries directly from Telegram.  \n"
      },
      "typeVersion": 1
    },
    {
      "id": "77de37c2-b6f5-4fba-9932-154f3144a73a",
      "name": "Basic LLM Chain",
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "position": [
        2600,
        0
      ],
      "parameters": {
        "text": "=Summarize the following abstract:  \n\n{{ $('HTTP Request9').item.json.successful['0'].data.abstractNote }}",
        "batching": {},
        "messages": {
          "messageValues": [
            {
              "message": "=You are an assistant that summarizes academic paper abstracts.   Your task is to generate a short and clear summary of the abstract in plain English.   Keep the summary concise (2\u20133 sentences), highlight the main contribution or finding, and avoid technical jargon if possible.  "
            }
          ]
        },
        "promptType": "define"
      },
      "typeVersion": 1.7
    },
    {
      "id": "f5af851a-9a9e-445c-b9c6-a96fdea644f4",
      "name": "OpenRouter Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenRouter",
      "position": [
        2600,
        200
      ],
      "parameters": {
        "model": "google/gemini-2.0-flash-exp:free",
        "options": {}
      },
      "typeVersion": 1
    },
    {
      "id": "aa28ca2d-8590-431f-b01f-c80494be010c",
      "name": "Send a text message",
      "type": "n8n-nodes-base.telegram",
      "position": [
        2940,
        0
      ],
      "parameters": {
        "text": "=\ud83d\udcc4 Research Paper Summary\nTitle: {{ $('HTTP Request9').item.json.successful['0'].data.title }}\nURL:  {{ $('HTTP Request1').item.json.successful['0'].data.url }}\n\n\ud83d\udcdd Summary:\n{{ $json.text }}\n",
        "chatId": "={{ $('Telegram Trigger').item.json.message.chat.id }}",
        "additionalFields": {
          "appendAttribution": false
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "74ac8241-a6b5-4229-99f0-c57b2ae36009",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -20,
        -180
      ],
      "parameters": {
        "color": 2,
        "width": 780,
        "height": 380,
        "content": "- Start the workflow when a user sends a message to your Telegram bot.  \n- Automatically extract DOI or arXiv identifiers from the message text.  \n- Store the Zotero API Key for subsequent steps (e.g., creating or updating Zotero items).  \n- Sends a simple HTTP request to the Zotero API to validate and fetch information associated with your Zotero API Key. It is useful as a first step to ensure that your credentials are correctly set up before running more advanced Zotero automations."
      },
      "typeVersion": 1
    },
    {
      "id": "cc9533ee-5edc-4573-9dfa-1cca98a3c854",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        820,
        -500
      ],
      "parameters": {
        "color": 4,
        "width": 600,
        "height": 940,
        "content": "- **Crossref API Request** \u2013 Fetch bibliographic data from Crossref using the provided DOI.  \n- **DataCite API Request** \u2013 Retrieve additional metadata and attributes from DataCite.  \n- **Unpaywall API Request** \u2013 Check open-access availability and possible full-text links.  \n- **Structured Data Storage** \u2013 Save API responses into separate fields (`crossref`, `datacite`, `unpay`) for merging and downstream processing.  \n"
      },
      "typeVersion": 1
    },
    {
      "id": "23d15a9f-ebeb-416f-a66d-967cc27b9cf9",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1460,
        -280
      ],
      "parameters": {
        "color": 5,
        "width": 360,
        "height": 440,
        "content": "- Combine metadata from Crossref, DataCite, and Unpaywall into a single object.  \n- Prioritize PDF links from Crossref, fallback to Unpaywall, DataCite, or arXiv.  \n- Generate a Zotero-ready object including title, DOI, date, publication title, abstract, authors, and tags.  \n- Identify whether the resource is a journal article or preprint.  \n"
      },
      "typeVersion": 1
    },
    {
      "id": "66f99fac-0698-400d-9bb2-1e57ce4c05c0",
      "name": "Send a text message1",
      "type": "n8n-nodes-base.telegram",
      "position": [
        2160,
        200
      ],
      "parameters": {
        "text": "=PDF not found",
        "chatId": "={{ $('Telegram Trigger').item.json.message.chat.id }}",
        "additionalFields": {
          "appendAttribution": false
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "bd043ae9-6d80-4bf0-b80b-79bb921b3340",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1880,
        -200
      ],
      "parameters": {
        "color": 6,
        "width": 640,
        "height": 600,
        "content": "- Uses an IF node to check whether a PDF URL is available.  \n- Creates a new Zotero item with complete metadata.  \n- Automatically attaches the full-text PDF to the Zotero item if available.  \n- Alerts the user in Telegram when no PDF could be found.  \n"
      },
      "typeVersion": 1
    },
    {
      "id": "60bda7fc-c9dc-457a-8cc1-8f6a2c981a49",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2580,
        -200
      ],
      "parameters": {
        "width": 600,
        "height": 600,
        "content": "- Uses a basic LLM chain to summarize paper abstracts.  \n- Delivers the paper title, URL, and generated summary back to the user in a formatted message.  \n"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "f31f5475-f6e7-47c7-afdd-0b9ad3346cf3",
  "connections": {
    "If3": {
      "main": [
        [
          {
            "node": "HTTP Request9",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Send a text message1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code": {
      "main": [
        [
          {
            "node": "Edit Fields",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code4": {
      "main": [
        [
          {
            "node": "If3",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge": {
      "main": [
        [
          {
            "node": "Code4",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Edit Fields": {
      "main": [
        [
          {
            "node": "HTTP Request",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Edit Fields1": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Edit Fields2": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Edit Fields3": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 2
          }
        ]
      ]
    },
    "HTTP Request": {
      "main": [
        [
          {
            "node": "HTTP Request3",
            "type": "main",
            "index": 0
          },
          {
            "node": "HTTP Request2",
            "type": "main",
            "index": 0
          },
          {
            "node": "HTTP Request4",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP Request1": {
      "main": [
        [
          {
            "node": "Basic LLM Chain",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP Request2": {
      "main": [
        [
          {
            "node": "Edit Fields2",
            "type": "main",
            "index": 0
          }
        ],
        []
      ]
    },
    "HTTP Request3": {
      "main": [
        [
          {
            "node": "Edit Fields1",
            "type": "main",
            "index": 0
          }
        ],
        []
      ]
    },
    "HTTP Request4": {
      "main": [
        [
          {
            "node": "Edit Fields3",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP Request9": {
      "main": [
        [
          {
            "node": "HTTP Request1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Basic LLM Chain": {
      "main": [
        [
          {
            "node": "Send a text message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Telegram Trigger": {
      "main": [
        [
          {
            "node": "Code",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenRouter Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "Basic LLM Chain",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    }
  }
}
Pro

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

About this workflow

This workflow allows you to automatically import research papers into your Zotero library by simply sending a DOI link through Telegram. It fetches metadata from reliable sources such as Crossref, DataCite, and Unpaywall, enriches the bibliographic details, attaches the best…

Source: https://n8n.io/workflows/7676/ — 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

Effortlessly track your expenses with MoneyMate, an n8n workflow that transforms receipts into organized financial insights.

HTTP Request, Telegram Trigger, Chain Llm +4
Slack & Telegram

Disclaimer: This template requires the community node, which is only available on self-hosted n8n instances. You’ll need a self-hosted n8n setup to use this workflow.

HTTP Request, Telegram Trigger, Chain Llm +4
Slack & Telegram

This workflow turns a short text idea into stunning, AI-generated anime-style images, all from Telegram. It combines a chat LLM for prompt enhancement with Gemini (free) or Leonardo.AI (paid) image mo

Telegram Trigger, HTTP Request, Output Parser Structured +3
Slack & Telegram

Send any URL to your Telegram bot and get an AI summary instantly.

Telegram Trigger, HTTP Request, Chain Llm +4
Slack & Telegram

End-to-End Video Creation from user idea or transcript AI-Powered Scriptwriting using LLMs (e.g., DeepSeek via OpenRouter) Voiceover Generation with customizable TTS voices Image Scene Generation usin

HTTP Request, Form Trigger, Output Parser Structured +6