{"openapi":"3.0.3","info":{"title":"Monoes API","version":"1.0.0","description":"REST API backing monoes.me: the community (features, bugs, orgs, posts, voting) and the MonoAgent library (workflows, web automations, orgs). Generated from the same registry that powers https://monoes.me/docs/reference."},"servers":[{"url":"https://monoes.me/api"}],"security":[{"oauth2":["community:read","community:write"]}],"components":{"securitySchemes":{"oauth2":{"type":"oauth2","flows":{"authorizationCode":{"authorizationUrl":"https://monoes.me/api/auth/oauth2/authorize","tokenUrl":"https://monoes.me/api/auth/oauth2/token","scopes":{"community:read":"Read feed, bugs, orgs, posts, and votes","community:write":"Post, comment, vote, and upload","library:read":"Read your library, including private items","library:write":"Publish, update and delete library items"}}}}}},"paths":{"/community/feed":{"get":{"summary":"List recent activity across posts, bugs, features, org uploads, and public workflows and web automations.","tags":["Feed"],"description":"Session is read if present (to compute the viewer's own vote on each item) but not required. A Bearer token without community:read is silently treated as anonymous rather than rejected. Workflow and web automation items are public or official library items; their url points at /library/{workflows|automations}/{slug}, and votes on them go to /api/community/library/{id}/vote.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"},"description":"Query params: sort ('latest' | 'popular'), page (number, 0-indexed), authorId (string, optional)"}}},"responses":{"default":{"description":"{ items: FeedItem[], hasMore: boolean }. FeedItem: { id, type: 'post'|'bug'|'feature'|'org'|'workflow'|'automation', title, preview, authorId, authorUsername, createdAt, score, myVote, url? }"}}}},"/community/bugs":{"post":{"summary":"File a bug report.","tags":["Bugs"],"description":"title 1-100 chars, description 1-1000 chars.","security":[{"oauth2":["community:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"},"description":"{ title: string, description: string, severity: 'low'|'medium'|'high'|'critical' }"}}},"responses":{"default":{"description":"201 { id, title, description, authorId, status: 'open', severity, createdAt, updatedAt }"}}}},"/community/bugs/{id}":{"patch":{"summary":"Update a bug's status and/or severity.","tags":["Bugs"],"description":"At least one field required. Additionally requires the acting user to have the admin or moderator role.","security":[{"oauth2":["community:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"},"description":"{ status?: 'open'|'in_progress'|'resolved'|'wontfix', severity?: 'low'|'medium'|'high'|'critical' }"}}},"responses":{"default":{"description":"{ status?, severity? }"}}},"delete":{"summary":"Delete a bug report.","tags":["Bugs"],"description":"Additionally requires the acting user to have the admin or moderator role.","security":[{"oauth2":["community:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"default":{"description":"{ id }"}}}},"/community/bugs/{id}/vote":{"post":{"summary":"Upvote, downvote, or clear your vote on a bug.","tags":["Bugs"],"description":"0 removes an existing vote. Idempotent upsert per (bug, user).","security":[{"oauth2":["community:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"},"description":"{ value: 1 | -1 | 0 }"}}},"responses":{"default":{"description":"{ score: number, myVote: 1|-1|0 }"}}}},"/community/bugs/{id}/comments":{"post":{"summary":"Post a comment on a bug.","tags":["Bugs"],"description":"body 1-1000 chars.","security":[{"oauth2":["community:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"},"description":"{ body: string }"}}},"responses":{"default":{"description":"201 { id, bugId, authorId, authorUsername, body, createdAt }"}}}},"/community/bugs/{id}/comments/{commentId}":{"delete":{"summary":"Delete your own comment (or any comment, as a moderator/admin).","tags":["Bugs"],"security":[{"oauth2":["community:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"commentId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"default":{"description":"{ id }"}}}},"/community/bugs/{id}/labels":{"post":{"summary":"Attach a label to a bug.","tags":["Bugs"],"description":"Idempotent: attaching an already-attached label is a no-op. Additionally requires the acting user to have the admin or moderator role.","security":[{"oauth2":["community:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"},"description":"{ labelId: string }"}}},"responses":{"default":{"description":"{ bugId, labelId }"}}}},"/community/bugs/{id}/labels/{labelId}":{"delete":{"summary":"Detach a label from a bug.","tags":["Bugs"],"description":"Additionally requires the acting user to have the admin or moderator role.","security":[{"oauth2":["community:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"labelId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"default":{"description":"{ bugId, labelId }"}}}},"/community/labels":{"post":{"summary":"Create a new label.","tags":["Labels"],"description":"name 1-30 chars; color is a #rrggbb hex string; 409 if the name is already taken. Additionally requires the acting user to have the admin or moderator role.","security":[{"oauth2":["community:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"},"description":"{ name: string, color: string }"}}},"responses":{"default":{"description":"201 { id, name, color }"}}}},"/community/features":{"post":{"summary":"Submit a feature request.","tags":["Feature requests"],"description":"title 1-100 chars, description 1-1000 chars.","security":[{"oauth2":["community:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"},"description":"{ title: string, description: string }"}}},"responses":{"default":{"description":"201 { id, title, description, authorId, status: 'open', createdAt, updatedAt }"}}}},"/community/features/{id}":{"delete":{"summary":"Delete a feature request.","tags":["Feature requests"],"description":"Additionally requires the acting user to have the admin or moderator role.","security":[{"oauth2":["community:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"default":{"description":"{ id }"}}}},"/community/features/{id}/status":{"patch":{"summary":"Change a feature request's status.","tags":["Feature requests"],"description":"Additionally requires the acting user to have the admin role.","security":[{"oauth2":["community:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"},"description":"{ status: 'open'|'planned'|'shipped'|'declined' }"}}},"responses":{"default":{"description":"{ status }"}}}},"/community/features/{id}/vote":{"post":{"summary":"Upvote, downvote, or clear your vote on a feature request.","tags":["Feature requests"],"security":[{"oauth2":["community:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"},"description":"{ value: 1 | -1 | 0 }"}}},"responses":{"default":{"description":"{ score: number, myVote: 1|-1|0 }"}}}},"/community/orgs":{"post":{"summary":"Upload an org definition (JSON matching the org schema).","tags":["Org gallery"],"description":"orgJson is validated against a Zod schema before insert. The request also needs a numeric Content-Length header under ~1 MB — a chunked-transfer client with no Content-Length is rejected outright, regardless of the actual body size.","security":[{"oauth2":["community:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"},"description":"{ orgJson: string }, a JSON-encoded org definition, max 500 KB"}}},"responses":{"default":{"description":"201 { id, name, goal, topology, roleCount, createdAt }"}}}},"/community/orgs/{id}":{"patch":{"summary":"Update an org's name, tagline, description, body, or banner image.","tags":["Org gallery"],"description":"Requires ownership (or moderator/admin). Limits: name 1-100 chars, tagline ≤150, description ≤1000, body ≤20000. bannerUrl must start with /api/images/org/ or be null; empty strings on tagline/description/body are coerced to null.","security":[{"oauth2":["community:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"},"description":"{ name?, tagline?, description?, body?, bannerUrl? } (all optional, at least one required)"}}},"responses":{"default":{"description":"{ id, ...updatedFields }"}}},"delete":{"summary":"Delete an org upload.","tags":["Org gallery"],"security":[{"oauth2":["community:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"default":{"description":"{ id }"}}}},"/community/orgs/{id}/vote":{"post":{"summary":"Upvote, downvote, or clear your vote on an org.","tags":["Org gallery"],"security":[{"oauth2":["community:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"},"description":"{ value: 1 | -1 | 0 }"}}},"responses":{"default":{"description":"{ score: number, myVote: 1|-1|0 }"}}}},"/community/orgs/{id}/comments":{"post":{"summary":"Post a comment on an org.","tags":["Org gallery"],"description":"body 1-1000 chars.","security":[{"oauth2":["community:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"},"description":"{ body: string }"}}},"responses":{"default":{"description":"201 { id, orgUploadId, authorId, authorUsername, body, createdAt }"}}}},"/community/orgs/{id}/comments/{commentId}":{"delete":{"summary":"Delete your own comment (or any comment, as a moderator/admin).","tags":["Org gallery"],"security":[{"oauth2":["community:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"commentId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"default":{"description":"{ id }"}}}},"/community/orgs/{id}/images":{"post":{"summary":"Upload an image (used for the org body and/or banner).","tags":["Org gallery"],"security":[{"oauth2":["community:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"},"description":"multipart/form-data, field 'image': PNG/JPEG/WebP, max 2 MB"}}},"responses":{"default":{"description":"201 { url }"}}}},"/community/orgs/{id}/runs":{"post":{"summary":"Upload a run's output files (Markdown and/or HTML).","tags":["Org gallery"],"description":"label is optional despite the field existing — a blank or missing label is stored as null.","security":[{"oauth2":["community:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"},"description":"multipart/form-data: field 'label' (string, optional, ≤100 chars), field 'files' (up to 10 .md/.html files, 2 MB each)"}}},"responses":{"default":{"description":"201 { id, label: string | null, createdAt, files: [{ id, filename, fileType, sizeBytes }] }"}}}},"/community/orgs/{id}/runs/{runId}":{"delete":{"summary":"Delete a run and its files.","tags":["Org gallery"],"description":"Requires ownership of the run (or moderator/admin).","security":[{"oauth2":["community:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"runId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"default":{"description":"{ id }"}}}},"/community/org-run-files/{fileId}":{"get":{"summary":"Fetch a run output file's raw content.","tags":["Org gallery"],"description":"Unauthenticated: anyone with the file id can view it, same as the linked org.","security":[],"parameters":[{"name":"fileId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"default":{"description":"The raw file body, Content-Type text/markdown or text/html."}}}},"/community/posts":{"post":{"summary":"Create a post.","tags":["Posts"],"description":"title 1-100 chars, body 1-2000 chars.","security":[{"oauth2":["community:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"},"description":"{ title: string, body: string }"}}},"responses":{"default":{"description":"201 { id, title, body, authorId, createdAt }"}}}},"/community/posts/{id}/vote":{"post":{"summary":"Upvote, downvote, or clear your vote on a post.","tags":["Posts"],"security":[{"oauth2":["community:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"},"description":"{ value: 1 | -1 | 0 }"}}},"responses":{"default":{"description":"{ score: number, myVote: 1|-1|0 }"}}}},"/community/blog/{slug}/comments":{"post":{"summary":"Post a comment on a blog post.","tags":["Blog comments"],"description":"slug must match a real post; body 1-1000 chars.","security":[{"oauth2":["community:write"]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"},"description":"{ body: string }"}}},"responses":{"default":{"description":"201 { id, postSlug, authorId, authorUsername, body, createdAt }"}}}},"/community/blog/{slug}/comments/{commentId}":{"delete":{"summary":"Delete your own comment (or any comment, as a moderator/admin).","tags":["Blog comments"],"security":[{"oauth2":["community:write"]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}},{"name":"commentId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"default":{"description":"{ id }"}}}},"/community/me":{"get":{"summary":"Get the authenticated user's id, username, name, and avatar URL.","tags":["Profile & identity"],"description":"avatarUrl (when set) is /api/images/avatar/<key>?v=<updatedAt ms> — the query param is a cache-buster, not part of the key.","security":[{"oauth2":["community:read"]}],"responses":{"default":{"description":"{ id, username, name: string | null, avatarUrl: string | null }"}}}},"/community/profile":{"patch":{"summary":"Update your profile: name, tagline, job, tags, and social links.","tags":["Profile & identity"],"description":"name required, 1-100 chars. tagline ≤140, jobTitle ≤80, company ≤80. Up to 10 tags (1-24 chars, alnum/underscore/hyphen). githubUrl/linkedinUrl must be https and match their platform's domain; twitterUrl accepts twitter.com or x.com (or a subdomain of either); websiteUrl just needs to be https.","security":[{"oauth2":["community:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"},"description":"{ name, tagline?, jobTitle?, company?, tags?: string[], githubUrl?, twitterUrl?, linkedinUrl?, websiteUrl? }"}}},"responses":{"default":{"description":"{ name, tagline, jobTitle, company, tags, githubUrl, twitterUrl, linkedinUrl, websiteUrl }"}}}},"/community/profile/avatar":{"post":{"summary":"Upload a new avatar image.","tags":["Profile & identity"],"description":"Stored at a fixed per-user key (avatars/<userId>) — re-uploading overwrites the previous image.","security":[{"oauth2":["community:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"},"description":"multipart/form-data, field 'avatar': PNG/JPEG/WebP, max 2 MB"}}},"responses":{"default":{"description":"{ avatarKey, updatedAt }"}}}},"/community/username":{"post":{"summary":"Set or change your username (required once, during onboarding).","tags":["Profile & identity"],"description":"3-24 chars, letters/numbers/underscore/hyphen; must be unique — a taken username is a 400, not a 409 (see /docs/errors).","security":[{"oauth2":["community:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"},"description":"{ username: string }"}}},"responses":{"default":{"description":"{ username }"}}}},"/community/admin/users":{"get":{"summary":"List all users.","tags":["Admin"],"description":"Admin-only — a moderator token gets 403 here. Additionally requires the acting user to have the admin role.","security":[{"oauth2":["community:read"]}],"responses":{"default":{"description":"{ users: [{ id, email, username, role, blockedAt, createdAt }] }"}}}},"/community/admin/users/{id}/block":{"patch":{"summary":"Block or unblock a user.","tags":["Admin"],"description":"blockedAt is an ISO timestamp when blocking, null when unblocking. Additionally requires the acting user to have the admin or moderator role.","security":[{"oauth2":["community:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"},"description":"{ blocked: boolean }"}}},"responses":{"default":{"description":"{ blockedAt: string | null }"}}}},"/community/admin/users/{id}/role":{"patch":{"summary":"Change a user's role.","tags":["Admin"],"description":"Additionally requires the acting user to have the admin role.","security":[{"oauth2":["community:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"},"description":"{ role: 'member'|'moderator'|'admin' }"}}},"responses":{"default":{"description":"{ role }"}}}},"/library/items":{"get":{"summary":"List library items.","tags":["Library"],"description":"scope=mine needs library:read (401 without credentials). Item: { id, kind, slug, name, description, version, visibility, tags, owner: { id, username, name }, sha256, size, meta, score (net community votes), created_at, updated_at, url, artifact_url }. The community workflow and web automation galleries (/community/workflows, /community/automations) are this list with scope=public and sort=latest|popular. Community gallery orgs are listed as public kind=org items with meta.gallery = true.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"},"description":"Query params: kind ('workflow'|'automation'|'org'), scope ('public' (default: public + official) | 'official' | 'mine'), q, tag, sort ('latest' (default, last updated first) | 'popular' (net votes first)), page (1-indexed), per_page (≤ 100, default 24)"}}},"responses":{"default":{"description":"{ items: Item[], page, per_page, total }"}}},"post":{"summary":"Publish a new item.","tags":["Library"],"description":"The server validates the file: automations are .mpkg zips with a valid automation.json (≤ 20 MB; the item version is automation.json's); workflows are MonoAgent workflow exports (≤ 20 MB); orgs must pass the org schema (≤ 500 KB). meta is derived from the file. At most 30 uploads per hour (429).","security":[{"oauth2":["library:write"]}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object"},"description":"multipart/form-data: kind, file, visibility ('private' default | 'public' | 'official' for admins), name?, description?, tags? (comma-separated), version? (semver)"}}},"responses":{"default":{"description":"201 Item"}}}},"/library/items/{ref}":{"get":{"summary":"Get one item by id, or by kind and slug (/api/library/items/automation/instagram).","tags":["Library"],"description":"A private item is 404 unless the caller is its owner (session, or a token with library:read).","security":[],"parameters":[{"name":"ref","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"default":{"description":"Item"}}}},"/library/items/{id}/artifact":{"get":{"summary":"Download the artifact: an .mpkg for automations, JSON for workflows and orgs.","tags":["Library"],"description":"Downloading needs a login (a session or a token with library:read); anonymous callers get 401 'Log in to monoes.me to download'. Browsing (list, item, versions) is open to everyone. Verify X-Content-SHA256 before installing.","security":[{"oauth2":["library:read"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"},"description":"Query params: version (optional; defaults to the current version)"}}},"responses":{"default":{"description":"The bytes, with Content-Type, Content-Length, Content-Disposition, X-Content-SHA256 (hex) and X-Library-Version headers"}}},"put":{"summary":"Publish a new version of an item you own.","tags":["Library"],"description":"The version must be newer than the current one (409 version_conflict). Earlier versions stay downloadable.","security":[{"oauth2":["library:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object"},"description":"multipart/form-data: file, version? (semver; default: next patch, or automation.json's version)"}}},"responses":{"default":{"description":"Item (with the new version)"}}}},"/library/items/{id}/versions":{"get":{"summary":"List an item's versions, newest first.","tags":["Library"],"security":[],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"default":{"description":"{ versions: [{ version, sha256, size, created_at, artifact_url }] }"}}}},"/library/items/{id}":{"patch":{"summary":"Edit an item you own.","tags":["Library"],"description":"Only admins move items into or out of 'official'. Gallery orgs are edited on the org gallery instead (409 gallery_org).","security":[{"oauth2":["library:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"},"description":"{ name?, description?, tags?: string[] | string, visibility? }"}}},"responses":{"default":{"description":"Item"}}},"delete":{"summary":"Delete an item and all its versions (owner or admin).","tags":["Library"],"security":[{"oauth2":["library:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"default":{"description":"{ id, deleted: true }"}}}},"/community/library/{id}/vote":{"post":{"summary":"Upvote, downvote, or clear your vote on a public or official library item.","tags":["Library"],"description":"Community conventions: errors are { error: string }. Private items and gallery orgs are 404 here; gallery orgs use /api/community/orgs/{id}/vote.","security":[{"oauth2":["community:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"},"description":"{ value: 1 | -1 | 0 }"}}},"responses":{"default":{"description":"{ score, myVote }"}}}},"/community/library/{id}/comments":{"post":{"summary":"Comment on a public or official library item.","tags":["Library"],"security":[{"oauth2":["community:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"},"description":"{ body: string } (1–1000 characters)"}}},"responses":{"default":{"description":"201 { id, itemId, authorId, authorUsername, body, createdAt }"}}}},"/community/library/{id}/comments/{commentId}":{"delete":{"summary":"Delete a comment on a library item (its author, a moderator or an admin).","tags":["Library"],"security":[{"oauth2":["community:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"commentId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"default":{"description":"{ id }"}}}},"/library/me":{"get":{"summary":"Who the token belongs to, and what it was granted.","tags":["Library"],"description":"Requires a session or any valid token (401 otherwise). MonoAgent uses it to show who is logged in.","security":[],"responses":{"default":{"description":"{ user: { id, name, username, email, image }, scopes: string[] }"}}}}}}