This workflow follows the Gmail → HTTP Request recipe pattern — see all workflows that pair these two integrations.
The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"name": "Control Plane - Recovery Mode",
"nodes": [
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "",
"name": "message",
"value": "Control Plane is online",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
208,
0
],
"id": "",
"name": "Edit Fields"
},
{
"parameters": {
"url": "https://api.ouraring.com/v2/usercollection/daily_readiness",
"sendQuery": true,
"queryParameters": {
"parameters": [
{
"name": "start_date",
"value": "={{ $now.minus({ days: 5 }).toFormat('yyyy-MM-dd') }}"
},
{
"name": "end_date",
"value": "={{ $now.toFormat('yyyy-MM-dd') }}"
}
]
},
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "Bearer {{OURA_API_TOKEN}}"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.4,
"position": [
416,
0
],
"id": "",
"name": "HTTP Request"
},
{
"parameters": {
"jsCode": "const input = $input.first().json;\nconst records = input.data || [];\n\nif (!records.length) {\n return [{\n json: {\n day: null,\n readinessScore: null,\n recoveryMode: false,\n noData: true,\n activityBalance: null,\n bodyTemperature: null,\n previousNight: null,\n recoveryIndex: null,\n recommendation: \"No readiness data found. Wear your ring tonight and make sure the Oura app syncs in the morning.\",\n message: \"No Oura readiness data found today. Recovery Mode was not triggered.\"\n }\n }];\n}\n\nconst latest = records[records.length - 1];\n\nconst readinessScore = latest.score ?? null;\nconst day = latest.day ?? null;\nconst contributors = latest.contributors || {};\n\nconst activityBalance = contributors.activity_balance ?? null;\nconst bodyTemperature = contributors.body_temperature ?? null;\nconst previousNight = contributors.previous_night ?? null;\nconst recoveryIndex = contributors.recovery_index ?? null;\n\nconst recoveryMode = readinessScore !== null && readinessScore < 70;\n\nlet recommendation = \"You're good to go today.\";\n\nif (recoveryMode) {\n recommendation = \"Prioritize recovery. Skip intense training, take a walk, hydrate, and aim for an earlier bedtime.\";\n}\n\nreturn [{\n json: {\n day,\n readinessScore,\n recoveryMode,\n noData: false,\n activityBalance,\n bodyTemperature,\n previousNight,\n recoveryIndex,\n recommendation,\n message: recoveryMode\n ? `Recovery Mode ON. Readiness ${readinessScore}. ${recommendation}`\n : `Normal Mode. Readiness ${readinessScore}. ${recommendation}`\n }\n}];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
624,
0
],
"id": "",
"name": "Code in JavaScript"
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 3
},
"conditions": [
{
"id": "",
"leftValue": "={{ $('Code in JavaScript').item.json.recoveryMode }}",
"rightValue": "",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
}
}
],
"combinator": "and"
},
"options": {}
},
"type": "n8n-nodes-base.if",
"typeVersion": 2.3,
"position": [
1184,
0
],
"id": "",
"name": "If"
},
{
"parameters": {
"sendTo": "{{EMAIL_TO}}",
"subject": "=Control Plane | {{$('Code in JavaScript').item.json.recoveryMode ? 'Recovery Mode' : 'Normal Mode'}} | Readiness {{$('Code in JavaScript').item.json.readinessScore}}",
"message": "=Good morning,\n\n{{$('Message a model').item.json.output[0].content[0].text}}\n\n---\nGenerated by Control Plane\nOura \u2192 GPT \u2192 Nest \u2192 n8n",
"options": {}
},
"type": "n8n-nodes-base.gmail",
"typeVersion": 2.2,
"position": [
1648,
0
],
"id": "",
"name": "Send a message",
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"rule": {
"interval": [
{
"triggerAtHour": 8
}
]
}
},
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.3,
"position": [
0,
0
],
"id": "",
"name": "Schedule Trigger"
},
{
"parameters": {
"modelId": {
"__rl": true,
"value": "gpt-5",
"mode": "list",
"cachedResultName": "GPT-5"
},
"responses": {
"values": [
{
"role": "system",
"content": "You are Control Plane, an AI health and performance advisor.\n\nAnalyze Oura readiness data and produce a concise morning briefing.\n\nInclude:\n1. Recovery status\n2. Likely drivers of readiness\n3. Training recommendation\n4. Recovery recommendation\n5. Brief summary for the day\n\nKeep the response under 150 words."
},
{
"content": "=Date: {{$json.day}}\n\nReadiness Score: {{$json.readinessScore}}\n\nRecovery Mode: {{$json.recoveryMode}}\n\nActivity Balance: {{$json.activityBalance}}\n\nBody Temperature: {{$json.bodyTemperature}}\n\nPrevious Night: {{$json.previousNight}}\n\nRecovery Index: {{$json.recoveryIndex}}\n\nRecommendation: {{$json.recommendation}}\n\nSummary:\n{{$json.message}}"
}
]
},
"builtInTools": {},
"options": {}
},
"type": "@n8n/n8n-nodes-langchain.openAi",
"typeVersion": 2.3,
"position": [
832,
0
],
"id": "",
"name": "Message a model",
"credentials": {
"openAiApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"method": "POST",
"url": "https://smartdevicemanagement.googleapis.com/v1/enterprises/{{GOOGLE_SDM_PROJECT_ID}}/devices/{{NEST_DEVICE_ID}}:executeCommand",
"authentication": "genericCredentialType",
"genericAuthType": "oAuth2Api",
"sendBody": true,
"specifyBody": "json",
"jsonBody": "{\n \"command\": \"sdm.devices.commands.ThermostatTemperatureSetpoint.SetCool\",\n \"params\": {\n \"coolCelsius\": 21.1\n }\n}",
"options": {}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.4,
"position": [
1424,
-112
],
"id": "",
"name": "Nest - Recovery Mode 70F",
"credentials": {
"oAuth2Api": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"method": "POST",
"url": "https://smartdevicemanagement.googleapis.com/v1/enterprises/...",
"authentication": "genericCredentialType",
"genericAuthType": "oAuth2Api",
"sendBody": true,
"specifyBody": "json",
"jsonBody": "{\n \"command\": \"sdm.devices.commands.ThermostatTemperatureSetpoint.SetCool\",\n \"params\": {\n \"coolCelsius\": 24\n }\n}",
"options": {}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.4,
"position": [
1424,
128
],
"id": "",
"name": "Nest - Normal Mode 75F",
"credentials": {
"oAuth2Api": {
"name": "<your credential>"
}
}
}
],
"connections": {
"Edit Fields": {
"main": [
[
{
"node": "HTTP Request",
"type": "main",
"index": 0
}
]
]
},
"HTTP Request": {
"main": [
[
{
"node": "Code in JavaScript",
"type": "main",
"index": 0
}
]
]
},
"Code in JavaScript": {
"main": [
[
{
"node": "Message a model",
"type": "main",
"index": 0
}
]
]
},
"If": {
"main": [
[
{
"node": "Nest - Recovery Mode 70F",
"type": "main",
"index": 0
}
],
[
{
"node": "Nest - Normal Mode 75F",
"type": "main",
"index": 0
}
]
]
},
"Schedule Trigger": {
"main": [
[
{
"node": "Edit Fields",
"type": "main",
"index": 0
}
]
]
},
"Message a model": {
"main": [
[
{
"node": "If",
"type": "main",
"index": 0
}
]
]
},
"Nest - Recovery Mode 70F": {
"main": [
[
{
"node": "Send a message",
"type": "main",
"index": 0
}
]
]
},
"Nest - Normal Mode 75F": {
"main": [
[
{
"node": "Send a message",
"type": "main",
"index": 0
}
]
]
}
},
"active": false,
"settings": {
"executionOrder": "v1",
"binaryMode": "separate",
"availableInMCP": false
},
"versionId": "",
"meta": {
"templateCredsSetupCompleted": true
},
"nodeGroups": [],
"id": "",
"tags": []
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
gmailOAuth2oAuth2ApiopenAiApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Control Plane - Recovery Mode. Uses httpRequest, gmail, openAi. Scheduled trigger; 9 nodes.
Source: https://github.com/ryankander/control-plane-personal-ai/blob/main/workflows/control-plane-recovery-mode-template.json — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
Workflow runs at 08:00 (UK), AI stories from TechCrunch, The Verge, and the OpenAI Blog via RSS, AI to select and editorially shape one signal into a post and image prompt, generates and QA-checks a p
A scheduled process aggregates content from eight distinct data sources and standardizes all inputs into a unified format. AI models perform sentiment scoring, detect conspiracy or misinformation sign
This workflow monitors filesystem sync and backup jobs by validating their execution logs, not by running or inspecting the jobs themselves.
Stop wasting billable hours on manual time-tracking. AutoTimesheet Pro uses AI to collect emails, meetings, and GitHub work, then writes a clean timesheet straight into Google Sheets. Perfect for deve
Imagine a dedicated financial expert tirelessly working behind the scenes, sifting through every transaction, every investment move, and every accounting entry. That's exactly what this automated syst