{ "name": "Ceki: Search browser → assign backlog event", "nodes": [ { "parameters": { "rule": { "interval": [ { "field": "hours", "hoursInterval": 1 } ] } }, "id": "schedule-1", "name": "Every 1 hour", "type": "n8n-nodes-base.scheduleTrigger", "typeVersion": 1.2, "position": [ 240, 300 ] }, { "parameters": { "assignments": { "assignments": [ { "id": "c1", "name": "contract_id", "value": 0, "type": "number" }, { "id": "c2", "name": "agent_id", "value": 0, "type": "number" } ] }, "options": {} }, "id": "config-1", "name": "Config", "type": "n8n-nodes-base.set", "typeVersion": 3.4, "position": [ 440, 300 ], "notes": "Defaults are 0 — set your own contract_id and agent_id." }, { "parameters": { "method": "GET", "url": "https://api.ceki.me/api/browsers/search", "authentication": "genericCredentialType", "genericAuthType": "httpHeaderAuth", "sendQuery": true, "queryParameters": { "parameters": [ { "name": "limit", "value": "50" }, { "name": "sort", "value": "price" } ] }, "options": {} }, "id": "get-browsers-1", "name": "Search browsers", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [ 640, 300 ], "credentials": { "httpHeaderAuth": { "name": "Ceki API" } } }, { "parameters": { "jsCode": "// Join browsers with their accumulated spend (static data), pick the first under $5.\n// If none fit the budget, return [] → the next node won't run (a natural stop).\nconst sd = $getWorkflowStaticData('global');\nconst spend = sd.spend || {};\nconst input = $input.first().json;\nconst data = Array.isArray(input.data) ? input.data : [];\nconst BUDGET = 5;\nconst candidates = data.map(s => ({\n schedule_id: s.schedule_id,\n price_per_min: s.price_per_min,\n spent: spend[s.schedule_id] || 0,\n})).filter(c => c.schedule_id != null && c.spent < BUDGET);\nif (candidates.length === 0) return [];\nreturn [{ json: candidates[0] }];" }, "id": "pick-1", "name": "Pick browser (<$5)", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 840, 300 ] }, { "parameters": { "method": "GET", "url": "=https://api.ceki.me/api/agent/contract/{{ $('Config').item.json.contract_id }}/events", "authentication": "genericCredentialType", "genericAuthType": "httpHeaderAuth", "options": {} }, "id": "get-events-1", "name": "Get backlog events", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [ 1040, 300 ], "credentials": { "httpHeaderAuth": { "name": "Ceki API" } } }, { "parameters": { "jsCode": "// tasks = events (KalEvent). backlog = status_id 100 (Pending). Pick the first one.\nconst resp = $input.first().json;\nconst events = Array.isArray(resp.data) ? resp.data : [];\nconst ev = events.find(e => e && e.status_id === 100);\nif (!ev) return []; // no backlog → the flow stops\nconst scheduleId = $('Pick browser (<$5)').first().json.schedule_id;\n// TODO: source the platform credentials.\nconst creds = 'TODO: platform credentials';\nconst base = ev.description || '';\nconst description = `${base}\\n\\n--- assigned via n8n ---\\nBrowser schedule_id: ${scheduleId}\\nCreds: ${creds}`;\nreturn [{ json: { event_id: ev.id, schedule_id: scheduleId, description } }];" }, "id": "prepare-1", "name": "Prepare patch", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 1240, 300 ] }, { "parameters": { "method": "PATCH", "url": "=https://api.ceki.me/api/agent/kal/event/{{ $('Prepare patch').item.json.event_id }}", "authentication": "genericCredentialType", "genericAuthType": "httpHeaderAuth", "sendBody": true, "contentType": "json", "specifyBody": "keypair", "bodyParameters": { "parameters": [ { "name": "description", "value": "={{ $('Prepare patch').item.json.description }}" } ] }, "options": {} }, "id": "patch-desc-1", "name": "Patch description", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [ 1440, 300 ], "credentials": { "httpHeaderAuth": { "name": "Ceki API" } } }, { "parameters": { "method": "PATCH", "url": "=https://api.ceki.me/api/agent/kal/event/{{ $('Prepare patch').item.json.event_id }}", "authentication": "genericCredentialType", "genericAuthType": "httpHeaderAuth", "sendBody": true, "contentType": "json", "specifyBody": "json", "jsonBody": "={\n \"benefitable\": { \"type\": \"agent\", \"value\": {{ $('Config').item.json.agent_id }} }\n}", "options": {} }, "id": "assign-1", "name": "Assign agent (benefitable)", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [ 1640, 300 ], "credentials": { "httpHeaderAuth": { "name": "Ceki API" } } }, { "parameters": { "method": "PATCH", "url": "=https://api.ceki.me/api/agent/kal/event/{{ $('Prepare patch').item.json.event_id }}", "authentication": "genericCredentialType", "genericAuthType": "httpHeaderAuth", "sendBody": true, "contentType": "json", "specifyBody": "keypair", "bodyParameters": { "parameters": [ { "name": "status_id", "value": 200 } ] }, "options": {} }, "id": "patch-status-1", "name": "Set status 200", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [ 1840, 300 ], "credentials": { "httpHeaderAuth": { "name": "Ceki API" } } } ], "connections": { "Every 1 hour": { "main": [ [ { "node": "Config", "type": "main", "index": 0 } ] ] }, "Config": { "main": [ [ { "node": "Search browsers", "type": "main", "index": 0 } ] ] }, "Search browsers": { "main": [ [ { "node": "Pick browser (<$5)", "type": "main", "index": 0 } ] ] }, "Pick browser (<$5)": { "main": [ [ { "node": "Get backlog events", "type": "main", "index": 0 } ] ] }, "Get backlog events": { "main": [ [ { "node": "Prepare patch", "type": "main", "index": 0 } ] ] }, "Prepare patch": { "main": [ [ { "node": "Patch description", "type": "main", "index": 0 } ] ] }, "Patch description": { "main": [ [ { "node": "Assign agent (benefitable)", "type": "main", "index": 0 } ] ] }, "Assign agent (benefitable)": { "main": [ [ { "node": "Set status 200", "type": "main", "index": 0 } ] ] } }, "active": false, "settings": { "executionOrder": "v1" }, "pinData": {}, "meta": { "templateCredsSetupCompleted": false } }