
iMessage Food Photo Nutritional Analysis with GPT-4 Vision & Memory Storage
Description
Categories
📊 Productivity🤖 AI & Machine Learning
Nodes Used
n8n-nodes-base.ifn8n-nodes-base.ifn8n-nodes-base.coden8n-nodes-base.webhookn8n-nodes-base.aggregaten8n-nodes-base.stickyNoten8n-nodes-base.stickyNoten8n-nodes-base.stickyNoten8n-nodes-base.stickyNoten8n-nodes-base.stickyNote
PriceGratis
Views0
Last Updated11/28/2025
workflow.json
{
"meta": {
"instanceId": "9fe2e2e308ee9fa575b11a458a16465194c029a4f53a09a925eb0b5fa7b5761a",
"templateCredsSetupCompleted": true
},
"nodes": [
{
"id": "22f351db-4581-450b-a260-b50962f4f35a",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
1220,
0
],
"parameters": {
"width": 880,
"height": 1000,
"content": "## Using the n8n HTTP Request Node to Send a Blooio.com Message\n\nFollow these steps to configure your existing HTTP Request node in n8n so you can send SMS or email via the Blooio.com API.\n\n---\n\n### 1. Open Your HTTP Request Node\n\n- In your workflow, click on the HTTP Request node you’ve already added (e.g. **Send Message**).\n\n---\n\n### 2. Set Up the Request\n\n| Field | Value |\n|-----------------------|----------------------------------------------------|\n| **Request Method** | `POST` |\n| **URL** | `https://api.blooio.com/send-message` |\n| **Response Format** | `JSON` |\n| **Body Content Type** | `JSON (application/json)` |\n\n---\n\n### 3. Add Required Headers\n\nAdd three headers exactly as shown:\n\n```text\nAccept: application/json\nAuthorization: Bearer YOUR_API_TOKEN\nContent-Type: application/json"
},
"typeVersion": 1
},
{
"id": "334e086c-872b-4a75-8a33-aaec66ec3f02",
"name": "Send Message",
"type": "n8n-nodes-base.httpRequest",
"position": [
1280,
780
],
"parameters": {
"url": "https://api.blooio.com/send-message",
"method": "POST",
"options": {},
"sendBody": true,
"sendHeaders": true,
"authentication": "genericCredentialType",
"bodyParameters": {
"parameters": [
{
"name": "identifier",
"value": "={{ $('Receive Message (From Blooio)').item.json.body.message.sender }}"
},
{
"name": "message",
"value": "={{ $json.output }}"
}
]
},
"genericAuthType": "httpBearerAuth",
"headerParameters": {
"parameters": [
{
"name": "accept",
"value": "application/json"
}
]
}
},
"credentials": {
"httpBearerAuth": {
"id": "WxjvtozS2uLOEBkw",
"name": "Blooio Bearer Auth account"
}
},
"typeVersion": 4.2
},
{
"id": "d4df3023-17d3-44f1-bafd-1a70a370f98f",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2000,
980
],
"parameters": {
"color": 3,
"width": 780,
"height": 360,
"content": "## Message Read Webhook:\n```\n{\n \"type\": \"updated-message\",\n \"message\": {\n \"messageId\": \"218BCBB7-92E5-455B-AF47-380DB39ACD16\",\n \"content\": \"Test\",\n \"sender\": \"+11111111111\",\n \"selfMessage\": true,\n \"sentAt\": 1750755023004,\n \"technology\": \"iMessage\",\n \"delivered\": true,\n \"deliveredAt\": 1750755023334,\n \"readAt\": 1750755049887,\n \"attachments\": [],\n \"conversation\": null\n }\n}\n```"
},
"typeVersion": 1
},
{
"id": "9330aeee-82ed-4549-9927-c7802a809cd9",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2000,
380
],
"parameters": {
"color": 6,
"width": 780,
"height": 580,
"content": "## Message Received Webhook:\n```\n{\n \"type\": \"new-message\",\n \"message\": {\n \"messageId\": \"B525F710-521F-4D39-8C8F-A44BB737A3B6\",\n \"content\": \"Attached the csv file for you\",\n \"sender\": \"+11111111111\",\n \"selfMessage\": false,\n \"sentAt\": 1750757604774,\n \"technology\": \"iMessage\",\n \"delivered\": true,\n \"deliveredAt\": null,\n \"readAt\": null,\n \"attachments\": [\n {\n \"id\": \"F933522B-8DC1-47DB-9274-7508B16D15BF\",\n \"filename\": \"high_volume_b2b_laser_cnc_products.csv\",\n \"mimeType\": \"text/csv\",\n \"url\": \"https://bucket.blooio.com/custom-webhook-attachments/-xxxx.csv\",\n \"size\": 1962,\n \"expiresAt\": \"2025-07-24T09:33:26.934Z\",\n \"expiresAtUnix\": 1753349606934\n }\n ],\n \"conversation\": {\n \"id\": \"iMessage;-;+11111111111\",\n \"recipient\": \"+11111111111\",\n \"name\": null\n }\n }\n}\n```"
},
"typeVersion": 1
},
{
"id": "b7a92947-9617-4639-8c1a-b80242bb3571",
"name": "AI Agent",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
-160,
780
],
"parameters": {
"text": "=User message: {{ $('Receive Message (From Blooio)').item.json.body.message.content }}",
"options": {
"systemMessage": "<identity>\nYou are a world-class AI Nutrition Analyst trained to estimate nutrition from food photos using visual analysis, expert knowledge, and common food portion assumptions.\n</identity>\n\n<mission>\nYour task is to analyze a single food photo and provide a complete nutritional summary, without asking the user for any additional information. You must visually identify all items, estimate portion sizes, and calculate total calories and nutrients. Your response should be accurate, clear, and formatted as a friendly iMessage-style explanation — no JSON, no technical markup.\n\n</mission>\n\n<analysis_protocol>\n1. **Identify** all foods and beverages in the image.\n2. **Estimate** portion sizes using visual cues and standard serving sizes.\n3. **Calculate** total:\n - Calories\n - Protein\n - Carbs\n - Fat\n - Fiber\n - Sugar\n - Sodium\n4. **Score**:\n - Confidence Score (0.0 to 1.0): How sure you are based on image clarity, food visibility, and assumptions.\n - Health Score (0 to 10): Nutritional quality based on processing, balance, and content.\n\n</analysis_protocol>\n\n<response_format>\nRespond in a conversational tone. Start by describing the identified meal. Then list the estimated nutrition facts in simple bullet points. Finally, include:\n- A health rating from 0–10.\n- A confidence rating from 0.0–1.0.\n- A short, friendly rationale for your estimate and assumptions.\n\n⚠️ Do NOT ask the user for input or confirmation.\n⚠️ Do NOT include JSON, markdown, or structured code output.\n⚠️ Speak as if you're texting back a friend with a nutrition summary.\n\nGive the user a day report so far, a week report so far and a month report so far.</response_format>\n\n<error_handling>\nIf the image is unclear or does not show food, reply kindly to get the user to upload a different image or images.\n</error_handling>",
"passthroughBinaryImages": true
},
"promptType": "define"
},
"typeVersion": 1.9
},
{
"id": "79696185-e706-4c36-83c1-8f7294f5ec8b",
"name": "OpenAI Chat Model",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"position": [
-160,
960
],
"parameters": {
"model": {
"__rl": true,
"mode": "list",
"value": "gpt-4.1-mini",
"cachedResultName": "gpt-4.1-mini"
},
"options": {}
},
"credentials": {
"openAiApi": {
"id": "JrqIdyKAvwxNgaEM",
"name": "Tay - SLUG"
}
},
"typeVersion": 1.2
},
{
"id": "cc4c91c1-aacc-4a43-a530-5f902cb4274f",
"name": "Postgres Chat Memory",
"type": "@n8n/n8n-nodes-langchain.memoryPostgresChat",
"position": [
-160,
1120
],
"parameters": {
"tableName": "n8n_calorie_tracker",
"sessionKey": "={{ $('Receive Message (From Blooio)').item.json.body.message.conversation.id }}",
"sessionIdType": "customKey",
"contextWindowLength": 200
},
"credentials": {
"postgres": {
"id": "asiZOOtRYUAuWsWd",
"name": "Neon"
}
},
"typeVersion": 1.3
},
{
"id": "3860f4f4-1af7-4951-a52c-3d7c7f07cb9a",
"name": "Receive Message (From Blooio)",
"type": "n8n-nodes-base.webhook",
"position": [
-1440,
760
],
"webhookId": "00dbce9f-70b6-4e2d-9da4-ba8747f95e5b",
"parameters": {
"path": "receive-event",
"options": {},
"httpMethod": "POST"
},
"typeVersion": 2
},
{
"id": "40a29005-81ce-4fea-9572-230d27a79894",
"name": "HTTP Request",
"type": "n8n-nodes-base.httpRequest",
"position": [
400,
400
],
"parameters": {
"url": "={{ $json.url }}",
"options": {}
},
"typeVersion": 4.2
},
{
"id": "7b06c8a8-c330-45bc-a3a1-5dd1353b8603",
"name": "If has images, download them",
"type": "n8n-nodes-base.if",
"position": [
-700,
760
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "551f9536-48c3-4757-a58b-35ee1ef81a80",
"operator": {
"type": "array",
"operation": "lengthGt",
"rightType": "number"
},
"leftValue": "={{ $('Receive Message (From Blooio)').item.json.body.message.attachments }}",
"rightValue": 0
}
]
}
},
"typeVersion": 2.2
},
{
"id": "e3bb4c52-b673-4d97-b9b5-e980349366ec",
"name": "Loop Over Items",
"type": "n8n-nodes-base.splitInBatches",
"position": [
40,
380
],
"parameters": {
"options": {
"reset": false
}
},
"typeVersion": 3
},
{
"id": "f14e056e-2756-4ed9-8233-61fb4a86ee62",
"name": "Code",
"type": "n8n-nodes-base.code",
"position": [
-280,
380
],
"parameters": {
"jsCode": "let output = [];\n\nfor (const item of $input.first().json.body.message.attachments) {\n output.push({\n json: {\n url: item.url\n }\n });\n}\n\nreturn output;"
},
"typeVersion": 2
},
{
"id": "4bd4284d-fafe-4aca-976e-c822a8170823",
"name": "AI Agent1",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
600,
780
],
"parameters": {
"text": "={{ $json.data.toJsonString() }}",
"options": {
"systemMessage": "Summarize these messages and give the user a report that will be send in an iMessage. Do not say \"here's the summary\" or anything like that. Just respond with the summary by itself."
},
"promptType": "define"
},
"typeVersion": 2
},
{
"id": "274b2815-92bf-4a8a-bcd6-98fdb977dfa0",
"name": "Aggregate",
"type": "n8n-nodes-base.aggregate",
"position": [
260,
780
],
"parameters": {
"options": {},
"aggregate": "aggregateAllItemData"
},
"typeVersion": 1
},
{
"id": "ddc20f94-42a0-4227-ad11-afb0feb34db5",
"name": "OpenAI Chat Model1",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"position": [
620,
940
],
"parameters": {
"model": {
"__rl": true,
"mode": "list",
"value": "gpt-4.1-mini"
},
"options": {}
},
"credentials": {
"openAiApi": {
"id": "JrqIdyKAvwxNgaEM",
"name": "Tay - SLUG"
}
},
"typeVersion": 1.2
},
{
"id": "21264d57-60f5-4594-b450-07662078b23e",
"name": "Don't respond to yourself",
"type": "n8n-nodes-base.if",
"position": [
-960,
760
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "cecd3adf-a9e5-41d3-87ae-4a9699bd641b",
"operator": {
"type": "boolean",
"operation": "false",
"singleValue": true
},
"leftValue": "={{ $json.body.message.selfMessage }}",
"rightValue": ""
}
]
}
},
"typeVersion": 2.2
},
{
"id": "a098d03a-a4af-4b9a-aac2-5f5b57fd30e0",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
-360,
260
],
"parameters": {
"color": 4,
"width": 980,
"height": 400,
"content": "## Image downloader \n"
},
"typeVersion": 1
},
{
"id": "4a009bbd-4457-4bc9-8a03-9de40736f931",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2000,
-700
],
"parameters": {
"width": 760,
"height": 1040,
"content": "## 🚀 Start Here: Blooio Nutrition Tracker Setup\n\nWelcome! Before this n8n workflow can analyze meal photos and send nutrition summaries via SMS or iMessage, follow these steps to get set up:\n\n---\n\n### ✅ Step 1: Get Your Blooio API Token\n1. Visit [https://blooio.com](https://blooio.com)\n2. Sign up for a dedicated instance\n3. Navigate to **Settings → API Keys**\n4. Generate a new token and **copy** it.\n\n> 🔐 Keep it safe! You’ll paste it in the HTTP Request node where it says `YOUR_API_TOKEN`.\n\n---\n\n### ✅ Step 2: Connect Blooio to This Workflow\nIn the **Send Message** node:\n- Replace the value of the `Authorization` header with:\n\n\n### ✅ Step 3: Test the Webhook\nSend an iMessage with a meal photo or description to your Blooio-connected number.\n\nThis will:\n- Trigger the `Receive Message (From Blooio)` webhook\n- Analyze the meal using AI\n- Return a nutrition breakdown with daily/weekly/monthly stats\n\n---\n\n### 📷 What You Can Send\n- Meal photos (ideal!)\n- Text descriptions of meals\n- Multiple items in one image\n\nEnjoy tracking your nutrition effortlessly! 🥦📊📩"
},
"typeVersion": 1
},
{
"id": "eb88206b-19c3-41cb-a409-2b924c780852",
"name": "Sticky Note5",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1220,
-700
],
"parameters": {
"width": 680,
"height": 1040,
"content": "\n"
},
"typeVersion": 1
}
],
"pinData": {
"Receive Message (From Blooio)": [
{
"body": {
"type": "new-message",
"message": {
"readAt": null,
"sender": "+11111111111",
"sentAt": 1751234680604,
"content": "And a Diet Coke",
"delivered": true,
"messageId": "6409C11D-9C0B-404B-B2E3-052DA7C14D07",
"technology": "iMessage",
"attachments": [
{
"id": "E843680B-8F00-460C-A0AA-34B1B1DD9624",
"url": "https://bucket.blooio.com/custom-webhook-attachments/R3ZJISuC-t9CssQNM3i2J.jpeg",
"size": 979912,
"filename": "Pasta.jpeg",
"mimeType": "image/jpeg",
"expiresAt": "2025-07-29T22:04:42.432Z",
"expiresAtUnix": 1753826682432
}
],
"deliveredAt": null,
"selfMessage": false,
"conversation": {
"id": "iMessage;-;+11111111111",
"name": null,
"recipient": "+11111111111"
}
}
},
"query": {},
"params": {},
"headers": {
"host": "workflows.xx.com",
"cf-ray": "9578b8a804fa2f17-LAX",
"cdn-loop": "cloudflare; loops=1; subreqs=1",
"cf-ew-via": "15",
"cf-worker": "blooio.com",
"cf-visitor": "{\"scheme\":\"https\"}",
"cf-ipcountry": "US",
"content-type": "application/json",
"content-length": "622",
"accept-encoding": "gzip, br",
"x-forwarded-for": "162.158.91.171",
"cf-connecting-ip": "2a06:98c0:3600::103",
"x-forwarded-host": "workflows.xx.com",
"x-forwarded-proto": "https"
},
"webhookUrl": "https://workflows.xx.com/webhook/receive-event",
"executionMode": "production"
}
]
},
"connections": {
"Code": {
"main": [
[
{
"node": "Loop Over Items",
"type": "main",
"index": 0
}
]
]
},
"AI Agent": {
"main": [
[
{
"node": "Aggregate",
"type": "main",
"index": 0
}
]
]
},
"AI Agent1": {
"main": [
[
{
"node": "Send Message",
"type": "main",
"index": 0
}
]
]
},
"Aggregate": {
"main": [
[
{
"node": "AI Agent1",
"type": "main",
"index": 0
}
]
]
},
"HTTP Request": {
"main": [
[
{
"node": "Loop Over Items",
"type": "main",
"index": 0
}
]
]
},
"Loop Over Items": {
"main": [
[
{
"node": "AI Agent",
"type": "main",
"index": 0
}
],
[
{
"node": "HTTP Request",
"type": "main",
"index": 0
}
]
]
},
"OpenAI Chat Model": {
"ai_languageModel": [
[
{
"node": "AI Agent",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"OpenAI Chat Model1": {
"ai_languageModel": [
[
{
"node": "AI Agent1",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Postgres Chat Memory": {
"ai_memory": [
[
{
"node": "AI Agent",
"type": "ai_memory",
"index": 0
}
]
]
},
"Don't respond to yourself": {
"main": [
[
{
"node": "If has images, download them",
"type": "main",
"index": 0
}
]
]
},
"If has images, download them": {
"main": [
[
{
"node": "Code",
"type": "main",
"index": 0
}
],
[
{
"node": "AI Agent",
"type": "main",
"index": 0
}
]
]
},
"Receive Message (From Blooio)": {
"main": [
[
{
"node": "Don't respond to yourself",
"type": "main",
"index": 0
}
]
]
}
}
}