Build a Webhook-to-Discord Automation
Transform local webhook events into formatted Discord notifications with n8n.
Introduction
30 Second Summary
Important job updates are easy to miss when they stay inside the tool that created them. A shared chat channel puts each update where people already look.
In this project, you will build a local automation for archive-job updates. Each Webhook request becomes a clean Discord notification through n8n's JSON transformation.
What You'll Build
Picture a single PowerShell request producing a tidy Discord alert that shows every archive-job detail in a readable format.
By the end of this project, you'll have:
- A local endpoint that accepts a realistic archive job through an HTTP POST request.
- A raw-to-clean comparison that reveals the useful payload inside the full request envelope.
- A published Production URL that posts repeatable job updates into your Discord channel while the local n8n lab is running.
- Secret Mission: Give failed archive jobs a distinct alert heading so they stand out from queued jobs.
Are there any prerequisites?
You need the working local n8n lab from Project 1, with the editor available at http://localhost:5678. You also need PowerShell plus a Discord account.
Before We Start
Before any hands-on work, lock in the path your archive-job event will take. This gives every later workflow choice a clear purpose.
Verify the Lab and Create the Workflow
The local n8n lab from Project 1 already contains the infrastructure this automation needs. This step confirms that foundation is running before any webhook work begins.
You'll create an empty Personal workflow named Archive Job to Discord. You'll also place PowerShell beside the editor so each test stays easy to follow.
In this step, get ready to:
- Bring the existing local n8n lab online.
- Create an empty Personal workflow named Archive Job to Discord.
- Place PowerShell beside the n8n editor.
Start the existing lab
Docker Desktop keeps your local n8n service available. Project 1 already configured this lab for you.
- Press the Windows key to open Windows search.
- Type Docker Desktop and press Enter to open it.
You'll see Docker Desktop open.
- Wait until Docker Desktop reports that its engine is running.
- Start the local n8n stack using the same method from Project 1.
- Confirm the local n8n stack shows the same running state you verified in Project 1.
- Enter http://localhost:5678 in your browser's address bar.
- Sign in with the local owner account from Project 1 if n8n asks for it.
You'll see the local n8n editor load with the Personal project available. Your existing lab is back online and ready for the workflow that turns archive jobs into notifications.
Local Editor Not Loading?
- Confirm Docker Desktop has finished starting before you start the local n8n stack.
- Use the same n8n start method that worked in Project 1.
- Still stuck? Help me restore my local n8n lab.
Create the Personal workflow
This workflow becomes the home for the archive-job automation. Its empty canvas gives you a clean starting point for the trigger you add next.
- Select Personal in the n8n sidebar.
- Select Create workflow.
You'll see an empty canvas with Add first step... in the centre.
- Select the current workflow name in the canvas header.
- Enter Archive Job to Discord as the workflow name.
You'll see Archive Job to Discord in the canvas header.
- Wait for n8n to auto-save the draft.
- Confirm the canvas contains no nodes.
The workflow remains an unpublished draft. Its canvas stays empty for the Webhook trigger in the next step.
Why Use Personal?
Community Edition stores workflows in the Personal project. This keeps your local workflow in the space n8n already prepared for your owner account.
✔️ Awesome, I've got everything!
Great. Your Personal workflow has an empty unpublished canvas with no nodes.
ⓧ I'd like to double check the full code
This step creates workflow state. Use this exact checkpoint:
Created in the Personal project with an empty, unpublished canvas and no nodes.
Place PowerShell beside the editor
PowerShell sends the sample archive-job requests later in the project. Keeping it beside the n8n canvas makes each send-and-inspect loop visible in one view.
- Press the Windows key to open Windows search.
- Type PowerShell and press Enter to open it.
You'll see a PowerShell window with a command prompt ready for input.
- Drag the PowerShell window to one side of your screen.
- Move the browser window to the open side of your screen.
Before you check, which visible details should prove that the lab is ready for its first request?
- Confirm Docker Desktop is running.
- Confirm n8n displays Archive Job to Discord on an empty canvas.
- Confirm PowerShell is visible beside the browser.
You should see the empty n8n canvas load without an error. PowerShell should sit beside it with a prompt ready for the first request.
You now have the full testing workspace in one view.
Your lab is running and your empty workflow is ready. Next, you'll add the Webhook trigger and inspect the raw archive-job request.
Capture a Raw Archive Job
Your empty n8n workflow canvas is ready. The next check proves that a real archive job can reach it from PowerShell.
A webhook receives the business payload inside a larger HTTP request envelope. You need to see that noisy structure before deciding which fields should move downstream.
In this step, get ready to:
- Configure a Webhook trigger for POST requests.
- Send a sample archive job from PowerShell.
- Inspect the raw request envelope.
Add the Webhook trigger
The Webhook trigger starts the workflow when HTTP data reaches its URL. Its Test URL lets you capture one request directly in the editor.
- Select Add first step on the empty canvas.
- Enter Webhook in the node search field.
- Select Webhook from the search results.
- Set HTTP Method to POST.
- Set Path to archive-jobs.
- Select Test URL in the Webhook node.
- Confirm the displayed URL is http://localhost:5678/webhook-test/archive-jobs.
- Select Listen for test event.
The Webhook node now waits for a test request at the displayed URL.
Webhook Node Not Listening?
- Check that HTTP Method is set to POST.
- Check that Path contains archive-jobs.
- Select Listen for test event again if the listening period ended.
- Still stuck? Help me configure my n8n Webhook node for a test POST request.
Send the sample archive job
The request body uses a JSON object to describe one archive job. These five fields form the event contract used throughout the rest of the project.
- Return to the PowerShell window from the previous step.
Before you send the request, do you expect the five job fields to appear alone or inside a larger item? Hold that prediction as you run the request.
- Send the sample archive job to the listening Webhook node by running this code:
$uri = 'http://localhost:5678/webhook-test/archive-jobs'
$body = ConvertTo-Json @{
jobId = 'archive-001'
course = 'Machine Learning Foundations'
lesson = 'Week 1 - Introduction'
status = 'queued'
requestedAt = '2026-11-04T10:00:00Z'
}
Invoke-RestMethod -uri $uri -Method Post -body $body -ContentType 'application/json'
What Does This Request Do?
- The $uri variable stores the local Test URL.
- The $body variable holds the five archive-job values as JSON.
- ConvertTo-Json converts the PowerShell object into a JSON-formatted string.
- Invoke-RestMethod sends the request with the POST method.
- The application/json content type tells n8n how to interpret the request body.
- Return to the Webhook node in the n8n editor.
You should see a completed Webhook test with one output item. The five archive values sit inside body.
Request details also surround the body object. That noisy wrapper is the intended result.
Request Not Reaching n8n?
- Return to the Webhook node to confirm it is listening for a test event.
- Select Listen for test event again before rerunning the PowerShell request.
- Confirm that $uri contains http://localhost:5678/webhook-test/archive-jobs.
- Still stuck? Help me troubleshoot my local PowerShell request to the n8n Test URL.
Inspect the request envelope
Transport metadata describes how the request arrived. The body object carries the archive-job contract.
Before you inspect the full item, which sections do you expect to matter to a Discord alert? Keep your prediction in mind as you compare the output.
- Expand the entire Webhook output item.
- Inspect the headers section.
- Inspect the params section.
- Inspect the query section.
- Expand the body object.
Under body, you should see jobId set to archive-001. You should see course set to Machine Learning Foundations.
You should see lesson set to Week 1 - Introduction. You should see status set to queued.
You should see requestedAt set to 2026-11-04T10:00:00Z.
Outside body, you should see headers. You should also see params.
You should also see query. These outer sections belong to the HTTP request envelope.
You have captured the raw request structure that many automations hide. Next up, you will extract the five useful fields into a compact Discord-ready event.
Transform the Archive Job Data
Your n8n Webhook already receives the sample archive-job JSON from PowerShell. The useful values are still buried inside a larger request envelope.
Transport details such as headers, params, and query would make a Discord alert difficult to read. Edit Fields creates a small event containing the five business values plus one formatted message.
In this step, get ready to:
- Connect Edit Fields to the Webhook trigger.
- Extract the five archive-job values from the request body.
- Create a Discord-ready message with no transport metadata.
Map the archive-job fields
Manual Mapping gives each output value a stable field name. Each expression reads from $json.body because the Webhook placed the incoming business payload inside the request envelope's body object.
- Use the add-node control on the right edge of the Webhook node to add Edit Fields (Set).
- Choose Manual Mapping.
- Add a field named jobId with the value {{$json.body.jobId}}.
- Add a field named course with the value {{$json.body.course}}.
- Add a field named lesson with the value {{$json.body.lesson}}.
- Add a field named status with the value {{$json.body.status}}.
- Add a field named requestedAt with the value {{$json.body.requestedAt}}.
- Select Execute step to test the five mappings against the archive job from earlier.
You'll see five populated fields with values such as archive-001, Machine Learning Foundations, and queued. This proves the expressions can reach the business payload inside body.
Seeing Empty Field Values?
- Return to the Webhook output from earlier to confirm its body object still contains the sample archive job.
- Check that every expression starts with $json.body.
- Reselect Listen for test event if the previous test data is no longer available.
- Still stuck? Help me troubleshoot empty Edit Fields values in n8n.
Build the Discord-ready message
A single formatted string gives the next node everything it needs to send a readable notification. Line breaks keep each archive-job value scannable inside the final Discord message.
- Add a String field named discordMessage.
- Set the field value by pasting this expression:
{{ 'Archive job received\nJob: ' + $json.body.jobId + '\nCourse: ' + $json.body.course + '\nLesson: ' + $json.body.lesson + '\nStatus: ' + $json.body.status + '\nRequested: ' + $json.body.requestedAt }}
What Does This Expression Do?
- The opening text gives every queued notification the heading Archive job received.
- Each \n starts a new line in the finished message.
- Each $json.body expression inserts one value from the original archive-job payload.
- Enable Keep Only Set Fields to remove the unused request metadata.
Before you execute the node, consider whether headers, params, or query will remain in the output.
- Select Execute step to generate the final transformed event.
You'll see only jobId, course, lesson, status, requestedAt, and discordMessage. That is the noisy request envelope reduced to a clean event.
✔️ Awesome, I've got everything!
Great work. Your Edit Fields node now produces the exact event shape needed for the Discord notification.
ⓧ I'd like to double check the full code
Compare your Edit Fields configuration with this complete mapping.
- Confirm Edit Fields (Set) is connected directly after the Webhook node.
- Confirm the mapping mode is Manual Mapping.
- Confirm jobId is set to {{$json.body.jobId}}.
- Confirm course is set to {{$json.body.course}}.
- Confirm lesson is set to {{$json.body.lesson}}.
- Confirm status is set to {{$json.body.status}}.
- Confirm requestedAt is set to {{$json.body.requestedAt}}.
- Confirm discordMessage is set to {{ 'Archive job received\nJob: ' + $json.body.jobId + '\nCourse: ' + $json.body.course + '\nLesson: ' + $json.body.lesson + '\nStatus: ' + $json.body.status + '\nRequested: ' + $json.body.requestedAt }}.
- Confirm Keep Only Set Fields is enabled.
- Confirm the output contains only the five archive-job fields plus discordMessage.
Still Seeing Request Metadata?
- Check that Keep Only Set Fields is enabled in Edit Fields.
- Execute Edit Fields again after changing the setting.
- Make sure the message value is being evaluated as an expression instead of fixed text.
- Still stuck? Help me clean the output from my n8n Edit Fields node.
Your workflow now turns a raw HTTP request into a compact archive-job event. Next, you'll connect that event to Discord so each request becomes a channel notification.
Send the Alert to Discord
Your workflow now turns the raw request envelope into one clean archive-job event. The final missing piece is a visible destination for that event.
In this step, you'll create a channel destination in Discord. You'll protect its secret incoming webhook URL inside an n8n credential before testing the complete flow.
In this step, get ready to:
- Create the Discord destination for archive-job alerts.
- Store the webhook URL in an n8n credential.
- Send one formatted archive-job alert.
Create the Discord channel webhook
An incoming webhook grants permission to post messages into one selected Discord channel. This project uses that permission for one-way archive-job notifications.
Why a webhook instead of a bot?
An incoming webhook fits this one-way alert because the workflow only sends messages. A bot would add application setup plus permissions that this event flow does not need.
The built-in Discord node stores the webhook URL in a credential. A generic HTTP Request would expose more connection details on the canvas.
- In Discord, select Add a Server from the server list.
- Select Create My Own.
- Select For me and my friends.
- Enter Archive Automation Lab in the server name field.
- Select Create.
You now have a dedicated notification space for this automation. The selected text channel is where each archive-job update will land.
- Select Archive Automation Lab at the top of the channel list.
- Select Server Settings from the server menu.
- Select Integrations.
- Choose Create Webhook.
- Enter Archive Job Alerts in the webhook name field.
- Choose the text channel that should receive archive-job notifications.
Keep the Webhook URL Private
You only handle this sensitive URL once during the setup. It contains a secure token that can post into your channel.
You will paste the URL directly into n8n's credential form. This keeps it out of ordinary workflow fields.
- Select Copy Webhook URL.
Connect Discord to n8n
n8n credentials separate secrets from ordinary node fields. The Discord node can use the stored URL without exposing it in the message mapping.
- Switch back to the Archive Job to Discord workflow from earlier.
- Select the add-node control on the right side of Edit Fields.
- Enter Discord in the node search field.
- Select Discord from the results.
- Set Connection Type to Webhook.
The Discord node now expects a credential containing the incoming channel webhook URL.
- Use the credential selector to create a Discord Webhook credential.
- Paste the copied URL into Webhook URL.
- Save the credential.
The sensitive connection is now stored in one reusable credential. Your workflow fields stay focused on message data.
- Confirm Discord Webhook is selected in the credential selector.
- Keep Send a Message as the operation.
- Set Message to {{$json.discordMessage}}.
Send the test alert
A fresh test event proves the entire chain works from the trigger to the selected Discord channel. The request must enter while the Webhook node is listening.
- Return to the Webhook node.
- Select Listen for test event.
- Return to the PowerShell session from earlier.
Before you send the request, do you expect Discord to receive the raw envelope or the clean message from Edit Fields?
- Send the saved archive-job payload to the Test URL by running:
Invoke-RestMethod -uri $uri -Method Post -body $body -ContentType 'application/json'
What Does This Command Do?
The command sends the saved $body to the Test URL stored in $uri as JSON.
The Webhook receives the event. Edit Fields reshapes it before the Discord node posts discordMessage to your channel.
- Return to the selected text channel in Archive Automation Lab.
What Should I See?
- The first line says Archive job received.
- The Job: line shows archive-001.
- The Course: line shows Machine Learning Foundations.
- The Lesson: line shows Week 1 - Introduction.
- The Status: line shows queued.
- The Requested: line shows 2026-11-04T10:00:00Z.
You now have a complete test path from PowerShell to a readable Discord notification.
No Message in Discord?
- Select Listen for test event again if the Webhook node stopped waiting.
- Confirm Discord Webhook remains selected in the Discord node.
- Check that Message contains {{$json.discordMessage}}.
- Still stuck? Help me troubleshoot my n8n Discord webhook test..
Your test alert now travels through all three nodes successfully. Next up, you'll publish the workflow so its Production URL can accept repeat requests.
Publish the Production Webhook
Your transformed archive event already reaches Discord through the webhook's Test URL. That proves the workflow logic works.
The Test URL is temporary because it serves editor testing. Publishing in n8n registers the Production URL for repeatable local calls.
PowerShell can then send archive jobs through the published workflow. The resulting production execution gives you evidence that the full automation works.
In this step, get ready to:
- Copy the webhook's Production URL into PowerShell.
- Publish the current workflow version.
- Send the archive job through the production endpoint.
Copy the Production URL
The Production URL is the stable local endpoint for published versions of your workflow. It keeps the same archive-jobs path that you configured earlier.
- In the workflow canvas from earlier, select the Webhook node.
- Select Production URL above the URL field.
You'll see http://localhost:5678/webhook/archive-jobs. This URL uses the published webhook path.
- Copy the displayed Production URL.
- Switch back to PowerShell from earlier.
- Store the Production URL in $uri by running the commands below:
$uri = 'http://localhost:5678/webhook/archive-jobs'
$uri
What does this PowerShell do?
- The first line stores the Production URL in $uri for the request you send later.
- The second line prints the stored value so you can catch a copied URL mistake before publishing.
PowerShell prints http://localhost:5678/webhook/archive-jobs. This confirms your next request targets the production endpoint.
Publish the workflow
Publishing makes the current draft available through the Production URL. The registered endpoint works while your local n8n stack is running.
- Select Publish in the canvas header.
- Select Publish in the publishing modal.
The workflow status changes to published. That is the publishing hurdle cleared.
Published state not appearing?
- Wait for n8n's draft autosave to finish before selecting Publish again.
- Confirm Docker Desktop is still running if the editor loses its local connection.
- Still stuck? Help me publish my local n8n workflow.
Run the production request
The published endpoint accepts the same archive-job payload that worked during testing. The Executions tab records the production run.
Before you send the request, do you think the published workflow will produce the same Discord message as the Test URL?
- Send the archive-001 queued payload through the Production URL by running:
$body = ConvertTo-Json @{
jobId = 'archive-001'
course = 'Machine Learning Foundations'
lesson = 'Week 1 - Introduction'
status = 'queued'
requestedAt = '2026-11-04T10:00:00Z'
}
Invoke-RestMethod -uri $uri -Method Post -body $body -ContentType 'application/json'
What does this request send?
- The ConvertTo-Json command converts the archive-job values into a JSON request body.
- The payload preserves the job ID, course, lesson, status, and request time used during testing.
- The Invoke-RestMethod command sends an HTTP POST request to the Production URL stored in $uri.
- Switch back to the selected Discord text channel in Archive Automation Lab.
The newest message begins with Archive job received. It shows job ID archive-001 with status queued.
The course line shows Machine Learning Foundations. The lesson line shows Week 1 - Introduction.
The requested time shows 2026-11-04T10:00:00Z. The complete notification confirms the transformation still works in production.
- Return to the Archive Job to Discord workflow from earlier.
- Select the Executions tab.
You'll see a successful production execution for the request you just sent. This proves the Production URL reached the published workflow.
- Select the newest execution to inspect the processed run.
The execution shows the Webhook, Edit Fields, and Discord nodes completing the production path. Your archive-job data has travelled through the full workflow.
Production URL not responding?
- Check that $uri contains http://localhost:5678/webhook/archive-jobs.
- Confirm the workflow still shows its published state before sending another request.
- Still stuck? Help me trace my production webhook request.
You have the complete production loop working now. Your published workflow turns local archive events into visible Discord notifications.
Secret mission
Make Failed Jobs Stand Out
Give failed archive jobs a heading that catches your attention in Discord. You will add one conditional expression, publish the update, and prove that failed and queued events still follow the correct paths.
Clean Up Your Resources
Clean Up Your Resources
The resources created in this project add no ongoing cost. Use the options below to keep, pause, or delete the automation.
Resources you used:
- The published n8n workflow Archive Job to Discord.
- The n8n credential Discord Webhook containing the secret incoming webhook URL.
- The incoming Discord channel webhook configured for archive-job notifications.
- The Discord server Archive Automation Lab, which contains the selected text channel.
Keep everything running
No action is needed. Choose this option if you plan to continue with Project 3 or send more archive-job notifications.
- Leave Archive Job to Discord published.
- Keep the local n8n stack running whenever you want http://localhost:5678/webhook/archive-jobs to accept requests.
- Retain the Discord Webhook credential in n8n.
- Retain the incoming Discord channel webhook.
- Retain the Archive Automation Lab server.
Pause - I'll come back to this later
Pausing blocks new production requests from reaching the workflow. Your saved resources remain ready for later.
- Use the publishing controls in the canvas header to unpublish Archive Job to Discord.
- Confirm the canvas shows that the workflow is no longer published.
- Stop the local n8n stack with the same method you used in Project 1.
Your n8n resources remain stored for later. Your Discord resources also remain in place.
Delete - I don't want to use this again
Deleting these items is permanent. Your local n8n lab from Project 1 stays available.
Remove the n8n resources:
- Use the workflow options menu to delete Archive Job to Discord.
- Return to Personal to check the workflow list.
- Confirm that Archive Job to Discord no longer appears.
- Open Discord Webhook from the credentials list in Personal.
- Use the credential options menu to delete Discord Webhook.
- Return to the credentials list to check the saved credentials.
- Confirm that Discord Webhook no longer appears.
Remove the incoming Discord webhook:
- Switch back to Archive Automation Lab in Discord.
- Open Server Settings to manage the server resources.
- Select Integrations to find the incoming channel webhook.
- Select the webhook configured for archive-job notifications.
- Use the webhook deletion control to remove it.
- Confirm that the webhook no longer appears under Integrations.
Remove the test Discord server:
- Return to Server Settings to find the server deletion control.
- Use the server deletion control to delete Archive Automation Lab.
- Confirm that Archive Automation Lab no longer appears in your Discord server list.
Nice Work!
Nice Work!
You did it! Your published n8n automation accepts archive-job JSON through a local production webhook. Each request becomes a focused Discord alert with a clear status heading.
You've learned how to:
- Receive realistic archive-job data through a published POST endpoint that stays available while your local n8n stack runs.
- Turn a noisy HTTP request envelope into a stable event with Edit Fields and n8n expressions.
- Send credential-backed Discord notifications that show every archive-job value in one readable message.
- Complete the optional Secret Mission by giving failed jobs the conditional ARCHIVE JOB FAILED heading.
Ready to quiz yourself?