Docs

One API for every
v4 hook.

Read hooks and pools, scan tokens, quote through hooks, build unsigned swaps and mine hook addresses on Robinhood Chain (chain id 4663). No key, no account. JSON over HTTPS, and the same tools over MCP.

Quickstart

Every endpoint lives under https://tacklehooks.xyz/v1. Addresses are checksummed or lowercase 0x strings, amounts are human units ("0.1"), and every response is JSON.

curl https://tacklehooks.xyz/v1/stats
curl "https://tacklehooks.xyz/v1/hooks?sort=pools&limit=10"
curl https://tacklehooks.xyz/v1/scan/0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168

MCP for agents

The MCP server speaks streamable HTTP at https://tacklehooks.xyz/mcp, with ten tools: scan, decode_hook, inspect_hook, list_hooks, list_pools, get_pool, compute_pool_id, quote, build_swap, mine_hook_salt and get_stats.

Claude Code

claude mcp add --transport http tackle https://tacklehooks.xyz/mcp

Cursor and other clients

{
  "mcpServers": {
    "tackle": { "url": "https://tacklehooks.xyz/mcp" }
  }
}

Then ask in plain words: “which hooks on this token can take a fee?”, “quote 0.1 ETH through this pool”, “mine a beforeSwap and afterSwap address for this init code hash”.

Scanner

GET/v1/scan/:input

Paste anything: a token address returns its pools, the hooks they run and a verdict for each; a hook address returns its profile; a 32-byte pool id returns the live pool and its hook.

Each hook comes with a verdict: a tone (clear, caution, risky, missing) and four plain checks: fixed or upgradeable code, curve or custom pricing, hook fee or none, and whether LP withdrawals can be blocked.

Hooks

GET/v1/hooks?sort=pools|recent&q=&limit=25&offset=0

The registry: every hook used by at least one v4 pool, with its verified name when the source is on Sourcify, its permissions and its pool count. q searches names and addresses.

GET/v1/hooks/:address

The full profile: name, permission bits, what each one allows, bytecode size and hash, EIP-1967 and EIP-1167 proxy detection, the verdict, and the latest pools.

GET/v1/hooks/:address/flags

Decode an address only: pure, no chain call, works for hooks not deployed yet.

GET/v1/hooks/flags

The table of the 14 flags with their bits.

Hook miner

The PoolManager reads a hook’s permissions from the last 14 bits of its address, so the hook has to be deployed at an address that carries exactly those bits. The miner finds the CREATE2 salt.

POST/v1/hooks/mine

Body: flags (names) or mask, initCodeHash = keccak256(creationCode ++ constructor args), optional deployer (default: the CREATE2 deployer 0x4e59…956C).
curl -X POST https://tacklehooks.xyz/v1/hooks/mine \
  -H 'content-type: application/json' \
  -d '{"flags":["beforeSwap","afterSwap"],"initCodeHash":"0x…"}'

Deploy by sending salt ++ creationCode to the deployer. Each call starts from a random salt; if found is false, call again.

Pools

GET/v1/pools?hook=&token=&hooked=true|false&limit=25&offset=0

Every v4 pool since the chain’s first block, newest first, indexed from the PoolManager’s Initialize events and followed live.

GET/v1/pools/:poolId

Live state from StateView: sqrtPriceX96, tick, liquidity, current LP fee, prices both ways, and the hook’s capabilities and verdict.

POST/v1/pools/id

Compute a PoolId from a pool key (currencies get sorted).

Quotes

GET/v1/quote?poolId=&tokenIn=&amount=&exactOut=false&hookData=0x

Runs the V4Quoter on-chain, so the hook executes: its fee or custom pricing is in the result. Also as POST with a JSON body.
curl "https://tacklehooks.xyz/v1/quote?poolId=0x…&tokenIn=0x0000000000000000000000000000000000000000&amount=0.1"

Swaps

POST/v1/swap/build

Body: poolId, tokenIn, amount, sender, optional slippageBps (default 50), hookData, deadline.

Returns the transactions to sign, in order: an ERC-20 approval to Permit2 and a Permit2 approval to the Universal Router when needed, then execute(0x10, …) with SWAP_EXACT_IN_SINGLE, SETTLE_ALL and TAKE_ALL. When no approval is pending, the swap is dry-run from the sender and the result is in simulation. Tackle never signs or sends anything.

Permission bits

Bit 13 is the highest, bit 0 the lowest. A *ReturnDelta flag needs its base flag, or the PoolManager rejects the address.

beforeInitialize1<<130x2000
afterInitialize1<<120x1000
beforeAddLiquidity1<<110x0800
afterAddLiquidity1<<100x0400
beforeRemoveLiquidity1<<90x0200
afterRemoveLiquidity1<<80x0100
beforeSwap1<<70x0080
afterSwap1<<60x0040
beforeDonate1<<50x0020
afterDonate1<<40x0010
beforeSwapReturnDelta1<<30x0008
afterSwapReturnDelta1<<20x0004
afterAddLiquidityReturnDelta1<<10x0002
afterRemoveLiquidityReturnDelta1<<00x0001

Contracts

Uniswap v4 on Robinhood Chain, all verified. GET /v1/chain returns the same list.

PoolManager
StateView
V4Quoter
UniversalRouter
PositionManager
Permit2

Limits and errors

120 requests a minute per IP (a mining call counts as 10). Errors come back as { "error": { "code", "message" } } with a 4xx status: bad_address, pool_not_found, quote_reverted (often a hook refusing the swap), rate_limited.

Capability notes describe what a permission makes possible, not what a hook does. They are not an audit: read the verified source before trusting a hook with real funds.