HTTP Hooks
Level: π³ Expert Source: Hooks
HTTP hooks send lifecycle event data as HTTP POST requests to a URL endpoint, instead of running a shell command. They use the same JSON input/output format as command hooks, making them interchangeable for most use cases.
When to Use HTTP Hooks
HTTP hooks are the right choice when your hook logic lives outside the local machine:
- External validation services β a shared API that checks code quality or security policies
- Centralized logging/auditing β send every tool invocation to your observability stack
- CI/CD webhooks β trigger builds or deployments from Claude Code events
- Team-shared policy servers β enforce organization-wide rules from a single endpoint
- Services that arenβt local scripts β anything reachable over HTTP that can process JSON
If your logic is a local script or one-liner, a command hook is simpler. Use HTTP hooks when the handler is a running service.
Configuration
HTTP hooks are configured in the same hooks section of your settings JSON as command hooks. Instead of type: "command", use type: "http":
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "http",
"url": "http://localhost:8080/validate",
"headers": {
"Authorization": "Bearer $API_TOKEN"
},
"allowedEnvVars": ["API_TOKEN"],
"timeout": 30,
"statusMessage": "Validating command..."
}
]
}
]
}
}
Fields
| Field | Required | Description |
|---|---|---|
type | Yes | Must be "http" |
url | Yes | URL to POST to |
headers | No | Key-value pairs for request headers. Supports env var interpolation via $VAR_NAME or ${VAR_NAME} |
allowedEnvVars | No | List of env var names allowed for interpolation in headers |
timeout | No | Seconds before canceling the request (command hooks default to 600; no documented default specific to HTTP) |
statusMessage | No | Custom spinner text shown while the request is in flight |
How It Works
Claude Code POSTs the eventβs JSON input to your URL with Content-Type: application/json. The request body is the same JSON that a command hook receives on stdin.
Response handling
| Response | Result |
|---|---|
| 2xx + empty body | Success β execution continues |
| 2xx + plain text body | Success β text is added as context to the conversation |
| 2xx + JSON body | Parsed using the same JSON output schema as command hooks |
| Non-2xx status | Non-blocking error β execution continues |
| Connection failure / timeout | Non-blocking error β execution continues |
Blocking actions
To block an action (e.g., deny a tool call), return a 2xx response with a JSON body containing a blocking decision:
{
"decision": "block",
"reason": "This command is not allowed by policy"
}
For PermissionRequest hooks, use hookSpecificOutput:
{
"hookSpecificOutput": {
"permissionDecision": "deny"
}
}
Common Patterns
Local validation service
A PreToolUse hook that validates Bash commands against a local policy service:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "http",
"url": "http://localhost:9000/validate-command",
"headers": {
"Authorization": "Bearer $POLICY_TOKEN"
},
"allowedEnvVars": ["POLICY_TOKEN"],
"statusMessage": "Checking command policy..."
}
]
}
]
}
}
Centralized audit logging
A PostToolUse hook that logs every tool invocation to a remote endpoint (fire-and-forget):
{
"hooks": {
"PostToolUse": [
{
"hooks": [
{
"type": "http",
"url": "https://logs.example.com/claude-audit",
"headers": {
"X-Team": "engineering"
},
"timeout": 5
}
]
}
]
}
}
Policy server for permission decisions
A PermissionRequest hook that delegates allow/deny decisions to a centralized policy server:
{
"hooks": {
"PermissionRequest": [
{
"hooks": [
{
"type": "http",
"url": "https://policy.internal.example.com/claude/permissions",
"headers": {
"Authorization": "Bearer $POLICY_SERVER_KEY"
},
"allowedEnvVars": ["POLICY_SERVER_KEY"],
"statusMessage": "Checking permissions..."
}
]
}
]
}
}
The server returns {"hookSpecificOutput": {"permissionDecision": "allow"}} or {"hookSpecificOutput": {"permissionDecision": "deny"}}.
Important Notes
- Manual configuration only β HTTP hooks must be configured by editing settings JSON directly. The
/hooksinteractive menu only supports command hooks. - Deduplication β Identical HTTP hooks are deduplicated by URL. If the same URL appears multiple times for the same event, it is called only once.
- Parallel execution β All matching hooks for an event run in parallel, including HTTP hooks alongside command or prompt hooks.
Next Steps
- See Hooks for lifecycle events, matchers, and command/prompt hook types
- See the official hooks reference for full event schemas
- Return to Automating Your Workflows to compare with Skills and Sub Agents