# Feedhook > Turn a YouTube channel into a webhook: register a channel id + callback URL and your > endpoint receives a signed JSON POST ~8 seconds after every new video. YouTube WebSub > underneath (hub subscription, verification handshake, ~5-day lease renewals, retries) — > no polling, no YouTube API quota. Free: 1 feed. Pro: $9/mo, 10 feeds. Base URL: https://feedhook.walls.sh Auth: Authorization: Bearer fh_… (get a key once via POST /accounts) ## API - POST /accounts {"email"} → account + apiKey (shown once; free plan: 1 feed) - GET /account → plan, feed limit, feeds in use (auth) - POST /account/rotate-key → new API key (shown once); the old key stops working immediately (auth) - DELETE /account → delete the account and unsubscribe all its feeds (auth) - POST /subscriptions {"channel":"@handle | UC… id | channel URL","callbackUrl":"https://…"} → subscription + per-subscription secret (shown once) (auth) - POST /subscriptions {"url":"x.com/instagram.com/tiktok.com/facebook.com PROFILE URL","callbackUrl":"https://…"} → a POLLED feed: new posts are detected on a ~10-min cadence and delivered as post.published events {"event","subscriptionId","platform","postId","url","title","author","publishedAt","receivedAt"} — same signing + retry contract. Optional "secret" (16–128 chars) supplies your own signing secret. (auth) - GET /subscriptions → your subscriptions (auth) - GET /subscriptions/:id → one subscription incl. recent delivery log (auth) - POST /subscriptions/:id/test → send a signed test.ping through the real delivery pipeline to verify your receiver (auth) - POST /subscriptions/:id/deliveries/:deliveryId/redeliver → re-send a failed delivery (payloads are kept) (auth) - DELETE /subscriptions/:id → unsubscribe (auth) - POST /billing/checkout → Stripe Checkout URL for Pro $9/mo, 10 feeds (auth) - POST /billing/portal → Stripe customer portal URL: invoices, payment method, cancel anytime (auth) - GET /openapi.json → full OpenAPI 3.1 spec - GET /metrics → live usage numbers (public) ## The webhook you receive POST to your callbackUrl with headers x-feedhook-event, x-feedhook-delivery, and x-feedhook-signature: sha256=. Body: {"event":"video.published","subscriptionId","videoId","channelId","title", "author","publishedAt","url","receivedAt"}. Non-2xx → 5 retries with backoff. Reply in 15s. ## Try it in one command npx -y feedhook-quickstart @mkbhd — creates a free account, subscribes the channel, fires a real signed delivery, verifies the signature, prints the body. ~5s, no endpoint of your own. ## MCP (agents) npx -y feedhook-mcp — tools: create_account, get_account, create_subscription, list_subscriptions, get_subscription, delete_subscription. Env: FEEDHOOK_API_KEY. Registry: io.github.patwalls/feedhook-mcp ## Free tools https://feedhook.walls.sh/tools/channel-id — resolve any YouTube @handle / URL to its canonical UC… channel id (and WebSub topic feed). API: GET https://feedhook.walls.sh/api/channel-id?input=@handle → JSON. ## Deployable templates github.com/patwalls/feedhook-discord-worker — one-click Cloudflare Worker: verifies the signature and posts every new video to a Discord channel, no server to run. ## Further reading https://feedhook.walls.sh/youtube-websub — how YouTube WebSub/PubSubHubbub push works end to end (handshake, signature, lease renewal, gotchas). https://feedhook.walls.sh/compare — polling vs DIY WebSub vs Feedhook. https://feedhook.walls.sh/recipes — Discord, Slack, no-code receivers. https://feedhook.walls.sh/faq — common questions. A walls.sh product. "channel" accepts an @handle, a youtube.com channel URL, or the raw UC… id.