{
  "name": "Snapi — Job Listings: AI Application Screening",
  "nodes": [
    {
      "parameters": {
        "content": "## AI Application Screening\n\nFires when someone submits the **Application** form. Looks up the real job (via the `job_id` carried through from the Job Detail page) and asks an LLM to compare the applicant against that job's actual requirements — one workflow handles every posting, no duplicating per job. Writes a suggested fit score onto the application record — **a human still makes the call** by opening the card and dragging it forward. This does not auto-reject anyone.\n\n**Setup**\n1. Install the **Job Listings & AI Screening** app in Snapi first.\n2. Create a **Snapi API** credential (Snapi → Settings → API keys → copy your `snapi_...` key) and attach it to both Snapi nodes below.\n3. Open the **Snapi Trigger** node, copy its Production URL.\n4. In Snapi, open the **Application** form → **Webhooks** → paste it as the *post-webhook*.\n5. **Required:** still on the Snapi Trigger node, open the **Form** dropdown and select your Application form — it's blank by default, so without this the workflow fires (and calls OpenAI) on every form submission across your whole workspace, not just applications.\n6. Add your own OpenAI API key to the **Score applicant** HTTP Request node's Authorization header.\n7. Activate this workflow.\n\nApplicant data is at `{{ $json.record.data }}`.",
        "height": 500,
        "width": 420
      },
      "id": "note-job-listings",
      "name": "Read me first",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [-180, 20]
    },
    {
      "parameters": {
        "event": "record",
        "formId": "",
        "boardId": "",
        "toColumnId": ""
      },
      "id": "hook-job-listings",
      "name": "Snapi Trigger",
      "type": "@snapi-ca/n8n-nodes-snapi.snapiTrigger",
      "typeVersion": 1,
      "position": [320, 220],
      "webhookId": "snapi-job-listings",
      "credentials": {
        "snapiApi": {
          "id": "",
          "name": "Snapi API"
        }
      }
    },
    {
      "parameters": {
        "resource": "record",
        "operation": "get",
        "recordId": "={{ $json.record.data.job_id }}"
      },
      "id": "snapi-get-job",
      "name": "Snapi: Get the job posting",
      "type": "@snapi-ca/n8n-nodes-snapi.snapi",
      "typeVersion": 1,
      "position": [580, 220],
      "credentials": {
        "snapiApi": {
          "id": "",
          "name": "Snapi API"
        }
      }
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://api.openai.com/v1/chat/completions",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            { "name": "Authorization", "value": "Bearer YOUR_OPENAI_API_KEY" },
            { "name": "Content-Type", "value": "application/json" }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify({\n  model: \"gpt-4o-mini\",\n  response_format: { type: \"json_object\" },\n  messages: [\n    { role: \"system\", content: \"You screen job applicants against a job's requirements. Respond ONLY with JSON: {\\\"fit\\\": true|false, \\\"reason\\\": \\\"one sentence\\\"}. Be conservative — when in doubt, fit:false so a human reviews it.\" },\n    { role: \"user\", content: \"Job requirements:\\n\" + $json.data.requirements + \"\\n\\nApplicant cover letter:\\n\" + $('Snapi Trigger').item.json.record.data.cover_letter }\n  ]\n}) }}",
        "options": {}
      },
      "id": "http-score-applicant",
      "name": "Score applicant",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [820, 220]
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "parsed-fit",
              "name": "fit",
              "value": "={{ JSON.parse($json.choices[0].message.content).fit }}",
              "type": "boolean"
            },
            {
              "id": "parsed-reason",
              "name": "reason",
              "value": "={{ JSON.parse($json.choices[0].message.content).reason }}",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "id": "set-parse-result",
      "name": "Parse AI result",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [1060, 220]
    },
    {
      "parameters": {
        "resource": "record",
        "operation": "update",
        "recordId": "={{ $('Snapi Trigger').item.json.record.id }}",
        "data": "={{ JSON.stringify({ screening_result: ($json.fit ? '✅ Possible fit — ' : '⚠️ Needs a closer look — ') + $json.reason }) }}"
      },
      "id": "snapi-write-result",
      "name": "Write result to application",
      "type": "@snapi-ca/n8n-nodes-snapi.snapi",
      "typeVersion": 1,
      "position": [1300, 220],
      "credentials": {
        "snapiApi": {
          "id": "",
          "name": "Snapi API"
        }
      }
    }
  ],
  "connections": {
    "Snapi Trigger": {
      "main": [
        [
          { "node": "Snapi: Get the job posting", "type": "main", "index": 0 }
        ]
      ]
    },
    "Snapi: Get the job posting": {
      "main": [
        [
          { "node": "Score applicant", "type": "main", "index": 0 }
        ]
      ]
    },
    "Score applicant": {
      "main": [
        [
          { "node": "Parse AI result", "type": "main", "index": 0 }
        ]
      ]
    },
    "Parse AI result": {
      "main": [
        [
          { "node": "Write result to application", "type": "main", "index": 0 }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1"
  },
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "pinData": {},
  "tags": [
    { "name": "Snapi" }
  ]
}
