Claude Code http hook: send paid Sume call records to an audit log
An http hook POSTs hook input to a URL, with headers from allowed environment variables only. Log Sume tool names and idempotency keys with a tiny receiver.

Yes, Claude Code can send every Sume tool call to your own logging service with an http hook. The hooks reference shows the shape: a url, optional headers such as Authorization: Bearer $MY_TOKEN, an allowedEnvVars list that names which environment variables may be expanded into headers, and a timeout. Tool event hooks receive tool_name, tool_input and tool_use_id, which is enough for a spend audit.
A shared audit log helps a team that connects several people to Sume with one API key. Sume's docs say write and paid tools carry an idempotency_key, so the log can show which key went with which tool call.
Fields that matter
From the hooks reference.
| Field | Role | Note |
|---|---|---|
| url | Where the hook input goes | Use https for anything off your machine |
| headers | Request headers | May reference environment variables |
| allowedEnvVars | Which variables may be expanded | List every variable you want expanded |
| timeout | Seconds before the hook is canceled | Default 600 for http |
| matcher (on the group) | Which tool names fire it | Use the Sume tool prefix |
A receiver you can run
This standard-library receiver prints the tool name and the idempotency key of each POSTed call and answers 200. It assumes the body is the JSON hook input; confirm that against your first request before you build on it.
import json
from http.server import BaseHTTPRequestHandler, HTTPServer
class Audit(BaseHTTPRequestHandler):
def do_POST(self):
size = int(self.headers.get("Content-Length", "0"))
data = json.loads(self.rfile.read(size) or b"{}")
args = data.get("tool_input") or {}
print(data.get("tool_name"), args.get("idempotency_key"), flush=True)
self.send_response(200)
self.end_headers()
HTTPServer(("127.0.0.1", 8099), Audit).serve_forever()Steps
Start the receiver, add a PreToolUse or PostToolUse hook with type: http and url: http://127.0.0.1:8099, set the matcher to the Sume prefix, and run one harmless read such as balance_get. You should see its name in the receiver output. Then widen to the paid tools. Put real traffic behind https and a token passed through allowedEnvVars.
- Never put the Sume API key in the audit log; log the tool name and idempotency key only.
- Use PostToolUse if you want to log what ran, PreToolUse if you want to log what was attempted.
- Check
claude --debug-file hooks.logif nothing arrives.
What to record and what to leave out
A useful audit row has four fields: when the call was attempted, which tool, which idempotency key, and who ran it. The hook input also includes a session id and the working directory, so you can tie a row to a session and a project. Leave out the bearer token, any signed download URLs that appear in tool results, and the full prompt text unless you have a reason to keep it, since prompts for image and video work can contain private material.
Add a retention rule at the same time. A log of paid calls is useful for a month of reconciliation against Sume's job list, and a liability after that if it also holds prompts.
What Sume does not do
Sume keeps its own job records, which you read with jobs_list. It does not forward calls to your log, and the hook is on your side of the connection. A log built this way records what Claude Code attempted, not what Sume billed.
Sources
Related posts
More in Developers
- Claude per-message effort: drop to low while a Sume job runs
Claude's per-message effort beta keeps the prompt cache when you change effort mid-conversation. How to use it around Sume jobs, and its Haiku 5.5 limit.
- Hook matcher for a plugin-bundled Sume server: mcp__plugin_ names
A Sume server shipped inside a Claude Code plugin gets a longer tool prefix than one added by hand. Write the PreToolUse matcher for it and test it first.
- Where a Claude Code plugin keeps Sume state: CLAUDE_PLUGIN_DATA
A plugin's data directory survives updates, while its root changes. Where to put a Sume call log or cache, and when uninstalling deletes it.
- Ship a Sume Claude Code plugin off by default: defaultEnabled false
A manifest can set defaultEnabled to false, so a Sume plugin with paid tools starts disabled until someone turns it on. What persists after updates.
Written by Sume