Skip to main content

Overview

n8n workflows are deployed via the REST API at https://hab.so1.io/api/v1/workflows/{id}. Workflow JSON files are untracked in git by preference.

API Details

FieldValue
Base URLhttps://hab.so1.io
Auth headerX-N8N-API-KEY
TOMMY workflow IDMasflGBKdowUZwpJ
FORGE workflow IDmSJmBzpIcuCKz1WT

Deployment Protocol

Step 1: Build Clean Payload

The n8n PUT API accepts only: name, nodes, connections, settings
jq '{name, nodes, connections, settings}' TOMMY.json > /tmp/clean.json

Step 2: Strip Duplicate Nodes (FORGE only)

FORGE JSON may contain duplicate nodes with 1 suffix. Remove them:
jq '
  ([.nodes[].name]) as $all |
  [.nodes[].name | select(
    (endswith("1") and (rtrimstr("1") | IN($all[])))
    or IN("Sticky Note5","Sticky Note6","Sticky Note7","Sticky Note8","Sticky Note9")
  )] as $remove |
  {
    name: .name,
    nodes: [.nodes[] | select(.name | IN($remove[]) | not)],
    connections: (
      .connections | to_entries
      | [.[] | select(.key | IN($remove[]) | not)]
      | from_entries
      | map_values(.main |= [.[] | [.[] | select(.node | IN($remove[]) | not)]])
    ),
    settings: .settings
  }
' "FORGE Resolve-Next-Ticket.json" > /tmp/forge-clean.json

Step 3: Push via PUT

curl -s -X PUT \
  "https://hab.so1.io/api/v1/workflows/{WORKFLOW_ID}" \
  -H "Content-Type: application/json" \
  -H "X-N8N-API-KEY: {API_KEY}" \
  -d @/tmp/clean.json

Step 4: Verify

curl -s "https://hab.so1.io/api/v1/workflows/{WORKFLOW_ID}" \
  -H "X-N8N-API-KEY: {API_KEY}" \
  | jq '{name, id, node_count: (.nodes | length), active, updatedAt}'
Expected: HTTP 200, node_count matches (TOMMY: 34, FORGE: 43), active: true.

Step 5: Re-bind Credentials (MANDATORY)

The n8n PUT API detaches credential bindings even though IDs are preserved. After pushing:
  1. Open workflow in n8n UI at hab.so1.io
  2. Open each node that uses credentials
  3. Re-select the credential from the dropdown
  4. Save the workflow

Quick Reference Commands

Push TOMMY

jq '{name, nodes, connections, settings}' TOMMY.json | \
  curl -s -X PUT "https://hab.so1.io/api/v1/workflows/MasflGBKdowUZwpJ" \
  -H "Content-Type: application/json" \
  -H "X-N8N-API-KEY: <key>" \
  -d @-

Trigger TOMMY (dry run)

curl -s -X POST "https://hab.so1.io/webhook/atomiser" \
  -H "Content-Type: application/json" \
  -d '{"repo": "traceo-ai/traceo-mcp-server", "branch": "main",
       "project_path": "/root/projects/so1-platform",
       "ssh_host": "root@vps.devarno.cloud", "dry_run": true}'

Trigger FORGE (manual mode)

curl -s -X POST "https://hab.so1.io/webhook/forge-resolve-next-ticket" \
  -H "Content-Type: application/json" \
  -d '{"gh_org": "traceo-ai", "gh_repo": "traceo-mcp-server",
       "epic_issue_number": 22, "execution_mode": "manual"}'

Timeout Chain

Browser → Vercel proxy (300s) → Railway BFF (configurable) → n8n (per-node)
LayerTimeoutConfigurable?
Vercel proxy300s (maxDuration)Yes, via export
BFF n8n adaptertimeoutMs, default 120sYes, per-request
n8n node-levelPer HTTP Request nodeYes, in workflow JSON
FORGE → TOMMY600sYes, in node config