New: hand feedback to your AI agent over MCP

Using the REST API

Updated

What the API does

The Huddlekit REST API lets your own code and tools read a workspace's projects and comments, create comments, change a comment's status, and subscribe to webhooks. It can't edit a comment's text, delete comments, post replies, or set priority, tags, or assignees.

The API is on the Team plan, and only workspace owners and admins can create keys. For an overview, see Webhooks & API. The full reference, with every field and response, is the OpenAPI description at huddlekit.com/openapi.json.

Create an API key

  1. Open Integrations in your workspace sidebar.
  2. In the API keys card, click Create key.
  3. Give the key a Name, such as the tool that will use it.
  4. Under Access, choose Read only or Read and write.
  5. Click Create key.
  6. Copy the key from Save your API key, then click I've saved it.

The key starts with hk_live_. It is shown once and can't be retrieved later, because Huddlekit stores only a hash of it. A key covers every project in the workspace.

Read only keys can list projects and comments. Read and write keys can also create comments, change their status, and manage webhook subscriptions.

To stop a key working, choose Revoke key from its menu. There's no confirmation step: calls with it are refused straight away, and any webhook subscriptions it created stop receiving events. They show Key revoked in the Webhooks card and can only be removed.

Make a request

Send requests to:

https://app.huddlekit.com/api/v1

Pass the key in the Authorization header:

curl https://app.huddlekit.com/api/v1/projects \
  -H "Authorization: Bearer hk_live_…"

Request and response bodies are JSON.

Endpoints

MethodPathWhat it doesScope
GET/meThe key's workspace, scopes, and source valueread
GET/projectsEvery website, web app, and media project in the workspaceread
GET/commentsThe newest comments on one projectread
POST/commentsCreate a commentwrite
PATCH/comments/{id}Change a comment's statuswrite
GET/hooksWebhook subscriptions this key createdread
POST/hooksSubscribe a URL to webhook eventswrite
DELETE/hooks/{id}Remove a subscriptionwrite
GET/events/recentSample webhook bodies built from recent commentsread

Projects and surfaces

Each project from GET /projects has a surface: website, webapp, or document for a media project. Pass the project's id as parent_id, and its surface, when you read or write its comments. surface defaults to website.

Listing comments

GET /comments?parent_id=…&surface=… returns the newest comments first. Add limit to choose how many, a whole number from 1 to 200; the default is 50. There is no paging past the newest 200.

Creating a comment

curl -X POST https://app.huddlekit.com/api/v1/comments \
  -H "Authorization: Bearer hk_live_…" \
  -H "Content-Type: application/json" \
  -d '{
    "parent_id": "b6d767d2-f8e3-4c1a-9b2e-5a7c3d1f0e84",
    "surface": "website",
    "text": "The footer links on the pricing page go nowhere",
    "path": "/pricing"
  }'
  • text is required, up to 10,000 characters.
  • status is optional: open (the default), in-review, in-progress, or resolved.
  • Where the comment sits depends on the surface: path for a website; url, page_title, and path for a web app; page_number, and video_timestamp in seconds on a video, for a media project. A field that belongs to another surface is refused, except path on a media project, which is ignored.

The comment gets its number like any other, and it appears in Huddlekit from a guest named API. The API has no position to give it, so it's placed at the top-left of the page, and it has no screenshot or browser details.

Changing a status

curl -X PATCH https://app.huddlekit.com/api/v1/comments/COMMENT_ID \
  -H "Authorization: Bearer hk_live_…" \
  -H "Content-Type: application/json" \
  -d '{ "status": "resolved", "surface": "website" }'

status is the only field you can change. Send the comment's surface too, or a web app or media comment returns 404.

Webhook subscriptions

POST /hooks with a targetUrl (https:// only, and not a Huddlekit address) subscribes that URL. Add event_types to receive only some events; leave it out to receive all four. The response includes the signing secret, once.

Subscribing the same URL again with the same key turns it back on with the new event list and doesn't return a new secret. GET /hooks and DELETE /hooks/{id} only see subscriptions made with the key you're using. Deleting one the key can't see, or an id that isn't valid, returns 200 with "deleted": false. They also show in the app's Webhooks card, where you can check their delivery log.

Deliveries are signed and retried the same way as endpoints added in the app. See Setting up webhooks.

Rate limits

Each key can make up to 200 read requests and 30 write requests a minute on each endpoint. Reads and writes are counted separately, so reading comments never uses up the budget for creating them. POST /hooks and DELETE /hooks/{id} share one write limit, and POST /comments and PATCH /comments/{id} have one each. Refused calls count too.

Going over a limit returns 429 with a Retry-After header giving the number of seconds to wait.

Errors

A failed call returns a JSON body with error and sometimes detail:

{ "error": "Unauthorized", "detail": "Invalid or revoked API key" }
StatusMeaning
400Something in the request is missing or invalid. error says what
401The key is missing, malformed, unknown or revoked
403The key lacks the scope, or the workspace has no active Team subscription (the body lists requiredPlans)
404Not found. An id from another workspace, or one that isn't a valid id at all, also returns 404 (except DELETE /hooks/{id}, which answers 200 with "deleted": false)
429Rate limit reached. Retry-After says how many seconds to wait
500Something failed on our side. Try again
503A temporary problem on our side, such as "Could not verify the API key. Please retry." Try again

Good to know

  • Plan — if the workspace leaves the Team plan, or a payment is past due, every call returns 403 except DELETE /hooks/{id}, so you can still switch off your subscriptions.
  • Avoiding loops — subscriptions you make with POST /hooks already skip events your own key caused. For webhooks added in the app or with another key, filter on source: events caused by your key carry source: "connector:<key id>", and GET /me returns that value.
  • Zapier connects with an API key. See Connecting Zapier.
  • AI tools like Claude and Cursor connect over MCP instead, with no key. See Connecting AI tools with MCP.

Related articles

Collect feedback in minutes without the friction.