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.
Memorybufferwindow Workflow. Uses emailSend, httpRequest, executeWorkflowTrigger, formTrigger. Event-driven trigger; 45 nodes.
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
Content - Newsletter Agent. Uses formTrigger, chainLlm, outputParserStructured, httpRequest. Event-driven trigger; 91 nodes.
Host Your Own AI Deep Research Agent with n8n, Apify and OpenAI. Uses outputParserStructured, lmChatOpenAi, formTrigger, chainLlm. Event-driven trigger; 87 nodes.
This template attempts to replicate OpenAI's DeepResearch feature which, at time of writing, is only available to their pro subscribers.