{
  "name": "Do4U: job finished (webhook)",
  "nodes": [
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "do4u-job-finished",
        "responseMode": "onReceived",
        "options": {
          "rawBody": true
        }
      },
      "name": "Do4U webhook",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [
        0,
        0
      ],
      "webhookId": "do4u-job-finished"
    },
    {
      "parameters": {
        "jsCode": "// Do4U: check the signature (X-Do4U-Signature: t=<time>,v1=<hex>) against the raw body.\n// Self-hosted n8n: set NODE_FUNCTION_ALLOW_BUILTIN=crypto.\nconst crypto = require('crypto');\nconst SECRET = 'whsec_YOUR_SECRET';\nconst item = $input.first();\nconst raw = (await this.helpers.getBinaryDataBuffer(0, 'data')).toString('utf8');\nconst header = String((item.json.headers || {})['x-do4u-signature'] || '');\nconst t = (header.match(/t=(\\d+)/) || [])[1];\nconst v1 = (header.match(/v1=([0-9a-f]{64})/) || [])[1];\nif (!t || !v1 || Math.abs(Date.now() / 1000 - Number(t)) > 300) throw new Error('Do4U: signature missing or too old');\nconst expected = crypto.createHmac('sha256', SECRET).update(t + '.' + raw).digest('hex');\nif (!crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(v1))) throw new Error('Do4U: wrong signature');\nreturn [{ json: JSON.parse(raw) }];\n"
      },
      "name": "Check signature",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        240,
        0
      ]
    },
    {
      "parameters": {
        "conditions": {
          "string": [
            {
              "value1": "={{ $json.status }}",
              "operation": "equal",
              "value2": "done"
            }
          ]
        }
      },
      "name": "Done?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 1,
      "position": [
        480,
        0
      ]
    },
    {
      "parameters": {
        "url": "={{ $json.result_url }}",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Bearer YOUR_DO4U_API_KEY"
            }
          ]
        },
        "options": {}
      },
      "name": "Do4U: get result",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4,
      "position": [
        720,
        -100
      ]
    },
    {
      "parameters": {},
      "name": "Use the result (replace with your node)",
      "type": "n8n-nodes-base.noOp",
      "typeVersion": 1,
      "position": [
        960,
        -100
      ]
    },
    {
      "parameters": {},
      "name": "Job failed (no credits charged)",
      "type": "n8n-nodes-base.noOp",
      "typeVersion": 1,
      "position": [
        720,
        100
      ]
    }
  ],
  "connections": {
    "Do4U webhook": {
      "main": [
        [
          {
            "node": "Check signature",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check signature": {
      "main": [
        [
          {
            "node": "Done?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Done?": {
      "main": [
        [
          {
            "node": "Do4U: get result",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Job failed (no credits charged)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Do4U: get result": {
      "main": [
        [
          {
            "node": "Use the result (replace with your node)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {},
  "meta": {
    "templateCreatedBy": "Do4U",
    "note": "Template: check node versions in your n8n. Replace YOUR_DO4U_API_KEY (better: an n8n credential of type Header Auth)."
  }
}
