{"openapi":"3.1.0","info":{"title":"Feedback4.dev Agency API","version":"1.0.0","description":"Feedback4.dev turns comments from verified reviewers, anchored to elements on live client websites, into structured tickets with page, selector, viewport, browser, bounded DOM context and an approval trail. This production REST API manages agency projects, tickets, approvals, authorized reviewers, scoped credentials and signed webhooks. Feedback4.dev does not edit repositories, invoke AI models or deploy websites; the consuming team or external agent owns execution. Every API key is fixed to one workspace, can optionally be fixed to one project, and is restricted by explicit scopes. Authenticated responses are private, auditable and correlated with X-Request-Id. After a material legal update, an owner or administrator has a 30-day reacceptance window; expired workspaces receive legal.acceptance_required until the current documents are accepted in the account.","contact":{"email":"contact@feedback4.dev","url":"https://feedback4.dev"},"x-feedback4-agent-guide":"https://feedback4.dev/docs/agents.md","x-feedback4-mcp-endpoint":"https://feedback4.dev/api/mcp"},"servers":[{"url":"https://feedback4.dev/api/v1","description":"Production"}],"externalDocs":{"description":"Detailed guides, limits, examples and endpoint reference","url":"https://feedback4.dev/docs"},"tags":[{"name":"Identity","description":"Inspect the workspace, project boundary, scopes and expiration of the current key."},{"name":"Projects","description":"Create and configure projects and retrieve widget installation data."},{"name":"Feedback","description":"Read visual feedback, update workflow and request client approval."},{"name":"Reviewers","description":"Manage the project-level allowlist that protects client feedback submission."},{"name":"Members","description":"Manage workspace membership and pending invitations with workspace-scoped keys."},{"name":"Agents","description":"Issue and revoke project-scoped MCP credentials for automation agents."},{"name":"Webhooks","description":"Configure durable signed delivery endpoints and inspect or retry their deliveries."}],"paths":{"/me":{"get":{"operationId":"getApiIdentity","tags":["Identity"],"summary":"Inspect the current API identity","description":"Requires projects:read. Use this endpoint as the first integration check and to confirm the effective workspace, optional project boundary, scopes and expiration.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"API identity","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/ApiIdentity"}}}}}},"400":{"description":"Invalid request","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient scope or current legal acceptance required","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}},"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/projects":{"get":{"operationId":"listProjects","tags":["Projects"],"summary":"List projects","description":"Requires projects:read. A project-scoped key can only return its bound project.","security":[{"bearerAuth":[]}],"parameters":[{"name":"page[limit]","in":"query","description":"Number of resources to return, from 1 to 100.","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}},{"name":"page[after]","in":"query","description":"Opaque cursor returned as meta.next_cursor by the previous page. Do not construct or modify it.","schema":{"type":"string","maxLength":500}}],"responses":{"200":{"description":"Project collection","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Project"}},"meta":{"type":"object","properties":{"next_cursor":{"type":["string","null"]}}}}}}}},"400":{"description":"Invalid request","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient scope or current legal acceptance required","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}},"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"createProject","tags":["Projects"],"summary":"Create a project","description":"Requires a workspace-scoped key with projects:write. allowed_origin is normalized to scheme, host and port. Initial reviewer emails are normalized and deduplicated. agent_mode defaults to off; use propose or auto only when the project has an authorized automation agent.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectCreate"}}}},"responses":{"201":{"description":"Project created","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/Project"}}}}}},"400":{"description":"Invalid request","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient scope or current legal acceptance required","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Plan project limit reached","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"JSON request body exceeds 64 KiB","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Content-Type must be application/json and compressed request bodies are not accepted","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}},"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/projects/{project_id}":{"parameters":[{"name":"project_id","in":"path","required":true,"description":"Project ID","schema":{"type":"string","format":"uuid"}}],"get":{"operationId":"getProject","tags":["Projects"],"summary":"Get a project","description":"Requires projects:read. Resources outside the key boundary return 404.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Project","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/Project"}}}}}},"400":{"description":"Invalid request","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient scope or current legal acceptance required","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Project not found or outside the authorized boundary","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}},"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"operationId":"updateProject","tags":["Projects"],"summary":"Update project name, status or agent policy","description":"Requires projects:write. Supplied fields are updated atomically; unknown fields and empty objects are rejected. allowed_origin is immutable after project creation so a compromised key cannot redirect a widget to another site.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectUpdate"}}}},"responses":{"200":{"description":"Updated project","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/Project"}}}}}},"400":{"description":"Invalid request","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient scope or current legal acceptance required","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Project not found or outside the authorized boundary","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"JSON request body exceeds 64 KiB","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Content-Type must be application/json and compressed request bodies are not accepted","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}},"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/projects/{project_id}/widget":{"get":{"operationId":"getProjectWidget","tags":["Projects"],"summary":"Get the project widget tag","description":"Requires projects:read. Returns the loader URL, hosted feedback URL and a ready-to-install HTML script tag.","security":[{"bearerAuth":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"description":"Project ID","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Widget installation","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/Widget"}}}}}},"400":{"description":"Invalid request","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient scope or current legal acceptance required","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Project not found or outside the authorized boundary","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}},"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/projects/{project_id}/feedback":{"get":{"operationId":"listProjectFeedback","tags":["Feedback"],"summary":"List project tickets","description":"Requires feedback:read. Supports opaque cursor pagination and one optional workflow status filter.","security":[{"bearerAuth":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"description":"Project ID","schema":{"type":"string","format":"uuid"}},{"name":"page[limit]","in":"query","description":"Number of resources to return, from 1 to 100.","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}},{"name":"page[after]","in":"query","description":"Opaque cursor returned as meta.next_cursor by the previous page. Do not construct or modify it.","schema":{"type":"string","maxLength":500}},{"name":"filter[status]","in":"query","description":"Return only tickets in this workflow status.","schema":{"$ref":"#/components/schemas/FeedbackStatus"}}],"responses":{"200":{"description":"Feedback collection","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Feedback"}},"meta":{"type":"object","properties":{"next_cursor":{"type":["string","null"]}}}}}}}},"400":{"description":"Invalid request","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient scope or current legal acceptance required","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Project not found or outside the authorized boundary","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}},"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/feedback/{feedback_id}":{"parameters":[{"name":"feedback_id","in":"path","required":true,"description":"Feedback ticket ID","schema":{"type":"string","format":"uuid"}}],"get":{"operationId":"getFeedback","tags":["Feedback"],"summary":"Get a ticket including the selected element link","description":"Requires feedback:read. selected_element.highlight_url returns to the captured page and highlights the original DOM anchor when available.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Feedback ticket","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/Feedback"}}}}}},"400":{"description":"Invalid request","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient scope or current legal acceptance required","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Feedback not found or outside the authorized boundary","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}},"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"operationId":"updateFeedback","tags":["Feedback"],"summary":"Update ticket status, priority or assignee","description":"Requires feedback:write. All supplied fields are updated atomically. The assignee must be a current member of the same workspace.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FeedbackUpdate"}}}},"responses":{"200":{"description":"Updated feedback","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/Feedback"}}}}}},"400":{"description":"Invalid request","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient scope or current legal acceptance required","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Feedback not found or outside the authorized boundary","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"JSON request body exceeds 64 KiB","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Content-Type must be application/json and compressed request bodies are not accepted","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}},"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/feedback/{feedback_id}/approval-request":{"post":{"operationId":"requestFeedbackApproval","tags":["Feedback"],"summary":"Send a client approval request","description":"Requires approvals:write. Moves the ticket to review, records activity and queues an email for the authorized reviewer. Limited to five requests per feedback item per hour.","security":[{"bearerAuth":[]}],"parameters":[{"name":"feedback_id","in":"path","required":true,"description":"Feedback ticket ID","schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApprovalRequestCreate"}}}},"responses":{"202":{"description":"Approval request accepted and queued","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/ApprovalRequest"}}}}}},"400":{"description":"Invalid request","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient scope or current legal acceptance required","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Feedback not found or outside the authorized boundary","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"An authorized reviewer email is required","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"JSON request body exceeds 64 KiB","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Content-Type must be application/json and compressed request bodies are not accepted","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}},"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/feedback/{feedback_id}/proposed-prompt":{"get":{"operationId":"getFeedbackProposedPrompt","tags":["Feedback"],"summary":"Get the proposed implementation prompt","description":"Requires feedback:read. Reading the proposal does not execute an agent or mutate the ticket.","security":[{"bearerAuth":[]}],"parameters":[{"name":"feedback_id","in":"path","required":true,"description":"Feedback ticket ID","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Proposed prompt","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/ProposedPrompt"}}}}}},"400":{"description":"Invalid request","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient scope or current legal acceptance required","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Feedback not found or outside the authorized boundary","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}},"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/projects/{project_id}/reviewers":{"get":{"operationId":"listProjectReviewers","tags":["Reviewers"],"summary":"List authorized project reviewers","description":"Requires projects:read. Includes active and revoked entries and the last successful verification time.","security":[{"bearerAuth":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"description":"Project ID","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Reviewer collection","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Reviewer"}},"meta":{"type":"object","properties":{"next_cursor":{"type":["string","null"]}}}}}}}},"400":{"description":"Invalid request","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient scope or current legal acceptance required","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Project not found or outside the authorized boundary","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}},"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"authorizeProjectReviewer","tags":["Reviewers"],"summary":"Authorize or reactivate a reviewer email","description":"Requires projects:write. Authorizing an email does not create a permanent anonymous identity. The visitor exchanges a one-time email code for a project-bound browser session with an absolute 24-hour maximum, and revoking the reviewer invalidates every active session.","security":[{"bearerAuth":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"description":"Project ID","schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewerCreate"}}}},"responses":{"201":{"description":"Reviewer authorized","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/Reviewer"}}}}}},"400":{"description":"Invalid request","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient scope or current legal acceptance required","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Project not found or outside the authorized boundary","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"JSON request body exceeds 64 KiB","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Content-Type must be application/json and compressed request bodies are not accepted","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}},"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/projects/{project_id}/reviewers/{reviewer_id}":{"delete":{"operationId":"revokeProjectReviewer","tags":["Reviewers"],"summary":"Revoke reviewer access and active sessions","description":"Requires projects:write. Revocation invalidates every active reviewer session for this project.","security":[{"bearerAuth":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"description":"Project ID","schema":{"type":"string","format":"uuid"}},{"name":"reviewer_id","in":"path","required":true,"description":"Reviewer ID","schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":"Reviewer and active sessions revoked","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}}},"400":{"description":"Invalid request","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient scope or current legal acceptance required","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Reviewer not found or outside the authorized boundary","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}},"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/members":{"get":{"operationId":"listWorkspaceMembers","tags":["Members"],"summary":"List agency members and pending invitations","description":"Requires a workspace-scoped key with members:read. Pending invitations are returned under included.pending_invitations.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Workspace members and current pending invitations","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"type":"object","required":["data","included"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Member"}},"included":{"type":"object","required":["pending_invitations"],"properties":{"pending_invitations":{"type":"array","items":{"$ref":"#/components/schemas/PendingInvitation"}}}}}}}}},"400":{"description":"Invalid request","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient scope or current legal acceptance required","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}},"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"inviteWorkspaceMember","tags":["Members"],"summary":"Invite an agency member","description":"Requires a workspace-scoped key with members:write. The invite URL is returned once and invitation creation is limited to 30 per key per hour.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemberInvite"}}}},"responses":{"201":{"description":"Invitation created","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/WorkspaceInvitation"}}}}}},"400":{"description":"Invalid request","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient scope or current legal acceptance required","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"JSON request body exceeds 64 KiB","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Content-Type must be application/json and compressed request bodies are not accepted","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}},"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/members/{membership_id}":{"parameters":[{"name":"membership_id","in":"path","required":true,"description":"Workspace membership ID","schema":{"type":"string","format":"uuid"}}],"patch":{"operationId":"updateWorkspaceMember","tags":["Members"],"summary":"Update a member role","description":"Requires a workspace-scoped key with members:write. The last owner cannot be demoted.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemberUpdate"}}}},"responses":{"200":{"description":"Member role updated","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/MemberRoleUpdate"}}}}}},"400":{"description":"Invalid request","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient scope or current legal acceptance required","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Member not found","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The last workspace owner cannot be demoted","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"JSON request body exceeds 64 KiB","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Content-Type must be application/json and compressed request bodies are not accepted","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}},"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"removeWorkspaceMember","tags":["Members"],"summary":"Remove a member and revoke credentials created by that member","description":"Requires a workspace-scoped key with members:write. REST and MCP credentials created by the removed user are revoked.","security":[{"bearerAuth":[]}],"responses":{"204":{"description":"Member removed and credentials revoked","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}}},"400":{"description":"Invalid request","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient scope or current legal acceptance required","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Member not found","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The last workspace owner cannot be removed","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}},"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/invitations/{invitation_id}":{"delete":{"operationId":"revokeWorkspaceInvitation","tags":["Members"],"summary":"Revoke a pending invitation","description":"Requires a workspace-scoped key with members:write. Accepted, expired, revoked or foreign invitations return 404.","security":[{"bearerAuth":[]}],"parameters":[{"name":"invitation_id","in":"path","required":true,"description":"Invitation ID","schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":"Pending invitation revoked","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}}},"400":{"description":"Invalid request","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient scope or current legal acceptance required","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Invitation not found","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}},"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/projects/{project_id}/agent-credentials":{"get":{"operationId":"listAgentCredentials","tags":["Agents"],"summary":"List project agent credentials","description":"Requires agents:read. Secrets are never returned; only the prefix, state, usage and expiration are exposed.","security":[{"bearerAuth":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"description":"Project ID","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Agent credential collection","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/AgentCredential"}},"meta":{"type":"object","properties":{"next_cursor":{"type":["string","null"]}}}}}}}},"400":{"description":"Invalid request","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient scope or current legal acceptance required","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Project not found or outside the authorized boundary","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}},"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"createAgentCredential","tags":["Agents"],"summary":"Create a project-scoped MCP credential","description":"Requires agents:write. The mcp_ token is returned once and expires after 1–365 days. Store it in a server-side secret manager.","security":[{"bearerAuth":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"description":"Project ID","schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentCredentialCreate"}}}},"responses":{"201":{"description":"Agent credential created; token returned once","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/AgentCredentialSecret"}}}}}},"400":{"description":"Invalid request","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient scope or current legal acceptance required","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Project not found or outside the authorized boundary","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"JSON request body exceeds 64 KiB","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Content-Type must be application/json and compressed request bodies are not accepted","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}},"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/projects/{project_id}/agent-credentials/{credential_id}":{"delete":{"operationId":"revokeAgentCredential","tags":["Agents"],"summary":"Revoke an MCP credential","description":"Requires agents:write. Revocation is immediate and restricted to the requested project.","security":[{"bearerAuth":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"description":"Project ID","schema":{"type":"string","format":"uuid"}},{"name":"credential_id","in":"path","required":true,"description":"Agent credential ID","schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":"Agent credential revoked","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}}},"400":{"description":"Invalid request","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient scope or current legal acceptance required","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Agent credential not found or outside the authorized boundary","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}},"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/webhook-endpoints":{"get":{"operationId":"listWebhookEndpoints","tags":["Webhooks"],"summary":"List webhook endpoints","description":"Requires webhooks:read. A project-scoped key sees only endpoints bound to its project; workspace-wide endpoints are intentionally hidden from it.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Webhook endpoint collection","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/WebhookEndpoint"}},"meta":{"type":"object","properties":{"next_cursor":{"type":["string","null"]}}}}}}}},"400":{"description":"Invalid request","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient scope or current legal acceptance required","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}},"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"createWebhookEndpoint","tags":["Webhooks"],"summary":"Create a durable signed webhook endpoint","description":"Requires webhooks:write. Only public HTTPS destinations are accepted. DNS and IP controls reject loopback, private, link-local and metadata networks. signing_secret is returned once.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointCreate"}}}},"responses":{"201":{"description":"Webhook endpoint created; signing secret returned once","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/WebhookEndpointSecret"}}}}}},"400":{"description":"Invalid request","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient scope or current legal acceptance required","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Project not found or outside the authorized boundary","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"JSON request body exceeds 64 KiB","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Content-Type must be application/json and compressed request bodies are not accepted","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}},"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/webhook-endpoints/{endpoint_id}":{"delete":{"operationId":"deleteWebhookEndpoint","tags":["Webhooks"],"summary":"Delete an endpoint and its delivery history","description":"Requires webhooks:write. Deletion is permanent and tenant/project bounded.","security":[{"bearerAuth":[]}],"parameters":[{"name":"endpoint_id","in":"path","required":true,"description":"Webhook endpoint ID","schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":"Webhook endpoint deleted","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}}},"400":{"description":"Invalid request","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient scope or current legal acceptance required","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Webhook endpoint not found or outside the authorized boundary","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}},"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/webhook-endpoints/{endpoint_id}/deliveries":{"get":{"operationId":"listWebhookDeliveries","tags":["Webhooks"],"summary":"Inspect recent delivery attempts","description":"Requires webhooks:read. Returns up to 25 recent attempts without exposing the payload or secret.","security":[{"bearerAuth":[]}],"parameters":[{"name":"endpoint_id","in":"path","required":true,"description":"Webhook endpoint ID","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Webhook delivery collection","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/WebhookDelivery"}},"meta":{"type":"object","properties":{"next_cursor":{"type":["string","null"]}}}}}}}},"400":{"description":"Invalid request","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient scope or current legal acceptance required","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Webhook endpoint not found or outside the authorized boundary","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}},"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/webhook-deliveries/{delivery_id}/retry":{"post":{"operationId":"retryWebhookDelivery","tags":["Webhooks"],"summary":"Retry a pending or dead-lettered delivery","description":"Requires webhooks:write. Resets the attempt counter and schedules the delivery immediately. A delivery that already succeeded cannot be retried.","security":[{"bearerAuth":[]}],"parameters":[{"name":"delivery_id","in":"path","required":true,"description":"Webhook delivery ID","schema":{"type":"string","format":"uuid"}}],"responses":{"202":{"description":"Delivery queued","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/WebhookDeliveryRetry"}}}}}},"400":{"description":"Invalid request","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient scope or current legal acceptance required","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Delivery not found, outside the authorized boundary or already succeeded","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","headers":{"X-Request-Id":{"description":"Request correlation identifier. Echoes a valid client value or contains a generated req_ UUID.","schema":{"type":"string"}},"Cache-Control":{"description":"Authenticated API responses always use no-store.","schema":{"type":"string","const":"no-store"}},"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"Feedback4 API key","description":"Use Authorization: Bearer f4_live_..."}},"schemas":{"ApiIdentity":{"type":"object","required":["object","api_key_id","label","workspace_id","project_id","scopes","expires_at"],"properties":{"object":{"type":"string","const":"api_identity"},"api_key_id":{"type":"string","format":"uuid"},"label":{"type":"string"},"workspace_id":{"type":"string","format":"uuid"},"project_id":{"type":["string","null"],"format":"uuid"},"scopes":{"type":"array","items":{"type":"string"}},"expires_at":{"type":["string","null"],"format":"date-time"}}},"Project":{"type":"object","required":["object","id","name","slug","status","public_key","allowed_origin","feedback_access","agent_mode","created_at","updated_at"],"properties":{"object":{"type":"string","const":"project"},"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"slug":{"type":"string"},"status":{"enum":["active","paused","archived"]},"public_key":{"type":"string"},"allowed_origin":{"type":["string","null"],"format":"uri"},"feedback_access":{"enum":["public","reviewer_allowlist"]},"agent_mode":{"enum":["off","propose","auto"]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"ProjectCreate":{"type":"object","additionalProperties":false,"required":["name","allowed_origin"],"properties":{"name":{"type":"string","minLength":2,"maxLength":120},"allowed_origin":{"type":"string","format":"uri"},"reviewer_emails":{"type":"array","maxItems":100,"items":{"type":"string","format":"email"}},"agent_mode":{"enum":["off","propose","auto"],"default":"off","description":"Controls the policy exposed to an external automation: off does not dispatch agent work, propose requires authorization before implementation, and auto permits the external agent to implement before requesting client approval. Feedback4.dev itself does not edit code or deploy."}}},"ProjectUpdate":{"type":"object","additionalProperties":false,"minProperties":1,"properties":{"name":{"type":"string","minLength":2,"maxLength":120},"status":{"enum":["active","paused","archived"]},"agent_mode":{"enum":["off","propose","auto"]}}},"Widget":{"type":"object","required":["object","project_id","public_key","allowed_origin","loader_url","public_feedback_url","html"],"properties":{"object":{"type":"string","const":"project_widget"},"project_id":{"type":"string","format":"uuid"},"public_key":{"type":"string"},"allowed_origin":{"type":["string","null"],"format":"uri"},"loader_url":{"type":"string","format":"uri"},"public_feedback_url":{"type":"string","format":"uri"},"html":{"type":"string"}}},"FeedbackStatus":{"type":"string","enum":["new","in_progress","review","resolved"]},"Feedback":{"type":"object","required":["object","id","local_number","project_id","title","description","type","status","priority","approval_status","assignee_user_id","reporter_email","page_url","selected_element","created_at","updated_at"],"properties":{"object":{"type":"string","const":"feedback"},"id":{"type":"string","format":"uuid"},"local_number":{"type":"integer"},"project_id":{"type":"string","format":"uuid"},"title":{"type":"string"},"description":{"type":"string"},"type":{"type":"string"},"status":{"$ref":"#/components/schemas/FeedbackStatus"},"priority":{"enum":["urgent","high","normal","low","unset"]},"approval_status":{"enum":["not_requested","pending","approved","changes_requested"]},"assignee_user_id":{"type":["string","null"],"pattern":"^[A-Za-z0-9_-]{8,255}$"},"reporter_email":{"type":["string","null"],"format":"email"},"page_url":{"type":["string","null"],"format":"uri"},"selected_element":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/SelectedElement"}]},"proposed_prompt":{"type":["string","null"]},"proposed_prompt_model":{"type":["string","null"]},"proposed_prompt_updated_at":{"type":["string","null"],"format":"date-time"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"SelectedElement":{"type":"object","properties":{"selector":{"type":"string"},"label":{"type":["string","null"]},"tag_name":{"type":["string","null"]},"rect":{"type":["object","null"]},"context":{"type":["object","null"]},"highlight_url":{"type":["string","null"],"format":"uri"}}},"FeedbackUpdate":{"type":"object","additionalProperties":false,"minProperties":1,"properties":{"status":{"$ref":"#/components/schemas/FeedbackStatus"},"priority":{"enum":["urgent","high","normal","low","unset"]},"assignee_user_id":{"type":["string","null"],"pattern":"^[A-Za-z0-9_-]{8,255}$"}}},"ApprovalRequestCreate":{"type":"object","additionalProperties":false,"required":["change_summary"],"properties":{"change_summary":{"type":"string","minLength":12,"maxLength":5000,"description":"Client-visible summary of the completed changes."}}},"ApprovalRequest":{"type":"object","required":["object","feedback_id","status","change_summary"],"properties":{"object":{"type":"string","const":"approval_request"},"feedback_id":{"type":"string","format":"uuid"},"status":{"type":"string","const":"pending"},"change_summary":{"type":"string"}}},"ProposedPrompt":{"type":"object","required":["object","feedback_id","project_id","prompt","model","updated_at"],"properties":{"object":{"type":"string","const":"proposed_prompt"},"feedback_id":{"type":"string","format":"uuid"},"project_id":{"type":"string","format":"uuid"},"prompt":{"type":["string","null"]},"model":{"type":["string","null"]},"updated_at":{"type":["string","null"],"format":"date-time"}}},"Reviewer":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"project_id":{"type":"string","format":"uuid"},"email":{"type":"string","format":"email"},"status":{"enum":["active","revoked"]},"last_verified_at":{"type":["string","null"],"format":"date-time"}}},"ReviewerCreate":{"type":"object","additionalProperties":false,"required":["email"],"properties":{"email":{"type":"string","format":"email","maxLength":254,"description":"Email added to the project allowlist. It is normalized to lowercase."}}},"MemberRole":{"type":"string","enum":["admin","manager","contributor","viewer"]},"Member":{"type":"object","required":["object","id","user_id","name","email","role","joined_at"],"properties":{"object":{"type":"string","const":"workspace_member"},"id":{"type":"string","format":"uuid"},"user_id":{"type":"string"},"name":{"type":"string"},"email":{"type":"string","format":"email"},"role":{"type":"string","enum":["owner","admin","manager","contributor","viewer"]},"joined_at":{"type":"string","format":"date-time"}}},"MemberInvite":{"type":"object","additionalProperties":false,"required":["email","role"],"properties":{"email":{"type":"string","format":"email"},"role":{"$ref":"#/components/schemas/MemberRole"}}},"MemberUpdate":{"type":"object","additionalProperties":false,"required":["role"],"properties":{"role":{"$ref":"#/components/schemas/MemberRole"}}},"MemberRoleUpdate":{"type":"object","required":["object","id","role"],"properties":{"object":{"type":"string","const":"workspace_member"},"id":{"type":"string","format":"uuid"},"role":{"$ref":"#/components/schemas/MemberRole"}}},"WorkspaceInvitation":{"type":"object","required":["object","id","email","role","expires_at","invite_url"],"properties":{"object":{"type":"string","const":"workspace_invitation"},"id":{"type":"string","format":"uuid"},"email":{"type":"string","format":"email"},"role":{"$ref":"#/components/schemas/MemberRole"},"expires_at":{"type":"string","format":"date-time"},"invite_url":{"type":"string","format":"uri","description":"Returned only when the invitation is created. Treat it as a bearer secret."}}},"PendingInvitation":{"type":"object","required":["id","email","role","expires_at"],"properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string","format":"email"},"role":{"$ref":"#/components/schemas/MemberRole"},"expires_at":{"type":"string","format":"date-time"}}},"AgentCredentialCreate":{"type":"object","additionalProperties":false,"required":["label"],"properties":{"label":{"type":"string","minLength":3,"maxLength":80},"expires_in_days":{"type":"integer","minimum":1,"maximum":365,"default":365}}},"AgentCredential":{"type":"object","required":["object","id","project_id","label","token_prefix","status","last_used_at","expires_at","created_at"],"properties":{"object":{"type":"string","const":"agent_credential"},"id":{"type":"string","format":"uuid"},"project_id":{"type":"string","format":"uuid"},"label":{"type":"string"},"token_prefix":{"type":"string"},"status":{"enum":["active","expired","revoked"]},"last_used_at":{"type":["string","null"],"format":"date-time"},"expires_at":{"type":["string","null"],"format":"date-time"},"created_at":{"type":"string","format":"date-time"}}},"AgentCredentialSecret":{"type":"object","required":["object","id","project_id","token","expires_at"],"properties":{"object":{"type":"string","const":"agent_credential"},"id":{"type":"string","format":"uuid"},"project_id":{"type":"string","format":"uuid"},"token":{"type":"string","pattern":"^mcp_[A-Za-z0-9_-]{43}$","writeOnly":true},"expires_at":{"type":["string","null"],"format":"date-time"}}},"WebhookEventType":{"type":"string","enum":["feedback.created","feedback.external_comment_added","feedback.approved","feedback.changes_requested"]},"WebhookEndpointCreate":{"type":"object","additionalProperties":false,"required":["label","url"],"properties":{"label":{"type":"string","minLength":3,"maxLength":80},"url":{"type":"string","format":"uri","maxLength":2000,"description":"Public HTTPS URL. Redirects are not followed."},"project_id":{"type":["string","null"],"format":"uuid","description":"Null creates a workspace-wide endpoint. Project-scoped API keys are always forced to their own project."},"event_types":{"type":"array","minItems":1,"maxItems":4,"uniqueItems":true,"items":{"$ref":"#/components/schemas/WebhookEventType"}},"authentication":{"enum":["hmac_sha256","hmac_sha256_and_shared_secret"],"default":"hmac_sha256"},"shared_secret":{"type":"string","minLength":32,"maxLength":256,"writeOnly":true,"description":"Required only for compatibility mode. It becomes both the HMAC secret and x-feedback4-secret value."}}},"WebhookEndpoint":{"type":"object","required":["object","id","project_id","label","url","authentication","secret_prefix","event_types","status","failure_count","created_at"],"properties":{"object":{"type":"string","const":"webhook_endpoint"},"id":{"type":"string","format":"uuid"},"project_id":{"type":["string","null"],"format":"uuid"},"label":{"type":"string"},"url":{"type":"string","format":"uri"},"authentication":{"enum":["hmac_sha256","hmac_sha256_and_shared_secret"]},"secret_prefix":{"type":"string"},"event_types":{"type":"array","items":{"$ref":"#/components/schemas/WebhookEventType"}},"status":{"enum":["active","disabled"]},"failure_count":{"type":"integer","minimum":0},"last_delivered_at":{"type":["string","null"],"format":"date-time"},"last_failed_at":{"type":["string","null"],"format":"date-time"},"created_at":{"type":"string","format":"date-time"}}},"WebhookEndpointSecret":{"type":"object","required":["object","id","project_id","url","event_types","authentication","signing_secret","created_at"],"properties":{"object":{"type":"string","const":"webhook_endpoint"},"id":{"type":"string","format":"uuid"},"project_id":{"type":["string","null"],"format":"uuid"},"url":{"type":"string","format":"uri"},"event_types":{"type":"array","items":{"$ref":"#/components/schemas/WebhookEventType"}},"authentication":{"enum":["hmac_sha256","hmac_sha256_and_shared_secret"]},"signing_secret":{"type":"string","writeOnly":true},"created_at":{"type":"string","format":"date-time"}}},"WebhookDelivery":{"type":"object","required":["object","id","project_id","event_id","event_type","status","attempts","next_attempt_at","response_status","last_error","succeeded_at","created_at"],"properties":{"object":{"type":"string","const":"webhook_delivery"},"id":{"type":"string","format":"uuid"},"project_id":{"type":"string","format":"uuid"},"event_id":{"type":"string"},"event_type":{"$ref":"#/components/schemas/WebhookEventType"},"status":{"enum":["pending","succeeded","dead_lettered"]},"attempts":{"type":"integer","minimum":0},"next_attempt_at":{"type":["string","null"],"format":"date-time"},"response_status":{"type":["integer","null"],"minimum":100,"maximum":599},"last_error":{"type":["string","null"]},"succeeded_at":{"type":["string","null"],"format":"date-time"},"created_at":{"type":"string","format":"date-time"}}},"WebhookDeliveryRetry":{"type":"object","required":["object","id","status"],"properties":{"object":{"type":"string","const":"webhook_delivery"},"id":{"type":"string","format":"uuid"},"status":{"type":"string","const":"pending"}}},"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message","request_id"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"request_id":{"type":"string"},"details":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string"},"code":{"type":"string"}}}}}}}}}}}