{"openapi":"3.1.0","info":{"title":"FeedLab API","version":"1.0.0","description":"Authenticated REST API for building your own feedback pipeline with FeedLab: push feedback in from your own tools, or read and update what's already there. Every request needs an fl_ API token (Settings → API Tokens in the dashboard), sent as `Authorization: Bearer fl_...`. A token acts as the user who created it and only reaches projects in their workspaces, and the workspace's plan must include API access (Solo or Studio).\n\nThis is the same access control and business logic used by the FeedLab MCP server (see /ai) and the `feedlab` CLI — all three are thin clients over the same underlying service layer."},"servers":[{"url":"https://feedlab.cloud/api"}],"security":[{"bearerAuth":[]}],"paths":{"/v1/feedback":{"get":{"summary":"List feedback items for a project","parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"status","in":"query","schema":{"type":"string","enum":["open","resolved","all"],"default":"open"},"description":"open = pending or in_progress"},{"name":"source","in":"query","schema":{"type":"string","enum":["code_review","all"],"default":"all"}},{"name":"limit","in":"query","schema":{"type":"integer","default":100,"maximum":200}}],"responses":{"200":{"description":"Matching feedback items","content":{"application/json":{"schema":{"type":"object","properties":{"project":{"$ref":"#/components/schemas/ProjectRef"},"issues":{"type":"array","items":{"$ref":"#/components/schemas/FeedbackSummary"}}}}}}},"400":{"description":"Request understood but rejected (bad input, missing access, plan doesn't include API access, etc.)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid Authorization header","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"summary":"Submit feedback from your own pipeline","description":"Also reachable without a token for the embedded widget and public feedback form, which accept a narrower field set and are rate-limited by IP instead of by token.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["projectId","content"],"properties":{"projectId":{"type":"string"},"content":{"type":"string","description":"The feedback body (becomes description)"},"title":{"type":"string","description":"Defaults to the start of content"},"type":{"type":"string","enum":["bug","feature","general"],"default":"general"},"tags":{"type":"array","items":{"type":"string"},"maxItems":20},"metadata":{"type":"object","description":"Arbitrary JSON, e.g. { \"build\": \"1.4.2\", \"sentry_issue_id\": \"...\" }. Capped at 4KB serialized."},"screenshot":{"type":"string","description":"data: URI, e.g. data:image/png;base64,..."},"userName":{"type":"string"},"userEmail":{"type":"string"},"pageUrl":{"type":"string"}}}}}},"responses":{"200":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"id":{"type":"string"}}}}}},"400":{"description":"Request understood but rejected (bad input, missing access, plan doesn't include API access, etc.)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid Authorization header","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/feedback/{id}":{"get":{"summary":"Get one feedback item in full","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The item","content":{"application/json":{"schema":{"type":"object","properties":{"issue":{"$ref":"#/components/schemas/FeedbackDetail"}}}}}},"400":{"description":"Request understood but rejected (bad input, missing access, plan doesn't include API access, etc.)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid Authorization header","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"summary":"Update a feedback item's status","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["pending","in_progress","completed"]},"note":{"type":"string","description":"Appended to the description with a timestamp"}}}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"type":"object","properties":{"issue":{"$ref":"#/components/schemas/FeedbackSummary"}}}}}},"400":{"description":"Request understood but rejected (bad input, missing access, plan doesn't include API access, etc.)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid Authorization header","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/projects":{"get":{"summary":"List projects the token's user can access","responses":{"200":{"description":"Projects","content":{"application/json":{"schema":{"type":"object","properties":{"projects":{"type":"array","items":{"$ref":"#/components/schemas/Project"}}}}}}},"401":{"description":"Missing or invalid Authorization header","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/me":{"get":{"summary":"Check a token and see who it belongs to","responses":{"200":{"description":"Token owner","content":{"application/json":{"schema":{"type":"object","properties":{"user_id":{"type":"string"},"email":{"type":"string","nullable":true},"name":{"type":"string","nullable":true}}}}}},"401":{"description":"Missing or invalid Authorization header","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"fl_...","description":"API token from Settings → API Tokens"}},"schemas":{"Error":{"type":"object","properties":{"error":{"type":"string"}}},"ProjectRef":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}}},"Project":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"website_url":{"type":"string","nullable":true},"organization":{"type":"string","nullable":true}}},"FeedbackSummary":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"type":{"type":"string","enum":["bug","feature","general"]},"status":{"type":"string","enum":["pending","in_progress","completed"]},"tags":{"type":"array","items":{"type":"string"}},"source":{"type":"string","enum":["widget","manual","mobile","public_form","test_session","code_review","api"]},"created_at":{"type":"string","format":"date-time"}}},"FeedbackDetail":{"allOf":[{"$ref":"#/components/schemas/FeedbackSummary"},{"type":"object","properties":{"description":{"type":"string"},"is_resolved":{"type":"boolean"},"screenshot_url":{"type":"string","nullable":true},"user_name":{"type":"string","nullable":true},"user_email":{"type":"string","nullable":true},"page_url":{"type":"string","nullable":true},"metadata":{"type":"object"},"locked":{"type":"boolean","description":"True if the workspace was over its monthly submission limit when this arrived; content is withheld until upgrade."}}}]}}}}