This workflow follows the HTTP Request → Anthropic Chat 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": "Szybkie Kursiki - AI Course Generator (Webhook)",
"nodes": [
{
"parameters": {
"httpMethod": "POST",
"path": "generate-course",
"responseMode": "responseNode",
"options": {}
},
"id": "webhook-trigger",
"name": "Webhook Trigger",
"type": "n8n-nodes-base.webhook",
"typeVersion": 1.1,
"position": [
250,
300
]
},
{
"parameters": {
"jsCode": "// Extract course prompt from webhook payload\nconst body = $input.first().json.body;\n\nif (!body || !body.coursePrompt) {\n throw new Error('Missing coursePrompt in request body');\n}\n\nreturn {\n json: {\n coursePrompt: body.coursePrompt,\n metadata: body.metadata || {}\n }\n};"
},
"id": "extract-prompt",
"name": "Extract Prompt",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
450,
300
]
},
{
"parameters": {
"authentication": "predefinedCredentialType",
"nodeCredentialType": "anthropicApi",
"resource": "message",
"model": "claude-sonnet-4-5-20250929",
"text": "={{ $json.coursePrompt }}",
"options": {
"systemMessage": "Jeste\u015b ekspertem w tworzeniu kurs\u00f3w edukacyjnych online. Twoim zadaniem jest wygenerowanie kompletnej struktury kursu w formacie JSON.\n\nKurs musi zawiera\u0107:\n1. Podstawowe informacje o kursie (tytu\u0142, kr\u00f3tki opis, pe\u0142ny opis, ikona Font Awesome, tagi)\n2. Seri\u0119 lekcji (minimum 3-5 lekcji)\n3. Ka\u017cda lekcja MUSI zawiera\u0107:\n - Tytu\u0142\n - Kolejno\u015b\u0107 (order)\n - Tre\u015b\u0107 w formacie Markdown (content_markdown) - szczeg\u00f3\u0142owa, merytoryczna tre\u015b\u0107 lekcji z przyk\u0142adami kodu\n - Quiz z 3-5 pytaniami wielokrotnego wyboru\n - Zadanie praktyczne (practical_task) z przyk\u0142adami i rozwi\u0105zaniem\n\nFormat JSON:\n```json\n{\n \"course\": {\n \"title\": \"Nazwa kursu\",\n \"short_description\": \"Kr\u00f3tki opis kursu (max 200 znak\u00f3w)\",\n \"description\": \"Pe\u0142ny opis kursu - czego si\u0119 nauczysz, dla kogo jest kurs\",\n \"icon\": \"fas fa-code\",\n \"tags\": [\"Python\", \"Backend\", \"API\"]\n },\n \"lessons\": [\n {\n \"title\": \"Tytu\u0142 lekcji\",\n \"order\": 0,\n \"content_markdown\": \"# Wprowadzenie\\n\\nTre\u015b\u0107 lekcji w markdown...\\n\\n```python\\nprint('Hello World')\\n```\\n\\n## Kolejna sekcja\\n\\nWi\u0119cej tre\u015bci...\",\n \"quiz\": {\n \"title\": \"Quiz - Tytu\u0142 lekcji\",\n \"description\": \"Sprawd\u017a swoj\u0105 wiedz\u0119\",\n \"questions\": [\n {\n \"text\": \"Tre\u015b\u0107 pytania?\",\n \"order\": 0,\n \"explanation\": \"Wyja\u015bnienie poprawnej odpowiedzi\",\n \"answers\": [\n {\n \"text\": \"Odpowied\u017a 1\",\n \"is_correct\": true,\n \"order\": 0\n },\n {\n \"text\": \"Odpowied\u017a 2\",\n \"is_correct\": false,\n \"order\": 1\n }\n ]\n }\n ]\n },\n \"practical_task\": {\n \"title\": \"Zadanie praktyczne - Tytu\u0142\",\n \"content_markdown\": \"# Zadanie\\n\\nOpis zadania do wykonania...\",\n \"instructions_markdown\": \"## Instrukcje\\n\\n1. Krok 1\\n2. Krok 2\",\n \"example_markdown\": \"## Przyk\u0142ad\\n\\n```python\\nprzyk\u0142adowy_kod()\\n```\",\n \"hints_markdown\": \"## Wskaz\u00f3wki\\n\\n- Wskaz\u00f3wka 1\\n- Wskaz\u00f3wka 2\",\n \"solution_markdown\": \"## Rozwi\u0105zanie\\n\\n```python\\nrozwiazanie_zadania()\\n```\\n\\nWyja\u015bnienie...\"\n }\n }\n ]\n}\n```\n\nWA\u017bNE:\n- Tre\u015b\u0107 lekcji (content_markdown) powinna by\u0107 szczeg\u00f3\u0142owa (min 500 s\u0142\u00f3w)\n- U\u017cywaj prawid\u0142owego formatowania Markdown\n- Bloki kodu musz\u0105 mie\u0107 okre\u015blony j\u0119zyk (```python, ```javascript, itp.)\n- Ka\u017cde pytanie w quizie musi mie\u0107 co najmniej 4 odpowiedzi\n- Tylko jedna odpowied\u017a mo\u017ce by\u0107 poprawna (is_correct: true)\n- Zadania praktyczne musz\u0105 by\u0107 konkretne i wykonalne\n- U\u017cywaj polskich znak\u00f3w (\u0105, \u0107, \u0119, \u0142, \u0144, \u00f3, \u015b, \u017a, \u017c)\n\nODPOWIED\u0179 WY\u0141\u0104CZNIE POPRAWNYM JSON-em, bez dodatkowych komentarzy ani wyja\u015bnie\u0144."
}
},
"id": "anthropic-claude",
"name": "Generate Course with Claude",
"type": "@n8n/n8n-nodes-langchain.lmChatAnthropic",
"typeVersion": 1,
"position": [
650,
300
]
},
{
"parameters": {
"jsCode": "// Extract JSON from Claude's response\nconst response = $input.first().json.response;\n\n// Try to parse the response\nlet courseData;\n\ntry {\n // Check if response contains markdown code blocks\n const jsonMatch = response.match(/```(?:json)?\\s*([\\s\\S]*?)```/);\n \n if (jsonMatch) {\n // Extract JSON from code block\n courseData = JSON.parse(jsonMatch[1].trim());\n } else {\n // Try to parse directly\n courseData = JSON.parse(response);\n }\n \n // Validate required fields\n if (!courseData.course || !courseData.course.title) {\n throw new Error('Missing course title');\n }\n \n if (!courseData.lessons || courseData.lessons.length === 0) {\n throw new Error('No lessons provided');\n }\n \n // Ensure all lessons have required fields\n courseData.lessons.forEach((lesson, index) => {\n if (!lesson.title) {\n throw new Error(`Lesson ${index} missing title`);\n }\n if (lesson.order === undefined) {\n lesson.order = index;\n }\n if (!lesson.content_markdown) {\n throw new Error(`Lesson ${index} missing content_markdown`);\n }\n });\n \n return {\n json: courseData\n };\n \n} catch (error) {\n throw new Error(`Failed to parse Claude response: ${error.message}\\n\\nResponse: ${response}`);\n}"
},
"id": "code-parser",
"name": "Parse and Validate JSON",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
850,
300
]
},
{
"parameters": {
"method": "POST",
"url": "={{ $env.DJANGO_APP_URL }}/api/import-course/",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "X-Import-Token",
"value": "={{ $env.COURSE_IMPORT_TOKEN }}"
},
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"sendBody": true,
"bodyParameters": {
"parameters": []
},
"body": "={{ JSON.stringify($json) }}",
"options": {}
},
"id": "http-import",
"name": "Import Course to Django",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.1,
"position": [
1050,
300
]
},
{
"parameters": {
"respondWith": "json",
"responseBody": "={{ JSON.stringify({\n status: 'success',\n message: 'Kurs zosta\u0142 pomy\u015blnie utworzony!',\n course_title: $json.course_title,\n course_slug: $json.course_slug,\n lessons_count: $json.lessons_count,\n admin_url: $env.DJANGO_APP_URL + $json.admin_url,\n preview_url: $env.DJANGO_APP_URL + '/course/' + $json.course_slug + '/'\n}) }}",
"options": {}
},
"id": "webhook-response-success",
"name": "Webhook Response (Success)",
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1,
"position": [
1250,
200
]
},
{
"parameters": {
"respondWith": "json",
"responseCode": 500,
"responseBody": "={{ JSON.stringify({\n status: 'error',\n message: 'Nie uda\u0142o si\u0119 zaimportowa\u0107 kursu',\n error: $json.error || 'Unknown error'\n}) }}",
"options": {}
},
"id": "webhook-response-error",
"name": "Webhook Response (Error)",
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1,
"position": [
1250,
400
]
}
],
"connections": {
"Webhook Trigger": {
"main": [
[
{
"node": "Extract Prompt",
"type": "main",
"index": 0
}
]
]
},
"Extract Prompt": {
"main": [
[
{
"node": "Generate Course with Claude",
"type": "main",
"index": 0
}
]
]
},
"Generate Course with Claude": {
"main": [
[
{
"node": "Parse and Validate JSON",
"type": "main",
"index": 0
}
]
]
},
"Parse and Validate JSON": {
"main": [
[
{
"node": "Import Course to Django",
"type": "main",
"index": 0
}
]
]
},
"Import Course to Django": {
"main": [
[
{
"node": "Webhook Response (Success)",
"type": "main",
"index": 0
}
]
]
}
},
"settings": {
"executionOrder": "v1"
},
"staticData": null,
"tags": [],
"triggerCount": 1,
"updatedAt": "2026-02-02T00:00:00.000Z",
"versionId": "1"
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Szybkie Kursiki - AI Course Generator (Webhook). Uses lmChatAnthropic, httpRequest. Webhook trigger; 7 nodes.
Source: https://github.com/Sul3j/szybkie-kursiki/blob/7a41c67048c38e3d720c52f72553d5ea0cd49935/n8n-workflows/course-generator-webhook-workflow.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.
cold-outbound-engine-claude. Uses httpRequest, lmChatAnthropic, airtable, slack. Webhook trigger; 10 nodes.
Episode 18 Scary Stories TikTok final. Uses httpRequest, lmChatOpenAi, lmChatOllama, lmChatDeepSeek. Event-driven trigger; 83 nodes.
The Ultimate Scraper for n8n uses Selenium and AI to retrieve any information displayed on a webpage. You can also use session cookies to log in to the targeted webpage for more advanced scraping need
z-Api. Uses httpRequest, openAi, redis, postgres. Webhook trigger; 61 nodes.
How it works: • Receives WhatsApp messages via webhook from Whapi.Cloud • Routes commands: AI chat (/ai), numeric commands (1-9), or help menu • Sends responses: text, images, documents, videos, conta