monoesdocs
Menu

API reference

All endpoints

Every endpoint is under https://monoes.me. Base path for all resources below: /api/community (except the file server, which is called out). See Authentication for what the auth badges mean.

Feed

The unified, cross-resource activity feed shown on the community homepage.

GET/api/community/feedPublic

List recent activity across posts, bugs, features, org uploads, and public workflows and web automations.

Request

Query params: sort ('latest' | 'popular'), page (number, 0-indexed), authorId (string, optional)

Response

{ items: FeedItem[], hasMore: boolean }. FeedItem: { id, type: 'post'|'bug'|'feature'|'org'|'workflow'|'automation', title, preview, authorId, authorUsername, createdAt, score, myVote, url? }

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.

Bugs

Bug reports, voting, comments, and moderation labels.

POST/api/community/bugscommunity:write

File a bug report.

Request

{ title: string, description: string, severity: 'low'|'medium'|'high'|'critical' }

Response

201 { id, title, description, authorId, status: 'open', severity, createdAt, updatedAt }

title 1-100 chars, description 1-1000 chars.

PATCH/api/community/bugs/{id}community:write · admin/moderator

Update a bug's status and/or severity.

Request

{ status?: 'open'|'in_progress'|'resolved'|'wontfix', severity?: 'low'|'medium'|'high'|'critical' }

Response

{ status?, severity? }

At least one field required.

DELETE/api/community/bugs/{id}community:write · admin/moderator

Delete a bug report.

Response

{ id }
POST/api/community/bugs/{id}/votecommunity:write

Upvote, downvote, or clear your vote on a bug.

Request

{ value: 1 | -1 | 0 }

Response

{ score: number, myVote: 1|-1|0 }

0 removes an existing vote. Idempotent upsert per (bug, user).

POST/api/community/bugs/{id}/commentscommunity:write

Post a comment on a bug.

Request

{ body: string }

Response

201 { id, bugId, authorId, authorUsername, body, createdAt }

body 1-1000 chars.

DELETE/api/community/bugs/{id}/comments/{commentId}community:write

Delete your own comment (or any comment, as a moderator/admin).

Response

{ id }
POST/api/community/bugs/{id}/labelscommunity:write · admin/moderator

Attach a label to a bug.

Request

{ labelId: string }

Response

{ bugId, labelId }

Idempotent: attaching an already-attached label is a no-op.

DELETE/api/community/bugs/{id}/labels/{labelId}community:write · admin/moderator

Detach a label from a bug.

Response

{ bugId, labelId }

Labels

Moderator-managed labels attachable to bug reports.

POST/api/community/labelscommunity:write · admin/moderator

Create a new label.

Request

{ name: string, color: string }

Response

201 { id, name, color }

name 1-30 chars; color is a #rrggbb hex string; 409 if the name is already taken.

Feature requests

Community feature requests and voting.

POST/api/community/featurescommunity:write

Submit a feature request.

Request

{ title: string, description: string }

Response

201 { id, title, description, authorId, status: 'open', createdAt, updatedAt }

title 1-100 chars, description 1-1000 chars.

DELETE/api/community/features/{id}community:write · admin/moderator

Delete a feature request.

Response

{ id }
PATCH/api/community/features/{id}/statuscommunity:write · admin

Change a feature request's status.

Request

{ status: 'open'|'planned'|'shipped'|'declined' }

Response

{ status }
POST/api/community/features/{id}/votecommunity:write

Upvote, downvote, or clear your vote on a feature request.

Request

{ value: 1 | -1 | 0 }

Response

{ score: number, myVote: 1|-1|0 }

Org gallery

Uploaded agent-org definitions, voting, comments, banner images, and run outputs.

POST/api/community/orgscommunity:write

Upload an org definition (JSON matching the org schema).

Request

{ orgJson: string }, a JSON-encoded org definition, max 500 KB

Response

201 { id, name, goal, topology, roleCount, createdAt }

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.

PATCH/api/community/orgs/{id}community:write

Update an org's name, tagline, description, body, or banner image.

Request

{ name?, tagline?, description?, body?, bannerUrl? } (all optional, at least one required)

Response

{ id, ...updatedFields }

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.

DELETE/api/community/orgs/{id}community:write

Delete an org upload.

Response

{ id }
POST/api/community/orgs/{id}/votecommunity:write

Upvote, downvote, or clear your vote on an org.

Request

{ value: 1 | -1 | 0 }

Response

{ score: number, myVote: 1|-1|0 }
POST/api/community/orgs/{id}/commentscommunity:write

Post a comment on an org.

Request

{ body: string }

Response

201 { id, orgUploadId, authorId, authorUsername, body, createdAt }

body 1-1000 chars.

DELETE/api/community/orgs/{id}/comments/{commentId}community:write

Delete your own comment (or any comment, as a moderator/admin).

Response

{ id }
POST/api/community/orgs/{id}/imagescommunity:write

Upload an image (used for the org body and/or banner).

Request

multipart/form-data, field 'image': PNG/JPEG/WebP, max 2 MB

Response

201 { url }
POST/api/community/orgs/{id}/runscommunity:write

Upload a run's output files (Markdown and/or HTML).

Request

multipart/form-data: field 'label' (string, optional, ≤100 chars), field 'files' (up to 10 .md/.html files, 2 MB each)

Response

201 { id, label: string | null, createdAt, files: [{ id, filename, fileType, sizeBytes }] }

label is optional despite the field existing — a blank or missing label is stored as null.

DELETE/api/community/orgs/{id}/runs/{runId}community:write

Delete a run and its files.

Response

{ id }

Requires ownership of the run (or moderator/admin).

GET/api/community/org-run-files/{fileId}Public

Fetch a run output file's raw content.

Response

