open source · single binary · zero dependencies

sendword

Webhooks that run commands.
Receive. Validate. Execute.

Get StartedView Source
incoming webhook
curl -X POST https://your-server/hook/deploy \
  -H "Authorization: Bearer $TOKEN" \
  -d '{"repo": "myapp", "branch": "main"}'
sendword executes
cd /app && git pull origin { branch }
docker compose up -d
echo "deployed { repo } on { branch }"

What it does

Webhook Authentication

Bearer tokens, HMAC-SHA256 signature verification, or open access. Secrets can reference environment variables. Constant-time comparison prevents timing attacks.

Payload Validation

Define a JSON schema per hook. Sendword validates every incoming request and rejects malformed payloads before your command ever runs.

Trigger Rules

Filter by payload fields (equals, regex, contains), restrict to time windows, enforce cooldowns, and apply rate limits — all before execution begins.

Three Executors

Run shell commands with payload interpolation, execute managed scripts, or forward to HTTP endpoints. Each hook picks one, with per-hook timeout and working directory.

Retries & Backoff

Automatic retries on failure with none, linear, or exponential backoff strategies. Configurable per hook or globally, with max delay caps.

Barriers & Approval

Mutex or queue-based concurrency control prevents resource exhaustion. Optional approval workflows let you gate production deployments behind a human review.

Log Masking

Mask environment variable values and regex patterns in execution logs. Sensitive data never appears in the web UI or log files.

Backup & Restore

Snapshot your database and config to S3-compatible storage on a cron schedule. Restore with a single command. Retention policies keep storage tidy.

How it works

01

Configure a hook

[[hooks]]
name = "Deploy"
slug = "deploy"

[hooks.executor]
type = "shell"
command = "bash deploy.sh { branch }"

[hooks.auth]
mode = "bearer"
token = "${DEPLOY_TOKEN}"
02

Add rules & guards

[hooks.trigger_rules]
cooldown = "5m"

[[hooks.trigger_rules.payload_filters]]
field = "branch"
operator = "regex"
value = "^(main|release/.*)"

[hooks.concurrency]
mode = "queue"
queue_depth = 5
03

Run sendword

$ sendword serve
listening on 127.0.0.1:8080

# hooks available:
#   POST /hook/deploy
#   POST /hook/notify
#   POST /hook/sync

# dashboard at /

One file. Full control.

Everything lives in sendword.toml. Export as JSON, import it on another machine, version-control the whole thing.

[server]
bind = "0.0.0.0"
port = 8080

[defaults.timeout]
timeout = "30s"

[defaults.retries]
count = 3
backoff = "exponential"
initial_delay = "2s"
max_delay = "60s"

[masking]
env_vars = ["API_KEY", "DB_PASSWORD"]
patterns = ["(token)[=:]\\s*\\S+"]

[backup]
bucket = "my-backups"
schedule = "0 2 * * *"
retention.max_count = 30
cargo install sendword

Read the quickstart guide →