AutomationFlowsAI & RAG › Generate .com Brand Names with Openai and API Ninjas Into Google Sheets

Generate .com Brand Names with Openai and API Ninjas Into Google Sheets

ByPavel Zamorev @zamorev on n8n.io

Use OpenAI to generate short, memorable brand names for your app and automatically check .com availability — results go straight into Google Sheets.

Event trigger★★★★☆ complexity22 nodesGoogle SheetsHTTP Request
AI & RAG Trigger: Event Nodes: 22 Complexity: ★★★★☆ Added:

This workflow corresponds to n8n.io template #13571 — we link there as the canonical source.

This workflow follows the Google Sheets → HTTP Request 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": "9418fcb2-faa2-4b09-a586-0e2407f29bc1",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2576,
        144
      ],
      "parameters": {
        "color": 7,
        "width": 280,
        "height": 148,
        "content": "## Write to sheets\n\nAppends available domains to sheet \"available\", taken ones to sheet \"closed\"."
      },
      "typeVersion": 1
    },
    {
      "id": "76f9496b-5028-4289-ad46-638e8eee772d",
      "name": "Manual Trigger",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        368,
        336
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "12966170-54f2-4adb-8986-e21a98ecadc2",
      "name": "Read sheet available",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        528,
        336
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "available"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_GOOGLE_SHEET_ID"
        }
      },
      "typeVersion": 4.5,
      "continueOnFail": true
    },
    {
      "id": "0a434fcb-3328-40da-af7a-6c5fb3f6c2e8",
      "name": "Trigger closed read",
      "type": "n8n-nodes-base.code",
      "position": [
        688,
        336
      ],
      "parameters": {
        "jsCode": "return [{ json: {} }];"
      },
      "typeVersion": 2
    },
    {
      "id": "939ea07b-1f6a-4d31-928d-2a9cfa70e0ee",
      "name": "Read sheet closed",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        848,
        336
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "closed"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_GOOGLE_SHEET_ID"
        }
      },
      "typeVersion": 4.5,
      "continueOnFail": true
    },
    {
      "id": "1e5e0aca-0d40-4f79-9cc1-78e77055910e",
      "name": "Build initial state",
      "type": "n8n-nodes-base.code",
      "position": [
        1008,
        336
      ],
      "parameters": {
        "jsCode": "let availableRows = [];\nlet closedRows = [];\ntry { availableRows = $('Read sheet available').all().map(i => i.json || i) || []; } catch (e) { }\ntry { closedRows = $('Read sheet closed').all().map(i => i.json || i) || []; } catch (e) { }\nconst totalFound = Array.isArray(availableRows) ? availableRows.length : 0;\nconst dom = (r) => (r && (r.domain || r.name || r.Domain || r.Name));\nconst fromAv = (Array.isArray(availableRows) ? availableRows : []).map(dom).filter(Boolean);\nconst fromCl = (Array.isArray(closedRows) ? closedRows : []).map(dom).filter(Boolean);\nconst alreadyChecked = [...new Set([...fromAv, ...fromCl])];\nreturn { json: { totalFound, alreadyChecked, iteration: 0 } };"
      },
      "typeVersion": 2
    },
    {
      "id": "1c6e05de-3a65-4778-99fa-2bc1be51d184",
      "name": "Prepare prompt",
      "type": "n8n-nodes-base.code",
      "position": [
        1232,
        336
      ],
      "parameters": {
        "jsCode": "const input = $input.first().json;\nconst totalFound = input.totalFound ?? 0;\nconst alreadyChecked = Array.isArray(input.alreadyChecked) ? input.alreadyChecked : [];\nconst iteration = input.iteration ?? 0;\nconst excludeText = alreadyChecked.length > 0\n  ? ` Do NOT suggest these names or domains (already checked, taken or already used): ${alreadyChecked.join(', ')}.`\n  : '';\nconst systemPrompt = `You are a naming expert. Generate short, distinctive, memorable brand names in English for a product or app. Use only letters, no numbers or hyphens. Each name must be under 14 characters. Return a valid JSON object with a single key \"names\" containing an array of exactly 20 strings.${excludeText}`;\nconst userPrompt = `Generate 20 new, unique names for a product or app. Letters only, no numbers or hyphens, under 14 characters per name.${excludeText} Return ONLY valid JSON: { \"names\": [\"Name1\", \"Name2\", ...] }`;\nreturn { json: { systemPrompt, userPrompt, totalFound, alreadyChecked, iteration } };"
      },
      "typeVersion": 2
    },
    {
      "id": "e04b598d-b421-466f-8371-91c406e2c896",
      "name": "Generate names (OpenAI)",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1392,
        336
      ],
      "parameters": {
        "url": "https://api.openai.com/v1/chat/completions",
        "method": "POST",
        "options": {},
        "jsonBody": "={{ JSON.stringify({ model: 'gpt-4o', temperature: 0.7, max_tokens: 2000, messages: [{ role: 'system', content: $json.systemPrompt }, { role: 'user', content: $json.userPrompt }], response_format: { type: 'json_object' } }) }}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        }
      },
      "typeVersion": 4
    },
    {
      "id": "114d5465-a2cb-40f0-8166-9bb144f4a7e9",
      "name": "Normalize to domains",
      "type": "n8n-nodes-base.code",
      "position": [
        1552,
        336
      ],
      "parameters": {
        "jsCode": "const openaiResponse = $json;\nif (!openaiResponse.choices || !openaiResponse.choices[0] || !openaiResponse.choices[0].message || !openaiResponse.choices[0].message.content) {\n  throw new Error('OpenAI returned empty or invalid response');\n}\nconst parsed = JSON.parse(openaiResponse.choices[0].message.content);\nconst names = Array.isArray(parsed.names) ? parsed.names : [];\nif (names.length === 0) throw new Error('AI returned no names');\nconst items = names.map(name => {\n  const clean = String(name).trim().replace(/\\s+/g, '').replace(/[^a-zA-Z]/g, '');\n  if (!clean) return null;\n  const domain = clean.toLowerCase() + '.com';\n  return { json: { name: clean, domain } };\n}).filter(Boolean);\nreturn items;"
      },
      "typeVersion": 2
    },
    {
      "id": "493049ef-0815-4d22-893f-b45a9d56d61b",
      "name": "Check domain (API Ninjas)",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1760,
        336
      ],
      "parameters": {
        "url": "https://api.api-ninjas.com/v1/domain",
        "options": {
          "response": {
            "response": {
              "neverError": true
            }
          }
        },
        "sendQuery": true,
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "queryParameters": {
          "parameters": [
            {
              "name": "domain",
              "value": "={{ $json.domain }}"
            }
          ]
        }
      },
      "typeVersion": 4.2,
      "continueOnFail": true
    },
    {
      "id": "0a48d7ba-d5a0-4d2c-92bb-7f198ec317bf",
      "name": "Merge name and API result",
      "type": "n8n-nodes-base.code",
      "position": [
        1984,
        336
      ],
      "parameters": {
        "jsCode": "const apiItems = $input.all();\nconst normNode = $('Normalize to domains');\nconst normItems = normNode.all();\nconst state = $('Prepare prompt').last().json;\nconst roundState = { totalFound: state.totalFound ?? 0, alreadyChecked: Array.isArray(state.alreadyChecked) ? state.alreadyChecked : [], iteration: state.iteration ?? 0 };\nconst result = [];\nfor (let i = 0; i < apiItems.length; i++) {\n  const item = apiItems[i];\n  const apiJson = item.json || {};\n  if (typeof apiJson.available === 'boolean') {\n    result.push({ json: { ...normItems[i].json, ...apiJson, _roundState: roundState } });\n  }\n}\nreturn result;"
      },
      "typeVersion": 2
    },
    {
      "id": "edc50197-55e6-49c3-b123-5763435d5ea8",
      "name": "Closed only",
      "type": "n8n-nodes-base.code",
      "position": [
        1984,
        720
      ],
      "parameters": {
        "jsCode": "const items = $input.all();\nreturn items.filter(i => i.json && i.json.available === false).map(i => ({ json: { domain: i.json.domain, name: i.json.name } }));"
      },
      "typeVersion": 2
    },
    {
      "id": "ce7811b1-cf8d-45e2-955f-fa248a4d6ec1",
      "name": "State for next run",
      "type": "n8n-nodes-base.code",
      "position": [
        1984,
        544
      ],
      "parameters": {
        "jsCode": "const mergeItems = $input.all();\nconst first = mergeItems[0] && mergeItems[0].json;\nconst prev = first && first._roundState ? first._roundState : { totalFound: 0, alreadyChecked: [], iteration: 0 };\nconst totalFound = prev.totalFound ?? 0;\nconst alreadyChecked = prev.alreadyChecked ?? [];\nconst iteration = prev.iteration ?? 0;\nconst availableCount = mergeItems.filter(i => i.json && i.json.available === true).length;\nconst domainsThisRound = mergeItems.map(i => i.json && i.json.domain).filter(Boolean);\nconst newAlreadyChecked = [...new Set([...alreadyChecked, ...domainsThisRound])];\nconst newTotalFound = totalFound + availableCount;\nconst newIteration = iteration + 1;\nreturn { json: { totalFound: newTotalFound, alreadyChecked: newAlreadyChecked, iteration: newIteration } };"
      },
      "typeVersion": 2
    },
    {
      "id": "035d99e3-e056-4909-80a9-f5d81258cc3d",
      "name": "Exit or loop",
      "type": "n8n-nodes-base.if",
      "position": [
        2208,
        544
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "or",
          "conditions": [
            {
              "id": "cond-exit",
              "operator": {
                "type": "boolean",
                "operation": "equals"
              },
              "leftValue": "={{ $json.totalFound >= 15 }}",
              "rightValue": true
            },
            {
              "id": "cond-iter",
              "operator": {
                "type": "boolean",
                "operation": "equals"
              },
              "leftValue": "={{ $json.iteration > 10 }}",
              "rightValue": true
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "8ea1d3ca-12f4-42d3-bd4c-ccbb79d0aae9",
      "name": "Filter available only",
      "type": "n8n-nodes-base.filter",
      "position": [
        2208,
        336
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "cond-available",
              "operator": {
                "type": "boolean",
                "operation": "equals"
              },
              "leftValue": "={{ $json.available }}",
              "rightValue": true
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "fc2c9eca-d842-4b28-afbb-8f456f42ffed",
      "name": "Append to sheet available",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        2640,
        336
      ],
      "parameters": {
        "columns": {
          "value": {},
          "schema": [
            {
              "id": "domain",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "domain",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "name",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "autoMapInputData",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "available"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_GOOGLE_SHEET_ID"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "319bf54c-7c74-4276-85e1-48fc779bd217",
      "name": "Append to sheet closed",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        2208,
        720
      ],
      "parameters": {
        "columns": {
          "value": {},
          "schema": [
            {
              "id": "domain",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "domain",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "name",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "autoMapInputData",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "closed"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_GOOGLE_SHEET_ID"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "98e14d9d-acdb-4ded-bd01-a9c7dc1cbde9",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -208,
        -208
      ],
      "parameters": {
        "width": 464,
        "height": 448,
        "content": "## How it works\n\nManual Trigger starts a run. The workflow reads your Google Sheet (tabs \"available\" and \"closed\") to get domains already checked. Build initial state builds the alreadyChecked list and totalFound count.\n\nPrepare prompt builds the prompt with your app context and passes alreadyChecked so the AI does not suggest the same names again. Generate names (OpenAI) returns 20 new names; Normalize to domains turns them into .com domains.\n\nCheck domain (API Ninjas) checks each name. Merge name and API result keeps only items with a valid API response. Filter available only and Closed only split results into available vs taken. Available domains go to Append to sheet available, taken ones to Append to sheet closed. State for next run updates the counters and alreadyChecked list. Exit or loop stops when you have at least 15 available domains or after 10 iterations (20 names per iteration), otherwise it loops back to Prepare prompt.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "3537e384-9162-44f4-ac92-513c1fab213b",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -208,
        288
      ],
      "parameters": {
        "width": 464,
        "height": 288,
        "content": "## Setup steps\n\n1. Credentials: Add OpenAI API key to the Generate names (OpenAI) node. Add API Ninjas key (header X-Api-Key from api-ninjas.com) to Check domain (API Ninjas). Add Google Sheets OAuth2 to all four Google Sheets nodes.\n2. In one Google spreadsheet create two sheets named \"available\" and \"closed\", each with header row: domain, name. In all four Google Sheets nodes set Document to your sheet ID (replace YOUR_GOOGLE_SHEET_ID in the node settings).\n3. Optional: Edit Prepare prompt to describe your product so the AI suggests fitting names (e.g. app category, style, reference brands)."
      },
      "typeVersion": 1
    },
    {
      "id": "ff9b747e-9b86-4997-9284-115fce0105ba",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        512,
        144
      ],
      "parameters": {
        "color": 7,
        "content": "## Start & load state\n\nReads sheets \"available\" and \"closed\", builds alreadyChecked and totalFound for the loop."
      },
      "typeVersion": 1
    },
    {
      "id": "fb7e0fae-f61b-40eb-a991-655691c480cd",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1392,
        144
      ],
      "parameters": {
        "color": 7,
        "content": "## Prompt & names\n\nEdit Prepare prompt for your product; OpenAI returns 20 names; Normalize to domains makes them .com."
      },
      "typeVersion": 1
    },
    {
      "id": "9fe661d2-b771-4e3f-a674-add5a79c3d1e",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1712,
        144
      ],
      "parameters": {
        "color": 7,
        "content": "## Check & route\n\nAPI Ninjas checks each domain; results split into available/closed; state updated; loop or exit."
      },
      "typeVersion": 1
    }
  ],
  "connections": {
    "Closed only": {
      "main": [
        [
          {
            "node": "Append to sheet closed",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Exit or loop": {
      "main": [
        [],
        [
          {
            "node": "Prepare prompt",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Manual Trigger": {
      "main": [
        [
          {
            "node": "Read sheet available",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare prompt": {
      "main": [
        [
          {
            "node": "Generate names (OpenAI)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Read sheet closed": {
      "main": [
        [
          {
            "node": "Build initial state",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "State for next run": {
      "main": [
        [
          {
            "node": "Exit or loop",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build initial state": {
      "main": [
        [
          {
            "node": "Prepare prompt",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Trigger closed read": {
      "main": [
        [
          {
            "node": "Read sheet closed",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Normalize to domains": {
      "main": [
        [
          {
            "node": "Check domain (API Ninjas)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Read sheet available": {
      "main": [
        [
          {
            "node": "Trigger closed read",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter available only": {
      "main": [
        [
          {
            "node": "Append to sheet available",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate names (OpenAI)": {
      "main": [
        [
          {
            "node": "Normalize to domains",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check domain (API Ninjas)": {
      "main": [
        [
          {
            "node": "Merge name and API result",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge name and API result": {
      "main": [
        [
          {
            "node": "Filter available only",
            "type": "main",
            "index": 0
          },
          {
            "node": "State for next run",
            "type": "main",
            "index": 0
          },
          {
            "node": "Closed only",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Pro

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

About this workflow

Use OpenAI to generate short, memorable brand names for your app and automatically check .com availability — results go straight into Google Sheets.

Source: https://n8n.io/workflows/13571/ — 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 n8n workflow automatically generates presentation-style "screen recording" videos with AI-generated slides and a talking head avatar overlay. You provide a topic and intention, and the workflow h

HTTP Request, N8N Nodes Veed, Google Drive +1
AI & RAG

Monitor Google Drive folder, parsing PDF, DOCX and image file into a destination folder, ready for further processing (e.g. RAG ingestion, translation, etc.) Keep processing log in Google Sheet and se

Google Drive Trigger, Google Drive, HTTP Request +2
AI & RAG

This workflow is designed for individuals and businesses looking to streamline the creation of engaging promotional videos. Whether you're marketing a product or developing a personal brand, this AI-d

HTTP Request, Google Cloud Storage, Google Sheets
AI & RAG

Transform trending Google News articles into engaging YouTube Shorts with this fully automated workflow. Save time and effort while creating dynamic, eye-catching videos that are perfect for content c

HTTP Request, Google Cloud Storage, Google Sheets +1
AI & RAG

13195 Search Slack For N8N Templates With Openai Tips Google Sheets Cache And Weekly Analytics. Uses slackTrigger, googleSheets, httpRequest, slack. Event-driven trigger; 31 nodes.

Slack Trigger, Google Sheets, HTTP Request +2