Webhooks
The local webhook receiver: addresses, authentication, payloads, limits, responses, and starting Murage tasks from n8n, Zapier and other tools.
A webhook lets another tool start a task for one of your bots. Each accepted request becomes a new task in that bot's chat. Use it when something happens elsewhere, such as a failed build or a new form entry, and you want a bot to act on it.
For the short version, see Routines and webhooks.
The receiver
Webhooks arrive at a small receiver that runs only on your own computer:
- Address:
http://127.0.0.1:8800 - It listens on your computer only. Nothing on your network or the internet can reach it unless you add a tunnel.
- It answers only two things: a health check and your webhook addresses. It doesn't expose the rest of Murage.
- It runs only while Murage is running. Close Murage and requests fail.
The receiver uses the port one above Murage's own. If Murage had to start on a fallback port (see Startup and ports), the receiver moves with it, to 18800 or 28800. The command Murage copies for you always has the right address.
The top of the Webhooks screen shows Receiver running when it's ready, or Receiver unavailable (or the reason) when it isn't.
To check it by hand:
curl -sS http://127.0.0.1:8800/health
It answers {"app":"murage-webhooks","ready":true}.
Create a webhook
Webhooks are managed in the desktop app only, not from a paired phone.
- Choose Routines in the sidebar, then Webhooks at the top.
- Choose New webhook (or Create local webhook if you have none yet).
- Under Who receives the tasks?, pick the bot.
- Optionally open Advanced options:
- Name: up to 80 characters. Murage suggests one if you leave it empty.
- Default instructions: one handling rule for every event. Leave it empty to use the task sent in each request.
- Run on: This computer.
- Only accept event types: a comma-separated list, up to 20, matched against the sender's event-type header.
- Choose Create local webhook.
- Under Setup, choose Copy command. This copies a ready-to-run
curlcommand with your webhook's private URL.
A new webhook is switched on straight away. Use Pause and Enable to stop and restart it, Edit settings to change it, and Delete to remove it. Deleting keeps the task history. If you delete the bot, its webhooks are paused.
The private URL is shown once. If you lose it, choose Generate new private URL (or Rotate private URL). The old URL and any command you copied before stop working.
Addresses and authentication
Each webhook has an ID that starts with wh_ and a secret that starts with whsec_. You can send the secret in one of two ways.
Private URL. The secret is the last part of the address. Use this when the sending tool can't set headers:
POST http://127.0.0.1:8800/hooks/wh_XXXX/whsec_YYYY
Bearer token. Leave the secret off the address and send it in a header. This keeps it out of URLs and most logs, so prefer it when the tool supports headers:
POST http://127.0.0.1:8800/hooks/wh_XXXX Authorization: Bearer whsec_YYYY
An X-Murage-Secret: whsec_YYYY header works too.
Murage stores only a fingerprint of the secret, never the secret itself. Anyone who has the private URL or secret can start tasks for that bot, so treat it like a password.
Example request
The command Murage copies looks like this:
curl -sS 'http://127.0.0.1:8800/hooks/wh_XXXX/whsec_YYYY' \
--json '{"task":"A customer wrote: This app saved me hours. Write a short thank-you reply."}'
--json needs curl 7.82 or later. The same request with a bearer token and older curl:
curl -sS http://127.0.0.1:8800/hooks/wh_XXXX \
-H 'Authorization: Bearer whsec_YYYY' \
-H 'Content-Type: application/json' \
-d '{"task":"Check the failed build"}'
What the bot is asked to do
Only POST requests are accepted. Murage reads the body by its content type:
- JSON (
application/json, or any+jsontype) is parsed. Invalid JSON is refused. - Form data (
application/x-www-form-urlencoded) becomes a set of fields. - Anything else is passed along as plain text.
The task comes from one place, in this order:
- The webhook's Default instructions, if you set them.
- Otherwise, a
taskfield in the JSON body, or amessagefield if there's notask. - Otherwise, a built-in instruction: review the event, summarize what happened, and take no outside action unless the event clearly needs it and the bot's permissions allow it.
The whole request is also handed to the bot, marked as untrusted event data along with the time, the event type and the sender. The bot keeps its own model, tools, permissions and computer setup.
How the task runs
- Each accepted request starts a new task in the chosen bot's chat. Open it from Recent deliveries with Open chat.
- If the bot is busy, the task waits its turn.
- Webhook tasks are judged as Auto for approvals, even if the bot is on Full access or No limits, because someone other than you wrote the input. They also skip your Always allow grants, so those actions wait for your approval. See Permissions and the stop line.
- If you've paused automatic work, new deliveries are refused until you resume it.
Recent deliveries shows each request as Accepted, Duplicate, Ignored or Rejected, with a preview.
Limits
- Request body: up to 256 KB.
- Event data given to the bot: up to 48,000 characters. Longer data is cut off with a note.
- Task text and Default instructions: up to 20,000 characters.
- Rate: 10 new tasks per minute for each webhook.
- Queue: 3 unfinished tasks for each webhook. Wait for one to finish before sending more.
Duplicates and event types
If the sender includes a delivery ID in an Idempotency-Key, X-Webhook-Id, X-GitHub-Delivery or Webhook-Id header, a repeat of the same ID doesn't start a second task. Murage answers with the first task instead.
Only accept event types is checked against the X-GitHub-Event, X-Webhook-Event, X-Event-Type or ce-type header. Other events are marked Ignored and start nothing.
Responses
A 202 means accepted (including duplicates and ignored events), with "accepted": true and a deliveryId in the body. Errors: 400 unreadable body or invalid JSON, 401 wrong address or secret, 404 not a webhook address, 405 not a POST, 409 webhook or automatic work paused, 410 the bot no longer exists, 413 body over 256 KB, 429 over the rate limit or 3 tasks already unfinished.
n8n and Zapier
n8n and Zapier can start a Murage task through a webhook today. Use an HTTP request step that sends a POST to your webhook address with a JSON body containing task, and your secret in an Authorization: Bearer header.
- n8n running on the same computer as Murage can send straight to
http://127.0.0.1:8800. - Zapier, n8n Cloud and other cloud services can't reach
127.0.0.1. They need a tunnel (see below).
To go the other way and have bots run n8n workflows or Zaps, add the n8n or Zapier MCP server. See MCP. Deeper built-in n8n support is coming.
Tunnels
To receive events from the internet, run your own tunnel, such as Cloudflare Tunnel or ngrok, and point it only at the webhook receiver's address (127.0.0.1:8800). Then give the sending service the tunnel's public address followed by /hooks/wh_..., and use a bearer token.
Never point a tunnel at Murage's main port (8799). That port is the whole app, not just webhooks.
Troubleshooting
- Receiver unavailable: another program may be using the port. Quit it, or quit and reopen Murage.
- Connection refused: Murage isn't running, or the sender isn't on this computer and has no tunnel.
- 401: the secret was rotated. Copy the new command.
- Nothing happens in chat: Recent deliveries shows the reason.