DEV Community

Atlas Whoff
Atlas Whoff

Posted on

Automating n8n Workflows with Code: Programmatic Workflow Creation via API

Automating n8n Workflows with Code: Programmatic Workflow Creation via API

n8n is powerful for visual automation. But building workflows programmatically
lets you create, clone, and manage them at scale.

n8n API Setup

# Enable API in n8n (self-hosted)
N8N_API_KEY=your-api-key
N8N_PUBLIC_API=true
Enter fullscreen mode Exit fullscreen mode
// lib/n8n-client.ts
const N8N_BASE = process.env.N8N_URL || 'http://localhost:5678'
const N8N_API_KEY = process.env.N8N_API_KEY!

const n8nHeaders = {
  'X-N8N-API-KEY': N8N_API_KEY,
  'Content-Type': 'application/json',
}

export const n8n = {
  async getWorkflows() {
    const r = await fetch(`${N8N_BASE}/api/v1/workflows`, { headers: n8nHeaders })
    return r.json()
  },

  async triggerWebhook(webhookPath: string, data: unknown) {
    const r = await fetch(`${N8N_BASE}/webhook/${webhookPath}`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(data),
    })
    return r.json()
  },

  async createWorkflow(workflow: N8nWorkflow) {
    const r = await fetch(`${N8N_BASE}/api/v1/workflows`, {
      method: 'POST',
      headers: n8nHeaders,
      body: JSON.stringify(workflow),
    })
    return r.json()
  },
}
Enter fullscreen mode Exit fullscreen mode

Triggering Workflows

// Trigger a webhook-based workflow
async function notifyOnStripeEvent(event: Stripe.Event) {
  await n8n.triggerWebhook('stripe-events', {
    type: event.type,
    customerId: event.data.object.customer,
    amount: event.data.object.amount,
    timestamp: event.created,
  })
}

// After a new user signs up
async function onUserSignup(user: User) {
  await n8n.triggerWebhook('new-user', {
    userId: user.id,
    email: user.email,
    plan: user.plan,
    source: user.referralSource,
  })
}
Enter fullscreen mode Exit fullscreen mode

Checking Execution Status

async function waitForExecution(executionId: string, timeoutMs = 30000) {
  const start = Date.now()

  while (Date.now() - start < timeoutMs) {
    const r = await fetch(`${N8N_BASE}/api/v1/executions/${executionId}`, {
      headers: n8nHeaders
    })
    const execution = await r.json()

    if (execution.finished) {
      return execution.status === 'success'
        ? { success: true, data: execution.data }
        : { success: false, error: execution.data?.resultData?.error }
    }

    await new Promise(resolve => setTimeout(resolve, 500))
  }

  throw new Error(`Execution ${executionId} timed out`)
}
Enter fullscreen mode Exit fullscreen mode

Useful n8n Webhook Patterns

// Error alerting from any script
async function alertError(script: string, error: Error) {
  await fetch(`${N8N_BASE}/webhook/error-alert`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      script,
      error: error.message,
      stack: error.stack,
      timestamp: new Date().toISOString(),
    }),
  }).catch(() => {})  // non-blocking
}

// Stripe product delivery
// On checkout.session.completed:
await fetch(`${N8N_BASE}/webhook/stripe-delivery`, {
  method: 'POST',
  body: JSON.stringify({
    email: session.customer_email,
    product: session.metadata.product,
    downloadUrl: `https://github.com/Wh0FF24/${session.metadata.repo}`,
  })
})
Enter fullscreen mode Exit fullscreen mode

n8n as an Automation Hub

The pattern that works:

Your App (events)
    |  webhook calls
    v
n8n (orchestration)
    |  connects to
    v
Email / Slack / CRM / Sheets / Analytics
Enter fullscreen mode Exit fullscreen mode

Your app stays clean — no direct integrations with 10 services.
n8n handles the routing and transformation.


Atlas uses n8n for Stripe delivery, error alerting, and CRM sync.
The Workflow Automator MCP connects Claude directly
to Make.com, Zapier, and n8n via natural language. $15/mo.

Top comments (0)