Convertir un plan d'entraînement PDF en plan Hevy avec l'IA Gemini

Avancé

Ceci est unPersonal Productivity, AI Summarizationworkflow d'automatisation du domainecontenant 16 nœuds.Utilise principalement des nœuds comme Set, Aggregate, FormTrigger, HttpRequest, ExtractFromFile. Utiliser l'IA Gemini pour convertir des plans d'entraînement PDF en plans d'entraînement pour l'application Hevy

Prérequis
  • Peut nécessiter les informations d'identification d'authentification de l'API cible
Aperçu du workflow
Visualisation des connexions entre les nœuds, avec support du zoom et du déplacement
Exporter le workflow
Copiez la configuration JSON suivante dans n8n pour importer et utiliser ce workflow
{
  "meta": {
    "instanceId": "42450f423595f391b7c323eb4191c0bc81df9f6de5483a12f34f76cb4146556c",
    "templateCredsSetupCompleted": true
  },
  "nodes": [
    {
      "id": "9378321b-87f0-479f-8846-9e40a41c91ca",
      "name": "À la soumission du formulaire",
      "type": "n8n-nodes-base.formTrigger",
      "position": [
        -1240,
        -140
      ],
      "webhookId": "833ba56e-1dcb-45f7-9702-57800ff9095c",
      "parameters": {
        "options": {},
        "formTitle": "Upload Training Plan",
        "formFields": {
          "values": [
            {
              "fieldType": "file",
              "fieldLabel": "data",
              "multipleFiles": false,
              "requiredField": true,
              "acceptFileTypes": ".jpg, .png, .pdf, .jpeg"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "634600e6-0b0b-4051-ade7-e0b9f1e353ac",
      "name": "Analyseur de sortie structurée",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        228,
        80
      ],
      "parameters": {
        "schemaType": "manual",
        "inputSchema": "{\n  \"type\": \"object\",\n  \"properties\": {\n    \"routine\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"title\": {\n          \"type\": \"string\",\n          \"description\": \"The title of the routine\"\n        },\n        \"folder_id\": {\n          \"type\": \"number\",\n          \"nullable\": true,\n          \"default\": 1352963,\n          \"description\": \"The folder id the routine should be added to. Pass null to insert the routine into default 'My Routines' folder\"\n        },\n        \"notes\": {\n          \"type\": \"string\",\n          \"description\": \"Additional notes for the routine\"\n        },\n        \"exercises\": {\n          \"type\": \"array\",\n          \"description\": \"List of exercises in the routine\",\n          \"items\": {\n            \"type\": \"object\",\n            \"properties\": {\n              \"exercise_template_id\": {\n                \"type\": \"string\",\n                \"description\": \"The ID of the exercise template\"\n              },\n              \"superset_id\": {\n                \"type\": \"integer\",\n                \"nullable\": true,\n                \"description\": \"The ID of the superset\"\n              },\n              \"rest_seconds\": {\n                \"type\": \"integer\",\n                \"nullable\": true,\n                \"description\": \"The rest time in seconds (Pause). Never negative.\"\n              },\n              \"notes\": {\n                \"type\": \"string\",\n                \"nullable\": true,\n                \"description\": \"Additional notes for the exercise\"\n              },\n              \"sets\": {\n                \"type\": \"array\",\n                \"description\": \"Sets for the exercise\",\n                \"items\": {\n                  \"type\": \"object\",\n                  \"properties\": {\n                    \"type\": {\n                      \"type\": \"string\",\n                      \"enum\": [\"warmup\", \"normal\", \"failure\", \"dropset\"],\n                      \"description\": \"The type of the set\"\n                    },\n                    \"weight_kg\": {\n                      \"type\": \"number\",\n                      \"nullable\": true,\n                      \"description\": \"The weight in kilograms\"\n                    },\n                    \"reps\": {\n                      \"type\": \"integer\",\n                      \"nullable\": true,\n                      \"description\": \"The number of repetitions (wdhl.). Never negative.\"\n                    },\n                    \"distance_meters\": {\n                      \"type\": \"integer\",\n                      \"nullable\": true,\n                      \"description\": \"The distance in meters\"\n                    },\n                    \"duration_seconds\": {\n                      \"type\": \"integer\",\n                      \"nullable\": true,\n                      \"description\": \"The duration in seconds\"\n                    },\n                    \"custom_metric\": {\n                      \"type\": \"number\",\n                      \"nullable\": true,\n                      \"description\": \"A custom metric for the set. Currently used for steps and floors\"\n                    }\n                  }\n                }\n              }\n            },\n            \"required\": [\"exercise_template_id\", \"sets\"]\n          }\n        }\n      },\n      \"required\": [\"title\", \"exercises\"]\n    }\n  },\n  \"required\": [\"routine\"]\n}"
      },
      "typeVersion": 1.2
    },
    {
      "id": "9cf95512-03fc-44ce-8a4c-bdf828927ac2",
      "name": "google/gemini-2.5-flash",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenRouter",
      "position": [
        60,
        80
      ],
      "parameters": {
        "model": "google/gemini-2.5-flash",
        "options": {}
      },
      "credentials": {
        "openRouterApi": {
          "id": "aCsTDT5LGS5D8Ndl",
          "name": "OpenRouter account"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "d13c6c4d-c938-4617-a679-5e4cd356168e",
      "name": "Note adhésive",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1740,
        -200
      ],
      "parameters": {
        "color": 7,
        "width": 420,
        "height": 280,
        "content": "## Scan Any Workout Plan into the Hevy App with AI\n\nThis workflow extracts a workout plan from a PDF, uses AI to match the exercises to those available in the Hevy app, and automatically creates the routine for you.\nSetup:\n\nConfigure the trigger.\nAdd your OpenRouter & Hevy credentials.\nActivate and test!"
      },
      "typeVersion": 1
    },
    {
      "id": "d7a3ba9a-d86d-42bf-a6f9-5f30e699398a",
      "name": "Note adhésive1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1100,
        -360
      ],
      "parameters": {
        "width": 260,
        "height": 180,
        "content": "This node converts the incoming PDF file into a Base64 text string. This format is required to send the file content to the AI model in the next step."
      },
      "typeVersion": 1
    },
    {
      "id": "5b42918d-1446-4b91-b867-b9b0f771bfb7",
      "name": "Note adhésive2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -800,
        -360
      ],
      "parameters": {
        "width": 300,
        "height": 180,
        "content": "This node sends the PDF content to an AI model to perform OCR and extract all the text from the document.\nRequires: OpenRouter.ai API credentials."
      },
      "typeVersion": 1
    },
    {
      "id": "a137506d-75c3-45e6-8c78-8f6e0104914f",
      "name": "Note adhésive3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -440,
        -360
      ],
      "parameters": {
        "width": 300,
        "height": 180,
        "content": "These nodes fetch all available exercises from your Hevy account and combine them into a single list. This list provides the context for the AI to know which exercises are valid.\nRequires: https://api.hevyapp.com/docs/ credentials."
      },
      "typeVersion": 1
    },
    {
      "id": "c8ae0644-c339-4929-990c-ca99ab0247b1",
      "name": "Note adhésive4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        40,
        -420
      ],
      "parameters": {
        "width": 340,
        "height": 240,
        "content": "This is the core of the workflow.\nIt uses Google's Gemini model to:\n\nRead the messy text from the PDF.\nCompare the exercises mentioned against the official Hevy exercise list.\nCreate a clean, structured JSON output ready for the Hevy API.\nThe prompt and the Schema in the Structured Output Parser are critical here."
      },
      "typeVersion": 1
    },
    {
      "id": "88dbdb21-34e3-4faf-a226-2b3633b1dc4c",
      "name": "Note adhésive8",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        440,
        -340
      ],
      "parameters": {
        "content": "This final node takes the structured data from the AI and makes a POST request to the Hevy API, creating the complete workout routine in your account."
      },
      "typeVersion": 1
    },
    {
      "id": "0002347a-a9e3-43a3-be10-1773e3efd6cf",
      "name": "Convertir le PDF en Base64",
      "type": "n8n-nodes-base.extractFromFile",
      "position": [
        -1020,
        -140
      ],
      "parameters": {
        "options": {},
        "operation": "binaryToPropery"
      },
      "typeVersion": 1
    },
    {
      "id": "fcce2688-1ecc-4337-9737-3b92764ce718",
      "name": "Extraire le texte du PDF via IA",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -800,
        -140
      ],
      "parameters": {
        "url": "https://openrouter.ai/api/v1/chat/completions",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"model\": \"google/gemini-2.5-flash\",\n  \"messages\": [\n    {\n      \"role\": \"user\",\n      \"content\": [\n        {\n          \"type\": \"text\",\n          \"text\": \"Please perform OCR on this document and provide the full extracted content in your response\"\n        },\n        {\n          \"type\": \"image_url\",\n          \"image_url\": {\n            \"url\": \"data:image/jpeg;base64,{{ $json.data }}\"\n          }\n        }\n      ]\n    }\n  ]\n}",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth"
      },
      "credentials": {
        "httpHeaderAuth": {
          "id": "hPXTjlgijwj0mJav",
          "name": "Header Auth account"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "51ad34e9-0aaa-4ebe-adfa-6fd263cba56c",
      "name": "Obtenir la liste d'exercices depuis Hevy",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -580,
        -140
      ],
      "parameters": {
        "url": "https://api.hevyapp.com/v1/exercise_templates",
        "options": {
          "pagination": {
            "pagination": {
              "parameters": {
                "parameters": [
                  {
                    "name": "page",
                    "value": "={{ $pageCount + 1 }}"
                  }
                ]
              },
              "maxRequests": 10,
              "requestInterval": 100,
              "limitPagesFetched": true,
              "paginationCompleteWhen": "receiveSpecificStatusCodes",
              "statusCodesWhenComplete": "404"
            }
          }
        },
        "sendQuery": true,
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "queryParameters": {
          "parameters": [
            {
              "name": "pageSize",
              "value": "100"
            }
          ]
        }
      },
      "credentials": {
        "httpHeaderAuth": {
          "id": "wmbngFqWDYUxVqMb",
          "name": "Hevy Auth"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "20ccb4bb-b0bd-4567-bb26-1015b3fa0105",
      "name": "Formater les noms d'exercices",
      "type": "n8n-nodes-base.set",
      "position": [
        -360,
        -140
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "85dd9d76-d527-43ce-bd36-955bb2a3b3f6",
              "name": "exercise_templates",
              "type": "array",
              "value": "={{ $json.exercise_templates }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "16434525-113f-4f93-b6df-05a096658087",
      "name": "Combiner la liste d'exercices",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        -140,
        -140
      ],
      "parameters": {
        "options": {
          "mergeLists": true
        },
        "fieldsToAggregate": {
          "fieldToAggregate": [
            {
              "fieldToAggregate": "exercise_templates"
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "291e75d6-a372-4a15-ad66-92043cfc107b",
      "name": "Correspondre les exercices et structurer la routine",
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "position": [
        80,
        -140
      ],
      "parameters": {
        "text": "=# GOAL\nYour task is to analyze the provided OCR data of a workout routine, interpret its contents, and convert it into a structured JSON object. You must strictly adhere to the provided JSON schema.\n\n# CONTEXT\n- The OCR data is imperfect and may contain typos or formatting quirks.\n- You will be given a list of available exercises from an application database (`Base Exercise Data`).\n\n# INPUT DATA\n1.  **OCR Data:**\n    ```\n    {{ $('Extract Text from PDF via AI').item.json.choices[0].message.content }}\n    ```\n2.  **Base Exercise Data:**\n    ```json\n    {{ $json.exercise_templates.toJsonString() }}\n    ```\n\n# EXTRACTION RULES & SPECIFICS\nThis section contains specific instructions to guide the extraction process.\n\n- **Exercise Matching:** For each exercise name found in the OCR data, you MUST find the most semantically similar exercise in the `Base Exercise Data`. Use its `id` for the `exercise_template_id` in the final JSON. Do not invent new IDs.\n- **Default Folder:** If no folder is specified, use the default `folder_id` of `1352963`.\n- **Interpreting Sets:** A line like \"3x10 @ 50kg\" means 3 sets of 10 repetitions with 50 kilograms.\n- **Rest Times:** Look for terms like \"Pause,\" \"Rest,\" or time values (e.g., \"90s,\" \"1 min\") between exercises to determine the `rest_seconds`.\n- **Supersets:** If exercises are grouped with labels like \"A1, A2\" or listed together without a rest period, they are a superset. Assign them the same, incrementing `superset_id` (e.g., the first superset pair gets `superset_id: 1`, the next pair gets `superset_id: 2`).\n- **Tempo Information (optional):** Look for a 3 or 4-digit number (e.g., `4010`, `31X0`, `311`), often labeled \"Tempo\". If found for an exercise, capture this and include it in that exercise's `notes` field (e.g., `notes: \"Tempo: 4010\"`).\n\n\n\n# OUTPUT INSTRUCTIONS\n- Produce ONLY the final JSON object.\n- Do not include any explanatory text, markdown formatting, or apologies in your response.\n- The output must be a single, valid JSON object conforming to the schema.\n",
        "batching": {},
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 1.7
    },
    {
      "id": "7d710a1d-7e86-4da1-bda1-741d8008cb02",
      "name": "Créer une routine Hevy",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        456,
        -140
      ],
      "parameters": {
        "url": "https://api.hevyapp.com/v1/routines",
        "method": "POST",
        "options": {},
        "jsonBody": "={{ $json.output.toJsonString() }}",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth"
      },
      "credentials": {
        "httpHeaderAuth": {
          "id": "wmbngFqWDYUxVqMb",
          "name": "Hevy Auth"
        }
      },
      "typeVersion": 4.2
    }
  ],
  "pinData": {},
  "connections": {
    "9378321b-87f0-479f-8846-9e40a41c91ca": {
      "main": [
        [
          {
            "node": "0002347a-a9e3-43a3-be10-1773e3efd6cf",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "16434525-113f-4f93-b6df-05a096658087": {
      "main": [
        [
          {
            "node": "291e75d6-a372-4a15-ad66-92043cfc107b",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "0002347a-a9e3-43a3-be10-1773e3efd6cf": {
      "main": [
        [
          {
            "node": "fcce2688-1ecc-4337-9737-3b92764ce718",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "20ccb4bb-b0bd-4567-bb26-1015b3fa0105": {
      "main": [
        [
          {
            "node": "16434525-113f-4f93-b6df-05a096658087",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "9cf95512-03fc-44ce-8a4c-bdf828927ac2": {
      "ai_languageModel": [
        [
          {
            "node": "291e75d6-a372-4a15-ad66-92043cfc107b",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "634600e6-0b0b-4051-ade7-e0b9f1e353ac": {
      "ai_outputParser": [
        [
          {
            "node": "291e75d6-a372-4a15-ad66-92043cfc107b",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "51ad34e9-0aaa-4ebe-adfa-6fd263cba56c": {
      "main": [
        [
          {
            "node": "20ccb4bb-b0bd-4567-bb26-1015b3fa0105",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "fcce2688-1ecc-4337-9737-3b92764ce718": {
      "main": [
        [
          {
            "node": "51ad34e9-0aaa-4ebe-adfa-6fd263cba56c",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "291e75d6-a372-4a15-ad66-92043cfc107b": {
      "main": [
        [
          {
            "node": "7d710a1d-7e86-4da1-bda1-741d8008cb02",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Foire aux questions

Comment utiliser ce workflow ?

Copiez le code de configuration JSON ci-dessus, créez un nouveau workflow dans votre instance n8n et sélectionnez "Importer depuis le JSON", collez la configuration et modifiez les paramètres d'authentification selon vos besoins.

Dans quelles scénarios ce workflow est-il adapté ?

Avancé - Productivité personnelle, Résumé IA

Est-ce payant ?

Ce workflow est entièrement gratuit et peut être utilisé directement. Veuillez noter que les services tiers utilisés dans le workflow (comme l'API OpenAI) peuvent nécessiter un paiement de votre part.

Workflows recommandés

Moniteur de questions communautaires avec crawling Reddit, forums et OpenRouter AI
Surveiller les problèmes communautaires sur Reddit et les forums avec OpenRouter AI et le scraping
Set
Code
Html
+
Set
Code
Html
29 NœudsJulian Kaiser
Étude de marché
Génération d'un bulletin d'action hebdomadaire pour les droits des animaux basé sur les projets de loi de la Chambre des représentants des États-Unis avec Gemini AI
Générer un bulletin d'action hebdomadaire sur les droits des animaux à partir des projets de loi de la Chambre des représentants américaine avec Gemini AI
If
Set
Html
+
If
Set
Html
26 NœudsOpen Paws
Réseaux sociaux
Automatisation de la recherche d'emploi et de la personnalisation des CV avec Mistral AI, LinkedIn et Google Sheets
Automatisation de la recherche d'offres d'emploi et de la personnalisation de CV avec Mistral AI, LinkedIn et Google Sheets
Set
Code
Html
+
Set
Code
Html
46 NœudsJordan Hoyle
Productivité personnelle
Générateur de vidéo automatisé
Générez des vidéos IA à partir d'un script avec DeepSeek, TTS et Together.ai
Set
Code
Wait
+
Set
Code
Wait
81 NœudsLakindu Siriwardana
Création de contenu
Extraction de données Twitter - n8n Creator
Génération automatisée de résumés de renseignements Twitter avec Gemini 2.5 Pro et envoi vers les groupes WhatsApp
Set
Code
Wait
+
Set
Code
Wait
39 NœudsDaniel Lianes
Résumé IA
Analyse intelligente quotidienne des groupes WhatsApp : Analyse GPT-4.1 et transcription des messages vocaux
Analyse intelligente des groupes WhatsApp quotidiens : analyse GPT-4.1 et transcription des messages vocaux
If
Set
Code
+
If
Set
Code
52 NœudsDaniel Lianes
Divers
Informations sur le workflow
Niveau de difficulté
Avancé
Nombre de nœuds16
Catégorie2
Types de nœuds9
Description de la difficulté

Adapté aux utilisateurs avancés, avec des workflows complexes contenant 16+ nœuds

Auteur
Julian Kaiser

Julian Kaiser

@jksr

Full Stack Developer turned AI & Automation Engineer, implementing intelligent solutions with custom code, LLMs & n8n. Use my link to book a free 30-minute call to discuss your AI challenges and see if my services might be a good fit for your needs.

Liens externes
Voir sur n8n.io

Partager ce workflow

Catégories

Catégories: 34