Appearance
Webhook Triggers
Any task can be triggered via an HTTP POST to a unique webhook URL. This lets external systems — GitHub Actions, monitoring tools, other APIs — fire a task on demand without needing an ApiMeld account.
Setting up a webhook trigger
- Open a task — the Webhook Trigger section is in the right column of the edit form
- Toggle Enable Webhook on
- Optionally enter a Shared Secret (recommended — see below)
- Save the task — the webhook URL is then displayed with a copy button:
https://tasks.example.com/api/webhook/a1b2c3d4-e5f6-7890-abcd-ef1234567890
The GUID in the URL is unique to this task. Anyone with this URL can trigger the task, so treat it like a secret.
Triggering a task
Send an HTTP POST to the webhook URL. No authentication header is required — the GUID in the URL serves as the token.
bash
curl -X POST https://tasks.example.com/api/webhook/a1b2c3d4-e5f6-7890-abcd-ef1234567890With a payload:
bash
curl -X POST \
-H "Content-Type: application/json" \
-d '{"event": "deploy", "version": "1.2.3", "environment": "production"}' \
https://tasks.example.com/api/webhook/a1b2c3d4-e5f6-7890-abcd-ef1234567890The response is immediate — ApiMeld queues the task and returns 202 Accepted. The task runs asynchronously.
Accessing the payload in scripts
When a webhook fires a task, ApiMeld injects a $webhook (PowerShell) or webhook (JavaScript/TypeScript/Python) object containing the request details.
| Property | Description |
|---|---|
Body / body | Raw request body string (JSON, form data, etc.) |
Params / params | Query string parameters as a key/value object |
Headers / headers | Request headers as a key/value object |
TriggeredAt / triggeredAt | ISO 8601 timestamp of when the webhook was received |
PowerShell:
powershell
if ($webhook.Body) {
$data = $webhook.Body | ConvertFrom-Json
$logger.Info("Deploy version: $($data.version) to $($data.environment)")
}JavaScript:
javascript
if (webhook.body) {
const data = JSON.parse(webhook.body)
logger.info(`Deploy version: ${data.version} to ${data.environment}`)
}TypeScript:
typescript
if (webhook.body) {
const data = JSON.parse(webhook.body) as { version: string; environment: string }
logger.info(`Deploy version: ${data.version} to ${data.environment}`)
}Python:
python
import json
if webhook_body:
data = json.loads(webhook_body)
print(f"Deploy version: {data['version']} to {data['environment']}")Bash:
bash
if [ -n "$WEBHOOK_BODY" ]; then
version=$(echo "$WEBHOOK_BODY" | jq -r '.version')
echo "Deploy version: $version"
fiC#:
csharp
if (!string.IsNullOrEmpty(WebhookBody))
{
var data = JsonSerializer.Deserialize<JsonElement>(WebhookBody);
Logger.Info($"Deploy version: {data.GetProperty("version").GetString()}");
}Python variable names
| Variable | Content |
|---|---|
webhook_body | Request body string |
webhook_params | Query params dict |
webhook_headers | Request headers dict |
webhook_triggered_at | Timestamp string |
Bash variable names
| Variable | Content |
|---|---|
$WEBHOOK_BODY | Request body string |
$WEBHOOK_TRIGGERED_AT | Timestamp string |
Use cases
- GitHub Actions: trigger a deployment task after a successful build
- Monitoring: trigger an alert-response task when Grafana fires an alert
- External schedulers: trigger ApiMeld tasks from an existing scheduler you're migrating away from
- IoT / edge devices: trigger a data ingestion task when a device reports in
Shared Secret
A shared secret adds a second layer of protection on top of the GUID URL. When set, every request must include the secret in the X-Webhook-Secret header — requests without it or with the wrong value are rejected with 404 (not 401, to avoid confirming that the GUID is valid).
Set the shared secret when creating or editing the webhook trigger. Store it alongside the webhook URL in your calling system.
bash
# Trigger with a shared secret
curl -X POST \
-H "X-Webhook-Secret: your-shared-secret" \
https://tasks.example.com/api/webhook/a1b2c3d4-e5f6-7890-abcd-ef1234567890With a payload:
bash
curl -X POST \
-H "X-Webhook-Secret: your-shared-secret" \
-H "Content-Type: application/json" \
-d '{"event": "deploy", "version": "1.2.3"}' \
https://tasks.example.com/api/webhook/a1b2c3d4-e5f6-7890-abcd-ef1234567890GitHub Actions example:
yaml
- name: Trigger ApiMeld task
run: |
curl -X POST \
-H "X-Webhook-Secret: ${{ secrets.APIMELD_WEBHOOK_SECRET }}" \
-H "Content-Type: application/json" \
-d "{\"ref\": \"${{ github.ref }}\", \"sha\": \"${{ github.sha }}\"}" \
https://tasks.example.com/api/webhook/a1b2c3d4-e5f6-7890-abcd-ef1234567890TIP
Use a long random string as the shared secret — at least 32 characters. You can generate one with openssl rand -hex 32.
Rotating the webhook URL
If your webhook URL is compromised, disable and re-enable the webhook trigger on the task — a new GUID is generated and the old URL stops working.
Combining with a cron schedule
A task can have both a cron schedule and a webhook trigger active simultaneously. The task runs on its schedule and can also be fired on demand via the webhook.