Configure OpenClaw Webhooks: Secure HTTP Integration Guide
Ever felt like your automation tools are stuck in a silo? You want your system to react to external events—like a new email or a GitHub ping—but setting up a complex listener often feels like overkill. Webhooks are the bridge you need to make your gateway truly reactive.
Gateway can expose a small HTTP webhook endpoint for external triggers, allowing you to connect your existing workflows directly to your agents.
Enable
Section titled “Enable”To get started, you need to flip a switch in your configuration. You can define the path and set up an allowlist for specific agents.
{ hooks: { enabled: true, token: "shared-secret", path: "/hooks", // Optional: restrict explicit `agentId` routing to this allowlist. // Omit or include "*" to allow any agent. // Set [] to deny all explicit `agentId` routing. allowedAgentIds: ["hooks", "main"], },}Notes:
hooks.tokenis required whenhooks.enabled=true.hooks.pathdefaults to/hooks.
Security is a priority here, so every request must include your hook token. You should prefer using headers for this:
Authorization: Bearer <token>(recommended)x-openclaw-token: <token>- Query-string tokens are rejected (
?token=...returns400). - Treat
hooks.tokenholders as full-trust callers for the hook ingress surface on that gateway. Hook payload content is still untrusted, but this is not a separate non-owner auth boundary.
Endpoints
Section titled “Endpoints”POST /hooks/wake
Section titled “POST /hooks/wake”Use this endpoint when you just need to nudge the system or signal that something happened.
Payload:
{ "text": "System line", "mode": "now" }textrequired (string): The description of the event (e.g., “New email received”).modeoptional (now|next-heartbeat): Whether to trigger an immediate heartbeat (defaultnow) or wait for the next periodic check.
Effect:
- Enqueues a system event for the main session
- If
mode=now, triggers an immediate heartbeat
POST /hooks/agent
Section titled “POST /hooks/agent”This endpoint is for more complex tasks where you want an agent to process the incoming data.
Payload:
{ "message": "Run this", "name": "Email", "agentId": "hooks", "sessionKey": "hook:email:msg-123", "wakeMode": "now", "deliver": true, "channel": "last", "to": "+15551234567", "model": "openai/gpt-5.2-mini", "thinking": "low", "timeoutSeconds": 120}messagerequired (string): The prompt or message for the agent to process.nameoptional (string): Human-readable name for the hook (e.g., “GitHub”), used as a prefix in session summaries.agentIdoptional (string): Route this hook to a specific agent. Unknown IDs fall back to the default agent. When set, the hook runs using the resolved agent’s workspace and configuration.sessionKeyoptional (string): The key used to identify the agent’s session. By default this field is rejected unlesshooks.allowRequestSessionKey=true.wakeModeoptional (now|next-heartbeat): Whether to trigger an immediate heartbeat (defaultnow) or wait for the next periodic check.deliveroptional (boolean): Iftrue, the agent’s response will be sent to the messaging channel. Defaults totrue. Responses that are only heartbeat acknowledgments are automatically skipped.channeloptional (string): The messaging channel for delivery. Uselastor any configured channel or plugin id, for examplediscord,matrix,telegram, orwhatsapp. Defaults tolast.tooptional (string): The recipient identifier for the channel (e.g., phone number for WhatsApp/Signal, chat ID for Telegram, channel ID for Discord/Slack/Mattermost (plugin), conversation ID for Microsoft Teams). Defaults to the last recipient in the main session.modeloptional (string): Model override (e.g.,anthropic/claude-sonnet-4-6or an alias). Must be in the allowed model list if restricted.thinkingoptional (string): Thinking level override (e.g.,low,medium,high).timeoutSecondsoptional (number): Maximum duration for the agent run in seconds.
Effect:
- Runs an isolated agent turn (own session key)
- Always posts a summary into the main session
- If
wakeMode=now, triggers an immediate heartbeat
Session key policy (breaking change)
Section titled “Session key policy (breaking change)”Heads up: /hooks/agent payload sessionKey overrides are disabled by default now.
- Recommended: set a fixed
hooks.defaultSessionKeyand keep request overrides off. - Optional: allow request overrides only when needed, and restrict prefixes.
Recommended config:
{ hooks: { enabled: true, token: "${OPENCLAW_HOOKS_TOKEN}", defaultSessionKey: "hook:ingress", allowRequestSessionKey: false, allowedSessionKeyPrefixes: ["hook:"], },}Compatibility config (legacy behavior):
{ hooks: { enabled: true, token: "${OPENCLAW_HOOKS_TOKEN}", allowRequestSessionKey: true, allowedSessionKeyPrefixes: ["hook:"], // strongly recommended },}POST /hooks/<name> (mapped)
Section titled “POST /hooks/<name> (mapped)”Custom hook names are resolved via hooks.mappings. A mapping can turn arbitrary payloads into wake or agent actions, with optional templates or code transforms.
Mapping options (summary):
hooks.presets: ["gmail"]enables the built-in Gmail mapping.hooks.mappingslets you definematch,action, and templates in config.hooks.transformsDir+transform.moduleloads a JS/TS module for custom logic.hooks.transformsDir(if set) must stay within the transforms root under your OpenClaw config directory (typically~/.openclaw/hooks/transforms).transform.modulemust resolve within the effective transforms directory (traversal/escape paths are rejected).
- Use
match.sourceto keep a generic ingest endpoint (payload-driven routing). - TS transforms require a TS loader (e.g.
bunortsx) or precompiled.jsat runtime. - Set
deliver: true+channel/toon mappings to route replies to a chat surface (channeldefaults tolastand falls back to WhatsApp). agentIdroutes the hook to a specific agent; unknown IDs fall back to the default agent.hooks.allowedAgentIdsrestricts explicitagentIdrouting. Omit it (or include*) to allow any agent. Set[]to deny explicitagentIdrouting.hooks.defaultSessionKeysets the default session for hook agent runs when no explicit key is provided.hooks.allowRequestSessionKeycontrols whether/hooks/agentpayloads may setsessionKey(default:false).hooks.allowedSessionKeyPrefixesoptionally restricts explicitsessionKeyvalues from request payloads and mappings.allowUnsafeExternalContent: truedisables the external content safety wrapper for that hook (dangerous; only for trusted internal sources).openclaw webhooks gmail setupwriteshooks.gmailconfig foropenclaw webhooks gmail run. See Gmail Pub/Sub for the full Gmail watch flow.
Responses
Section titled “Responses”Here is what you can expect back from the server after sending a request:
200for/hooks/wake200for/hooks/agent(async run accepted)401on auth failure429after repeated auth failures from the same client (checkRetry-After)400on invalid payload413on oversized payloads
Examples
Section titled “Examples”You can test your setup using these curl commands.
curl -X POST http://127.0.0.1:18789/hooks/wake \ -H 'Authorization: Bearer SECRET' \ -H 'Content-Type: application/json' \ -d '{"text":"New email received","mode":"now"}'curl -X POST http://127.0.0.1:18789/hooks/agent \ -H 'x-openclaw-token: SECRET' \ -H 'Content-Type: application/json' \ -d '{"message":"Summarize inbox","name":"Email","wakeMode":"next-heartbeat"}'Use a different model
Section titled “Use a different model”Add model to the agent payload (or mapping) to override the model for that specific run:
curl -X POST http://127.0.0.1:18789/hooks/agent \ -H 'x-openclaw-token: SECRET' \ -H 'Content-Type: application/json' \ -d '{"message":"Summarize inbox","name":"Email","model":"openai/gpt-5.2-mini"}'If you enforce agents.defaults.models, make sure the override model is included there.
curl -X POST http://127.0.0.1:18789/hooks/gmail \ -H 'Authorization: Bearer SECRET' \ -H 'Content-Type: application/json' \ -d '{"source":"gmail","messages":[{"from":"Ada","subject":"Hello","snippet":"Hi"}]}'Security
Section titled “Security”Before you go live, keep these safety tips in mind to protect your gateway:
- Keep hook endpoints behind loopback, tailnet, or trusted reverse proxy.
- Use a dedicated hook token; do not reuse gateway auth tokens.
- Prefer a dedicated hook agent with strict
tools.profileand sandboxing so hook ingress has a narrower blast radius. - Repeated auth failures are rate-limited per client address to slow brute-force attempts.
- If you use multi-agent routing, set
hooks.allowedAgentIdsto limit explicitagentIdselection. - Keep
hooks.allowRequestSessionKey=falseunless you require caller-selected sessions. - If you enable request
sessionKey, restricthooks.allowedSessionKeyPrefixes(for example,["hook:"]). - Avoid including sensitive raw payloads in webhook logs.
- Hook payloads are treated as untrusted and wrapped with safety boundaries by default. If you must disable this for a specific hook, set
allowUnsafeExternalContent: truein that hook’s mapping (dangerous).
Next Steps
Section titled “Next Steps”Need help configuring your first hook? Check out the AI Setup Assistant.
OpenClaw Expert
Still stuck?
If this page didn't answer your case, ask OpenClaw Expert for step-by-step guidance.