Script Webhooks
Turn any script into a secure HTTP endpoint. Trigger scripts from GitHub, monitoring services, or any external system with token auth, IP allowlists, and HMAC signatures.
Script Webhooks
A Script Webhook exposes one of your saved scripts as an HTTP endpoint. Any system that can send an HTTP request — GitHub Actions, alerting providers, chat bots, cron on another machine — can then trigger the script to run on your server. Every webhook is tied to a specific script on a specific server, and Devpilot issues a long random token that the caller must present before the script will run.
Webhooks pair naturally with other Devpilot automation:
- Kick off a Script Workflow when your CI finishes a build.
- Run a remediation script when your monitoring provider posts an alert.
- Trigger a daily job from an external cron runner or a chat slash command.
A webhook runs the script with its current saved content. If you edit the script and save, the next webhook call picks up the new version automatically. See Script Versions for the full history.
What Devpilot Tracks For You
When you create a webhook, Devpilot generates a 64-character token that you embed in calls from your external system — treat it like a password. You can give the webhook a descriptive name so you can tell multiple webhooks apart (for example "Deploy from GitHub" versus "Slack /restart command"), and there's an Active toggle so you can pause a webhook without deleting it. Paused webhooks reject calls with a 404 until you re-enable them.
For extra protection, you can add an Allowed IPs list to restrict which source addresses can reach the webhook, and an HMAC secret so each caller has to sign its request body. Either setting is optional and you can add or remove them later — except the token and the HMAC secret, which are set once and can only be rotated by creating a new webhook.
The detail page shows the total number of successful calls and the timestamp of the most recent valid call, so you can verify your external system is connected and firing when you expect.
Creating a Webhook
Open the Webhooks tab
On the script's detail page, switch to the Webhooks tab and click Create.
Name it
Give it a descriptive name so you can tell multiple webhooks apart later.
Optionally restrict by IP
Provide one or more IP addresses in the Allowed IPs field (comma-separated). Devpilot rejects requests from any source that isn't on the list. Leave it empty to accept calls from any IP.
Optionally add an HMAC secret
If the caller can sign requests, supply an HMAC secret. Every subsequent call must include a matching signature header or Devpilot will reject it.
Copy the token
Once created, copy the token from the webhook row. You'll include it in every request you make. Devpilot also exposes a curl snippet so you can copy a ready-made example.
Triggering the Webhook
Script webhooks flow through a single shared webhook endpoint. Your external system sends a POST request with the webhook's token in the JSON body, and Devpilot queues the script on the target server.
Consumer-facing payload:
POST /api/v1/webhooks/script_execute
Content-Type: application/json
{
"token": "<the 64-character token from the webhook record>"
}Devpilot runs the script in streaming mode on the target server. You can watch the output live from the script's Executions tab, and each webhook-triggered run is tagged as such in the history.
Signed Requests
If you configured an HMAC secret on the webhook, every request must include a SHA-256 HMAC of the raw request body in the X-Webhook-Signature header. Devpilot recomputes the expected signature with the stored secret and rejects any request where the header is missing or doesn't match — the comparison is constant-time so the signature check itself doesn't leak information.
BODY='{"token":"YOUR_TOKEN"}'
SIG=$(printf '%s' "$BODY" | openssl dgst -sha256 -hmac "$WEBHOOK_SECRET" | awk '{print $2}')
curl -X POST https://app.devpilot.africa/api/v1/webhooks/script_execute \
-H "Content-Type: application/json" \
-H "X-Webhook-Signature: $SIG" \
-d "$BODY"const crypto = require('crypto');
const body = JSON.stringify({ token: process.env.WEBHOOK_TOKEN });
const sig = crypto
.createHmac('sha256', process.env.WEBHOOK_SECRET)
.update(body)
.digest('hex');
await fetch('https://app.devpilot.africa/api/v1/webhooks/script_execute', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Webhook-Signature': sig,
},
body,
});import hmac, hashlib, os, requests, json
body = json.dumps({"token": os.environ["WEBHOOK_TOKEN"]})
sig = hmac.new(
os.environ["WEBHOOK_SECRET"].encode(),
body.encode(),
hashlib.sha256,
).hexdigest()
requests.post(
"https://app.devpilot.africa/api/v1/webhooks/script_execute",
data=body,
headers={
"Content-Type": "application/json",
"X-Webhook-Signature": sig,
},
)How Devpilot Handles a Call
For every incoming request, Devpilot:
- Confirms the body includes a token. Missing tokens are rejected up front.
- Looks up an active webhook matching that token. No match or an inactive webhook means the call is rejected.
- If you set an IP allowlist, checks the caller's IP against it and rejects anything that isn't listed.
- If you set an HMAC secret, verifies the signature header against the raw body. Missing or mismatched signatures are rejected.
- Updates the webhook's call counter and last-triggered timestamp so you can see activity in the UI.
- Starts the script in streaming mode on the target server.
The execution itself appears in the script's regular execution history, tagged so you know the run came from a webhook.
Managing Webhooks
You can edit the webhook's name, active state, and allowed IPs at any time. The token and HMAC secret are set once and can't be changed in place — to rotate either of them, delete the webhook and create a new one, then share the new token with whatever was calling the old one.
Flipping the Active toggle off is the fastest way to pause a webhook without losing its history.
Common Integrations
- GitHub / GitLab / Bitbucket — Trigger deploys, cache busts, or smoke tests on push, release, or pipeline events. Set up a webhook in your repo settings pointing at the Devpilot endpoint with the JSON body above.
- Monitoring and alerting — Have your alert provider POST to the endpoint when an incident fires. The script can gather diagnostics, restart a service, or open a ticket.
- External cron — Use a curl job from any machine to hit the webhook on a schedule. Useful when the built-in scheduler doesn't fit.
- Chat integrations — Expose "run script" slash commands by wiring your chat bot to call the webhook with the token in the body.
Security Best Practices
The token is the primary credential. Anyone who knows it can run the script. Treat it like a password:
- Store it in the calling system's secret manager, never in version-controlled config.
- Add an IP allowlist when the caller runs from known addresses.
- Add an HMAC secret when the caller supports request signing — that way a leaked token alone isn't enough to call the endpoint.
- Rotate by deleting and recreating the webhook if you suspect a leak.
Troubleshooting
| Problem | Likely cause |
|---|---|
| "Invalid or inactive webhook token" | Token is wrong, or the webhook was deactivated or deleted. |
| "IP not allowed" | Caller's IP isn't on the allowlist. Add it or remove the list. |
| "Invalid HMAC signature" | Signature header missing, stale secret, or body was altered. |
| Validation error on submit | The JSON body doesn't contain a token. |
| Script starts but fails immediately | Check the script's execution history — the webhook is fine. |
Next Steps
Scripts and Automation
Review the basics of writing, saving, and running the underlying scripts.
Script Workflows
Use a webhook to kick off a whole sequence of scripts with branching.
Script Triggers
Run scripts from metric thresholds instead of external HTTP calls.
Script Secrets
Keep API keys and tokens used inside webhook-triggered scripts out of the script body.