Extraction de données de contrats juridiques et envoi de rappels via VLM Run, Google Workspace et Slack

Intermédiaire

Ceci est uncontenant 14 nœuds.Utilise principalement des nœuds comme Set, Code, Slack, Webhook, GoogleDrive. Extraire des données de contrats juridiques et envoyer des rappels avec VLM Run, Google Workspace et Slack

Prérequis
  • Token Bot Slack ou URL Webhook
  • Point de terminaison HTTP Webhook (généré automatiquement par n8n)
  • Informations d'identification Google Drive API
  • Informations d'identification Google Sheets API

Catégorie

-
Aperçu du workflow
Visualisation des connexions entre les nœuds, avec support du zoom et du déplacement
Exporter le workflow
Copiez la configuration JSON suivante dans n8n pour importer et utiliser ce workflow
{
  "meta": {
    "instanceId": "96d35e452e0d9a182973416b7532cfc5643239aaaa764a5bf74d52ca84f4a35c",
    "templateCredsSetupCompleted": true
  },
  "nodes": [
    {
      "id": "bdfebade-893c-411c-80c6-0dace07f7dc9",
      "name": "📁 Documentation du Traitement des Entrées",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        0,
        0
      ],
      "parameters": {
        "color": 7,
        "width": 400,
        "height": 680,
        "content": "## 📁 Input Processing\n\n**Monitors & downloads contract files from Google Drive.**\n\n**Process:**\n1. Watches designated Drive folder\n2. Auto-triggers on new uploads\n3. Downloads files for AI processing\n\n**Supported Formats:**\n- Images (JPG, PNG, WEBP)\n- PDF documents\n- Mobile camera uploads\n- Scanned contracts"
      },
      "typeVersion": 1
    },
    {
      "id": "2fca40fa-ac4a-4515-a1e0-295cdcbfc595",
      "name": "Surveiller les Téléversements de Contrats",
      "type": "n8n-nodes-base.googleDriveTrigger",
      "notes": "Monitors Google Drive folder for new receipt uploads and triggers processing automatically.",
      "position": [
        48,
        480
      ],
      "parameters": {
        "event": "fileCreated",
        "options": {},
        "pollTimes": {
          "item": [
            {
              "mode": "everyMinute"
            }
          ]
        },
        "triggerOn": "specificFolder",
        "folderToWatch": {
          "__rl": true,
          "mode": "list",
          "value": "1S6baavqJn98MjUlbB6KtmARCWuWEekIZ",
          "cachedResultUrl": "https://drive.google.com/drive/folders/1S6baavqJn98MjUlbB6KtmARCWuWEekIZ",
          "cachedResultName": "test_data"
        }
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "id": "zYyIOFMdGz258avn",
          "name": "Google Drive account 6"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "95acb226-9205-4a21-9a2d-c9792bc81de4",
      "name": "Télécharger le Fichier de Contrat",
      "type": "n8n-nodes-base.googleDrive",
      "notes": "Downloads receipt files from Google Drive for AI processing.",
      "position": [
        256,
        480
      ],
      "parameters": {
        "fileId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $json.id }}"
        },
        "options": {
          "binaryPropertyName": "data"
        },
        "operation": "download"
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "id": "zYyIOFMdGz258avn",
          "name": "Google Drive account 6"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "61fa2c83-72cd-44b0-a5cd-5fbaeef5dfb1",
      "name": "🤖 Documentation de l'Extraction IA",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        512,
        0
      ],
      "parameters": {
        "width": 416,
        "height": 680,
        "content": "## 🤖 VLM Run Contract Extraction\n\n**Uses VLM Run node to extract structured data from contract images/PDFs.**\n\n**Extracts:**\n- Contract ID\n- Title\n- Parties\n- Effective Date\n- Termination Date\n\n**Features:**\n- Handles poor quality images\n- Various receipt formats\n- OCR text recognition"
      },
      "typeVersion": 1
    },
    {
      "id": "84d28c8a-b33c-4bc3-9489-846c3b412d4a",
      "name": "VLM Run ContractParser",
      "type": "@vlm-run/n8n-nodes-vlmrun.vlmRun",
      "position": [
        560,
        480
      ],
      "parameters": {
        "operation": "executeAgent",
        "agentPrompt": "extract data from the invoice or contract, Extract the key details from this lease contract. I am expecting the output to be in JSON format, with tags, using parameters : contract_id, title, parties (with role), property_address, effective_date, termination_date, rent_amount, security_deposit, payment_terms, governing_law . All the parameters should get values from the pdf of data file from the download contract file. \nNormalize dates to YYYY-MM-DD and amounts as numbers with currency.  \nIf a field is missing, return null.",
        "agentCallbackUrl": "https://playground.attensys.ai/webhook/b905e71d-8ea5-4fc2-a773-b0f92e5398e4"
      },
      "credentials": {
        "vlmRunApi": {
          "id": "B7ZYM8AfBgjnOEOl",
          "name": "VLM Run account 5"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "17996d92-afea-484c-88d3-9b2b673b1f4c",
      "name": "📊 Documentation du Stockage",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1056,
        0
      ],
      "parameters": {
        "color": 7,
        "width": 420,
        "height": 680,
        "content": "## 📊 Data Storage\n\n**Structures and stores extracted data in Google Sheets.**\n\n**Features:**\n- Clean, organized format\n- Centralized expense database\n- Auto-appends new entries\n- Analysis-ready data\n\n**Data Fields:**\n- ID\n- Title\n- Parties\n- Effective and Termination Date\n\n**Benefits:**\n- Real-time tracking\n- Easy exports\n- Mobile access"
      },
      "typeVersion": 1
    },
    {
      "id": "70c2c9c5-d950-495f-9e91-5a0b402ef739",
      "name": "Sauvegarder dans la Base de Données Dépenses",
      "type": "n8n-nodes-base.googleSheets",
      "notes": "Automatically saves extracted receipt data to Google Sheets for expense tracking.",
      "position": [
        1344,
        480
      ],
      "parameters": {
        "columns": {
          "value": {
            "Title": "={{$node[\"Format Contract Data\"].json[\"Title\"]}}",
            "Parties": "={{$node[\"Format Contract Data\"].json[\"Parties\"]}}",
            "Contract ID": "={{$node[\"Format Contract Data\"].json[\"Contract ID\"]}}",
            "Effective Date": "={{$node[\"Format Contract Data\"].json[\"Effective Date\"]}}",
            "Termination Date": "={{$node[\"Format Contract Data\"].json[\"Termination Date\"]}}"
          },
          "schema": [
            {
              "id": "Contract ID",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Contract ID",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Title",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Title",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Parties",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Parties",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Effective Date",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Effective Date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Termination Date",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Termination Date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "Customer"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/11_VjMdhv_JN2eSRZiw_t0dIN-yShkn2jlCDwiG8eb14/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1lg0aJKvd7E2pbhumHNjcgxUfEQKvlBs9h1zZbhSeqas",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1lg0aJKvd7E2pbhumHNjcgxUfEQKvlBs9h1zZbhSeqas/edit?usp=drivesdk",
          "cachedResultName": "test"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "id": "sdLQgQJjowDNfXMU",
          "name": "Google Sheets account 7"
        }
      },
      "typeVersion": 4.6
    },
    {
      "id": "f752ffb1-d4eb-4d69-919d-2f4d72fb753e",
      "name": "Formater les Données du Contrat",
      "type": "n8n-nodes-base.set",
      "notes": "Transforms AI-extracted receipt data into clean, structured format for spreadsheet storage.",
      "position": [
        1136,
        480
      ],
      "parameters": {
        "values": {
          "string": [
            {
              "name": "Contract ID",
              "value": "={{ $json.body.response.contract_id }}"
            },
            {
              "name": "Title",
              "value": "={{ $json.body.response.title }}"
            },
            {
              "name": "Parties",
              "value": "={{ $json.body.parties && $json.body.parties.length ? $json.body.parties.map(p => p.name + \" (\"+ p.role + \")\").join(\"; \") : \"\" }}"
            },
            {
              "name": "Effective Date",
              "value": "={{ $json.body.response.effective_date }}"
            },
            {
              "name": "Termination Date",
              "value": "={{ $json.body.response.termination_date }}"
            }
          ]
        },
        "options": {},
        "keepOnlySet": true
      },
      "typeVersion": 1
    },
    {
      "id": "d04b627c-1b80-4692-91a3-2df61bec0b4d",
      "name": "Envoyer un message",
      "type": "n8n-nodes-base.slack",
      "position": [
        1712,
        512
      ],
      "webhookId": "6b8dcfb9-51a9-418b-8469-4bf5b5894f2a",
      "parameters": {
        "text": "=*New Contract Processed* 📄\n• Contract ID: {{$node[\"Format Contract Data\"].json[\"Contract ID\"] || \"N/A\"}}\n• Title: {{$node[\"Format Contract Data\"].json[\"Title\"] || \"N/A\"}}\n• Parties: {{$node[\"Format Contract Data\"].json[\"Parties\"] || \"N/A\"}}\n• Effective: {{$node[\"Format Contract Data\"].json[\"Effective Date\"] || \"N/A\"}}\n• Termination: {{$node[\"Format Contract Data\"].json[\"Termination Date\"] || \"N/A\"}}\n🔗 {{$node[\"Format Contract Data\"].json[\"Drive Link\"] || $node[\"Save to Expense Database\"].json[\"driveLink\"] || \"No drive link available\"}}\n",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C081Z0KL546",
          "cachedResultName": "test"
        },
        "otherOptions": {}
      },
      "credentials": {
        "slackApi": {
          "id": "M00QrTNTmnr6yiTS",
          "name": "Slack account 11"
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "955768a3-5fac-4296-a5a3-d307a98b471c",
      "name": "Préparer les Événements Calendrier",
      "type": "n8n-nodes-base.code",
      "position": [
        1616,
        336
      ],
      "parameters": {
        "jsCode": "// n8n Function node code\n// Reads from Format Contract Data node and returns 1..3 items, each has .json with summary, description, start, end (YYYY-MM-DD)\n\nconst fmt = $node[\"Format Contract Data\"].json;\nconst title = fmt[\"Title\"] || \"Untitled Contract\";\nconst cid = fmt[\"Contract ID\"] || \"\";\nconst parties = fmt[\"Parties\"] || \"\";\nconst drive = fmt[\"Drive Link\"] || \"\";\n\nfunction isoDate(d) {\n  // return YYYY-MM-DD\n  return d.toISOString().split('T')[0];\n}\n\nfunction makeAllDayDates(dateStr) {\n  // Accepts YYYY-MM-DD (or other parseable), returns start and end for all-day event.\n  if(!dateStr) return null;\n  const d = new Date(dateStr + \"T00:00:00\");\n  const start = isoDate(d);\n  const endD = new Date(d);\n  endD.setDate(endD.getDate() + 1); // exclusive end for all-day events\n  const end = isoDate(endD);\n  return { start, end };\n}\n\nconst items = [];\n\n// Effective Date event\nconst eff = makeAllDayDates(fmt[\"Effective Date\"]);\nif (eff) {\n  items.push({\n    json: {\n      summary: `${title} — Effective Date`,\n      description: `Contract ID: ${cid}\\nParties: ${parties}\\nDrive: ${drive}`,\n      start: eff.start,\n      end: eff.end,\n      allDay: true,\n      metaType: \"effective\"\n    }\n  });\n}\n\n// Termination Date event\nconst term = makeAllDayDates(fmt[\"Termination Date\"]);\nif (term) {\n  items.push({\n    json: {\n      summary: `${title} — Termination Date`,\n      description: `Contract ID: ${cid}\\nParties: ${parties}\\nDrive: ${drive}`,\n      start: term.start,\n      end: term.end,\n      allDay: true,\n      metaType: \"termination\"\n    }\n  });\n\n  // Renewal review reminder 60 days before termination\n  const termDate = new Date(fmt[\"Termination Date\"] + \"T00:00:00\");\n  const reminderDate = new Date(termDate);\n  reminderDate.setDate(reminderDate.getDate() - 60); // change 60 to your preferred days\n  const remStart = isoDate(reminderDate);\n  const remEndD = new Date(reminderDate);\n  remEndD.setDate(remEndD.getDate() + 1);\n  const remEnd = isoDate(remEndD);\n\n  items.push({\n    json: {\n      summary: `${title} — Renewal Review (Reminder)`,\n      description: `Contract ID: ${cid}\\nTermination Date: ${fmt[\"Termination Date\"]}\\nAction: Review & decide renewal.`,\n      start: remStart,\n      end: remEnd,\n      allDay: true,\n      metaType: \"renewal_reminder\"\n    }\n  });\n}\n\nreturn items;\n"
      },
      "typeVersion": 2
    },
    {
      "id": "f3301d1a-5773-4598-ba4e-71019a4966bd",
      "name": "Créer un événement",
      "type": "n8n-nodes-base.googleCalendar",
      "position": [
        1808,
        336
      ],
      "parameters": {
        "end": "={{$json[\"end\"]}}",
        "start": "={{$json[\"start\"]}}",
        "calendar": {
          "__rl": true,
          "mode": "list",
          "value": "sayonaraistata@gmail.com",
          "cachedResultName": "sayonaraistata@gmail.com"
        },
        "additionalFields": {
          "allday": "yes",
          "summary": "={{$json[\"summary\"]}}",
          "description": "={{$json[\"description\"]}}"
        }
      },
      "credentials": {
        "googleCalendarOAuth2Api": {
          "id": "9TLut5ZDt3hcaQEo",
          "name": "Google Calendar account 3"
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "dd656271-d2a3-4f8a-9df8-1da0596b2734",
      "name": "📊 Documentation du Stockage1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1552,
        0
      ],
      "parameters": {
        "color": 7,
        "width": 420,
        "height": 680,
        "content": "## 🔔 Notifications Added:\n\n1. **Slack** → Posts contract details & AI-generated summary to #all-n8n-test for team visibility.\n\n2. **Google Calendar** → Auto-creates all-day events:\n   • Effective Date\n   • Termination Date\n   • Renewal Reminder (30 days before)\n   → Helps track key contract milestones.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "99fdd61d-c6a9-4e74-989a-e56b47caf2e9",
      "name": "Note Adhésive3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        368,
        704
      ],
      "parameters": {
        "color": 5,
        "width": 704,
        "height": 144,
        "content": "## 📝 Set the Callback URL\n\nMake sure to paste the **Production URL** of your n8n Webhook node into the **Callback URL** field in VLM Run. This ensures that the extracted image links are securely and reliably sent back to your live workflow. Do **not** use localhost or development URLs, they won’t be reachable by VLM Run’s servers."
      },
      "typeVersion": 1
    },
    {
      "id": "6d26e945-a724-4e3b-a8ff-c91dd8500f5f",
      "name": "Recevoir le Contrat",
      "type": "n8n-nodes-base.webhook",
      "position": [
        784,
        480
      ],
      "webhookId": "b905e71d-8ea5-4fc2-a773-b0f92e5398e4",
      "parameters": {
        "path": "b905e71d-8ea5-4fc2-a773-b0f92e5398e4",
        "options": {},
        "httpMethod": "POST"
      },
      "typeVersion": 2.1
    }
  ],
  "pinData": {},
  "connections": {
    "6d26e945-a724-4e3b-a8ff-c91dd8500f5f": {
      "main": [
        [
          {
            "node": "f752ffb1-d4eb-4d69-919d-2f4d72fb753e",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "f752ffb1-d4eb-4d69-919d-2f4d72fb753e": {
      "main": [
        [
          {
            "node": "70c2c9c5-d950-495f-9e91-5a0b402ef739",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "95acb226-9205-4a21-9a2d-c9792bc81de4": {
      "main": [
        [
          {
            "node": "84d28c8a-b33c-4bc3-9489-846c3b412d4a",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "955768a3-5fac-4296-a5a3-d307a98b471c": {
      "main": [
        [
          {
            "node": "f3301d1a-5773-4598-ba4e-71019a4966bd",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "2fca40fa-ac4a-4515-a1e0-295cdcbfc595": {
      "main": [
        [
          {
            "node": "95acb226-9205-4a21-9a2d-c9792bc81de4",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "70c2c9c5-d950-495f-9e91-5a0b402ef739": {
      "main": [
        [
          {
            "node": "d04b627c-1b80-4692-91a3-2df61bec0b4d",
            "type": "main",
            "index": 0
          },
          {
            "node": "955768a3-5fac-4296-a5a3-d307a98b471c",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Foire aux questions

Comment utiliser ce workflow ?

Copiez le code de configuration JSON ci-dessus, créez un nouveau workflow dans votre instance n8n et sélectionnez "Importer depuis le JSON", collez la configuration et modifiez les paramètres d'authentification selon vos besoins.

Dans quelles scénarios ce workflow est-il adapté ?

Intermédiaire

Est-ce payant ?

Ce workflow est entièrement gratuit et peut être utilisé directement. Veuillez noter que les services tiers utilisés dans le workflow (comme l'API OpenAI) peuvent nécessiter un paiement de votre part.

Informations sur le workflow
Niveau de difficulté
Intermédiaire
Nombre de nœuds14
Catégorie-
Types de nœuds10
Description de la difficulté

Adapté aux utilisateurs expérimentés, avec des workflows de complexité moyenne contenant 6-15 nœuds

Auteur
Shahrear

Shahrear

@shahrear

I’m Shahrear, a Software Engineer with over 5 years of experience in full-stack development and workflow automation. I specialize in building intelligent automations using n8n, helping teams streamline operations and boost productivity. I’m also an expert in developing custom n8n nodes, with published work on npm - including the @vlm-run/n8n-nodes-vlmrun package. Linkedin - https://www.linkedin.com/in/shahrear-amin/ Email - shahrearbinamin33@gmail.com

Liens externes
Voir sur n8n.io

Partager ce workflow

Catégories

Catégories: 34