{
  "name": "Kalima: new AI summaries",
  "nodes": [
    {
      "parameters": {
        "content": "## Kalima: new AI summaries\n\n**1. Connect Kalima.** Open **Get new summaries from Kalima** and create a credential: **Header Auth** with the name `Authorization` and the value `Bearer ` followed by your Kalima API key. You create the key in Kalima under **Settings > Integrations > API keys** (Pro and up). **Read only** is enough.\n\n**2. Add your app.** Replace **Connect your app here** with Slack, Notion, Google Drive, HubSpot, Asana or any other node, and map the fields: `recording`, `link`, `overview`, `keyPoints`, `decisions`, `actionItems`, `openQuestions`, `markdown`.\n\n**3. Activate the workflow.** It checks every 15 minutes and delivers each summary once.\n\nA manual test run always returns the newest summary. Only the active workflow remembers where it stopped.",
        "height": 440,
        "width": 540
      },
      "id": "00006b61-6c69-6d61-0000-000000000005",
      "name": "Setup",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -640,
        -140
      ]
    },
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "minutes",
              "minutesInterval": 15
            }
          ]
        }
      },
      "id": "00006b61-6c69-6d61-0000-000000000000",
      "name": "Every 15 minutes",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.2,
      "position": [
        0,
        0
      ]
    },
    {
      "parameters": {
        "jsCode": "// Where the last scheduled run stopped. n8n keeps this between runs of the\n// active workflow; a manual test run starts from scratch every time.\nconst state = $getWorkflowStaticData('global');\nconst params = new URLSearchParams({ limit: '50' });\nif (state.lastSequence) params.set('afterSequence', state.lastSequence);\nreturn [{ json: { url: `https://meetkalima.com/api/v1/summaries?${params}` } }];\n"
      },
      "id": "00006b61-6c69-6d61-0000-000000000001",
      "name": "Build request",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        220,
        0
      ]
    },
    {
      "parameters": {
        "url": "={{ $json.url }}",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "options": {}
      },
      "id": "00006b61-6c69-6d61-0000-000000000002",
      "name": "Get new summaries from Kalima",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        440,
        0
      ]
    },
    {
      "parameters": {
        "jsCode": "// Set to false to get a summary again each time it is regenerated or edited.\nconst ONLY_FIRST_SUMMARY = true;\n\nconst state = $getWorkflowStaticData('global');\nconst firstRun = !state.lastSequence;\nconst items = $input.first().json.data ?? [];\n\n// Remember the newest position, so the next run asks only for what is new.\nfor (const item of items) {\n  if (!state.lastSequence || BigInt(item.sequence) > BigInt(state.lastSequence)) {\n    state.lastSequence = item.sequence;\n  }\n}\n\nconst list = (values) => (values ?? []).map((value) => `- ${value}`).join('\\n');\n// Kalima lists the newest summary first.\nlet summaries = items.filter((item) => !ONLY_FIRST_SUMMARY || item.version === 1);\n// The very first run would deliver up to a week of summaries at once, so it\n// delivers only the newest one: enough to see the fields and map them.\nif (firstRun) summaries = summaries.slice(0, 1);\n\n// Oldest first, so the messages arrive in the order the recordings were made.\nreturn summaries.reverse().map((item) => ({\n  json: {\n    recording: item.recording.name ?? 'Untitled recording',\n    link: item.recording.url,\n    project: item.recording.projectName ?? '',\n    overview: item.summary.overview,\n    keyPoints: list(item.summary.keyPoints),\n    decisions: list(item.summary.decisions),\n    actionItems: (item.summary.actionItems ?? [])\n      .map((a) => `- ${a.task}${a.owner ? ` (${a.owner})` : ''}${a.due ? `, ${a.due}` : ''}`)\n      .join('\\n'),\n    openQuestions: list(item.summary.openQuestions),\n    markdown: item.summary.markdown ?? '',\n    version: item.version,\n    createdAt: item.createdAt,\n  },\n}));\n"
      },
      "id": "00006b61-6c69-6d61-0000-000000000003",
      "name": "One item per summary",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        660,
        0
      ]
    },
    {
      "parameters": {},
      "id": "00006b61-6c69-6d61-0000-000000000004",
      "name": "Connect your app here",
      "type": "n8n-nodes-base.noOp",
      "typeVersion": 1,
      "position": [
        880,
        0
      ]
    }
  ],
  "connections": {
    "Every 15 minutes": {
      "main": [
        [
          {
            "node": "Build request",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build request": {
      "main": [
        [
          {
            "node": "Get new summaries from Kalima",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get new summaries from Kalima": {
      "main": [
        [
          {
            "node": "One item per summary",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "One item per summary": {
      "main": [
        [
          {
            "node": "Connect your app here",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "pinData": {},
  "settings": {
    "executionOrder": "v1"
  }
}
