{"openapi":"3.1.0","info":{"title":"GetResolved API","version":"1.0.0","description":"Customer support platform API. Manage issues, conversations, and releases."},"servers":[{"url":"/api/v1"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"API key starting with gr_"}},"schemas":{"Pagination":{"type":"object","properties":{"total":{"type":"integer"},"limit":{"type":"integer"},"offset":{"type":"integer"}}},"Error":{"type":"object","properties":{"error_code":{"type":"string","enum":["unauthorized","forbidden","not_found","validation_error","internal_error"]},"detail":{"type":"string"},"fields":{"type":"object","additionalProperties":{"type":"string"}}},"required":["error_code","detail"]},"Member":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"members.id — the value to write to issues.assignee_id"},"user_id":{"type":"string","format":"uuid","nullable":true,"description":"auth.users id (null for Slack-only members)"},"role":{"type":"string","enum":["owner","admin","agent"]},"display_name":{"type":"string","nullable":true},"avatar_url":{"type":"string","nullable":true},"created_at":{"type":"string","format":"date-time"}}},"Me":{"type":"object","properties":{"workspace_id":{"type":"string","format":"uuid"},"api_key_id":{"type":"string","format":"uuid"},"member":{"type":"object","nullable":true,"description":"The workspace member tied to this API key (via api_keys.created_by). Null when the key has no creator (e.g. user deleted) or no matching member row.","properties":{"id":{"type":"string","format":"uuid"},"user_id":{"type":"string","format":"uuid","nullable":true},"role":{"type":"string","enum":["owner","admin","agent"]},"display_name":{"type":"string","nullable":true},"avatar_url":{"type":"string","nullable":true}}}}},"Product":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"workspace_id":{"type":"string","format":"uuid"},"name":{"type":"string"},"slug":{"type":"string"},"created_at":{"type":"string","format":"date-time"}}},"Issue":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"product_id":{"type":"string","format":"uuid"},"shortcode":{"type":"string","description":"Human-readable identifier, e.g. GET-001"},"title":{"type":"string"},"description":{"type":"string","nullable":true},"status":{"type":"string","enum":["pending","in_progress","icebox","done","released","dismissed"]},"priority":{"type":"string","enum":["low","normal","high","urgent"]},"assignee_id":{"type":"string","format":"uuid","nullable":true,"description":"members.id of the assigned workspace member (null if unassigned)"},"resolution_comment":{"type":"string","nullable":true,"description":"Free-form note on how the issue was fixed (or any post-fix context). Null if none."},"is_ai_generated":{"type":"boolean"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"linked_conversations_count":{"type":"integer","description":"Number of linked conversations (list endpoint only)"},"linked_conversations":{"type":"array","description":"Linked conversations (detail endpoint only)","items":{"$ref":"#/components/schemas/ConversationSummary"}}}},"ConversationSummary":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"title":{"type":"string"},"type":{"type":"string","enum":["ticket","idea","feedback","chat"]},"status":{"type":"string","enum":["open","in_progress","resolved","dismissed"]},"priority":{"type":"string","enum":["low","normal","high","urgent"]},"ai_summary":{"type":"string","nullable":true},"created_at":{"type":"string","format":"date-time"}}},"Conversation":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"product_id":{"type":"string","format":"uuid"},"contact_id":{"type":"string","format":"uuid","nullable":true},"type":{"type":"string","enum":["ticket","idea","feedback","chat"]},"source":{"type":"string","enum":["chat","form"],"description":"Origin channel — `chat` for widget conversations, `form` for form submissions mirrored into the inbox"},"status":{"type":"string","enum":["open","in_progress","resolved","dismissed"]},"priority":{"type":"string","enum":["low","normal","high","urgent"]},"title":{"type":"string"},"ai_summary":{"type":"string","nullable":true},"rating":{"type":"number","nullable":true},"upvotes":{"type":"integer"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"contact":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"name":{"type":"string"},"email":{"type":"string"}}},"messages":{"type":"array","items":{"$ref":"#/components/schemas/Message"}}}},"Message":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"sender_type":{"type":"string","enum":["agent","contact","system"]},"sender_id":{"type":"string"},"body":{"type":"string"},"sender_name":{"type":"string","nullable":true},"created_at":{"type":"string","format":"date-time"}}},"Release":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"workspace_id":{"type":"string","format":"uuid"},"product_id":{"type":"string","format":"uuid"},"title":{"type":"string"},"description":{"type":"string","nullable":true},"version":{"type":"string","nullable":true},"released_at":{"type":"string","format":"date-time","nullable":true,"description":"Null means the release is a draft (not yet published)."},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"product":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"name":{"type":"string"}}},"issues":{"type":"array","description":"Detail endpoint only","items":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"status":{"type":"string"},"priority":{"type":"string"}}}}}}},"parameters":{"limitParam":{"name":"limit","in":"query","schema":{"type":"integer","default":50,"maximum":200}},"offsetParam":{"name":"offset","in":"query","schema":{"type":"integer","default":0}}}},"paths":{"/me":{"get":{"operationId":"getMe","summary":"Identify the API key — returns the workspace and the member tied to this key. Use this to discover your own member id (e.g. for assignee_id), and to learn the workspace context.","responses":{"200":{"description":"Identity. `member` may be null if the API key has no creator on file."}}}},"/members":{"get":{"operationId":"listMembers","summary":"List workspace members. Use to look up member ids for assignee_id when \"me\" is not what you want.","parameters":[{"$ref":"#/components/parameters/limitParam"},{"$ref":"#/components/parameters/offsetParam"}],"responses":{"200":{"description":"Member list"}}}},"/products":{"get":{"operationId":"listProducts","summary":"List products in workspace","parameters":[{"$ref":"#/components/parameters/limitParam"},{"$ref":"#/components/parameters/offsetParam"}],"responses":{"200":{"description":"Product list"}}},"post":{"operationId":"createProduct","summary":"Create a product. widget_key, product_key, and issue_prefix are auto-generated.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string","description":"Product name (1–200 chars, trimmed)"},"slug":{"type":"string","description":"Optional. Lowercase alphanumeric with hyphens (e.g. \"my-product\"). Auto-derived from name if omitted; auto-suffixed on collision."}}}}}},"responses":{"201":{"description":"Created product (includes widget_key for embed snippet)"}}}},"/products/{id}":{"get":{"operationId":"getProduct","summary":"Get a product","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Product detail"}}},"patch":{"operationId":"updateProduct","summary":"Update a product. Changing issue_prefix only affects newly created issues (existing shortcodes are immutable).","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"1–200 chars, trimmed"},"slug":{"type":"string","description":"Lowercase alphanumeric with hyphens; unique within workspace"},"issue_prefix":{"type":"string","description":"1–3 uppercase letters/digits (e.g. \"GET\"); unique within workspace"},"widget_config":{"type":"object","nullable":true,"description":"Replaces the entire widget_config object"},"domain":{"type":"string","nullable":true}}}}}},"responses":{"200":{"description":"Updated product"}}}},"/issues":{"get":{"operationId":"listIssues","summary":"List issues (to-dos extracted from customer conversations)","parameters":[{"$ref":"#/components/parameters/limitParam"},{"$ref":"#/components/parameters/offsetParam"},{"name":"product_id","in":"query","schema":{"type":"string","format":"uuid"}},{"name":"status","in":"query","description":"Comma-separated: pending,in_progress,icebox,done,released,dismissed","schema":{"type":"string"}},{"name":"priority","in":"query","description":"Comma-separated: low,normal,high,urgent","schema":{"type":"string"}},{"name":"assignee_id","in":"query","description":"Comma-separated member ids, or \"none\" for unassigned","schema":{"type":"string"}}],"responses":{"200":{"description":"Issue list with linked_conversations_count"}}},"post":{"operationId":"createIssue","summary":"Create an issue. Shortcode (e.g. GET-005) is auto-generated.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["product_id","title"],"properties":{"product_id":{"type":"string","format":"uuid"},"title":{"type":"string","description":"Non-empty title, max 500 chars (trimmed)"},"description":{"type":"string","nullable":true,"description":"Free-form description"},"status":{"type":"string","enum":["pending","in_progress","icebox","done","released","dismissed"],"description":"Defaults to pending"},"priority":{"type":"string","enum":["low","normal","high","urgent"],"description":"Defaults to normal"},"assignee_id":{"type":"string","format":"uuid","nullable":true,"description":"members.id of the assignee (must belong to this workspace)"}}}}}},"responses":{"201":{"description":"Created issue (is_ai_generated is always false for API-created issues)"}}}},"/issues/maybe":{"post":{"operationId":"maybeCreateIssue","summary":"Create an issue only if no duplicate exists. Uses AI to compare title+description against existing pending/in_progress issues for the product; matches across paraphrasing and translation. On match, records this API call as a new source on the existing issue (issue_api_sources) and returns the existing issue with matched_existing=true. On no match, creates a new issue and returns matched_existing=false.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["product_id","title"],"properties":{"product_id":{"type":"string","format":"uuid"},"title":{"type":"string","description":"Non-empty title, max 500 chars (trimmed)"},"description":{"type":"string","nullable":true,"description":"Free-form description (improves match quality)"},"status":{"type":"string","enum":["pending","in_progress","icebox","done","dismissed"],"description":"Only used when creating; ignored when matched"},"priority":{"type":"string","enum":["low","normal","high","urgent"],"description":"Only used when creating; ignored when matched"},"assignee_id":{"type":"string","format":"uuid","nullable":true,"description":"Only used when creating; ignored when matched"}}}}}},"responses":{"200":{"description":"Duplicate found — existing issue returned with matched_existing=true and api_source_id of the logged source row"},"201":{"description":"No duplicate — new issue created with matched_existing=false and api_source_id of the logged source row"},"500":{"description":"Duplicate detection failed (e.g. LLM error). Safe to retry, or fall back to POST /issues to bypass."}}}},"/issues/{id}":{"get":{"operationId":"getIssue","summary":"Get issue with linked conversations. Accepts either the UUID or the human-readable shortcode (e.g. GET-005).","parameters":[{"name":"id","in":"path","required":true,"description":"Issue UUID or shortcode (e.g. GET-005)","schema":{"type":"string"}}],"responses":{"200":{"description":"Issue detail with linked_conversations array"}}},"patch":{"operationId":"updateIssue","summary":"Update issue title, description, status, priority, assignee, or resolution comment. Accepts either the UUID or shortcode.","parameters":[{"name":"id","in":"path","required":true,"description":"Issue UUID or shortcode (e.g. GET-005)","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string","description":"Non-empty title, max 500 chars (trimmed)"},"description":{"type":"string","nullable":true,"description":"Free-form description. Pass null or an empty string to clear."},"status":{"type":"string","enum":["pending","in_progress","icebox","done","released","dismissed"]},"priority":{"type":"string","enum":["low","normal","high","urgent"]},"assignee_id":{"type":"string","nullable":true,"description":"members.id (uuid) of the assignee, the literal string \"me\" to assign to the API key's owning member, or null to unassign"},"resolution_comment":{"type":"string","nullable":true,"description":"Free-form note on how the issue was fixed. Pass null or an empty string to clear."}}}}}},"responses":{"200":{"description":"Updated issue"}}}},"/actions":{"get":{"operationId":"listActions","deprecated":true,"summary":"Deprecated — use /issues instead","parameters":[{"$ref":"#/components/parameters/limitParam"},{"$ref":"#/components/parameters/offsetParam"},{"name":"product_id","in":"query","schema":{"type":"string","format":"uuid"}},{"name":"status","in":"query","schema":{"type":"string"}},{"name":"priority","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Alias for /issues"}}},"post":{"operationId":"createAction","deprecated":true,"summary":"Deprecated — use POST /issues instead","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"201":{"description":"Alias for POST /issues"}}}},"/actions/{id}":{"get":{"operationId":"getAction","deprecated":true,"summary":"Deprecated — use /issues/{id} instead","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Alias for /issues/{id}"}}},"patch":{"operationId":"updateAction","deprecated":true,"summary":"Deprecated — use /issues/{id} instead","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"Alias for /issues/{id}"}}}},"/conversations":{"get":{"operationId":"listConversations","summary":"List conversations (tickets, ideas, feedback, chats)","parameters":[{"$ref":"#/components/parameters/limitParam"},{"$ref":"#/components/parameters/offsetParam"},{"name":"product_id","in":"query","schema":{"type":"string","format":"uuid"}},{"name":"type","in":"query","description":"Comma-separated: ticket,idea,feedback,chat","schema":{"type":"string"}},{"name":"status","in":"query","description":"Comma-separated: open,in_progress,resolved,dismissed","schema":{"type":"string"}},{"name":"priority","in":"query","description":"Comma-separated: low,normal,high,urgent","schema":{"type":"string"}}],"responses":{"200":{"description":"Conversation list"}}}},"/conversations/{id}":{"get":{"operationId":"getConversation","summary":"Get conversation with all messages","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Conversation detail with messages array"}}},"patch":{"operationId":"updateConversation","summary":"Update conversation status or priority","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["open","in_progress","resolved","dismissed"]},"priority":{"type":"string","enum":["low","normal","high","urgent"]}}}}}},"responses":{"200":{"description":"Updated conversation"}}}},"/conversations/{id}/messages":{"post":{"operationId":"createMessage","summary":"Add a message to a conversation","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["body"],"properties":{"body":{"type":"string","description":"Message content"}}}}}},"responses":{"201":{"description":"Created message"}}}},"/releases":{"get":{"operationId":"listReleases","summary":"List releases","parameters":[{"$ref":"#/components/parameters/limitParam"},{"$ref":"#/components/parameters/offsetParam"},{"name":"product_id","in":"query","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Release list"}}},"post":{"operationId":"createRelease","summary":"Create a release bundling completed issues","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["product_id","title"],"properties":{"product_id":{"type":"string","format":"uuid"},"title":{"type":"string"},"description":{"type":"string"},"version":{"type":"string"},"issue_ids":{"type":"array","items":{"type":"string","format":"uuid"},"description":"Issue IDs to include in this release"}}}}}},"responses":{"201":{"description":"Created release with linked_issues_count"}}}},"/releases/{id}":{"get":{"operationId":"getRelease","summary":"Get release with linked issues","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Release detail with issues array"}}}}}}