Skip to content

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.

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.

Terminal window
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": ["..."] }
}

Pools are addressed by their 32-byte PoolId. This is the ETH/USDG 0.05% pool (no hook):

Terminal window
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
}

Quotes run the onchain V4Quoter, so a hooked pool’s hook actually executes. Amounts are decimal strings in the input token’s units.

Terminal window
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
}

/v1/swap/build returns unsigned transactions for sender to sign. HookKit never holds keys and never submits transactions.

Terminal window
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.

Terminal window
npm install @hookkit/sdk
import { HookKit, decodeHookAddress } from "@hookkit/sdk"
const hookkit = new HookKit()
// Full profile of a deployed hook
const hook = await hookkit.hooks.get("0x4e3468951D49f2EEa976eD0D6e75fFCb44a9a544")
// Offline: no network call
decodeHookAddress("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.

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()

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
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