AutomationFlowsGeneral › Template — Cross-system Handover with Correlation ID

Template — Cross-system Handover with Correlation ID

Template — Cross-system handover with correlation ID. Event-driven trigger; 8 nodes.

Event trigger★★★★☆ complexity8 nodes
General Trigger: Event Nodes: 8 Complexity: ★★★★☆ Added:

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
{
  "name": "Template \u2014 Cross-system handover with correlation ID",
  "nodes": [
    {
      "parameters": {
        "content": "## Pattern: Cross-system handover with correlation ID\n\n**When to use**: this workflow hands work off to another system (queue, downstream API, sub-workflow) and needs an audit-able correlation ID baked into every step's output so investigators can stitch the trace back together later.\n\n**Nodes that implement it**:\n- `Trigger`\n- `Mint correlation` \u2014 generates `correlationId` + `originSpanId`\n- `Persist origin event` \u2014 replace with your audit log writer (DB / Loki / S3)\n- `Hand off to system A` \u2014 replace with real call; carries the correlation ID in headers AND body\n- `Hand off to system B` \u2014 same, runs in parallel\n- `Merge handovers` \u2014 Merge node collects both downstream responses\n- `Persist handover result` \u2014 writes final state + downstream IDs to the audit store\n\n**Customise before activating**:\n1. Replace `Persist origin event` and `Persist handover result` with the real audit writer.\n2. Replace `Hand off to system A / B` with the real downstream APIs. Keep the `X-Correlation-ID` header.\n3. Decide your retention window for correlation IDs in your audit store.\n\n**Satisfies n8n-security-governance rules**: \u00a75 every cross-system hop carries an audit-able correlation ID \u00b7 \u00a76 audit trail must record before-and-after state \u00b7 \u00a77 downstream IDs must be persisted so failure investigation can stitch the trace.",
        "height": 460,
        "width": 540
      },
      "id": "note-1",
      "name": "Pattern note",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -720,
        -340
      ]
    },
    {
      "parameters": {},
      "id": "trigger-1",
      "name": "Trigger",
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [
        -100,
        -40
      ]
    },
    {
      "parameters": {
        "functionCode": "const id = `tpl-handover-${Date.now()}-${Math.floor(Math.random()*1e6)}`;\nconst spanId = `span-${Math.floor(Math.random()*1e9).toString(16)}`;\nreturn [{ json: { ...($input.first()?.json ?? {}), correlationId: id, originSpanId: spanId, startedAt: new Date().toISOString() } }];"
      },
      "id": "mint-1",
      "name": "Mint correlation",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        120,
        -40
      ]
    },
    {
      "parameters": {
        "functionCode": "// REPLACE with real audit log writer (DB / Loki / S3).\nreturn [{ json: { ...$json, auditEvent: 'origin', persisted: true } }];"
      },
      "id": "persist-origin-1",
      "name": "Persist origin event",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        360,
        -40
      ]
    },
    {
      "parameters": {
        "functionCode": "// REPLACE with real downstream-A call.\n// Keep the correlation ID in headers AND body so the receiver can log it.\nreturn [{ json: { downstream: 'A', acceptedId: `A-${Math.floor(Math.random()*1e9)}`, correlationId: $json.correlationId } }];"
      },
      "id": "handoff-a-1",
      "name": "Hand off to system A",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        620,
        -160
      ]
    },
    {
      "parameters": {
        "functionCode": "// REPLACE with real downstream-B call.\nreturn [{ json: { downstream: 'B', acceptedId: `B-${Math.floor(Math.random()*1e9)}`, correlationId: $json.correlationId } }];"
      },
      "id": "handoff-b-1",
      "name": "Hand off to system B",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        620,
        80
      ]
    },
    {
      "parameters": {
        "mode": "combine",
        "combinationMode": "mergeByPosition"
      },
      "id": "merge-1",
      "name": "Merge handovers",
      "type": "n8n-nodes-base.merge",
      "typeVersion": 2,
      "position": [
        880,
        -40
      ]
    },
    {
      "parameters": {
        "functionCode": "// REPLACE with real audit writer. Persist correlation ID + both downstream IDs.\nconst items = $input.all().map(i => i.json);\nreturn [{ json: { auditEvent: 'handover-complete', correlationId: items[0]?.correlationId, downstreamIds: items.map(i => i.acceptedId), completedAt: new Date().toISOString() } }];"
      },
      "id": "persist-final-1",
      "name": "Persist handover result",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        1120,
        -40
      ]
    }
  ],
  "connections": {
    "Trigger": {
      "main": [
        [
          {
            "node": "Mint correlation",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Mint correlation": {
      "main": [
        [
          {
            "node": "Persist origin event",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Persist origin event": {
      "main": [
        [
          {
            "node": "Hand off to system A",
            "type": "main",
            "index": 0
          },
          {
            "node": "Hand off to system B",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Hand off to system A": {
      "main": [
        [
          {
            "node": "Merge handovers",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Hand off to system B": {
      "main": [
        [
          {
            "node": "Merge handovers",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Merge handovers": {
      "main": [
        [
          {
            "node": "Persist handover result",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1"
  },
  "active": false,
  "tags": []
}
Pro

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

About this workflow

Template — Cross-system handover with correlation ID. Event-driven trigger; 8 nodes.

Source: https://github.com/MorrisLu-Taipei/TigerAI-A2A-Code2n8n-Skill-Pack/blob/5417647cddf7868cc10e32eacc7fdfdacd68ea4b/examples/templates/handover-trace.workflow.json — original creator credit. Request a take-down →

More General workflows → · Browse all categories →

Related workflows

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

General

Product - Google Search Console API Examples. Uses httpRequest. Event-driven trigger; 36 nodes.

HTTP Request
General

Metavoir Creative Intake To Review Brief. Event-driven trigger; 21 nodes.

General

Retry on fail except for known error Template. Uses stopAndError, noOp, stickyNote, manualTrigger. Event-driven trigger; 19 nodes.

Stop And Error
General

Retry on fail except for known error Template. Uses stopAndError. Event-driven trigger; 19 nodes.

Stop And Error
General

02 - Flow Control Demo (IF & Switch). Event-driven trigger; 16 nodes.