The raw file body, Content-Type text/markdown or text/html.

Unauthenticated: anyone with the file id can view it, same as the linked org.

Posts

Free-form community posts and voting.

POST/api/community/postscommunity:write

Create a post.

Request

{ title: string, body: string }

Response

201 { id, title, body, authorId, createdAt }

title 1-100 chars, body 1-2000 chars.

POST/api/community/posts/{id}/votecommunity:write

Upvote, downvote, or clear your vote on a post.

Request

{ value: 1 | -1 | 0 }

Response

{ score: number, myVote: 1|-1|0 }

Blog comments

Comments on monoes.me blog posts.

POST/api/community/blog/{slug}/commentscommunity:write

Post a comment on a blog post.

Request

{ body: string }

Response

201 { id, postSlug, authorId, authorUsername, body, createdAt }

slug must match a real post; body 1-1000 chars.

DELETE/api/community/blog/{slug}/comments/{commentId}community:write

Delete your own comment (or any comment, as a moderator/admin).

Response

{ id }

Profile & identity

The authenticated user's own profile: identity, avatar, and username.

GET/api/community/mecommunity:read

Get the authenticated user's id, username, name, and avatar URL.

Response

{ id, username, name: string | null, avatarUrl: string | null }

avatarUrl (when set) is /api/images/avatar/<key>?v=<updatedAt ms> — the query param is a cache-buster, not part of the key.

PATCH/api/community/profilecommunity:write

Update your profile: name, tagline, job, tags, and social links.

Request

{ name, tagline?, jobTitle?, company?, tags?: string[], githubUrl?, twitterUrl?, linkedinUrl?, websiteUrl? }

Response

{ name, tagline, jobTitle, company, tags, githubUrl, twitterUrl, linkedinUrl, websiteUrl }

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.

POST/api/community/profile/avatarcommunity:write

Upload a new avatar image.

Request

multipart/form-data, field 'avatar': PNG/JPEG/WebP, max 2 MB

Response

{ avatarKey, updatedAt }

Stored at a fixed per-user key (avatars/<userId>) — re-uploading overwrites the previous image.

POST/api/community/usernamecommunity:write

Set or change your username (required once, during onboarding).

Request

{ username: string }

Response

{ username }

3-24 chars, letters/numbers/underscore/hyphen; must be unique — a taken username is a 400, not a 409 (see /docs/errors).

Admin

Admin-only user management (blocking is also available to moderators).

GET/api/community/admin/userscommunity:read · admin

List all users.

Response

{ users: [{ id, email, username, role, blockedAt, createdAt }] }

Admin-only — a moderator token gets 403 here.

PATCH/api/community/admin/users/{id}/blockcommunity:write · admin/moderator

Block or unblock a user.

Request

{ blocked: boolean }

Response

{ blockedAt: string | null }

blockedAt is an ISO timestamp when blocking, null when unblocking.

PATCH/api/community/admin/users/{id}/rolecommunity:write · admin

Change a user's role.

Request

{ role: 'member'|'moderator'|'admin' }

Response

{ role }

Library

Workflows, web automations (.mpkg) and orgs that MonoAgent installs: list, download, publish and version them.

GET/api/library/itemsPublic

List library items.

Request

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)

Response

{ items: Item[], page, per_page, total }

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.

GET/api/library/items/{ref}Public

Get one item by id, or by kind and slug (/api/library/items/automation/instagram).

Response

Item

A private item is 404 unless the caller is its owner (session, or a token with library:read).

GET/api/library/items/{id}/artifactlibrary:read

Download the artifact: an .mpkg for automations, JSON for workflows and orgs.

Request

Query params: version (optional; defaults to the current version)

Response

The bytes, with Content-Type, Content-Length, Content-Disposition, X-Content-SHA256 (hex) and X-Library-Version headers

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.

GET/api/library/items/{id}/versionsPublic

List an item's versions, newest first.

Response

{ versions: [{ version, sha256, size, created_at, artifact_url }] }
POST/api/library/itemslibrary:write

Publish a new item.

Request

multipart/form-data: kind, file, visibility ('private' default | 'public' | 'official' for admins), name?, description?, tags? (comma-separated), version? (semver)

Response

201 Item

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).

PUT/api/library/items/{id}/artifactlibrary:write

Publish a new version of an item you own.

Request

multipart/form-data: file, version? (semver; default: next patch, or automation.json's version)

Response

Item (with the new version)

The version must be newer than the current one (409 version_conflict). Earlier versions stay downloadable.

PATCH/api/library/items/{id}library:write

Edit an item you own.

Request

{ name?, description?, tags?: string[] | string, visibility? }

Response

Item

Only admins move items into or out of 'official'. Gallery orgs are edited on the org gallery instead (409 gallery_org).

DELETE/api/library/items/{id}library:write

Delete an item and all its versions (owner or admin).

Response

{ id, deleted: true }
POST/api/community/library/{id}/votecommunity:write

Upvote, downvote, or clear your vote on a public or official library item.

Request

{ value: 1 | -1 | 0 }

Response

{ score, myVote }

Community conventions: errors are { error: string }. Private items and gallery orgs are 404 here; gallery orgs use /api/community/orgs/{id}/vote.

POST/api/community/library/{id}/commentscommunity:write

Comment on a public or official library item.

Request

{ body: string } (1–1000 characters)

Response

201 { id, itemId, authorId, authorUsername, body, createdAt }
DELETE/api/community/library/{id}/comments/{commentId}community:write

Delete a comment on a library item (its author, a moderator or an admin).

Response

{ id }
GET/api/library/mePublic

Who the token belongs to, and what it was granted.

Response

{ user: { id, name, username, email, image }, scopes: string[] }

Requires a session or any valid token (401 otherwise). MonoAgent uses it to show who is logged in.