Quickstart
The HookKit API is live at https://api.hookkit.dev. It is open during the
beta: no API key, open CORS, plain JSON over HTTPS.
Inspect a hook
Section titled “Inspect a hook”Every hook address encodes its permissions in its lowest 14 bits. The profile endpoint decodes them, reads the deployed bytecode, and lists the pools that use the hook.
curl https://api.hookkit.dev/v1/hooks/0x4e3468951D49f2EEa976eD0D6e75fFCb44a9a544{ "address": "0x4e3468951D49f2EEa976eD0D6e75fFCb44a9a544", "flags": 9540, "flagsHex": "0x2544", "enabled": ["beforeInitialize", "afterAddLiquidity", "afterRemoveLiquidity", "afterSwap", "afterSwapReturnDelta"], "errors": [], "capabilities": [ { "level": "warning", "flag": "afterSwapReturnDelta", "note": "Can charge or rebate tokens after each swap, e.g. a hook fee on top of the LP fee." }, { "level": "info", "flag": "afterSwap", "note": "Runs after every swap: oracles, points, limit orders, rebalancing." }, { "level": "info", "flag": "initialize", "note": "Runs when a pool is created with this hook (can restrict which pools use it)." } ], "code": { "deployed": true, "codeSize": 25533, "codeHash": "0xc41a9110...7ee631", "proxy": null }, "warnings": [], "pools": { "total": 61480, "recent": ["..."] }}Read a pool
Section titled “Read a pool”Pools are addressed by their 32-byte PoolId. This is the ETH/USDG 0.05% pool (no hook):
curl https://api.hookkit.dev/v1/pools/0x387bf619da4d3fb62bb276482693dba1b9b3520f573cabdfe033384a24125982{ "poolId": "0x387bf619da4d3fb62bb276482693dba1b9b3520f573cabdfe033384a24125982", "key": { "currency0": "0x0000000000000000000000000000000000000000", "currency1": "0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168", "fee": 500, "tickSpacing": 10, "hooks": "0x0000000000000000000000000000000000000000" }, "dynamicFee": false, "hooked": false, "state": { "initialized": true, "sqrtPriceX96": "3817689024831598151095999", "tick": -198819, "liquidity": "222096235281131263", "lpFee": 500, "lpFeePercent": 0.05, "protocolFee": 512125 }, "price": { "ETH/USDG": 2321.891551981005, "USDG/ETH": 0.0004306833362423039 }, "hook": null}Get a quote
Section titled “Get a quote”Quotes run the onchain V4Quoter, so a hooked pool’s hook actually executes. Amounts are decimal strings in the input token’s units.
curl "https://api.hookkit.dev/v1/quote?poolId=0x387bf619da4d3fb62bb276482693dba1b9b3520f573cabdfe033384a24125982&tokenIn=0x0000000000000000000000000000000000000000&amount=0.01"{ "zeroForOne": true, "exactOut": false, "tokenIn": { "address": "0x0000000000000000000000000000000000000000", "symbol": "ETH", "decimals": 18 }, "tokenOut": { "address": "0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168", "symbol": "USDG", "decimals": 6 }, "amountIn": "0.01", "amountOut": "23.204353", "executionPrice": 2320.4353, "gasEstimate": "42553", "hooked": false}Build a swap
Section titled “Build a swap”/v1/swap/build returns unsigned transactions for sender to sign. HookKit
never holds keys and never submits transactions.
curl -X POST https://api.hookkit.dev/v1/swap/build \ -H "content-type: application/json" \ -d '{ "poolId": "0x387bf619da4d3fb62bb276482693dba1b9b3520f573cabdfe033384a24125982", "tokenIn": "0x0000000000000000000000000000000000000000", "amount": "0.01", "sender": "0xYourWalletAddress", "slippageBps": 50 }'The response contains up to three transactions (ERC-20 approval to Permit2, Permit2 allowance for the UniversalRouter, then the swap), with the slippage bound already applied. See the Swap API for sending them with viem.
TypeScript SDK
Section titled “TypeScript SDK”npm install @hookkit/sdkimport { HookKit, decodeHookAddress } from "@hookkit/sdk"
const hookkit = new HookKit()
// Full profile of a deployed hookconst hook = await hookkit.hooks.get("0x4e3468951D49f2EEa976eD0D6e75fFCb44a9a544")
// Offline: no network calldecodeHookAddress("0x4e3468951D49f2EEa976eD0D6e75fFCb44a9a544").enabled// ["beforeInitialize", "afterAddLiquidity", "afterRemoveLiquidity", "afterSwap", "afterSwapReturnDelta"]
const poolId = "0x387bf619da4d3fb62bb276482693dba1b9b3520f573cabdfe033384a24125982"const pool = await hookkit.pools.get({ poolId })
const quote = await hookkit.quote({ poolId, tokenIn: "0x0000000000000000000000000000000000000000", amount: "0.01",})
const swap = await hookkit.swap.build({ poolId, tokenIn: "0x0000000000000000000000000000000000000000", amount: "0.01", sender: "0xYourWalletAddress",})Every response is typed, and errors throw HookKitError with status and
code.
From Python
Section titled “From Python”import requests
BASE = "https://api.hookkit.dev/v1"POOL = "0x387bf619da4d3fb62bb276482693dba1b9b3520f573cabdfe033384a24125982"
hooks = requests.get(f"{BASE}/hooks", params={"sort": "pools", "limit": 10}).json()
quote = requests.post(f"{BASE}/quote", json={ "poolId": POOL, "tokenIn": "0x0000000000000000000000000000000000000000", "amount": "0.01",}).json()Errors
Section titled “Errors”Every error has the same shape:
{ "error": { "code": "no_route", "message": "Quote reverted: no liquidity in range, the hook rejected the swap, or the amount exceeds the pool (revert 0x6190b2b0)" } }| Status | Code | When |
|---|---|---|
| 400 | bad_request |
Missing or malformed input |
| 404 | not_found |
Unknown route, pool not indexed, or pool not initialized |
| 422 | invalid_flags |
Mining with a *ReturnDelta flag but not its base flag |
| 422 | no_route |
The quote reverted (no liquidity, hook rejected, amount too large) |
| 503 | index_unavailable |
The pool index is not available on this deployment |
What you can build on
Section titled “What you can build on”| API | What it does |
|---|---|
| Hook API | Hook registry, profiles, and permission decoding |
| Hook Miner | CREATE2 salts for hook addresses |
| Pool API | Indexed pools, live state, PoolIds |
| Quote API | Quotes that execute the hook |
| Swap API | Unsigned Permit2 + UniversalRouter transactions |
| Agent API (MCP) | The same tools for AI agents |
