This workflow follows the Google Drive → Google Drive Trigger recipe pattern — see all workflows that pair these two integrations.
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 →
{
"name": "03-recording-ingest",
"nodes": [
{
"parameters": {
"triggerOn": "specificFolder",
"folderToWatch": "={{ $env.GDRIVE_INBOX_FOLDER_ID }}",
"event": "fileCreated",
"options": {}
},
"id": "drive-trigger",
"name": "Google Drive Trigger",
"type": "n8n-nodes-base.googleDriveTrigger",
"typeVersion": 1,
"position": [
0,
0
],
"credentials": {
"googleDriveOAuth2Api": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"conditions": {
"string": [
{
"value1": "={{ $json.mimeType }}",
"operation": "regex",
"value2": "^video/(mp4|quicktime)$"
}
]
}
},
"id": "check-mime",
"name": "IF: Valid Video MIME",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
200,
0
]
},
{
"parameters": {
"jsCode": "// Parse filename: expected {reel_id}_{pillar}_{brief}.mp4\nconst filename = $input.first().json.name ?? '';\nconst match = filename.match(/^([a-f0-9-]{36}|[a-f0-9]{8})_/);\nif (!match) {\n return [{ json: { ...($input.first().json), _parse_error: 'no_reel_id_prefix', filename } }];\n}\nconst reel_id = match[1];\nreturn [{ json: { ...($input.first().json), reel_id, filename } }];"
},
"id": "parse-filename",
"name": "Parse Filename",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
400,
-100
]
},
{
"parameters": {
"conditions": {
"string": [
{
"value1": "={{ $json._parse_error }}",
"operation": "exists"
}
]
}
},
"id": "if-parse-error",
"name": "IF: Parse Error",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
600,
-100
]
},
{
"parameters": {
"operation": "move",
"fileId": "={{ $json.id }}",
"targetFolderId": "={{ $env.GDRIVE_UNMATCHED_FOLDER_ID }}",
"options": {}
},
"id": "move-unmatched",
"name": "Move to Unmatched",
"type": "n8n-nodes-base.googleDrive",
"typeVersion": 3,
"position": [
800,
0
],
"credentials": {
"googleDriveOAuth2Api": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"url": "={{ $env.ALERT_WEBHOOK_URL }}",
"method": "POST",
"sendBody": true,
"bodyContentType": "json",
"body": {
"content": "\u26a0\ufe0f **Unmatched recording**: `{{ $json.filename }}` has no reel_id prefix. Moved to `unmatched/`."
}
},
"id": "alert-unmatched",
"name": "Alert Unmatched",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
1000,
0
]
},
{
"parameters": {
"operation": "executeQuery",
"query": "=select * from reels_queue where id::text like '{{ $json.reel_id }}%' limit 1"
},
"id": "supabase-lookup",
"name": "Supabase Lookup",
"type": "n8n-nodes-base.supabase",
"typeVersion": 1,
"position": [
800,
-200
],
"credentials": {
"supabaseApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"operation": "download",
"fileId": "={{ $('Parse Filename').item.json.id }}",
"options": {}
},
"id": "download-from-drive",
"name": "Download from Drive",
"type": "n8n-nodes-base.googleDrive",
"typeVersion": 3,
"position": [
1000,
-200
],
"credentials": {
"googleDriveOAuth2Api": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"operation": "upload",
"bucketName": "={{ $env.R2_BUCKET }}",
"fileName": "=raw/{{ $('Supabase Lookup').item.json.id }}.mp4",
"binaryPropertyName": "data",
"additionalFields": {
"contentType": "video/mp4"
}
},
"id": "r2-upload",
"name": "R2 Upload",
"type": "n8n-nodes-base.awsS3",
"typeVersion": 1,
"position": [
1200,
-200
],
"onError": "continueErrorOutput",
"credentials": {
"aws": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"operation": "update",
"schema": "public",
"table": "reels_queue",
"filters": {
"conditions": [
{
"keyName": "id",
"condition": "eq",
"keyValue": "={{ $('Supabase Lookup').item.json.id }}"
}
]
},
"fieldsToSend": "defineBelow",
"dataToSend": {
"values": [
{
"fieldId": "raw_clip_url",
"fieldValue": "={{ $env.R2_PUBLIC_BASE_URL }}/raw/{{ $('Supabase Lookup').item.json.id }}.mp4"
},
{
"fieldId": "status",
"fieldValue": "editing"
}
]
}
},
"id": "supabase-update",
"name": "Supabase Update (editing)",
"type": "n8n-nodes-base.supabase",
"typeVersion": 1,
"position": [
1400,
-200
],
"credentials": {
"supabaseApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"url": "={{ $env.N8N_WEBHOOK_URL_04_EDIT }}",
"method": "POST",
"sendBody": true,
"bodyContentType": "json",
"body": {
"reel_id": "={{ $('Supabase Lookup').item.json.id }}"
}
},
"id": "trigger-04",
"name": "Trigger 04-auto-edit",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
1600,
-200
]
},
{
"parameters": {
"url": "={{ $env.ALERT_WEBHOOK_URL }}",
"method": "POST",
"sendBody": true,
"bodyContentType": "json",
"body": {
"content": "\u26a0\ufe0f **Invalid file type** in reels-inbox: `{{ $json.name }}` ({{ $json.mimeType }}). Skipped."
}
},
"id": "alert-invalid-mime",
"name": "Alert Invalid MIME",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
400,
100
]
},
{
"parameters": {
"url": "={{ $env.ALERT_WEBHOOK_URL }}",
"method": "POST",
"sendBody": true,
"bodyContentType": "json",
"body": {
"content": "\ud83d\udea8 **R2 upload failed** for reel `{{ $('Supabase Lookup').item.json.id }}`: {{ $json.error ?? JSON.stringify($json) }}"
}
},
"id": "alert-r2-failed",
"name": "Alert R2 Upload Failed",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
1400,
-50
]
},
{
"parameters": {
"mode": "runOnceForAllItems",
"jsCode": "// If Supabase Lookup returned 0 rows the reel_id isn't in the queue.\n// Return a sentinel item so the IF node below can route to an alert.\nconst items = $input.all();\nif (items.length === 0) {\n const filename = $('Parse Filename').first().json.filename ?? '(unknown)';\n return [{ json: { _not_found: true, filename } }];\n}\nreturn items;"
},
"id": "check-reel-found",
"name": "Check Reel Found",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
900,
-200
]
},
{
"parameters": {
"conditions": {
"boolean": [
{
"value1": "={{ $json._not_found }}",
"value2": true
}
]
}
},
"id": "if-reel-found",
"name": "IF: Reel Not Found",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
1100,
-200
]
},
{
"parameters": {
"url": "={{ $env.ALERT_WEBHOOK_URL }}",
"method": "POST",
"sendBody": true,
"bodyContentType": "json",
"body": {
"content": "\u26a0\ufe0f **Recording uploaded for unknown reel**: `{{ $json.filename }}` has no matching row in reels_queue. Check the reel_id prefix and re-upload."
}
},
"id": "alert-reel-not-found",
"name": "Alert: Reel Not Found",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
1300,
-50
]
}
],
"connections": {
"Google Drive Trigger": {
"main": [
[
{
"node": "IF: Valid Video MIME",
"type": "main",
"index": 0
}
]
]
},
"IF: Valid Video MIME": {
"main": [
[
{
"node": "Parse Filename",
"type": "main",
"index": 0
}
],
[
{
"node": "Alert Invalid MIME",
"type": "main",
"index": 0
}
]
]
},
"Parse Filename": {
"main": [
[
{
"node": "IF: Parse Error",
"type": "main",
"index": 0
}
]
]
},
"IF: Parse Error": {
"main": [
[
{
"node": "Move to Unmatched",
"type": "main",
"index": 0
}
],
[
{
"node": "Supabase Lookup",
"type": "main",
"index": 0
}
]
]
},
"Move to Unmatched": {
"main": [
[
{
"node": "Alert Unmatched",
"type": "main",
"index": 0
}
]
]
},
"Supabase Lookup": {
"main": [
[
{
"node": "Check Reel Found",
"type": "main",
"index": 0
}
]
]
},
"Download from Drive": {
"main": [
[
{
"node": "R2 Upload",
"type": "main",
"index": 0
}
]
]
},
"R2 Upload": {
"main": [
[
{
"node": "Supabase Update (editing)",
"type": "main",
"index": 0
}
],
[
{
"node": "Alert R2 Upload Failed",
"type": "main",
"index": 0
}
]
]
},
"Supabase Update (editing)": {
"main": [
[
{
"node": "Trigger 04-auto-edit",
"type": "main",
"index": 0
}
]
]
},
"Check Reel Found": {
"main": [
[
{
"node": "IF: Reel Not Found",
"type": "main",
"index": 0
}
]
]
},
"IF: Reel Not Found": {
"main": [
[
{
"node": "Alert: Reel Not Found",
"type": "main",
"index": 0
}
],
[
{
"node": "Download from Drive",
"type": "main",
"index": 0
}
]
]
}
},
"settings": {},
"staticData": null,
"tags": [
"reels-automation"
],
"triggerCount": 1,
"updatedAt": "2026-04-18T00:00:00.000Z",
"versionId": "1"
}
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.
awsgoogleDriveOAuth2ApisupabaseApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
03-recording-ingest. Uses googleDriveTrigger, googleDrive, httpRequest, supabase. Event-driven trigger; 16 nodes.
Source: https://github.com/ksksrbiz-arch/reels-automation/blob/37630734bcd00a9986c9c64b4c4cdcc31014993d/n8n-workflows/03-recording-ingest.json — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
This workflow acts as a junior finance research analyst for a UK boutique M&A or corporate finance team. It listens for Slack messages, classifies the request, gathers company or market data, and prod
This workflow is a multi-system document synchronization pipeline built in n8n, designed to automatically sync and back up files between Microsoft SharePoint, Supabase/Postgres, and Google Drive.
This enables webhooks for nearly realtime updates (every 5 seconds) from Notion Databases.
dummy_client - Shopify abandoned carts. Uses httpRequest, shopifyTrigger, whatsApp, supabase. Event-driven trigger; 25 nodes.
This workflow automatically collects historical price data from Polymarket Up/Down markets and stores it in Supabase, creating a structured and query-ready dataset for analysis. By continuously fetchi