AutomationFlowsAI & RAG › Retrieve Templates from Google Drive via Webhook

Retrieve Templates from Google Drive via Webhook

Original n8n title: Edificia - Template Storage (retrieve)

EDIFICIA - Template Storage (Retrieve). Uses googleDrive. Webhook trigger; 10 nodes.

Webhook trigger★★★★☆ complexity10 nodesGoogle Drive
AI & RAG Trigger: Webhook Nodes: 10 Complexity: ★★★★☆ Added:

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
{
  "name": "EDIFICIA - Template Storage (Retrieve)",
  "nodes": [
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "template-retrieve",
        "responseMode": "responseNode",
        "options": {}
      },
      "id": "tr-wh-0001-0000-0000-000000000001",
      "name": "Webhook",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [
        240,
        340
      ]
    },
    {
      "parameters": {
        "jsCode": "// Valida X-Edificia-Auth contra la variable de entorno EDIFICIA_API_SECRET.\n// Extrae y expone el body para los nodos siguientes.\nconst items = $input.all();\nconst headers = items[0].json.headers;\nconst expectedSecret = $env.EDIFICIA_API_SECRET;\nconst receivedSecret = headers['x-edificia-auth'];\n\nif (!expectedSecret) {\n  throw new Error('EDIFICIA_API_SECRET environment variable is not configured in n8n.');\n}\n\nif (!receivedSecret || receivedSecret !== expectedSecret) {\n  return [{ json: { isValid: false } }];\n}\n\nconst body = items[0].json.body;\nreturn [{ json: { isValid: true, ...body } }];"
      },
      "id": "tr-auth-0001-0000-0000-000000000002",
      "name": "Validate Auth",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        460,
        340
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "loose"
          },
          "conditions": [
            {
              "id": "cond-auth-valid",
              "leftValue": "={{ Boolean($json.isValid) }}",
              "rightValue": "",
              "operator": {
                "type": "boolean",
                "operation": "true"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "tr-if-000001-0000-0000-000000000003",
      "name": "Auth Valid?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        680,
        340
      ]
    },
    {
      "parameters": {
        "respondWith": "text",
        "responseBody": "={{ JSON.stringify({ apiVersion: '1.0', operation: $json.operation ?? 'UNKNOWN', operationId: $json.operationId ?? '', success: false, code: 'AUTH_INVALID', message: 'Invalid or missing X-Edificia-Auth header', timestampUtc: new Date().toISOString() }) }}",
        "options": {
          "responseCode": 401,
          "responseHeaders": {
            "entries": [
              {
                "name": "Content-Type",
                "value": "application/json"
              }
            ]
          }
        }
      },
      "id": "tr-401-0001-0000-0000-000000000004",
      "name": "Respond 401",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.1,
      "position": [
        900,
        500
      ]
    },
    {
      "parameters": {
        "jsCode": "// Valida que la operaci\u00f3n sea GET_TEMPLATE y que storageKey est\u00e9 presente.\nconst item = $input.first();\nconst operation = item.json.operation;\nconst storageKey = item.json.payload?.storageKey;\n\nif (operation !== 'GET_TEMPLATE') {\n  return [{ json: { ...item.json, isValid: false, validationError: 'UNSUPPORTED_OPERATION', validationMessage: 'Este webhook solo acepta GET_TEMPLATE. Use /webhook/template-store para UPLOAD y DELETE.' } }];\n}\n\nif (!storageKey || typeof storageKey !== 'string' || storageKey.trim() === '') {\n  return [{ json: { ...item.json, isValid: false, validationError: 'REQUEST_INVALID', validationMessage: 'payload.storageKey es obligatorio para GET_TEMPLATE.' } }];\n}\n\nreturn [{ json: { ...item.json, isValid: true } }];"
      },
      "id": "tr-val-0001-0000-0000-000000000005",
      "name": "Validate GET Request",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        900,
        180
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "loose"
          },
          "conditions": [
            {
              "id": "cond-req-valid",
              "leftValue": "={{ Boolean($json.isValid) }}",
              "rightValue": "",
              "operator": {
                "type": "boolean",
                "operation": "true"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "tr-if2-00001-0000-0000-000000000006",
      "name": "Request Valid?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        1120,
        180
      ]
    },
    {
      "parameters": {
        "respondWith": "text",
        "responseBody": "={{ JSON.stringify({ apiVersion: '1.0', operation: $json.operation ?? 'GET_TEMPLATE', operationId: $json.operationId ?? '', success: false, code: $json.validationError ?? 'REQUEST_INVALID', message: $json.validationMessage ?? 'Petici\u00f3n inv\u00e1lida', timestampUtc: new Date().toISOString() }) }}",
        "options": {
          "responseCode": 400,
          "responseHeaders": {
            "entries": [
              {
                "name": "Content-Type",
                "value": "application/json"
              }
            ]
          }
        }
      },
      "id": "tr-400-0001-0000-0000-000000000007",
      "name": "Respond 400",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.1,
      "position": [
        1340,
        340
      ]
    },
    {
      "parameters": {
        "operation": "download",
        "fileId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $json.payload.storageKey }}"
        },
        "options": {}
      },
      "id": "tr-gdd-0001-0000-0000-000000000008",
      "name": "Download from Google Drive",
      "type": "n8n-nodes-base.googleDrive",
      "typeVersion": 3,
      "position": [
        1340,
        80
      ],
      "continueOnFail": true,
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "// Comprueba si la descarga fue exitosa y construye la respuesta.\n// Si continueOnFail captur\u00f3 un error de Drive, responde TEMPLATE_NOT_FOUND.\nconst input = $input.first();\nconst original = $('Validate GET Request').first().json;\nconst hasError = !!input.json.error || !input.binary?.data;\n\nif (hasError) {\n  return [{\n    json: {\n      apiVersion: '1.0',\n      operation: 'GET_TEMPLATE',\n      operationId: original.operationId,\n      success: false,\n      code: 'TEMPLATE_NOT_FOUND',\n      message: 'La plantilla no existe en el almacenamiento',\n      provider: 'google-drive',\n      timestampUtc: new Date().toISOString(),\n      data: null\n    },\n    _httpStatus: 404\n  }];\n}\n\n// Encode binary to base64\nconst binaryData = input.binary.data;\nconst buffer = await this.helpers.getBinaryDataBuffer(input, 'data');\nconst contentBase64 = buffer.toString('base64');\n\nreturn [{\n  json: {\n    apiVersion: '1.0',\n    operation: 'GET_TEMPLATE',\n    operationId: original.operationId,\n    success: true,\n    code: 'TEMPLATE_STORAGE_OK',\n    message: 'Plantilla recuperada correctamente',\n    provider: 'google-drive',\n    timestampUtc: new Date().toISOString(),\n    data: {\n      storageKey: original.payload.storageKey,\n      mimeType: binaryData.mimeType ?? 'application/vnd.openxmlformats-officedocument.wordprocessingml.template',\n      fileSizeBytes: binaryData.fileSize ?? null,\n      contentBase64\n    }\n  },\n  _httpStatus: 200\n}];"
      },
      "id": "tr-resp-0001-0000-0000-000000000009",
      "name": "Build GET Response",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1560,
        80
      ]
    },
    {
      "parameters": {
        "respondWith": "firstIncomingItem",
        "options": {
          "responseCode": "={{ $json._httpStatus ?? 200 }}",
          "responseHeaders": {
            "entries": [
              {
                "name": "Content-Type",
                "value": "application/json"
              }
            ]
          }
        }
      },
      "id": "tr-200-0001-0000-0000-000000000010",
      "name": "Respond GET",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.1,
      "position": [
        1780,
        80
      ]
    }
  ],
  "connections": {
    "Webhook": {
      "main": [
        [
          {
            "node": "Validate Auth",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Validate Auth": {
      "main": [
        [
          {
            "node": "Auth Valid?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Auth Valid?": {
      "main": [
        [
          {
            "node": "Validate GET Request",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Respond 401",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Validate GET Request": {
      "main": [
        [
          {
            "node": "Request Valid?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Request Valid?": {
      "main": [
        [
          {
            "node": "Download from Google Drive",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Respond 400",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Download from Google Drive": {
      "main": [
        [
          {
            "node": "Build GET Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build GET Response": {
      "main": [
        [
          {
            "node": "Respond GET",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "edificia-template-retrieve-v1",
  "meta": {
    "templateCredsSetupCompleted": false
  },
  "tags": [
    {
      "name": "edificia"
    },
    {
      "name": "templates"
    },
    {
      "name": "google-drive"
    }
  ]
}

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

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

About this workflow

EDIFICIA - Template Storage (Retrieve). Uses googleDrive. Webhook trigger; 10 nodes.

Source: https://github.com/jesusjbriceno/edificia/blob/6e21d29fa62e52c9f471e2e57dc85636d7e53d98/apps/n8n/workflow-template-retrieve.json — original creator credit. Request a take-down →

More AI & RAG workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

AI & RAG

This workflow is perfect for app developers, SaaS founders, and mobile growth teams who need constant UGC-style video ads without hiring creators or agencies. If you're spending $500+ per creator and

HTTP Request, Google Drive
AI & RAG

AI Background Generation with Nano Banana (Gemini Image). Uses httpRequest, googleDrive. Webhook trigger; 35 nodes.

HTTP Request, Google Drive
AI & RAG

This template is for developers, teams, and automation enthusiasts who want a private, PIN-protected Telegram chatbot that answers questions from their own documents — without relying on external AI A

Postgres, Telegram, HTTP Request +2
AI & RAG

Storage Sync - Google Drive. Uses supabase, googleDrive, httpRequest. Webhook trigger; 22 nodes.

Supabase, Google Drive, HTTP Request
AI & RAG

This workflow automates the creation of user-generated-content-style product videos by combining Gemini's image generation with OpenAI's SORA 2 video generation. It accepts webhook requests with produ

HTTP Request, Google Sheets, Google Drive