Connect Your ML Model to n8n

Route ML predictions through automated business logic using n8n webhooks.

Introduction

30 Second Summary

Machine learning models are powerful predictors, but a prediction sitting in a notebook doesn't help anyone make faster decisions. The real value comes when predictions flow directly into automated workflows that take action.

In this project, you will connect your AWS-deployed Iris classifier to an n8n automation workflow that accepts plant measurements, calls your ML model, and routes predictions into species-specific business decisions.

What You'll Build

A webhook-triggered n8n workflow that simulates a botanical nursery's plant intake system, routing ML predictions into automated greenhouse assignments, pricing tiers, and care instructions.

By the end of this project, you'll have:

  • A live webhook endpoint that accepts plant measurement data and returns ML-powered classification decisions.
  • A working Switch-based routing pattern that maps ML predictions to business actions including pricing, care instructions, and greenhouse assignment.
  • A tested end-to-end automation pipeline connecting n8n to an external ML API, demonstrating the predict-route-act pattern used in production ML systems.
  • Secret Mission: Wire up Google Sheets logging to track every classification with timestamp, measurements, and predicted species.

Do I need to complete the previous projects first?

Yes. This project requires a running n8n instance (self-hosted on Render) and a deployed Iris classifier on AWS Lambda with an API Gateway endpoint from Project 2.

Both services should be live and accessible before you start this project.

Set Up Your Workflow and Verify Connectivity

Your Iris classification model is live on AWS, ready to make predictions. But an API sitting idle isn't useful until something calls it, interprets the result, and takes action.

In this step, you'll create an n8n workflow with a Webhook trigger and an HTTP Request node pointed at your AWS Lambda endpoint. By the end, you'll confirm the two systems talk to each other successfully.

In this step, get ready to:
  • Create a Webhook-triggered workflow in n8n.
  • Connect the workflow to your AWS ML prediction endpoint.
  • Verify end-to-end connectivity with a test request.
Create the workflow and configure the Webhook node

The Webhook node acts as the front door of your workflow. It listens for incoming HTTP requests and kicks off the automation chain.

  • Open your n8n instance on Render in your browser.
  • Click the + button (or Create Workflow) to create a new workflow.
  • Double-click the workflow name at the top and rename it to Smart Plant Nursery Intake.
  • Click the + node on the canvas to open the node panel.
  • Search for Webhook and select it to add it as the trigger node.

Now configure the Webhook node settings.

  • Set HTTP Method to POST.
  • Set the Path field to plant-intake.
  • Set Respond to Using 'Respond to Webhook' Node.
  • Note the Test URL and Production URL displayed at the top of the node panel. You'll use the Test URL shortly.

What are the Test URL and Production URL?

n8n gives every Webhook node two URLs. The Test URL is active for 120 seconds each time you click Listen for Test Event. It lets you send data to the workflow while building it.

The Production URL only works after you activate (publish) the workflow. You'll switch to the Production URL in a later step.

Add and configure the HTTP Request node

The HTTP Request node is what actually calls your ML model. It takes the incoming measurement data from the Webhook and forwards it to your API Gateway endpoint on AWS.

  • Click the + connector on the right side of the Webhook node to add a new node after it.
  • Search for HTTP Request and select it.
  • Set Method to POST.
  • In the URL field, paste your AWS API Gateway endpoint URL from Project 2.

Where do I find my endpoint URL?

Your API Gateway endpoint follows the pattern https://{api-id}.execute-api.{region}.amazonaws.com/{stage}/{resource}. You can find this in the AWS Console under API Gateway > your API > Stages.

Next, configure the request body so the node forwards the Webhook's incoming data to AWS.

  • Toggle Send Body on.
  • Set Body Content Type to JSON.
  • Under Specify Body, select Using JSON.
  • In the JSON body field, click the expression toggle (the small { } icon to the right of the field) to switch from fixed value to expression mode.
  • Enter this expression:
{{ JSON.stringify($json.body) }}

What does this expression do?

