AutomationFlowsData & Sheets › AI Transcription to Postgres & Supabase

AI Transcription to Postgres & Supabase

Original n8n title: Postgres

Postgres. Uses openAi, postgres, postgresTool, httpRequest. Webhook trigger; 19 nodes.

Webhook trigger★★★★☆ complexityAI-powered19 nodesOpenAIPostgresPostgres ToolHTTP RequestSupabase
Data & Sheets Trigger: Webhook Nodes: 19 Complexity: ★★★★☆ AI nodes: yes Added:

This workflow follows the HTTP Request → OpenAI 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 →

Download .json
{
  "nodes": [
    {
      "id": "d44489b8-8cb7-4776-8c16-a8bb01e52171",
      "name": "OpenAI1",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "position": [
        300,
        -300
      ],
      "parameters": {
        "text": "={{ \n     JSON.parse($('Insert Transcription Part').item.json.dialog)\n        .filter(item => item.date_updated && new Date(item.date_updated) >= new Date($('Insert Transcription Part').item.json.date_updated))\n        .sort((a, b) => a.order - b.order)\n        .map(item => `${item.words}\\n${item.speaker}`)\n        .join('\\n\\n')\n}}",
        "memory": "threadId",
        "prompt": "define",
        "options": {},
        "resource": "assistant",
        "threadId": "={{ $json.thread_id }}",
        "assistantId": {
          "__rl": true,
          "mode": "list",
          "value": "asst_D5t6bNnNpenmfC7PmvywMqyR",
          "cachedResultName": "5minAI - Realtime Agent"
        }
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.6
    },
    {
      "id": "3425f1c1-ad68-495e-bb9a-95ea92e7cf23",
      "name": "Insert Transcription Part",
      "type": "n8n-nodes-base.postgres",
      "position": [
        -120,
        -300
      ],
      "parameters": {
        "query": "UPDATE public.data\nSET output = jsonb_set(\n    output,\n    '{dialog}', \n    (\n        COALESCE(\n            (output->'dialog')::jsonb, \n            '[]'::jsonb  -- Initialize as empty array if dialog does not exist\n        ) || jsonb_build_object(\n            'order', (COALESCE(jsonb_array_length(output->'dialog'), 0) + 1),  -- Calculate the next order\n            'words', '{{ $('Webhook2').item.json.body.data.transcript.words.map(word => word.text.replace(/'/g, \"''\")).join(\" \") }}',\n            'speaker', '{{ $('Webhook2').item.json.body.data.transcript.speaker }}',\n            'language', '{{ $('Webhook2').item.json.body.data.transcript.language }}',\n            'speaker_id', ('{{ $('Webhook2').item.json.body.data.transcript.speaker_id }}')::int,\n  'date_updated', to_jsonb('{{ $now }}'::text)\n        )\n    )\n)\nWHERE input->>'recall_bot_id' = $1\nReturning input->>'openai_thread_id' as thread_id;",
        "options": {
          "queryReplacement": "={{ $('Scenario 2 Start - Webhook').item.json.body.data.bot_id }}"
        },
        "operation": "executeQuery"
      },
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.5
    },
    {
      "id": "9bcc0605-fc35-4842-a3f4-30ef902f35c1",
      "name": "Create Note",
      "type": "n8n-nodes-base.postgresTool",
      "position": [
        180,
        -120
      ],
      "parameters": {
        "query": "UPDATE public.data\nSET output = jsonb_set(\n    output,\n    '{notes}', \n    (\n        COALESCE(\n            (output->'notes')::jsonb, \n            '[]'::jsonb  -- Initialize as empty array if dialog does not exist\n        ) || jsonb_build_object(\n            'order', (COALESCE(jsonb_array_length(output->'notes'), 0) + 1),  -- Calculate the next order\n            'text', '{{ $fromAI(\"note\",\"Text of note.\") }}'\n        )\n    )\n)\nWHERE input->>'recall_bot_id' = $1",
        "options": {
          "queryReplacement": "={{ $('Scenario 2 Start - Webhook').item.json.body.data.bot_id }}"
        },
        "operation": "executeQuery",
        "descriptionType": "manual",
        "toolDescription": "Create note record."
      },
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.5
    },
    {
      "id": "0831c139-ca4b-4b4c-aa7f-7495c4ca0110",
      "name": "Create Recall bot",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -60,
        -980
      ],
      "parameters": {
        "url": "https://us-west-2.recall.ai/api/v1/bot",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"meeting_url\":\"{{ $json.meeting_url }}\",\n  \"transcription_options\": {\n    \"provider\": \"assembly_ai\"\n  }\n,\n\"real_time_transcription\": {\n    \"destination_url\": \"https://n8n.lowcoding.dev/webhook/d074ca1e-52f9-47af-8587-8c24d431f9cd\"\n  },\n\"automatic_leave\": {\n  \"silence_detection\": {\n    \"timeout\": 300, \n    \"activate_after\": 600\n  },\n  \"bot_detection\": {\n    \"using_participant_events\": {\n      \"timeout\": 600, \n      \"activate_after\": 1200\n    }\n  },\n  \"waiting_room_timeout\": 600,\n  \"noone_joined_timeout\": 600,\n  \"everyone_left_timeout\": 2,\n  \"in_call_not_recording_timeout\": 600,\n  \"recording_permission_denied_timeout\": 600\n}\n}",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth"
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "e1122b5b-3af5-4836-802c-40c3a0eb3c93",
      "name": "Create OpenAI thread",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        140,
        -980
      ],
      "parameters": {
        "url": "https://api.openai.com/v1/threads",
        "method": "POST",
        "options": {},
        "sendHeaders": true,
        "authentication": "predefinedCredentialType",
        "headerParameters": {
          "parameters": [
            {
              "name": "OpenAI-Beta",
              "value": "assistants=v2"
            }
          ]
        },
        "nodeCredentialType": "openAiApi"
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "784c123d-adbb-4265-9485-2c88dd3091c2",
      "name": "Create data record",
      "type": "n8n-nodes-base.supabase",
      "position": [
        320,
        -980
      ],
      "parameters": {
        "tableId": "data",
        "fieldsUi": {
          "fieldValues": [
            {
              "fieldId": "input",
              "fieldValue": "={{ {\"openai_thread_id\": $('Create OpenAI thread').item.json.id, \"recall_bot_id\": $('Create Recall bot').item.json.id, \"meeting_url\":$('Webhook').item.json.body.meeting_url } }}"
            },
            {
              "fieldId": "output",
              "fieldValue": "={{ {\"dialog\":[]} }}"
            }
          ]
        }
      },
      "credentials": {
        "supabaseApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "f455c7de-1e64-4a28-9eef-11d19c982813",
      "name": "Sticky Note9",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -900,
        -380
      ],
      "parameters": {
        "color": 7,
        "width": 330.5152611046425,
        "height": 239.5888196628349,
        "content": "### ... or watch set up video [10 min]\n[![Youtube Thumbnail](https://res.cloudinary.com/de9jgixzm/image/upload/v1739773273/Youtube%20Thumbs/Realtim%20AI%20Agent.png)](https://www.youtube.com/watch?v=rtaX6BMiTeo)\n"
      },
      "typeVersion": 1
    },
    {
      "id": "ea90c110-18ad-4f4b-90ab-fcb88b92e709",
      "name": "Sticky Note7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1200,
        -1060
      ],
      "parameters": {
        "color": 7,
        "width": 636,
        "height": 657,
        "content": "![5min Logo](https://res.cloudinary.com/de9jgixzm/image/upload/v1739773200/Skool%20Assets/ejm3hqnvhgwpnu2fv92s.png)\n## AI Agent for realtime insights on meetings\n**Made by [Mark Shcherbakov](https://www.linkedin.com/in/marklowcoding/) from community [5minAI](https://www.skool.com/5minai)**\n\nTranscribing meetings manually can be tedious and prone to error. This workflow automates the transcription process in real-time, ensuring that key discussions and decisions are accurately captured and easily accessible for later review, thus enhancing productivity and clarity in communications.\n\nThe workflow employs an AI-powered assistant to join virtual meetings and capture discussions through real-time transcription. Key functionalities include:\n- Automatic joining of meetings on platforms like Zoom, Google Meet, and others with the ability to provide real-time transcription.\n- Integration with transcription APIs (e.g., AssemblyAI) to deliver seamless and accurate capture of dialogue.\n- Structuring and storing transcriptions efficiently in a database for easy retrieval and analysis.\n\n1. **Real-Time Transcription**: The assistant captures audio during meetings and transcribes it in real-time, allowing participants to focus on discussions.\n2. **Keyword Recognition**: Key phrases can trigger specific actions, such as noting important points or making prompts to the assistant.\n3. **Structured Data Management**: The assistant maintains a database of transcriptions linked to meeting details for organized storage and quick access later."
      },
      "typeVersion": 1
    },
    {
      "id": "378c19bb-0e4a-43d3-9ba5-2a77ebfb5b83",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1200,
        -380
      ],
      "parameters": {
        "color": 7,
        "width": 280,
        "height": 626,
        "content": "### Set up steps\n\n#### Preparation\n\n1. **Create Recall.ai API key**\n2. **Setup Supabase account and table**\n```\ncreate table\n  public.data (\n    id uuid not null default gen_random_uuid (),\n    date_created timestamp with time zone not null default (now() at time zone 'utc'::text),\n    input jsonb null,\n    output jsonb null,\n    constraint data_pkey primary key (id),\n  ) tablespace pg_default;\n\n```\n3. **Create OpenAI API key**\n\n#### Development\n\n1. **Bot Creation**: \n   - Use a node to create the bot that will join meetings. Provide the meeting URL and set transcription options within the API request.\n\n2. **Authentication**: \n   - Configure authentication settings via a Bearer token for interacting with your transcription service.\n\n3. **Webhook Setup**: \n   - Create a webhook to receive real-time transcription updates, ensuring timely data capture during meetings.\n\n4. **Join Meeting**: \n   - Set the bot to join the specified meeting and actively listen to capture conversations.\n\n5. **Transcription Handling**: \n   - Combine transcription fragments into cohesive sentences and manage dialog arrays for coherence.\n\n6. **Trigger Actions on Keywords**: \n   - Set up keyword recognition that can initiate requests to the OpenAI API for additional interactions based on captured dialogue.\n\n7. **Output and Summary Generation**: \n   - Produce insights and summary notes from the transcriptions that can be stored back into the database for future reference."
      },
      "typeVersion": 1
    },
    {
      "id": "9a4ff741-ccfd-42e9-883e-43297a73e2c3",
      "name": "Scenario 1 Start - Edit Fields",
      "type": "n8n-nodes-base.set",
      "position": [
        -260,
        -980
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "4891fa6e-2dd5-4433-925c-5497ec82e8ab",
              "name": "meeting_url",
              "type": "string",
              "value": "https://meet.google.com/iix-vrav-kuc"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "a4368763-b96e-45e7-884d-aa0cbae2d276",
      "name": "Scenario 2 Start - Webhook",
      "type": "n8n-nodes-base.webhook",
      "position": [
        -320,
        -300
      ],
      "parameters": {
        "path": "d074ca1e-52f9-47af-8587-8c24d431f9cd",
        "options": {},
        "httpMethod": "POST"
      },
      "typeVersion": 2
    },
    {
      "id": "107b26af-d1d2-40c7-ad4f-7193d3ae9b70",
      "name": "If Jimmy word",
      "type": "n8n-nodes-base.if",
      "position": [
        80,
        -300
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "ba6c2ae5-d0f4-4242-9cf8-97cb84335a93",
              "operator": {
                "type": "string",
                "operation": "contains"
              },
              "leftValue": "={{ $('Scenario 2 Start - Webhook').item.json.body.data.transcript.words.map(word => word.text.replace(/'/g, \"''\")).join(\" \") }}",
              "rightValue": "=Jimmy"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "49cf34f6-86cf-42cc-9da4-3efb37e6f565",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -380,
        -1040
      ],
      "parameters": {
        "width": 920,
        "height": 400,
        "content": "## Scenario 1\n\n"
      },
      "typeVersion": 1
    },
    {
      "id": "34660f39-6ecc-4f2d-98e8-a2c529255e98",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -380,
        -360
      ],
      "parameters": {
        "width": 1020,
        "height": 420,
        "content": "## Scenario 2\n\n"
      },
      "typeVersion": 1
    },
    {
      "id": "5027e72d-2b2c-40b4-921e-c4f40d85f251",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -200,
        -120
      ],
      "parameters": {
        "color": 3,
        "width": 270,
        "height": 80,
        "content": "### Replace Supabase credentials"
      },
      "typeVersion": 1
    },
    {
      "id": "dddea341-da40-4b6a-ae25-a8417e869cc9",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -100,
        -780
      ],
      "parameters": {
        "color": 3,
        "width": 200,
        "height": 80,
        "content": "### Replace server location\n\n"
      },
      "typeVersion": 1
    },
    {
      "id": "e8e76c2a-f949-400e-92b2-39da8034b471",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        340,
        -100
      ],
      "parameters": {
        "color": 4,
        "width": 270,
        "height": 80,
        "content": "### Replace OpenAI credentials"
      },
      "typeVersion": 1
    },
    {
      "id": "729a5f6e-5aea-4908-9a82-2a7d7bea1322",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        140,
        -780
      ],
      "parameters": {
        "color": 3,
        "width": 290,
        "height": 80,
        "content": "### Replace credentials"
      },
      "typeVersion": 1
    },
    {
      "id": "31178e90-62ce-4bf8-8381-dc8138088889",
      "name": "Sticky Note8",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -320,
        -780
      ],
      "parameters": {
        "color": 3,
        "width": 200,
        "height": 80,
        "content": "### Replace meeting url\n\n"
      },
      "typeVersion": 1
    }
  ],
  "connections": {
    "OpenAI1": {
      "main": [
        []
      ]
    },
    "Create Note": {
      "ai_tool": [
        [
          {
            "node": "OpenAI1",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "If Jimmy word": {
      "main": [
        [
          {
            "node": "OpenAI1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create Recall bot": {
      "main": [
        [
          {
            "node": "Create OpenAI thread",
            "type": "main",
            "index": 0
          }
        ],
        []
      ]
    },
    "Create data record": {
      "main": [
        []
      ]
    },
    "Create OpenAI thread": {
      "main": [
        [
          {
            "node": "Create data record",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Insert Transcription Part": {
      "main": [
        [
          {
            "node": "If Jimmy word",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Scenario 2 Start - Webhook": {
      "main": [
        [
          {
            "node": "Insert Transcription Part",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Scenario 1 Start - Edit Fields": {
      "main": [
        [
          {
            "node": "Create Recall bot",
            "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.

Pro

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

How this works

This workflow automates the creation of intelligent recall bots from transcribed content, enabling users to generate interactive AI assistants that summarise and query past conversations or notes effortlessly. It suits content creators, educators, or teams managing knowledge bases who need quick access to insights without manual organisation. The key step involves OpenAI processing the transcription to extract key points, followed by storing structured data in Postgres and Supabase for persistent retrieval, culminating in an HTTP request to deploy the bot.

Use this workflow when handling regular audio transcriptions or meeting notes that require AI-driven recall, such as in podcasting or coaching sessions, to build a searchable archive. Avoid it for one-off tasks or when data privacy demands fully on-premise solutions without cloud integrations like Supabase. Common variations include adapting the OpenAI prompt for domain-specific queries or integrating additional HTTP requests to sync with tools like Slack for notifications.

About this workflow

Postgres. Uses openAi, postgres, postgresTool, httpRequest. Webhook trigger; 19 nodes.

Source: https://github.com/Zie619/n8n-workflows — original creator credit. Request a take-down →

More Data & Sheets workflows → · Browse all categories →

Related workflows

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

Data & Sheets

upload_answer. Uses httpRequest, openAi, googleDrive, googleSheets. Webhook trigger; 27 nodes.

HTTP Request, OpenAI, Google Drive +2
Data & Sheets

Crop Planning. Uses postgres, httpRequest, respondToWebhook, googleGemini. Webhook trigger; 11 nodes.

Postgres, HTTP Request, Google Gemini +1
Data & Sheets

OTTO - Épico 1: Resolução Determinística de Identidade. Uses openAi, postgres, httpRequest. Webhook trigger; 11 nodes.

OpenAI, Postgres, HTTP Request
Data & Sheets

OTTO - Épico 2: Funil de Hipótese (IA Sugere, Sistema Julga). Uses openAi, postgres, httpRequest. Webhook trigger; 10 nodes.

OpenAI, Postgres, HTTP Request
Data & Sheets

Web Scraper with AI Extraction. Uses httpRequest, openAi, postgres. Webhook trigger; 7 nodes.

HTTP Request, OpenAI, Postgres