{
  "name": "Rename invoices & receipts for Japan e-Bookkeeping (Gemini OCR)",
  "tags": [],
  "nodes": [
    {
      "id": "d763f532-ef61-4602-8487-cf3b5ef50f6c",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -160,
        -48
      ],
      "parameters": {
        "width": 480,
        "height": 1080,
        "content": "## Rename invoices & receipts for Japan e-Bookkeeping (Gemini OCR)\n\n### Who's it for\n\nJapanese businesses, accountants and bookkeepers digitizing paper invoices and receipts under Japan's Electronic Bookkeeping Act (denshi-chobo-hozon-ho). Scanned files must be searchable by transaction date, partner and amount; renaming them by hand means opening every file, closing it, and typing the name. This workflow removes that manual work. Originals are never modified or deleted.\n\n### How it works\n\nThis workflow manually processes files from a Google Drive input folder and renames invoices or receipts for Japan e-Bookkeeping compliance. It downloads each file one at a time, filters for supported image or PDF formats, sends valid files to Gemini for OCR, and builds a compliant filename from the extracted document data. Files that pass validation are copied to an output folder with the new name, while unsupported or ambiguous files are copied to a skip folder for manual review.\n\n### Setup steps\n\n- Configure Google Drive credentials for all Drive nodes and ensure they have access to the input, output, and skip folders.\n- Set the inputFolderId, outputFolderId, skipFolderId, and maxFiles values in the configuration node.\n- Configure the Gemini HTTP request with a valid Google Generative Language API key and confirm the selected Gemini model supports image and PDF input.\n- Verify the code nodes' filename rules match the required Japan e-Bookkeeping naming convention before running on production files.\n\n### Customization\n\nAdjust the supported MIME types, maximum files per run, Gemini prompt, and filename-building logic to match your document formats and bookkeeping naming rules."
      },
      "typeVersion": 1
    },
    {
      "id": "5bc01d7b-8d77-48cb-8e14-e3a6bd0c93e4",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        400,
        112
      ],
      "parameters": {
        "color": 7,
        "width": 672,
        "height": 304,
        "content": "## Start and configure folders\n\nBegins the workflow manually, defines the Google Drive input, output, skip folder IDs and file limit, then lists files from the input folder."
      },
      "typeVersion": 1
    },
    {
      "id": "c2377aa9-213e-43f5-ab8f-626dc7d15e0d",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1200,
        112
      ],
      "parameters": {
        "color": 7,
        "width": 896,
        "height": 416,
        "content": "## Batch download and filter\n\nIterates through the listed files one at a time, downloads each file, converts it to base64, detects its MIME type, and checks whether it is a supported document type for OCR processing."
      },
      "typeVersion": 1
    },
    {
      "id": "54416a80-b1b2-4e64-9229-5e740f840c50",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2128,
        80
      ],
      "parameters": {
        "color": 7,
        "width": 512,
        "height": 336,
        "content": "## Extract and build filename\n\nSends supported images or PDFs to Gemini for invoice or receipt OCR, then uses code to interpret the response and construct a Japan e-Bookkeeping compliant filename and routing decision."
      },
      "typeVersion": 1
    },
    {
      "id": "033fd42d-2b33-48a6-bfd0-29bbe4b7b78e",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2688,
        -48
      ],
      "parameters": {
        "color": 7,
        "width": 416,
        "height": 576,
        "content": "## Validate and copy files\n\nChecks whether the extracted data represents a single valid document, then either copies and renames it into the output folder or sends it to the skip folder for manual review before returning to the next batch item."
      },
      "typeVersion": 1
    },
    {
      "id": "56f40dcf-557f-4a69-9431-52af0afdb795",
      "name": "Launch Workflow Manually",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        448,
        240
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "ff302bd0-d46b-4364-b132-0bee141bed93",
      "name": "Set Folder Configurations",
      "type": "n8n-nodes-base.set",
      "position": [
        688,
        240
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "0bb831be-1a13-4361-b190-6db5a0ee24ab",
              "name": "inputFolderId",
              "type": "string",
              "value": "YOUR_INPUT_FOLDER_ID"
            },
            {
              "id": "b3bc92a1-5659-4c0b-907d-8b5154e7be94",
              "name": "outputFolderId",
              "type": "string",
              "value": "YOUR_OUTPUT_FOLDER_ID"
            },
            {
              "id": "1a5e99d8-f1a8-4274-8d96-5a8d5e303a7b",
              "name": "skipFolderId",
              "type": "string",
              "value": "YOUR_SKIP_FOLDER_ID"
            },
            {
              "id": "297c7acf-48db-4f09-aa33-c9abc9ba464b",
              "name": "maxFiles",
              "type": "number",
              "value": 20
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "4b76ff2c-b701-4b5e-8a73-358efd2c22cc",
      "name": "Retrieve Input Folder Files",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        928,
        240
      ],
      "parameters": {
        "limit": "={{ $json.maxFiles }}",
        "filter": {},
        "options": {},
        "resource": "fileFolder",
        "queryString": "='{{ $json.inputFolderId }}' in parents and trashed=false",
        "searchMethod": "query"
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "e36a56e3-24b5-414e-95f4-2b2127cd3079",
      "name": "Process Files Individually",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        1248,
        240
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "a94aea0d-4a92-4c72-a4a6-9e8eb1840486",
      "name": "Download from Google Drive",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        1488,
        352
      ],
      "parameters": {
        "fileId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $json.id }}"
        },
        "options": {},
        "operation": "download"
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "295caf04-acb3-403e-87c6-50b7e26cf847",
      "name": "Validate Single Document Status",
      "type": "n8n-nodes-base.if",
      "position": [
        2736,
        256
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "250db40d-2b8c-447b-8716-e5ada857f716",
              "operator": {
                "type": "string",
                "operation": "notEmpty"
              },
              "leftValue": "={{ $json.newName }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "bf839723-c950-4d27-aafe-8aa079fdf730",
      "name": "Copy and Rename to Output Folder",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        2960,
        160
      ],
      "parameters": {
        "name": "={{ $json.newName }}",
        "fileId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $json.fileId }}"
        },
        "driveId": {
          "__rl": true,
          "mode": "list",
          "value": "My Drive"
        },
        "options": {},
        "folderId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('Set Folder Configurations').first().json.outputFolderId }}"
        },
        "operation": "copy",
        "sameFolder": false
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "81eda505-849c-430b-ae3e-66237aa1b684",
      "name": "Copy to Manual Review Folder",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        2960,
        368
      ],
      "parameters": {
        "name": "={{ $json.originalName }}",
        "fileId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $json.fileId }}"
        },
        "driveId": {
          "__rl": true,
          "mode": "list",
          "value": "My Drive"
        },
        "options": {},
        "folderId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('Set Folder Configurations').first().json.skipFolderId }}"
        },
        "operation": "copy",
        "sameFolder": false
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "11fdaeb9-9c1c-483a-bb47-a6abac56a62e",
      "name": "Encode File and Detect MIME",
      "type": "n8n-nodes-base.code",
      "position": [
        1728,
        352
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "const meta=$('Process Files Individually').item.json;\nconst ext=(meta.name||'').toLowerCase().split('.').pop();\nconst map={jpg:'image/jpeg',jpeg:'image/jpeg',png:'image/png',webp:'image/webp',heic:'image/heic',heif:'image/heif',tif:'image/tiff',tiff:'image/tiff',pdf:'application/pdf'};\nconst isSupported=Object.keys(map).includes(ext);\nconst buf= await this.helpers.getBinaryDataBuffer(0,'data');\nconst b64= buf.toString('base64');\nconst bin=$input.item.binary && $input.item.binary.data;\nconst mime=map[ext]||(bin&&bin.mimeType)||'application/octet-stream';\nconst prompt=\"\u3042\u306a\u305f\u306f\u65e5\u672c\u306e\u7d4c\u7406\u66f8\u985e\u3092\u8aad\u307f\u53d6\u308b\u30a2\u30b7\u30b9\u30bf\u30f3\u30c8\u3067\u3059\u3002\u6dfb\u4ed8\u30d5\u30a1\u30a4\u30eb\u306f\u8acb\u6c42\u66f8\u30fb\u9818\u53ce\u66f8\u306a\u3069\u306e\u5e33\u7968\u3001\u307e\u305f\u306f\u5e33\u7968\u3067\u306a\u3044\u753b\u50cf\u3067\u3059\u3002\u4ee5\u4e0b\u3092JSON\u306e\u307f\u3067\u51fa\u529b\uff08\u524d\u5f8c\u306e\u8aac\u660e\u30fb\u30b3\u30fc\u30c9\u30d5\u30a7\u30f3\u30b9\u7981\u6b62\uff09\u3002{\\\"document_count\\\":<0=\u5e33\u7968\u3067\u306a\u3044,1=\u5358\u4e00,2\u4ee5\u4e0a=\u8907\u6570>,\\\"doc_type\\\":\\\"\u8acb\u6c42\u66f8|\u9818\u53ce\u66f8|\u898b\u7a4d\u66f8|\u7d0d\u54c1\u66f8|\u305d\u306e\u4ed6\\\",\\\"transaction_date\\\":\\\"YYYYMMDD\\\",\\\"partner\\\":\\\"\u53d6\u5f15\u5148\u306e\u6b63\u5f0f\u540d\u79f0(\u767a\u884c\u5143)\\\",\\\"amount\\\":<\u7a0e\u8fbc\u5408\u8a08\u306e\u6570\u5024\u30fb\u30ab\u30f3\u30de\u306a\u3057>}\u30eb\u30fc\u30eb:\u5e33\u7968\u3067\u306a\u3044\u5199\u771f\u306fdocument_count=0\u30021\u30d5\u30a1\u30a4\u30eb\u306b\u8907\u6570\u5e33\u7968\u3084\u8907\u6570\u53d6\u5f15\u306a\u3089document_count\u30922\u4ee5\u4e0a\u3002\u65e5\u4ed8\u306f\u53d6\u5f15\u5e74\u6708\u65e5(\u8acb\u6c42\u65e5\u30fb\u9818\u53ce\u65e5)\u3002\u91d1\u984d\u306f\u7a0e\u8fbc\u5408\u8a08\u3002\u8aad\u3081\u306a\u3044\u9805\u76ee\u306fnull\u3002\";\nconst bodyObj={contents:[{parts:[{inline_data:{mime_type:mime,data:b64}},{text:prompt}]}],generationConfig:{temperature:0,response_mime_type:'application/json'}};\nreturn {json:{fileId:meta.id,originalName:meta.name,ext,mime,isSupported,body:JSON.stringify(bodyObj)}};"
      },
      "typeVersion": 2
    },
    {
      "id": "f961fedd-a32c-4e0f-85c7-f3781ad11d58",
      "name": "Check Supported File Type",
      "type": "n8n-nodes-base.if",
      "position": [
        1952,
        352
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "ext-c-0001",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ $json.isSupported }}",
              "rightValue": true
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "96bea0f3-c643-4268-9073-60ce2eb31166",
      "name": "Send to Gemini for OCR",
      "type": "n8n-nodes-base.httpRequest",
      "notes": "\u753b\u50cf\u3082PDF\u3082\u5171\u901a\u3067Gemini API\u306b\u76f4\u63a5\u9001\u308b\u3002x-goog-api-key\u30d8\u30c3\u30c0\u306bGemini API\u30ad\u30fc\u3092\u5165\u308c\u308b\uff08List/Download\u3068\u306f\u5225\u3002Google AI Studio\u306eAPI\u30ad\u30fc\uff09\u3002",
      "position": [
        2176,
        256
      ],
      "parameters": {
        "url": "=https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent",
        "method": "POST",
        "options": {},
        "jsonBody": "={{ $json.body }}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            },
            {
              "name": "x-goog-api-key",
              "value": "YOUR_GEMINI_API_KEY"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "b7bb9ab9-bb06-4452-a763-ab3651c16eb8",
      "name": "Generate Compliant Filename",
      "type": "n8n-nodes-base.code",
      "position": [
        2496,
        256
      ],
      "parameters": {
        "jsCode": "const c = $json;\nlet raw='';\ntry{ raw = c.candidates[0].content.parts.map(p=>p.text||'').join(''); }catch(e){ raw=''; }\nlet data; try{ data = JSON.parse(String(raw).replace(/```json|```/g,'').trim()); }catch(e){ data={document_count:-1}; }\nfunction san(s){ return String(s==null?'':s).replace(/[\\\\/:*?\\\"<>|]/g,'').replace(/\\s+/g,'').trim(); }\nconst p = $('Encode File and Detect MIME').item.json;\nlet newName=null;\nif(data.document_count===1 && data.transaction_date && data.amount!=null){\n  newName = `${san(data.transaction_date)}_${san(data.partner)}_${san(data.amount)}_${san(data.doc_type)}.${p.ext}`;\n}\nreturn [{ json: { ...data, originalName:p.originalName, fileId:p.fileId, ext:p.ext, newName } }];"
      },
      "typeVersion": 2
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "executionOrder": "v1"
  },
  "nodeGroups": [],
  "connections": {
    "Send to Gemini for OCR": {
      "main": [
        [
          {
            "node": "Generate Compliant Filename",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Launch Workflow Manually": {
      "main": [
        [
          {
            "node": "Set Folder Configurations",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Supported File Type": {
      "main": [
        [
          {
            "node": "Send to Gemini for OCR",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Copy to Manual Review Folder",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Folder Configurations": {
      "main": [
        [
          {
            "node": "Retrieve Input Folder Files",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Download from Google Drive": {
      "main": [
        [
          {
            "node": "Encode File and Detect MIME",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Process Files Individually": {
      "main": [
        [],
        [
          {
            "node": "Download from Google Drive",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Encode File and Detect MIME": {
      "main": [
        [
          {
            "node": "Check Supported File Type",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Compliant Filename": {
      "main": [
        [
          {
            "node": "Validate Single Document Status",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Retrieve Input Folder Files": {
      "main": [
        [
          {
            "node": "Process Files Individually",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Copy to Manual Review Folder": {
      "main": [
        [
          {
            "node": "Process Files Individually",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Validate Single Document Status": {
      "main": [
        [
          {
            "node": "Copy and Rename to Output Folder",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Copy to Manual Review Folder",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Copy and Rename to Output Folder": {
      "main": [
        [
          {
            "node": "Process Files Individually",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}