When the Webhook receives a POST request, n8n stores the request's JSON body at $json.body. This expression takes that entire body object and converts it to a JSON string so the HTTP Request node can forward it to your AWS endpoint unchanged.

This pass-through pattern means any measurements sent to your Webhook automatically reach your ML model without manual field mapping.

  • Scroll down to the Response section.
  • Set Response Format to JSON.

Your HTTP Request node is now fully configured. It will POST the incoming measurements to your AWS endpoint and parse the response as JSON.

Test connectivity with a curl request

Time to prove the two systems can communicate. You'll send a sample iris measurement through the Webhook and confirm the prediction arrives back from AWS.

  • In the n8n canvas, click on the Webhook node to open it.
  • Click Listen for Test Event. The node now listens on the Test URL for 120 seconds.
  • Open a terminal on your computer.
  • Send a test request with sample iris data by running this command:
curl --request POST [[WEBHOOK_TEST_URL="your Webhook Test URL from the node panel"]] \
  --header "Content-Type: application/json" \
  --data '{"sepal_length": 5.1, "sepal_width": 3.5, "petal_length": 1.4, "petal_width": 0.2}'

What should I see?

After a moment, the n8n canvas shows green checkmarks on both the Webhook and HTTP Request nodes. Click the HTTP Request node to inspect its output.

You should see a prediction field in the response, such as {"prediction": "setosa"}. The exact format depends on how your model was deployed in Project 2. Some deployments return a string label, others return a numeric class index like 0.

Not seeing a response from AWS?

  • Make sure you clicked Listen for Test Event before sending the curl request. The Test URL only stays active for 120 seconds.
  • Double-check the URL in the HTTP Request node matches your API Gateway endpoint exactly. A missing path segment like /predict at the end will return a 404 error.
  • Confirm your AWS Lambda function is still deployed and the API Gateway stage is active by visiting the endpoint URL directly in your browser (you should see a method-not-allowed or similar response, not a 404).

Still stuck? Help me debug why my n8n HTTP Request node can't reach my AWS endpoint.

Your workflow's foundation is solid. The Webhook receives data and the HTTP Request node successfully calls your ML model. Next up, you'll build the routing logic that turns a raw prediction into a business decision.

Build the Species Routing Logic

Your workflow can now reach your ML model and get a prediction back. The next challenge is deciding what to do with that prediction.

In a real nursery, different species need different greenhouses, different pricing, and different care routines. A Switch node lets you route data down separate paths based on a value, sending each species prediction to its own branch of business logic.

In this step, get ready to:
  • Add a Switch node that routes predictions to species-specific branches.
  • Configure three Edit Fields (Set) nodes with greenhouse, pricing, and care data.
  • Test the routing to confirm the correct branch activates for each species.
Add and configure the Switch node

Your ML model returns a prediction field containing a species name. The Switch node inspects that field and sends the data down the matching output.

  • On the n8n canvas, click the + connector on the right side of the HTTP Request node.
  • Search for Switch and select it to add it to your workflow.
  • In the Switch node panel, set Mode to Rules.
  • Under Routing Rules, configure Rule 0:
  • Click Add Routing Rule to create Rule 1.
  • Set Value 1 to the same expression {{ $json.prediction }}, comparison to is equal to, and Value 2 to versicolor.
  • Click Add Routing Rule again to create Rule 2.
  • Set Value 1 to {{ $json.prediction }}, comparison to is equal to, and Value 2 to virginica.
  • Scroll down to Fallback Output and set it to Extra Output.

Why use a Switch node instead of IF?

The IF node only supports two branches (true/false). Since you have three species to route, the Switch node is the right tool. It creates a separate output connector for each rule, giving you a clean branch per species.

The fallback output catches any unexpected prediction values that do not match your three rules, preventing the workflow from silently dropping data.

Don't see the expression option?

Click the Value 1 field, then look for the Expression tab or toggle above the input. Switch from Fixed to Expression before typing the expression.

help me configure an expression in my Switch node's routing rules

Connect Edit Fields nodes for each species

