This workflow corresponds to n8n.io template #4920 — we link there as the canonical source.
This workflow follows the Execute Workflow Trigger → Form 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 →
{
"meta": {
"templateCredsSetupCompleted": true
},
"nodes": [
{
"id": "ece7684b-64fa-4c80-9697-c6e7a4999eeb",
"name": "When Executed by Another Workflow",
"type": "n8n-nodes-base.executeWorkflowTrigger",
"position": [
-1420,
620
],
"parameters": {
"workflowInputs": {
"values": [
{
"name": "mime_type"
},
{
"name": "original_filename"
},
{
"name": "binary_data_base64"
}
]
}
},
"typeVersion": 1.1
},
{
"id": "6d600da3-a9e7-4015-bc73-a0fb5e400724",
"name": "Prepare Upload Data",
"type": "n8n-nodes-base.set",
"position": [
-940,
440
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "bucket-mapping",
"name": "bucket_name",
"type": "string",
"value": "={{ \n (() => {\n const mimeType = $json.mime_type || 'application/octet-stream';\n if (mimeType.startsWith('image/')) return 'image-files';\n if (mimeType.startsWith('audio/')) return 'audio-files';\n if (mimeType.startsWith('video/')) return 'video-files';\n return 'document-files';\n })()\n}}"
}
]
},
"includeOtherFields": true
},
"typeVersion": 3.4
},
{
"id": "5b5b91e9-b082-4d57-a191-c0fd71c84eae",
"name": "Success Response",
"type": "n8n-nodes-base.set",
"position": [
200,
440
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "action-type",
"name": "action",
"type": "string",
"value": "s3_upload"
},
{
"id": "success-status",
"name": "status",
"type": "string",
"value": "success"
}
]
},
"includeOtherFields": true
},
"typeVersion": 3.4
},
{
"id": "aa6355d3-5c2e-4b55-9f04-fcd1f5246428",
"name": "Convert to File",
"type": "n8n-nodes-base.convertToFile",
"notes": "Instead of the code note i would prefer to use the n8n dedicated note for this. only thing i am not sure of now is if i map the fields correct. ",
"position": [
-720,
440
],
"parameters": {
"options": {
"fileName": "={{ $json.original_filename }}",
"mimeType": "={{ $json.mime_type }}"
},
"operation": "toBinary",
"sourceProperty": "binary_data_base64"
},
"typeVersion": 1.1
},
{
"id": "2c1f3cf0-3726-4dd9-9121-e060e684d633",
"name": "temp form to test workflow",
"type": "n8n-nodes-base.formTrigger",
"position": [
-1420,
300
],
"parameters": {
"options": {
"path": "action-workflows-testform",
"appendAttribution": false
},
"formTitle": "test workflow form",
"formFields": {
"values": [
{
"fieldLabel": "original_filename",
"requiredField": true
},
{
"fieldType": "textarea",
"fieldLabel": "binary_data_base64",
"requiredField": true
},
{
"fieldLabel": "mime_type"
}
]
},
"formDescription": "use this form to test action workflows without having to use another workflow"
},
"typeVersion": 2.2
},
{
"id": "64932e5f-b7fc-46ad-9946-41703fec5823",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1800,
-100
],
"parameters": {
"color": 4,
"width": 1100,
"height": 260,
"content": "## \ud83d\udce6 Upload files to Supabase Storage\n\n- Link to [Supabase docs](https://supabase.com/docs/guides/storage)\n\nThis workflow shows how you could upload files to a Supabase Storage Instance. It's primarily designed to be called by other workflows, as there wasn't a default node for this yet, and this could be usefull in quite a lot of other workflows. \n\nIn this particular example we use mime-type to sort files to specific buckets, but this is of course dependent on your specific storage structure. \n\nThe output is a signed url for the object, to avoid having to share secrets for entire buckets to applications that need the object as input"
},
"typeVersion": 1
},
{
"id": "96202c5f-d481-4b20-a526-7ba0c79396a1",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1800,
180
],
"parameters": {
"width": 340,
"height": 340,
"content": "## \ud83e\uddea Quick Test Form during building\n\n\nThis form allowed me to quickly check this flow without having to execute another workflow.\n\nOf course you could also pin data, but given the fact i wanted to check different filetypes i opted for this temporary form, you can populate the base64 field with base64 encoded string of testfile (using for example `base64 -i /path/to/file | pbcopy`)\n\n\u26a0\ufe0f Remove before putting flow live."
},
"typeVersion": 1
},
{
"id": "c95e5ad4-0bad-4670-814b-198f51ecb1bb",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1800,
540
],
"parameters": {
"color": 3,
"width": 340,
"height": 280,
"content": "## \u2696\ufe0f Pro's and Con's of base64 encoding here\n\nI used the encoding step to be able to define input schema in this node below, it comes with a trade off though: file size of base 64 encoded files are 33% larger, also execution data is becoming quite large. \n\n\u26a0\ufe0fCarefully consider if this is usable if you are working with large files. "
},
"typeVersion": 1
},
{
"id": "36278709-336e-43a7-8f66-6f7b29cdca74",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1020,
180
],
"parameters": {
"color": 5,
"width": 460,
"height": 240,
"content": "## \ud83d\udd27Highlevel dataprep explanation\n\n\n**Prepare Upload Data:** maps inputs to buckets based on mimetype - passes through all other inputs.\n\n**Convert to file:** converts base64 encoded files back to actual files. (see red sticky node at start)"
},
"typeVersion": 1
},
{
"id": "0a2490ad-78ce-4252-884d-900e9848d865",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
-540,
180
],
"parameters": {
"color": 6,
"width": 640,
"height": 240,
"content": "## \ud83d\udd11 About Supabase Storage\n\nSupabase Storage uses HTTP API with Bearer YOUR_TOKEN_HERE authentication, not traditional AWS S3 SDK protocols.\n\nIn this set up we use an anon key/service key. We dont want to use that key all the time, so we generate a signed url to the object.\n\n\u26a0\ufe0f Replace the url in these nodes with your own."
},
"typeVersion": 1
},
{
"id": "309c7e12-bcfa-4756-85e8-2d54639296a6",
"name": "Upload to Supabase Storage",
"type": "n8n-nodes-base.httpRequest",
"onError": "continueErrorOutput",
"position": [
-460,
440
],
"parameters": {
"url": "=https://api-sb.janwillemaltink.com/storage/v1/object/{{ $('Prepare Upload Data').item.json.bucket_name }}/{{ $('Prepare Upload Data').item.json.original_filename }}",
"method": "POST",
"options": {},
"sendBody": true,
"contentType": "binaryData",
"authentication": "predefinedCredentialType",
"inputDataFieldName": "data",
"nodeCredentialType": "supabaseApi"
},
"credentials": {
"supabaseApi": {
"name": "<your credential>"
}
},
"typeVersion": 4.2
},
{
"id": "ad17d932-adc3-4a93-8e02-1f52fe8a8196",
"name": "Generate Signed Url",
"type": "n8n-nodes-base.httpRequest",
"onError": "continueErrorOutput",
"position": [
-220,
440
],
"parameters": {
"url": "=https://api-sb.janwillemaltink.com/storage/v1/object/sign/{{ $json.Key }}",
"method": "POST",
"options": {},
"jsonBody": "{\n\t\"expiresIn\": 2592000\n}",
"sendBody": true,
"specifyBody": "json",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "supabaseApi"
},
"credentials": {
"supabaseApi": {
"name": "<your credential>"
}
},
"typeVersion": 4.2
},
{
"id": "9be14ebe-84f1-4d91-8c54-392fabf89c05",
"name": "Upload Error Response",
"type": "n8n-nodes-base.set",
"position": [
-260,
620
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "action-type-error",
"name": "action",
"type": "string",
"value": "supabase_upload"
},
{
"id": "error-status",
"name": "status",
"type": "string",
"value": "error"
}
]
},
"includeOtherFields": true
},
"typeVersion": 3.4
},
{
"id": "8dbc6a1e-1a6b-4cc1-ac9f-51fe38c386b8",
"name": "add domain",
"type": "n8n-nodes-base.set",
"position": [
-20,
440
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "d346fd86-3905-4f89-8754-6966c9725a77",
"name": "full_signedURL",
"type": "string",
"value": "=https://api-sb.janwillemaltink.com/storage/v1{{ $json.signedURL }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "e21970f6-23d8-4e23-b42b-f5636dd52358",
"name": "Sign Error Response",
"type": "n8n-nodes-base.set",
"position": [
-20,
620
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "action-type-error",
"name": "action",
"type": "string",
"value": "supabase_sign"
},
{
"id": "error-status",
"name": "status",
"type": "string",
"value": "error"
}
]
},
"includeOtherFields": true
},
"typeVersion": 3.4
}
],
"connections": {
"add domain": {
"main": [
[
{
"node": "Success Response",
"type": "main",
"index": 0
}
]
]
},
"Convert to File": {
"main": [
[
{
"node": "Upload to Supabase Storage",
"type": "main",
"index": 0
}
]
]
},
"Success Response": {
"main": [
[]
]
},
"Generate Signed Url": {
"main": [
[
{
"node": "add domain",
"type": "main",
"index": 0
}
],
[
{
"node": "Sign Error Response",
"type": "main",
"index": 0
}
]
]
},
"Prepare Upload Data": {
"main": [
[
{
"node": "Convert to File",
"type": "main",
"index": 0
}
]
]
},
"Upload to Supabase Storage": {
"main": [
[
{
"node": "Generate Signed Url",
"type": "main",
"index": 0
}
],
[
{
"node": "Upload Error Response",
"type": "main",
"index": 0
}
]
]
},
"temp form to test workflow": {
"main": [
[
{
"node": "Prepare Upload Data",
"type": "main",
"index": 0
}
]
]
},
"When Executed by Another Workflow": {
"main": [
[
{
"node": "Prepare Upload Data",
"type": "main",
"index": 0
}
]
]
}
}
}
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.
supabaseApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
works with selfhosted Supabase
Source: https://n8n.io/workflows/4920/ — 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.
The AI-Powered Shopify SEO Content Automation is an enterprise-grade workflow that transforms product content creation for e-commerce stores. This sophisticated multi-agent system integrates GPT-4o, C
This template attempts to replicate OpenAI's DeepResearch feature which, at time of writing, is only available to their pro subscribers.
How it Works
Deep Research new (fr). Uses outputParserStructured, formTrigger, chainLlm, form. Event-driven trigger; 82 nodes.
Lection 9 main. Uses formTrigger, chatTrigger, agent, lmChatOpenAi. Event-driven trigger; 55 nodes.