{
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "nodes": [
    {
      "id": "9bb1c1b3-916f-47da-9596-f531966726af",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -17424,
        2688
      ],
      "parameters": {
        "width": 576,
        "height": 850,
        "content": "## AI Document Assistant: Branded PDF Generation from Email\n\nReceive an email with a document request and optional PDF attachments. The AI assistant can create drafts, summarize documents, compare multiple PDFs, or write new documents with internet research \u2014 all output as professionally branded PDFs using Autype.\n\n### How it works\n1. **Email Trigger** \u2014 Monitors inbox for incoming document requests with optional PDF attachments.\n2. **Extract & Split PDFs** \u2014 Extracts email content and splits PDF attachments into individual items for processing.\n3. **Loop: Upload + OCR each PDF** \u2014 Each PDF is uploaded to Autype, OCR'd via Lens, and the extracted text is collected.\n4. **Combine Results** \u2014 All OCR texts are merged with the original request text.\n5. **Download Syntax Reference** \u2014 Fetches Autype Extended Markdown syntax so the AI knows the output format.\n6. **AI Assistant** \u2014 Processes the request (summarize, compare, draft, research), writes a document in Autype Extended Markdown.\n7. **Render PDF** \u2014 Autype renders the markdown to a branded PDF with company styling.\n8. **Send via Email** \u2014 The PDF is emailed back to the sender via SMTP.\n\n### Requirements\n- Self-hosted n8n (community nodes)\n- `n8n-nodes-autype` community node\n- Autype API key\n- OpenRouter API key (or OpenAI/Anthropic)\n- Firecrawl API key\n- SerpAPI key\n- SMTP credentials (for email delivery)\n\n> **Note:** This workflow uses the [Autype](https://www.npmjs.com/package/n8n-nodes-autype) community node. Community nodes are only available on **self-hosted n8n instances**."
      },
      "typeVersion": 1
    },
    {
      "id": "6cb7e941-ffac-469b-b3bb-5c5548558606",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -16784,
        2864
      ],
      "parameters": {
        "color": 7,
        "width": 700,
        "height": 260,
        "content": "### 1. Email Input & Config\nThe IMAP Email Trigger monitors your inbox for incoming document requests. PDF attachments are automatically detected. The Set Company Config node defines branding variables."
      },
      "typeVersion": 1
    },
    {
      "id": "67d4eed1-67c4-40e0-a1c8-4f402327db8b",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -15856,
        3104
      ],
      "parameters": {
        "color": 7,
        "width": 1512,
        "height": 452,
        "content": "### 2. PDF Processing Loop\nEach uploaded PDF is processed sequentially: uploaded to Autype via the community node, OCR'd via Autype Lens (HTTP Request), then the extracted markdown text is collected. After all PDFs are processed, the results are combined into a single context string.\n\n**Lens OCR setup:** The Lens OCR and Poll OCR Status nodes use HTTP Request with **Generic Auth Type \u2192 Header Auth**. Create a Header Auth credential with **Name: `X-API-Key`** and **Value: your Autype API key**. A dedicated Autype community node for Lens OCR is coming soon."
      },
      "typeVersion": 1
    },
    {
      "id": "303e476e-c3ba-4ce7-987c-41bd83bf458e",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -15616,
        2640
      ],
      "parameters": {
        "color": 7,
        "width": 780,
        "height": 292,
        "content": "### 3. AI Document Assistant\nThe AI Assistant receives the request text, all OCR content from attached PDFs, and the Autype Extended Markdown syntax reference. It can summarize, compare, draft, or create documents from scratch \u2014 using Firecrawl and SerpAPI for research when needed."
      },
      "typeVersion": 1
    },
    {
      "id": "50b38871-3e87-4bfa-8a42-11e74a12005d",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -14560,
        2576
      ],
      "parameters": {
        "color": 7,
        "width": 668,
        "height": 308,
        "content": "### 4. Render & Send\nThe AI output is cleaned and rendered to a branded PDF via Autype Render from Markdown. Company styling is applied via a defaults JSON (fonts, colors, heading styles, table styles, header with logo, footer with page numbers). The PDF is sent back to the sender via SMTP."
      },
      "typeVersion": 1
    },
    {
      "id": "b5611b64-205a-4d01-b262-55cae1cd2af2",
      "name": "Set Company Config",
      "type": "n8n-nodes-base.set",
      "position": [
        -16496,
        2960
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "cfg-company",
              "name": "companyName",
              "type": "string",
              "value": "Your Company Name"
            },
            {
              "id": "cfg-logo",
              "name": "companyLogoUrl",
              "type": "string",
              "value": "https://placehold.co/50x50/orange/white"
            },
            {
              "id": "cfg-color",
              "name": "brandColor",
              "type": "string",
              "value": "#1a5276"
            }
          ]
        },
        "includeOtherFields": true
      },
      "typeVersion": 3.4
    },
    {
      "id": "13711b2a-2a55-4500-9390-9293a87af7d8",
      "name": "New Email Received",
      "type": "n8n-nodes-base.emailReadImap",
      "position": [
        -16736,
        2960
      ],
      "parameters": {
        "options": {},
        "downloadAttachments": true
      },
      "credentials": {
        "imap": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2
    },
    {
      "id": "9b84550e-70e7-4e43-91bb-70b1ba30a189",
      "name": "Extract & Split PDFs",
      "type": "n8n-nodes-base.code",
      "position": [
        -16288,
        2960
      ],
      "parameters": {
        "jsCode": "// Extract email data and split PDF attachments into separate items for loop processing\nconst item = $input.first();\nconst emailData = item.json;\nconst binary = item.binary || {};\n\n// Extract email fields\nconst subject = emailData.subject || '';\nconst bodyText = (emailData.textPlain || emailData.text || emailData.html || '').substring(0, 5000);\nconst fromRaw = emailData.from || '';\n// Extract email address from 'Name <user@example.com>' format\nconst emailMatch = fromRaw.match(/<([^>]+)>/);\nconst senderEmail = emailMatch ? emailMatch[1] : fromRaw;\nconst senderName = fromRaw.replace(/<[^>]+>/, '').trim();\n\n// Combine subject + body as the request text\nconst requestText = subject + (bodyText ? '\\n\\n' + bodyText : '');\n\n// Scan binary attachments for PDFs\nconst pdfItems = [];\nfor (const key of Object.keys(binary)) {\n  const bin = binary[key];\n  if (bin.mimeType === 'application/pdf' || (bin.fileName && bin.fileName.toLowerCase().endsWith('.pdf'))) {\n    pdfItems.push({ fileName: bin.fileName || `document-${pdfItems.length + 1}.pdf`, binaryKey: key });\n  }\n}\n\nif (pdfItems.length === 0) {\n  return [{ json: { requestText, senderEmail, senderName, hasPdfs: false, pdfCount: 0 } }];\n}\n\n// Output one item per PDF with its binary under the key 'data'\nconst results = [];\nfor (let i = 0; i < pdfItems.length; i++) {\n  const pdf = pdfItems[i];\n  results.push({\n    json: { requestText, senderEmail, senderName, hasPdfs: true, pdfCount: pdfItems.length, pdfIndex: i, pdfFileName: pdf.fileName, pdfBinaryKey: 'data' },\n    binary: { data: binary[pdf.binaryKey] }\n  });\n}\nreturn results;"
      },
      "typeVersion": 2
    },
    {
      "id": "214e9426-fff8-4a82-a015-233306d184c0",
      "name": "Has PDFs?",
      "type": "n8n-nodes-base.if",
      "position": [
        -16064,
        2960
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "has-pdfs",
              "operator": {
                "type": "boolean",
                "operation": "true"
              },
              "leftValue": "={{ $json.hasPdfs }}",
              "rightValue": true
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "27c24be6-1e45-46bc-bff3-b1228998b736",
      "name": "Loop Over PDFs",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        -15792,
        3360
      ],
      "parameters": {
        "options": {
          "reset": false
        }
      },
      "typeVersion": 3
    },
    {
      "id": "30a46778-ed0f-4ad6-86c9-e2c6b7d9b50d",
      "name": "Upload PDF to Autype",
      "type": "n8n-nodes-autype.autype",
      "position": [
        -15440,
        3312
      ],
      "parameters": {
        "resource": "file"
      },
      "credentials": {
        "autypeApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "360692db-d3be-42c4-8ae5-cb7149701ae3",
      "name": "Wait for OCR",
      "type": "n8n-nodes-base.wait",
      "position": [
        -14992,
        3312
      ],
      "parameters": {
        "amount": 8
      },
      "typeVersion": 1.1
    },
    {
      "id": "23289509-ed73-48a7-bae8-35de4ca79d6e",
      "name": "Poll OCR Status",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -14768,
        3312
      ],
      "parameters": {
        "url": "=https://api.autype.com/api/v1/dev/tools/jobs/{{ $('Autype Lens OCR').item.json.id }}",
        "options": {},
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth"
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "22ed08f4-1d00-417f-aca4-9a7b1be666dc",
      "name": "Extract OCR Text",
      "type": "n8n-nodes-base.code",
      "position": [
        -14544,
        3312
      ],
      "parameters": {
        "jsCode": "const item = $input.first();\nconst status = item.json.status;\nconst loopItem = $('Loop Over PDFs').first().json;\nconst fileName = loopItem.pdfFileName || 'document.pdf';\n\nlet ocrText = '';\nif (status === 'COMPLETED') {\n  ocrText = item.json.result?.markdown || item.json.result?.text || item.json.metadata?.markdown || item.json.metadata?.text || JSON.stringify(item.json.result || item.json.metadata || {});\n  ocrText = ocrText.substring(0, 15000);\n} else if (status === 'FAILED') {\n  ocrText = '[OCR failed \u2014 could not process this PDF]';\n} else {\n  ocrText = '[OCR still processing \u2014 try increasing wait time]';\n}\n\nreturn [{\n  json: {\n    pdfFileName: fileName,\n    ocrText\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "44aab7d9-445a-4978-8622-a190828fc3a4",
      "name": "Combine All OCR Results",
      "type": "n8n-nodes-base.code",
      "position": [
        -15600,
        3200
      ],
      "parameters": {
        "jsCode": "// Collect all OCR results from the loop and combine with original request\nconst allItems = $('Extract OCR Text').all();\nconst formData = $('Extract & Split PDFs').first().json;\n\nconst pdfSections = allItems.map((item, i) => {\n  const name = item.json.pdfFileName || `Document ${i + 1}`;\n  return `### PDF ${i + 1}: ${name}\\n\\n${item.json.ocrText}`;\n}).join('\\n\\n---\\n\\n');\n\nreturn [{\n  json: {\n    requestText: formData.requestText,\n    senderEmail: formData.senderEmail,\n    pdfContent: pdfSections,\n    pdfCount: allItems.length,\n    hasPdfs: true\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "53d42f3e-7327-4cd6-9f6d-3a6b296434fc",
      "name": "Prepare Text Only",
      "type": "n8n-nodes-base.code",
      "position": [
        -15776,
        2768
      ],
      "parameters": {
        "jsCode": "const formData = $input.first().json;\n\nreturn [{\n  json: {\n    requestText: formData.requestText,\n    senderEmail: formData.senderEmail,\n    pdfContent: '',\n    pdfCount: 0,\n    hasPdfs: false\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "d16c4859-0eeb-4951-af07-a94dbb80ffb4",
      "name": "Download Markdown Syntax",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -15504,
        2768
      ],
      "parameters": {
        "url": "https://autype.com/llm-resources/markdown-syntax.md",
        "options": {
          "response": {
            "response": {
              "responseFormat": "text"
            }
          }
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "9f865bee-62a8-407b-869b-29ad03844a17",
      "name": "Merge Context",
      "type": "n8n-nodes-base.code",
      "position": [
        -15312,
        2768
      ],
      "parameters": {
        "jsCode": "// Merge the context data with the downloaded markdown syntax\nconst syntaxData = $input.first().json?.data || '';\n\n// Get the context from whichever branch was executed\nlet context;\ntry {\n  context = $('Combine All OCR Results').first().json;\n} catch (e) {\n  try {\n    context = $('Prepare Text Only').first().json;\n  } catch (e2) {\n    context = $('Extract & Split PDFs').first().json;\n  }\n}\n\nreturn [{\n  json: {\n    ...context,\n    markdownSyntax: syntaxData.substring(0, 12000)\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "fb2f1810-2947-4d44-94b8-c10c87013228",
      "name": "AI Document Assistant",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        -15088,
        2768
      ],
      "parameters": {
        "text": "=## Document Request\n\n{{ $json.requestText }}\n\n{{ $json.hasPdfs ? '---\\n\\n## Attached Documents (' + $json.pdfCount + ' files)\\n\\nThe following content was extracted from the attached PDF documents. Use this as your PRIMARY source material.\\n\\n' + $json.pdfContent : '(No document attachments)' }}\n\n---\n\n**Your task:** Produce a well-structured document in Autype Extended Markdown format based on the request above.\n\nDetermine the best approach based on the request:\n- **Summarize**: If asked to summarize attached documents, produce a concise but thorough summary.\n- **Compare**: If multiple documents are attached and a comparison is requested, create a structured comparison with tables.\n- **Draft / Rewrite**: If asked to draft, restructure, or rewrite content, produce a polished version.\n- **Create from scratch**: If no documents are attached or the request asks for new content, write the document from your knowledge and use research tools if needed.\n\n**IMPORTANT rules for tool usage:**\n- If PDF documents were attached, use their content as the PRIMARY input. Do NOT search for information already in the PDFs.\n- Only use Firecrawl or SerpAPI if the request EXPLICITLY asks for external research or if you need to verify/supplement specific facts.\n- You may use a MAXIMUM of 5 tool calls total. Plan your searches carefully.\n- If the task is purely about the attached documents (summarize, compare, rewrite) \u2014 do NOT use any tools.\n\n**Document formatting:**\n1. Clear title (# heading)\n2. Executive summary or introduction\n3. Well-structured sections (##, ###)\n4. Tables where data comparison is useful\n5. Blockquotes for key insights or callouts\n6. Conclusion with actionable recommendations where appropriate\n\nReturn ONLY the Autype Extended Markdown content. No code fences, no explanation outside the document.",
        "options": {
          "maxIterations": 6,
          "systemMessage": "=You are a professional AI document assistant. You help users create, summarize, compare, and draft documents. You receive requests via email with optional PDF attachments and produce polished, PDF-ready documents.\n\n## Your capabilities\n1. **Summarize** \u2014 Create concise summaries of attached documents, preserving key facts and structure.\n2. **Compare** \u2014 Analyze multiple documents side-by-side, highlighting differences, similarities, and key takeaways in tables.\n3. **Draft / Rewrite** \u2014 Take existing content and produce a polished, restructured version.\n4. **Create from scratch** \u2014 Write new documents based on a topic, optionally using internet research.\n\n## CRITICAL: Tool usage rules\n- You have a STRICT MAXIMUM of 5 tool calls total. Every Firecrawl or SerpAPI call counts.\n- **If PDF documents are attached:** Their content is your PRIMARY source. Work with what you have. Do NOT search unless the user explicitly asks for external research or comparison with external data.\n- **If no PDFs are attached and research is needed:** Use SerpAPI for broad research (max 2-3 calls) and Firecrawl only to scrape specific URLs mentioned in the request.\n- **If the task is writing/creative:** Write directly from your knowledge. Only search if you need specific current facts.\n- NEVER call a tool repeatedly for the same or similar query. Plan your searches before executing.\n\n## Your tools\n- **Firecrawl**: Scrape a specific URL to extract its page content as markdown. Only use when a concrete URL is known.\n- **SerpAPI**: Web search for finding current information, statistics, and facts. One well-formulated query often suffices.\n\n## Output format\nYou write documents in **Autype Extended Markdown** format. Here is the syntax reference:\n\n{{ $json.markdownSyntax || 'Standard Markdown with extended features' }}\n\n## Key formatting rules\n- Use standard markdown headings: # for title, ## for sections, ### for subsections\n- Use **bold** and *italic* for emphasis\n- Use tables with | syntax for data comparisons\n- Use > blockquotes for callouts and key insights\n- Use --- for horizontal rules / section breaks\n- Use ordered and unordered lists\n- Do NOT use HTML tags or &nbsp;\n- Do NOT use ``` code blocks unless showing actual code\n- Keep the document professional and business-ready\n- Write in the same language as the incoming request\n\n## Document structure\nAlways structure your output as:\n1. # Title\n2. Executive Summary (brief overview)\n3. Main Content (multiple ## sections)\n4. Data/Comparisons (tables where useful)\n5. Conclusion & Recommendations\n\nReturn ONLY the markdown content. No wrapper, no code fences, no meta-commentary."
        },
        "promptType": "define"
      },
      "typeVersion": 2
    },
    {
      "id": "70d3be18-47e7-4640-a5f0-473d9e5553db",
      "name": "Prepare Render Payload",
      "type": "n8n-nodes-base.code",
      "position": [
        -14496,
        2704
      ],
      "parameters": {
        "jsCode": "const agentOutput = $json.output || $json.text || '';\nconst config = $('Set Company Config').first().json;\nconst context = $('Merge Context').first().json;\n\n// Clean markdown: remove code fences if the AI wrapped it\nlet markdown = agentOutput;\nif (markdown.startsWith('```')) {\n  markdown = markdown.replace(/^```(?:markdown|md)?\\n?/, '').replace(/\\n?```$/, '');\n}\nmarkdown = markdown.trim();\n\n// Build a clean filename\nconst requestText = context.requestText || 'document';\nconst cleanName = requestText\n  .substring(0, 60)\n  .replace(/[^a-zA-Z0-9\\s-]/g, '')\n  .replace(/\\s+/g, '-')\n  .toLowerCase();\n\nconst today = new Date().toISOString().split('T')[0];\n\nreturn [{\n  json: {\n    markdown,\n    filename: `${cleanName}-${today}`,\n    title: requestText.substring(0, 100),\n    senderEmail: context.senderEmail,\n    companyName: config.companyName,\n    companyLogoUrl: config.companyLogoUrl,\n    brandColor: config.brandColor\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "bea023a8-09d9-476e-896f-b937531efd8d",
      "name": "Render Branded PDF",
      "type": "n8n-nodes-autype.autype",
      "position": [
        -14304,
        2704
      ],
      "parameters": {
        "content": "={{ $json.markdown }}",
        "operation": "renderMarkdown",
        "downloadOutput": true,
        "markdownAdditionalFields": {
          "size": "A4",
          "title": "={{ $json.title }}",
          "defaults": "={{ JSON.stringify({ fontFamily: 'Roboto', fontSize: 11, color: '#333333', lineHeight: 1.5, headingNumbering: '1.1.1', spacing: { before: { h1: 20, h2: 18, h3: 16, h4: 14, h5: 12, h6: 10, text: 0, table: 10, list: 8, image: 10, code: 10, chart: 10, math: 10 }, after: { h1: 14, h2: 12, h3: 10, h4: 8, h5: 6, h6: 5, text: 8, table: 14, list: 8, image: 14, code: 14, chart: 14, math: 15 } }, chart: { colors: ['#3b82f6', '#ef4444', '#10b981', '#f59e0b', '#8b5cf6'], borderColors: ['#2563eb', '#dc2626', '#059669', '#d97706', '#7c3aed'] }, styles: { h1: { color: $json.brandColor || '#1a365d', fontSize: 24, fontWeight: 'bold', pageBreakBefore: true }, h2: { color: $json.brandColor || '#2c5282', fontSize: 20, fontWeight: 'bold' }, h3: { color: '#2d3748', fontSize: 16, fontWeight: 'bold' }, h4: { fontSize: 14, fontWeight: 'bold' }, h5: { fontSize: 12, fontWeight: 'normal' }, h6: { fontSize: 11, fontWeight: 'normal' }, text: { fontSize: 11 }, table: { header: { color: '#ffffff', backgroundColor: $json.brandColor || '#2c5282' }, borders: { inner: { color: '#e2e8f0', width: 1 }, outer: { color: '#e2e8f0', width: 1 } }, cellPadding: { top: 6, left: 8, right: 8, bottom: 6 } } }, header: { left: $json.companyLogoUrl ? { type: 'image', src: $json.companyLogoUrl, width: 60, align: 'left' } : ($json.companyName || ''), right: { type: 'text', content: [{ text: $json.companyName || '', color: '#666666', fontSize: 9 }] }, excludeFirstPage: true }, footer: { left: { type: 'text', content: [{ text: $json.companyName || '', color: '#999999', fontSize: 8 }] }, center: 'Page ${pageNumber} of ${totalPages}', excludeFirstPage: false } }) }}",
          "orientation": "portrait"
        }
      },
      "credentials": {
        "autypeApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "69c3f622-ab0c-4a55-bd62-d352782b6d68",
      "name": "Send Report via Email",
      "type": "n8n-nodes-base.emailSend",
      "position": [
        -14112,
        2704
      ],
      "parameters": {
        "options": {
          "attachments": "data"
        },
        "subject": "=Your Document: {{ $('Prepare Render Payload').item.json.title }}",
        "toEmail": "={{ $('New Email Received').item.json.from }}",
        "fromEmail": "=Your Name <your-email@example.com>"
      },
      "credentials": {
        "smtp": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "a20a6e19-7a60-4091-bd25-c939ad1f4505",
      "name": "/scrape in Firecrawl",
      "type": "@mendable/n8n-nodes-firecrawl.firecrawlTool",
      "position": [
        -14800,
        2960
      ],
      "parameters": {
        "url": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('URL', ``, 'string') }}",
        "operation": "scrape",
        "scrapeOptions": {
          "options": {
            "headers": {}
          }
        },
        "requestOptions": {}
      },
      "credentials": {
        "firecrawlApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "80f59ecf-1be3-4f3a-aa7c-587ff41410fe",
      "name": "OpenRouter Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenRouter",
      "position": [
        -15184,
        2944
      ],
      "parameters": {
        "model": "z-ai/glm-5",
        "options": {}
      },
      "credentials": {
        "openRouterApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "6f69382b-4322-4138-aa98-6c521738cda4",
      "name": "SerpAPI",
      "type": "@n8n/n8n-nodes-langchain.toolSerpApi",
      "position": [
        -14944,
        2960
      ],
      "parameters": {
        "options": {}
      },
      "credentials": {
        "serpApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "ff290efa-8e2d-4ce3-8f60-0c24587176df",
      "name": "Autype Lens OCR",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -15216,
        3312
      ],
      "parameters": {
        "url": "=https://api.autype.com/api/v1/dev/tools/lens/ocr",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"fileId\": \"{{ $json.id }}\",\n  \"outputFormat\": \"md\"\n}",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth"
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    }
  ],
  "connections": {
    "SerpAPI": {
      "ai_tool": [
        [
          {
            "node": "AI Document Assistant",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Has PDFs?": {
      "main": [
        [
          {
            "node": "Loop Over PDFs",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Prepare Text Only",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait for OCR": {
      "main": [
        [
          {
            "node": "Poll OCR Status",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge Context": {
      "main": [
        [
          {
            "node": "AI Document Assistant",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over PDFs": {
      "main": [
        [
          {
            "node": "Combine All OCR Results",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Upload PDF to Autype",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Autype Lens OCR": {
      "main": [
        [
          {
            "node": "Wait for OCR",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Poll OCR Status": {
      "main": [
        [
          {
            "node": "Extract OCR Text",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract OCR Text": {
      "main": [
        [
          {
            "node": "Loop Over PDFs",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Text Only": {
      "main": [
        [
          {
            "node": "Download Markdown Syntax",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "New Email Received": {
      "main": [
        [
          {
            "node": "Set Company Config",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Render Branded PDF": {
      "main": [
        [
          {
            "node": "Send Report via Email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Company Config": {
      "main": [
        [
          {
            "node": "Extract & Split PDFs",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "/scrape in Firecrawl": {
      "ai_tool": [
        [
          {
            "node": "AI Document Assistant",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Extract & Split PDFs": {
      "main": [
        [
          {
            "node": "Has PDFs?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Upload PDF to Autype": {
      "main": [
        [
          {
            "node": "Autype Lens OCR",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Document Assistant": {
      "main": [
        [
          {
            "node": "Prepare Render Payload",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenRouter Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "AI Document Assistant",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Render Payload": {
      "main": [
        [
          {
            "node": "Render Branded PDF",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Combine All OCR Results": {
      "main": [
        [
          {
            "node": "Download Markdown Syntax",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Download Markdown Syntax": {
      "main": [
        [
          {
            "node": "Merge Context",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}