{
  "name": "MendriX — Purchase line items",
  "nodes": [
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "hours",
              "hoursInterval": 1
            }
          ]
        }
      },
      "id": "trigger-pli-1",
      "name": "Every hour",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.2,
      "position": [
        240,
        300
      ]
    },
    {
      "parameters": {
        "mode": "manual",
        "duplicateItem": false,
        "assignments": {
          "assignments": [
            {
              "id": "pli-operator",
              "name": "operatorNumber",
              "value": "YOUR_OPERATOR_NUMBER",
              "type": "string"
            },
            {
              "id": "pli-from",
              "name": "fromDate",
              "value": "2026-06-01",
              "type": "string"
            },
            {
              "id": "pli-to",
              "name": "toDate",
              "value": "2026-07-01",
              "type": "string"
            },
            {
              "id": "pli-watermark",
              "name": "watermark",
              "value": "1",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "id": "params-pli-1",
      "name": "Query parameters",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        400,
        300
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://<your-client-name>.api.mendrix.cloud/api/account/login-api-token",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpCustomAuth",
        "options": {}
      },
      "id": "login-pli-1",
      "name": "Get access token",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        560,
        300
      ],
      "credentials": {
        "httpCustomAuth": {
          "id": "REPLACE_WITH_YOUR_CREDENTIAL_ID",
          "name": "MendriX API token"
        }
      }
    },
    {
      "parameters": {
        "url": "https://<your-client-name>.api.mendrix.cloud/api/purchase/line-items/",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "=Bearer {{ $('Get access token').first().json.data.items[0].access }}"
            }
          ]
        },
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "operatorNumber",
              "value": "={{ $('Query parameters').first().json.operatorNumber }}"
            },
            {
              "name": "fromDate",
              "value": "={{ $('Query parameters').first().json.fromDate }}"
            },
            {
              "name": "toDate",
              "value": "={{ $('Query parameters').first().json.toDate }}"
            },
            {
              "name": "limit",
              "value": "100"
            },
            {
              "name": "since",
              "value": "={{ $('Query parameters').first().json.watermark || '1' }}"
            }
          ]
        },
        "options": {}
      },
      "id": "http-pli-1",
      "name": "List purchase line items",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        720,
        300
      ]
    },
    {
      "parameters": {
        "fieldToSplitOut": "data.items",
        "options": {}
      },
      "id": "split-pli-1",
      "name": "Split into line items",
      "type": "n8n-nodes-base.splitOut",
      "typeVersion": 1,
      "position": [
        880,
        300
      ]
    },
    {
      "parameters": {
        "jsCode": "// The ride, task and operator data is returned once per response in\n// data.context, not on every line - look it up by the ids on the line.\nconst context = $('List purchase line items').first().json.data.context;\nconst rides = new Map(context.rides.map((r) => [r.rideId, r]));\nconst tasks = new Map(context.tasks.map((t) => [t.taskId, t]));\nconst operators = new Map(context.operators.map((o) => [o.operatorId, o]));\n\n// Upsert into your own reconciliation table here, keyed on the line item id.\n// Make it idempotent: recalculating a ride re-delivers all of its lines.\nreturn items.map((item) => ({\n  json: {\n    lineItemId: item.json.id,\n    description: item.json.description,\n    amountNet: item.json.amount,\n    currency: item.json.currencyCode,\n    date: item.json.date,\n    ride: rides.get(item.json.rideId),\n    tasks: (item.json.taskIds ?? []).map((id) => tasks.get(id)),\n    operator: operators.get(item.json.operatorId),\n  },\n}));"
      },
      "id": "code-pli-1",
      "name": "Resolve context",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1040,
        300
      ]
    },
    {
      "parameters": {
        "jsCode": "// Store data.maxSequence as the watermark for the next run, and pass it back\n// as since= then. It is a sequence number, not a date. Only a request carrying\n// since= reports a watermark frozen for the whole cycle - hence the since=1\n// default on the first run. Deletions are not visible in the feed, so\n// periodically resync with since=1.\nconst response = $('List purchase line items').first().json;\nreturn [{ json: { watermark: response.data.maxSequence } }];"
      },
      "id": "code-pli-2",
      "name": "Save watermark",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1200,
        300
      ]
    }
  ],
  "connections": {
    "Every hour": {
      "main": [
        [
          {
            "node": "Query parameters",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Query parameters": {
      "main": [
        [
          {
            "node": "Get access token",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get access token": {
      "main": [
        [
          {
            "node": "List purchase line items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "List purchase line items": {
      "main": [
        [
          {
            "node": "Split into line items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split into line items": {
      "main": [
        [
          {
            "node": "Resolve context",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Resolve context": {
      "main": [
        [
          {
            "node": "Save watermark",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "pinData": {},
  "meta": {
    "templateCredsSetupCompleted": false
  },
  "tags": [
    {
      "name": "MendriX"
    }
  ]
}