Each Switch output needs an Edit Fields (Set) node that attaches the business data for that species. You will create three Set nodes, one per branch.

  • Click the + connector on the Switch node's first output (Output 0).
  • Search for Edit Fields (Set) and add it.
  • Rename the node to Setosa Set by double-clicking its title on the canvas.
  • In the node panel, add the following fields using Manual Mapping mode. For each field, set the value type to Fixed:
  • To pass through the original measurements, add four more fields with values set to Expression mode:

What does $('Webhook').item.json.body do?

This expression reaches back to the Webhook node and pulls data from the original request body. The HTTP Request node replaces the current item data with the API response, so you need this cross-node reference to access the original measurements the caller submitted.

Match your endpoint's field names

The field names above (sepal_length, sepal_width, etc.) must match the JSON keys your curl request sends. If your Project 2 endpoint uses different names, adjust accordingly.

  • Click the + connector on the Switch node's second output (Output 1).
  • Add another Edit Fields (Set) node and rename it to Versicolor Set.
  • Add these fixed-value fields:
  • Add the same four measurement fields using expressions referencing the Webhook node, identical to the Setosa Set node.
  • Click the + connector on the Switch node's third output (Output 2).
  • Add another Edit Fields (Set) node and rename it to Virginica Set.
  • Add these fixed-value fields:
  • Add the same four measurement fields using expressions referencing the Webhook node.

Seeing an error about item linking?

If n8n shows an error when you reference $('Webhook').item.json, the item link between the Webhook and your current node may be broken. Try replacing .item with .first() so the expression becomes {{ $('Webhook').first().json.body.sepal_length }}. This explicitly grabs the first item from the Webhook output.

help me fix an item linking error in my Edit Fields node

Test the Switch routing

Time to confirm each species lands on the correct branch. You will send three test requests, each with measurements known to produce a different prediction.

  • Return to the Webhook node on the canvas and click Listen for Test Event.
  • Open your terminal and send a request with setosa-typical measurements by running this command:
curl --request POST [[N8N_TEST_URL="your Webhook Test URL"]] \
  --header "Content-Type: application/json" \
  --data '{"sepal_length": 5.1, "sepal_width": 3.5, "petal_length": 1.4, "petal_width": 0.2}'
  • Switch back to the n8n canvas. You should see the execution path highlighted through the Switch node's Output 0 and into the Setosa Set node.
  • Click the Setosa Set node and check its output. You should see all the fields: species, greenhouse, pricing_tier, care_instructions, plus the four measurement values.
  • Click Listen for Test Event again on the Webhook node, then send a versicolor-typical request:
curl --request POST [[N8N_TEST_URL="your Webhook Test URL"]] \
  --header "Content-Type: application/json" \
  --data '{"sepal_length": 6.0, "sepal_width": 2.7, "petal_length": 4.5, "petal_width": 1.5}'
  • Confirm the execution flows through Output 1 into the Versicolor Set node.
  • Click Listen for Test Event once more, then send a virginica-typical request:
curl --request POST [[N8N_TEST_URL="your Webhook Test URL"]] \
  --header "Content-Type: application/json" \
  --data '{"sepal_length": 6.7, "sepal_width": 3.0, "petal_length": 5.5, "petal_width": 2.1}'
  • Confirm the execution flows through Output 2 into the Virginica Set node.

What if my endpoint returns numbers instead of names?

Some Iris classifiers return numeric class indices (0, 1, 2) instead of species name strings. If that is the case for your endpoint, change the Switch rules to compare against 0, 1, and 2 using the Number data type instead of String.

Wrong branch activating?

Click the HTTP Request node output and inspect the prediction field. Make sure its value exactly matches one of your Switch rule values. Watch for extra spaces, capitalisation differences, or surrounding quotes.

Also confirm that the Webhook Test URL is still active. It expires after 120 seconds. If it timed out, click Listen for Test Event again before re-sending the curl request.

help me debug why my Switch node is routing to the wrong branch

Your workflow now classifies plants and routes them to species-specific business logic. Next up, you will close the loop by returning a structured JSON response back to the caller.

Return the Decision as a Structured Response

