{"openapi":"3.1.0","info":{"title":"Critics Room Actions API","version":"1.4.1","description":"Create, list, retrieve, update, and manage Critics Room reviews. For posting, prepare the draft, show assistantResponseMarkdown verbatim immediately above the confirmation card, then call publishPreparedReview with the tiny body {\"confirm\": true}."},"servers":[{"url":"https://criticsroom.com"}],"components":{"securitySchemes":{"OAuth2":{"type":"oauth2","flows":{"authorizationCode":{"authorizationUrl":"https://criticsroom.com/authorize","tokenUrl":"https://criticsroom.com/token","scopes":{"mcp":"Create and manage your Critics Room movie reviews"}}}}},"schemas":{"Tag":{"type":"object","additionalProperties":false,"properties":{"name":{"type":"string","maxLength":50},"sentiment":{"type":"string","enum":["positive","negative","neutral"]}},"required":["name","sentiment"]},"Review":{"type":"object","properties":{"id":{"type":"string"},"reviewId":{"type":"string","description":"Same value as id. Included for tool-call clarity."},"conversationId":{"type":"string","description":"Conversation associated with the saved review."},"movieTitle":{"type":"string","description":"Canonical movie or TV show title (bare show name for TV)."},"mediaType":{"type":["string","null"],"enum":["movie","tv",null],"description":"Whether this review is for a movie or a TV show."},"releaseYear":{"type":["integer","null"],"description":"Release year used to distinguish remakes and same-named titles."},"seasonNumber":{"type":["integer","null"],"description":"TV only: season the review is about."},"episodeNumber":{"type":["integer","null"],"description":"TV only: episode within the season the review is about."},"title":{"type":"string"},"rating":{"type":"number","minimum":1,"maximum":5},"summary":{"type":"string"},"reviewText":{"type":"string"},"containsSpoilers":{"type":"boolean"},"tags":{"type":"array","items":{"$ref":"#/components/schemas/Tag"}},"tmdbId":{"type":["integer","null"]},"posterPath":{"type":["string","null"],"description":"Optional TMDB poster path for saved review detail data."},"posterUrl":{"type":["string","null"],"format":"uri","description":"Optional direct poster image URL for saved review detail data."},"movieUrl":{"type":["string","null"],"format":"uri","description":"Typed Critics Room movie or TV detail URL."},"visibility":{"type":"string","enum":["public","private"]},"url":{"type":"string"},"deduplicated":{"type":"boolean","description":"True when a retry matched an already-saved identical review and returned the existing review instead of creating a duplicate."},"updated":{"type":"boolean","description":"True when the user already had a review of the same work (and season/episode) and it was updated in place instead of creating a second review. Tell the user their existing review was updated."},"assistantResponseMarkdown":{"type":"string","description":"Markdown confirmation already formatted for the user. After saving, use this exact string as the user-facing response."},"message":{"type":"string","description":"Short operational status for the assistant."}}}}},"security":[{"OAuth2":["mcp"]}],"paths":{"/api/actions/me":{"get":{"operationId":"getCurrentUser","summary":"Confirm the user is signed in to Critics Room and get their display name.","description":"Call first for any account request, and BEFORE telling the user to reconnect. Only suggest reconnecting if this returns 401 or the call fails to complete. A 200 means the user IS connected — never invent an auth failure or show a raw error like 'ClientResponseError'.","responses":{"200":{"description":"Authenticated user profile","content":{"application/json":{"schema":{"type":"object","properties":{"userId":{"type":"string"},"displayName":{"type":"string"},"email":{"type":"string"},"profileUrl":{"type":"string"}},"required":["userId","displayName","profileUrl"]}}}},"401":{"description":"OAuth sign-in required. ChatGPT should show the Critics Room sign-in button and retry this action after the user connects.","headers":{"WWW-Authenticate":{"description":"Bearer challenge with OAuth protected-resource metadata for Critics Room.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"error_description":{"type":"string"}},"required":["error","error_description"]}}}}},"security":[{"OAuth2":["mcp"]}]}},"/api/actions/session/disconnect":{"post":{"operationId":"disconnectCriticsRoom","x-openai-isConsequential":true,"summary":"Sign out of Critics Room for this GPT session and require reconnect before future account access","responses":{"200":{"description":"Disconnected","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string"},"message":{"type":"string"}},"required":["status","message"]}}}},"401":{"description":"OAuth sign-in required. ChatGPT should show the Critics Room sign-in button and retry this action after the user connects.","headers":{"WWW-Authenticate":{"description":"Bearer challenge with OAuth protected-resource metadata for Critics Room.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"error_description":{"type":"string"}},"required":["error","error_description"]}}}}},"security":[{"OAuth2":["mcp"]}]}},"/api/actions/conversations":{"get":{"operationId":"listConversations","summary":"List the authenticated user's review conversations. Use status=active to find one to resume.","parameters":[{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["active","review_generated"]}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":50,"default":10}}],"responses":{"200":{"description":"Conversation list","content":{"application/json":{"schema":{"type":"object","properties":{"conversations":{"type":"array","items":{"type":"object","properties":{"conversationId":{"type":"string"},"movieTitle":{"type":"string"},"status":{"type":"string"}}}}}}}}},"401":{"description":"OAuth sign-in required. ChatGPT should show the Critics Room sign-in button and retry this action after the user connects.","headers":{"WWW-Authenticate":{"description":"Bearer challenge with OAuth protected-resource metadata for Critics Room.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"error_description":{"type":"string"}},"required":["error","error_description"]}}}}},"security":[{"OAuth2":["mcp"]}]},"post":{"operationId":"startMovieReview","x-openai-isConsequential":false,"summary":"Start a movie review conversation","description":"Start an interview and use the returned instructions to actively move toward posting. Once the title, rating, and 2-3 concrete opinions are known, present a ready-to-post draft and ask whether to post it instead of continuing with broad follow-ups.","requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"movieTitle":{"type":"string","maxLength":300}}}}}},"responses":{"200":{"description":"Conversation created","content":{"application/json":{"schema":{"type":"object","properties":{"conversationId":{"type":"string"},"movieTitle":{"type":["string","null"]},"instructions":{"type":"string"}}}}}},"401":{"description":"OAuth sign-in required. ChatGPT should show the Critics Room sign-in button and retry this action after the user connects.","headers":{"WWW-Authenticate":{"description":"Bearer challenge with OAuth protected-resource metadata for Critics Room.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"error_description":{"type":"string"}},"required":["error","error_description"]}}}}},"security":[{"OAuth2":["mcp"]}]}},"/api/actions/conversations/{conversationId}":{"get":{"operationId":"getConversation","summary":"Resume a conversation: returns up to 100 recent saved messages so the assistant can continue the interview.","parameters":[{"name":"conversationId","in":"path","required":true,"schema":{"type":"string","maxLength":200}}],"responses":{"200":{"description":"Conversation with messages","content":{"application/json":{"schema":{"type":"object","properties":{"conversationId":{"type":"string"},"movieTitle":{"type":"string"},"status":{"type":"string"},"instructions":{"type":"string"},"historyTruncated":{"type":"boolean"},"messages":{"type":"array","items":{"type":"object","properties":{"role":{"type":"string","enum":["user","assistant"]},"content":{"type":"string"}}}}}}}}},"401":{"description":"OAuth sign-in required. ChatGPT should show the Critics Room sign-in button and retry this action after the user connects.","headers":{"WWW-Authenticate":{"description":"Bearer challenge with OAuth protected-resource metadata for Critics Room.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"error_description":{"type":"string"}},"required":["error","error_description"]}}}},"404":{"description":"Conversation not found"}},"security":[{"OAuth2":["mcp"]}]}},"/api/actions/conversations/{conversationId}/messages":{"post":{"operationId":"saveConversationMessage","x-openai-isConsequential":false,"summary":"Save a user or assistant conversation message","parameters":[{"name":"conversationId","in":"path","required":true,"schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"role":{"type":"string","enum":["user","assistant"]},"content":{"type":"string","maxLength":20000}},"required":["role","content"]}}}},"responses":{"200":{"description":"Message saved"},"401":{"description":"OAuth sign-in required. ChatGPT should show the Critics Room sign-in button and retry this action after the user connects.","headers":{"WWW-Authenticate":{"description":"Bearer challenge with OAuth protected-resource metadata for Critics Room.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"error_description":{"type":"string"}},"required":["error","error_description"]}}}},"404":{"description":"Conversation not found"}},"security":[{"OAuth2":["mcp"]}]}},"/api/actions/reviews/prepare":{"post":{"operationId":"prepareReviewPost","x-openai-isConsequential":false,"summary":"Prepare a completed review draft for final approval","description":"Creates a draft only; does NOT save or publish. After 200, in the same assistant turn, output assistantResponseMarkdown verbatim immediately above the confirmation card, then call publishPreparedReview with the tiny body {\"confirm\": true}. Do not browse/search.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"conversationId":{"type":"string","maxLength":200},"movieTitle":{"type":"string","maxLength":300,"description":"For TV reviews, pass the bare show name (e.g. 'Barry') — never include 'Season N Episode N'. Use seasonNumber/episodeNumber for that."},"mediaType":{"type":"string","enum":["movie","tv"],"description":"Whether this is a movie or TV show. Use tv when seasonNumber or episodeNumber is present."},"tmdbId":{"type":"integer","minimum":1,"description":"Stable TMDB identity. Use only an ID returned by an ambiguous-title response, together with mediaType. It is verified server-side and overrides title search."},"releaseYear":{"type":"integer","minimum":1870,"maximum":2200,"description":"Release year. Include this whenever the user identifies a year, remake, director, or the 'new' version. Use the canonical title as well; never guess between same-named works."},"tvReviewScope":{"type":"string","enum":["series","season","episode"],"description":"For TV reviews, always confirm whether the user is reviewing the whole series, a season, or an episode and pass that value. If unclear, ask; never guess or silently omit season/episode metadata. Complete seasonNumber/episodeNumber fields from older clients remain supported."},"seasonNumber":{"type":"integer","minimum":1,"maximum":200,"description":"TV only: which season the review is about. Omit for movies or whole-series reviews."},"episodeNumber":{"type":"integer","minimum":1,"maximum":1000,"description":"TV only: which episode within the season. Requires seasonNumber."},"title":{"type":"string","minLength":1,"maxLength":200,"description":"REQUIRED short headline for the review itself (e.g. 'Mindless Fun at Its Best'). Generate one from the user's take before calling this endpoint; never send an empty string."},"rating":{"type":"number","minimum":1,"maximum":5},"summary":{"type":"string","maxLength":1000},"reviewText":{"type":"string","maxLength":20000},"containsSpoilers":{"type":"boolean","description":"Set true if the review reveals plot twists, endings, or other surprises. Decide from the review content; do not ask the user."},"tags":{"type":"array","maxItems":20,"items":{"$ref":"#/components/schemas/Tag"}},"visibility":{"type":"string","enum":["public","private"],"default":"public","description":"Post publicly unless the user explicitly requests private. Do not ask a visibility question."},"approvalPreviewMarkdown":{"type":"string","maxLength":25000,"description":"Legacy compatibility only. Omit this field; the server formats the visible review preview from the validated review fields."}},"required":["movieTitle","title","rating","summary","reviewText"]}}}},"responses":{"200":{"description":"Temporary review draft prepared. Not posted until publishPreparedReview succeeds.","content":{"application/json":{"schema":{"type":"object","properties":{"approvalPreviewMarkdown":{"type":"string","description":"Full Markdown preview of exactly what will be posted: movie/show, rating, headline, summary, full review text, tags, and visibility. It is stored with the draft; do not pass it to publishPreparedReview."},"draftId":{"type":"string","description":"Internal temporary draft id. Do not pass it to publishPreparedReview."},"assistantResponseMarkdown":{"type":"string","description":"Full formatted Review to publish, including every saved field. Output this exact Markdown in the same assistant turn immediately before calling publishPreparedReview so it appears above the native confirmation card. Do not claim it is saved yet."},"message":{"type":"string","description":"Sequencing instruction: show assistantResponseMarkdown verbatim, then call publishPreparedReview with the body {\"confirm\": true}."}},"required":["approvalPreviewMarkdown","draftId","assistantResponseMarkdown","message"]}}}},"401":{"description":"OAuth sign-in required. ChatGPT should show the Critics Room sign-in button and retry this action after the user connects.","headers":{"WWW-Authenticate":{"description":"Bearer challenge with OAuth protected-resource metadata for Critics Room.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"error_description":{"type":"string"}},"required":["error","error_description"]}}}}},"security":[{"OAuth2":["mcp"]}]}},"/api/actions/reviews/prepared/publish":{"post":{"operationId":"publishPreparedReview","x-openai-isConsequential":true,"summary":"Post a prepared Critics Room review","description":"Post the prepared review after showing its formatted preview. Send only the body {\"confirm\": true} — the review is already stored server-side by prepareReviewPost. After a 200, output assistantResponseMarkdown.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"confirm":{"type":"boolean","description":"Set to true to publish the prepared draft. The review content is already stored server-side; send only this flag."}},"required":["confirm"]}}}},"responses":{"200":{"description":"Prepared review posted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Review"}}}},"401":{"description":"OAuth sign-in required. ChatGPT should show the Critics Room sign-in button and retry this action after the user connects.","headers":{"WWW-Authenticate":{"description":"Bearer challenge with OAuth protected-resource metadata for Critics Room.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"error_description":{"type":"string"}},"required":["error","error_description"]}}}}},"security":[{"OAuth2":["mcp"]}]}},"/api/actions/reviews":{"get":{"operationId":"listReviews","summary":"List the user's saved Critics Room reviews. Call this for requests like 'list my reviews'.","description":"For 'list my reviews'/saved review list/show/count/sort: always call this action. If not signed in, OAuth displays Sign in on ChatGPT app/browser. Never say tool unavailable. Omit limit unless user asks for N. After 200 output assistantResponseMarkdown; never stop after tool call.","parameters":[{"name":"sortBy","in":"query","required":false,"schema":{"type":"string","enum":["createdAt","updatedAt","rating","movieTitle"],"default":"createdAt"},"description":"Field to sort by. 'rating' = star rating, 'movieTitle' = alphabetical, 'createdAt' = when posted, 'updatedAt' = when last edited."},{"name":"sortOrder","in":"query","required":false,"schema":{"type":"string","enum":["asc","desc"],"default":"desc"},"description":"Sort direction. Default is desc (highest/newest first). Use asc for lowest-rated or oldest-first."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":500},"description":"Optional cap. Omit this for broad requests like 'list my reviews' to return up to 500 saved reviews."}],"responses":{"200":{"description":"Review list","content":{"application/json":{"schema":{"type":"object","properties":{"assistantResponseMarkdown":{"type":"string","description":"Markdown already formatted for the user. Use this exact string as the user-facing response."},"message":{"type":"string","description":"Same value as assistantResponseMarkdown, duplicated so ChatGPT has a simple final-answer field."},"reviewCount":{"type":"integer","description":"Number of reviews included in this response."},"totalReviewCount":{"type":"integer","description":"Total number of saved reviews matching the request before any explicit limit."},"reviews":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"movieTitle":{"type":"string"},"title":{"type":"string"},"rating":{"type":"number"},"summary":{"type":"string"},"containsSpoilers":{"type":"boolean"},"visibility":{"type":"string"},"url":{"type":"string"}}}}},"required":["assistantResponseMarkdown","message","reviewCount","totalReviewCount","reviews"]}}}},"401":{"description":"OAuth sign-in required. ChatGPT should show the Critics Room sign-in button and retry this action after the user connects.","headers":{"WWW-Authenticate":{"description":"Bearer challenge with OAuth protected-resource metadata for Critics Room.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"error_description":{"type":"string"}},"required":["error","error_description"]}}}}},"security":[{"OAuth2":["mcp"]}]}},"/api/actions/reviews/recent":{"get":{"operationId":"getRecentReviews","summary":"Verify recent save state. Call this whenever the user asks 'did you save it?' or before claiming a save failed.","description":"Answers 'did you save it?' from recent reviews in last withinSeconds. Use before claiming failure. If none are found and user asked to save, call prepareReviewPost then publishPreparedReview. Output assistantResponseMarkdown.","parameters":[{"name":"withinSeconds","in":"query","required":false,"schema":{"type":"integer","minimum":60,"maximum":86400,"default":600},"description":"Look-back window in seconds (default 600 = 10 minutes)."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":20,"default":5}}],"responses":{"200":{"description":"Recent reviews in window","content":{"application/json":{"schema":{"type":"object","properties":{"withinSeconds":{"type":"integer"},"found":{"type":"boolean","description":"True if at least one review was saved inside the window."},"assistantResponseMarkdown":{"type":"string","description":"Authoritative user-facing answer about the save state. Output this string verbatim."},"reviews":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"movieTitle":{"type":"string"},"mediaType":{"type":["string","null"],"enum":["movie","tv",null]},"seasonNumber":{"type":["integer","null"]},"episodeNumber":{"type":["integer","null"]},"rating":{"type":"number"},"visibility":{"type":"string","enum":["public","private"]},"createdAt":{"type":["string","null"],"format":"date-time"},"ageSeconds":{"type":"integer"},"url":{"type":"string"}}}}}}}}},"401":{"description":"OAuth sign-in required. ChatGPT should show the Critics Room sign-in button and retry this action after the user connects.","headers":{"WWW-Authenticate":{"description":"Bearer challenge with OAuth protected-resource metadata for Critics Room.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"error_description":{"type":"string"}},"required":["error","error_description"]}}}}},"security":[{"OAuth2":["mcp"]}]}},"/api/actions/reviews/{reviewId}":{"get":{"operationId":"getReview","summary":"Get one saved review by id","parameters":[{"name":"reviewId","in":"path","required":true,"schema":{"type":"string","maxLength":200}}],"responses":{"200":{"description":"Review","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Review"}}}},"401":{"description":"OAuth sign-in required. ChatGPT should show the Critics Room sign-in button and retry this action after the user connects.","headers":{"WWW-Authenticate":{"description":"Bearer challenge with OAuth protected-resource metadata for Critics Room.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"error_description":{"type":"string"}},"required":["error","error_description"]}}}},"404":{"description":"Review not found"}},"security":[{"OAuth2":["mcp"]}]},"delete":{"operationId":"deleteReview","x-openai-isConsequential":true,"summary":"Delete one saved review","description":"Delete one saved review by its id. If you don't have the id, call listReviews first to find it. Deleting is permanent, so invoking this shows the Allow card. After a 200, output assistantResponseMarkdown verbatim to confirm the deletion — never leave the delete unconfirmed.","parameters":[{"name":"reviewId","in":"path","required":true,"schema":{"type":"string","maxLength":200}}],"responses":{"200":{"description":"Review deleted","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string"},"assistantResponseMarkdown":{"type":"string","description":"Confirmation already formatted for the user. Output this exact string as the reply after deleting."},"message":{"type":"string","description":"Same value as assistantResponseMarkdown, duplicated as a simple final-answer field."}},"required":["status","assistantResponseMarkdown","message"]}}}},"401":{"description":"OAuth sign-in required. ChatGPT should show the Critics Room sign-in button and retry this action after the user connects.","headers":{"WWW-Authenticate":{"description":"Bearer challenge with OAuth protected-resource metadata for Critics Room.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"error_description":{"type":"string"}},"required":["error","error_description"]}}}},"404":{"description":"Review not found"}},"security":[{"OAuth2":["mcp"]}]}},"/api/actions/reviews/{reviewId}/update":{"post":{"operationId":"updateReview","x-openai-isConsequential":true,"summary":"Update an existing saved review","description":"Edit, revise, or correct an existing review. If reviewId is unknown, call listReviews/getReview first. Show a readable preview before invoking. Omitted fields stay unchanged; this never creates a new review. After 200, output assistantResponseMarkdown verbatim.","parameters":[{"name":"reviewId","in":"path","required":true,"schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"title":{"type":"string","minLength":1,"maxLength":200,"description":"Replacement review headline"},"rating":{"type":"number","minimum":1,"maximum":5},"summary":{"type":"string","minLength":1,"maxLength":1000},"reviewText":{"type":"string","minLength":1,"maxLength":20000},"tags":{"type":"array","maxItems":20,"items":{"$ref":"#/components/schemas/Tag"}},"visibility":{"type":"string","enum":["public","private"]},"containsSpoilers":{"type":"boolean","description":"Set true when the revised review reveals plot twists or endings, false to remove the spoiler warning; omit to preserve it"}}}}}},"responses":{"200":{"description":"Review updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Review"}}}},"401":{"description":"OAuth sign-in required. ChatGPT should show the Critics Room sign-in button and retry this action after the user connects.","headers":{"WWW-Authenticate":{"description":"Bearer challenge with OAuth protected-resource metadata for Critics Room.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"error_description":{"type":"string"}},"required":["error","error_description"]}}}},"404":{"description":"Review not found"}},"security":[{"OAuth2":["mcp"]}]}},"/api/actions/reviews/{reviewId}/visibility":{"patch":{"operationId":"setReviewVisibility","x-openai-isConsequential":true,"summary":"Set whether a review is public or private","parameters":[{"name":"reviewId","in":"path","required":true,"schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"visibility":{"type":"string","enum":["public","private"],"default":"public","description":"Post publicly unless the user explicitly requests private. Do not ask a visibility question."}},"required":["visibility"]}}}},"responses":{"200":{"description":"Visibility updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Review"}}}},"401":{"description":"OAuth sign-in required. ChatGPT should show the Critics Room sign-in button and retry this action after the user connects.","headers":{"WWW-Authenticate":{"description":"Bearer challenge with OAuth protected-resource metadata for Critics Room.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"error_description":{"type":"string"}},"required":["error","error_description"]}}}},"404":{"description":"Review not found"}},"security":[{"OAuth2":["mcp"]}]}}}}