{
  "format": "jsonpage-zap-template",
  "version": 1,
  "name": "Jsonpage - Verify and enrich a CSV file dropped in Google Drive or Dropbox",
  "description": "A CSV file dropped in a folder is verified and enriched, and the result file is saved next to it.",
  "importable": false,
  "importNote": "Zapier cannot import a Zap from a file: create the Zap with the steps below, in order. Each step lists the app, the action and the exact settings. {{...}} marks a field to map from a previous step.",
  "apiKeyPlaceholder": "PASTE_YOUR_JSONPAGE_API_KEY",
  "trigger": {
    "app": "Google Drive",
    "event": "New File in Folder",
    "alternative": {
      "app": "Dropbox",
      "event": "New File in Folder"
    },
    "note": "Add a Filter step: only continue if the file name ends with .csv and does not end with -verified.csv, so that the result file does not start the Zap again."
  },
  "steps": [
    {
      "order": 1,
      "title": "Read the file and prepare the request",
      "app": "Code by Zapier",
      "action": "Run Javascript",
      "inputData": {
        "file": "{{trigger.file}}",
        "defaultCountry": "FR"
      },
      "code": "// Code by Zapier (JavaScript): reads the CSV file and prepares the request body of the batch route (100 rows at most per run).\n// Input data: file = the file URL of the trigger, defaultCountry = FR\nconst text = (await (await fetch(inputData.file)).text()).replace(/^﻿/, '');\nconst lines = text.split(/\\r?\\n/).filter((l) => l.trim() !== '');\nconst delimiter = [';', ',', '\\t'].sort((a, b) => lines[0].split(b).length - lines[0].split(a).length)[0];\nconst split = (line) => line.split(delimiter).map((c) => c.replace(/^\"|\"$/g, '').trim());\nconst headers = split(lines[0]).map((h) => h.toLowerCase());\nconst col = ['id', 'siren', 'siret', 'vat', 'tva'].map((w) => headers.indexOf(w)).find((i) => i >= 0);\nif (col === undefined) throw new Error('No column named id, siren, siret, vat or tva');\nconst country = (inputData.defaultCountry || 'FR').toUpperCase();\nconst toId = (value) => {\n  const raw = String(value || '').trim();\n  if (/^[A-Za-z]{2}-[0-9A-Za-z]+$/.test(raw)) return raw.toUpperCase();\n  const c = raw.toUpperCase().replace(/[\\s.\\-]/g, '');\n  const vat = /^FR[0-9A-Z]{2}([0-9]{9})$/.exec(c);\n  if (vat) return 'FR-' + vat[1];\n  if (/^[0-9]{14}$/.test(c)) return country + '-' + c.slice(0, 9);\n  if (/^[0-9]{9}$/.test(c)) return country + '-' + c;\n  return '';\n};\nconst rows = lines.slice(1, 101).map((l) => { const v = split(l)[col] || ''; return { input: v, id: toId(v) }; });\nconst ids = rows.map((r) => r.id).filter(Boolean);\nif (ids.length === 0) throw new Error('No valid identifier in the file');\nreturn { ids: JSON.stringify(ids), body: JSON.stringify({ ids, include: ['address', 'vat'] }), rows: JSON.stringify(rows) };"
    },
    {
      "order": 2,
      "title": "Verify and enrich (batch)",
      "app": "Webhooks by Zapier",
      "action": "Custom Request",
      "method": "POST",
      "url": "https://api.jsonpage.com/v2/companies/batch",
      "headers": {
        "X-API-Key": "PASTE_YOUR_JSONPAGE_API_KEY",
        "Content-Type": "application/json"
      },
      "data": "{{step1.body}}",
      "unflatten": "no"
    },
    {
      "order": 3,
      "title": "Build the result file",
      "app": "Code by Zapier",
      "action": "Run Javascript",
      "inputData": {
        "response": "{{step2.response}}",
        "rows": "{{step1.rows}}"
      },
      "code": "// Code by Zapier (JavaScript): joins the answer of the batch route to the rows and writes the result CSV.\n// Input data: response = the raw response of the batch step, rows = the \"rows\" output of the previous Code step\nconst answer = JSON.parse(inputData.response).data || [];\nconst rows = JSON.parse(inputData.rows);\nconst byId = {};\nanswer.forEach((item) => { byId[item.id] = item; });\nconst columns = ['input', 'id', 'found', 'name', 'status', 'address', 'vat_number', 'vat_status', 'error'];\nconst cell = (v) => { const s = String(v ?? ''); return /[\";\\r\\n]/.test(s) ? '\"' + s.replace(/\"/g, '\"\"') + '\"' : s; };\nconst lines = rows.map((r) => {\n  const item = byId[r.id];\n  const c = item && item.data;\n  const out = c\n    ? { input: r.input, id: c.id, found: 'yes', name: c.name, status: c.status, address: (c.address || {}).formatted || '', vat_number: (c.vat || {}).number || '', vat_status: (c.vat || {}).status || '', error: '' }\n    : { input: r.input, id: r.id, found: 'no', error: r.id ? (item && item.error ? item.error.code : 'not_found') : 'invalid_identifier' };\n  return columns.map((k) => cell(out[k])).join(';');\n});\nreturn { csv: '﻿' + [columns.join(';'), ...lines].join('\\r\\n') + '\\r\\n' };"
    },
    {
      "order": 4,
      "title": "Save next to the original",
      "app": "Google Drive",
      "action": "Upload File",
      "fields": {
        "Folder": "the same folder as the trigger",
        "File": "{{step3.csv}}",
        "File Name": "{{trigger.name}}-verified.csv",
        "Convert to Document": "no"
      },
      "alternative": {
        "app": "Dropbox",
        "action": "Upload File",
        "note": "Same fields; Dropbox has its own trigger \"New File in Folder\"."
      }
    }
  ],
  "notes": [
    "The file needs one column named siren, siret, vat, tva or id.",
    "A run handles 100 rows. For bigger files use the n8n template, which cuts the file into batches of 100.",
    "In the batch step, paste {{step1.body}} (the JSON text prepared by the first Code step) in the Data field; the second Code step reads the response."
  ]
}