Your Switch node routes predictions to the correct species branch, and each Edit Fields node prepares the business data. The final piece is sending that data back to whoever called the webhook.

In this step, you will add a Respond to Webhook node that returns a structured JSON response to the caller. Then you will publish the workflow so its Production URL is permanently active, and test the full end-to-end pipeline with curl.

In this step, get ready to:
  • Add a Respond to Webhook node and connect all three species branches to it.
  • Publish the workflow to register the Production URL.
  • Test all three species end-to-end with curl against the Production URL.
Add the Respond to Webhook node

The Respond to Webhook node closes the loop between the incoming request and the outgoing response. It takes the data from whichever branch executed and sends it back as the HTTP response.

  • Click the + button on the canvas to add a new node.
  • Search for Respond to Webhook and select it.
  • In the node parameters, set Respond With to First Incoming Item.
  • Connect the output of your Setosa Edit Fields (Set) node to the Respond to Webhook node.
  • Connect the output of your Versicolor Edit Fields (Set) node to the same Respond to Webhook node.
  • Connect the output of your Virginica Edit Fields (Set) node to the same Respond to Webhook node.

Why does one node accept three connections?

In n8n, a node can accept inputs from multiple upstream nodes. Only the branch that actually executes during a given run sends data downstream.

The Respond to Webhook node runs once using the first incoming data item. Since only one species branch fires per request, it always returns exactly the data from the correct Edit Fields node.

Can't connect a second Set node to the Respond to Webhook?

Drag the connection line from the Set node's output dot to the Respond to Webhook node's input dot. n8n allows multiple connections into the same input. If the connection snaps back, zoom in closer to the input dot and try again.

help me connect multiple nodes to one Respond to Webhook node

Publish the workflow

Publishing locks your workflow to a specific version and registers the Production URL permanently. Unlike the Test URL (which expires after 120 seconds), the Production URL stays active until you unpublish the workflow.

  • Click the Publish button in the top-right corner of the canvas.
  • In the publishing modal, leave the default version name or add a description like v1 - full pipeline.
  • Click Publish to confirm.
  • Open the Webhook node by double-clicking it on the canvas.
  • At the top of the node panel, toggle from Test URL to Production URL.
  • Copy the Production URL displayed. It follows a pattern like https://your-n8n.onrender.com/webhook/plant-intake.

What is the difference between Test URL and Production URL?

The Test URL is temporary. It activates when you click Listen for Test Event and expires after 120 seconds. It shows incoming data in the editor, which is great for debugging.

The Production URL is permanent once the workflow is published. It does not display data in the editor, but you can review executions later in the Executions tab.

Test the full pipeline with curl

Now you will send three requests to the Production URL, one for each species. Each request uses measurements that your ML model is known to classify as a specific species.

  • Open a terminal on your computer.
  • Send a Setosa test request by running this command:
curl --request POST [[N8N_PRODUCTION_URL="your n8n Production URL (e.g. https://your-n8n.onrender.com/webhook/plant-intake)"]] \
  --header "Content-Type: application/json" \
  --data '{"sepal_length": 5.1, "sepal_width": 3.5, "petal_length": 1.4, "petal_width": 0.2}'

What does this command do?

This sends a POST request with iris sepal and petal measurements to your Production webhook. The measurements (5.1, 3.5, 1.4, 0.2) are typical values that an Iris classifier predicts as Setosa.

If your ML endpoint from Project 2 uses different field names, replace the JSON keys to match what your endpoint expects.

You should see a JSON response containing the Setosa business data, including greenhouse, pricing_tier, and care_instructions fields.

  • Send a Versicolor test request by running this command:
curl --request POST [[N8N_PRODUCTION_URL="your n8n Production URL (e.g. https://your-n8n.onrender.com/webhook/plant-intake)"]] \
  --header "Content-Type: application/json" \
  --data '{"sepal_length": 6.0, "sepal_width": 2.7, "petal_length": 4.5, "petal_width": 1.5}'
  • Confirm the response includes greenhouse set to B (Temperate) and pricing_tier set to Premium ($7.25).
  • Send a Virginica test request by running this command:
curl --request POST [[N8N_PRODUCTION_URL="your n8n Production URL (e.g. https://your-n8n.onrender.com/webhook/plant-intake)"]] \
  --header "Content-Type: application/json" \
  --data '{"sepal_length": 6.7, "sepal_width": 3.1, "petal_length": 5.6, "petal_width": 2.4}'
  • Confirm the response includes greenhouse set to C (Warm Humid) and pricing_tier set to Specialty ($12.00).

What should a successful response look like?

Each response should be a JSON object containing the fields your Edit Fields (Set) nodes configured: species, greenhouse, pricing_tier, care_instructions, plus the original measurement values passed through from the request.

Getting an empty response or a timeout?

Make sure you published the workflow (not just saved it). The Production URL only becomes active after publishing.

Double-check that all three Edit Fields (Set) nodes are connected to the Respond to Webhook node. If a branch executes but has no path to the response node, the webhook hangs until it times out.

Also verify your Webhook node has Respond set to Using 'Respond to Webhook' Node. If this is set to Immediately or When Last Node Finishes, the Respond to Webhook node is ignored.

help me debug why my n8n webhook is not returning data

Secret mission

Add Google Sheets Classification Logging

Your workflow classifies plants and returns decisions instantly. But what happens to all that data? In production, every prediction should be logged for auditing, retraining, and business reporting. Wire up Google Sheets to automatically record every classification that flows through your workflow.

Clean Up Your Resources

Clean Up Your Resources

This project runs entirely on your existing n8n instance (hosted on Render) and your existing AWS Lambda endpoint. There are no additional ongoing costs from the resources you created in this project.

Decide whether to keep your workflow running, pause it to come back later, or delete it entirely.

Resources you used:

  • n8n workflow: Smart Plant Nursery Intake (active on your Render-hosted n8n instance).
  • Google Sheets credentials configured in n8n (OAuth2 or Service Account).
  • Google Sheet: Plant Nursery Classifications (with logged classification data).

Keep everything running

No action needed. Choose this if you plan to keep using the Smart Plant Nursery Intake workflow or want to extend it further.

  • Your workflow remains active and will respond to POST requests at the Production URL.
  • Your Google Sheet will continue to log classifications when new requests come in.
  • Your Google Sheets credentials remain stored in n8n for future workflows.

Pause - I'll come back to this later

Deactivate the workflow so it stops responding to webhook requests. Your configuration stays intact for when you return.

  • Open the Smart Plant Nursery Intake workflow in your n8n editor.
  • Toggle the workflow from Active to Inactive using the toggle in the top bar.
  • The Production URL will stop accepting requests until you reactivate.

Delete - I don't want to use this again

Remove all project resources and start fresh. Follow each step below.

  • Open the Smart Plant Nursery Intake workflow in your n8n editor.
  • Open the three-dot menu (or right-click the workflow name) and select **Delete**. Confirm the deletion when prompted.
  • In the n8n side menu, click **Credentials**.
  • Find your Google Sheets credential, open its three-dot menu, and select **Delete**. Confirm the deletion.
  • Open Google Drive in your browser.
  • Find the Plant Nursery Classifications spreadsheet, right-click it, and select **Move to trash**.

Nice Work!

Nice Work!

You just built a production-ready ML integration pipeline that turns raw plant measurements into automated business decisions. Your n8n workflow now connects a live AWS Lambda classifier to conditional routing logic and returns structured JSON responses in a single webhook call.

You've learned how to:

  • Connect n8n to an external AWS Lambda ML endpoint using the HTTP Request node with JSON body forwarding, creating a live webhook that accepts plant measurement data and returns real-time predictions.
  • Implement Switch node conditional routing that maps ML predictions to species-specific business logic branches with greenhouse assignments, pricing tiers, and care instructions.
  • Test a full predict-route-respond automation cycle end-to-end with curl, returning structured JSON business decisions via the Respond to Webhook node.
  • Secret Mission: Added Google Sheets logging to persist every classification with a timestamp and full measurement data.

Ready to quiz yourself?