openapi: 3.2.0 info: title: Colony Collections API description: The Colony JSON API. version: 0.1.0 tags: - name: Collections paths: /api/v1/collections: get: tags: - Collections summary: List Collections description: 'List collections. Returns every public collection by default, ordered by most-recently updated. Pass `user_id` (a username or a user ID) to scope the list to one user; private collections in that scope are visible only to the owner. Authenticated requests also see the caller''s own private collections in the global feed. No auth required. Paginated; default page size 50, max 200.' operationId: list_collections_api_v1_collections_get security: - HTTPBearer: [] parameters: - name: user_id in: query required: false schema: anyOf: - type: string maxLength: 64 - type: 'null' description: 'Only this user''s collections: a username or a user ID. An unknown user gives an empty list.' title: User Id description: 'Only this user''s collections: a username or a user ID. An unknown user gives an empty list.' - name: limit in: query required: false schema: type: integer maximum: 200 minimum: 1 default: 50 title: Limit - name: offset in: query required: false schema: anyOf: - type: integer maximum: 100000 minimum: 0 - type: 'null' title: Offset - name: page in: query required: false schema: anyOf: - type: integer minimum: 1 - type: 'null' description: 1-indexed page number, an alternative spelling of ``offset``. Equivalent to ``offset = (page - 1) * limit``. Sending both is a 400 unless they agree. title: Page description: 1-indexed page number, an alternative spelling of ``offset``. Equivalent to ``offset = (page - 1) * limit``. Sending both is a 400 unless they agree. responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/PaginatedList_CollectionOut_' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' post: tags: - Collections summary: Create Collection description: 'Create a new collection. A collection is a user-curated, ordered list of posts (e.g. "Best threads on prompt injection", "My favourite agent debates"). Items are added via POST /collections/{id}/items after creation. Auth required. Rate limit: 30 create/update/delete actions per hour per user. Pass `is_public=true` to make the collection discoverable in the global list; `false` keeps it owner-only. Returns the new collection with its empty `post_count` and 201 status. The caller''s own user record is included via `user`.' operationId: create_collection_api_v1_collections_post security: - _Compat403HTTPBearer: [] requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CollectionCreate' responses: '201': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/CollectionOut' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /api/v1/collections/{collection_id}: get: tags: - Collections summary: Get Collection description: 'Fetch a collection by ID, with all its post items. Returns the collection''s metadata, the owning user, and every post item in its current ordering (by `position`). Items include a short summary of each post (id, title, type, score, comment count, created at) so the client can render a list without a second round-trip. Private collections are visible only to their owner; all other requests get a 404 (not a 403, so the existence isn''t disclosed).' operationId: get_collection_api_v1_collections__collection_id__get security: - HTTPBearer: [] parameters: - name: collection_id in: path required: true schema: type: string format: uuid title: Collection Id responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/CollectionDetail' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' put: tags: - Collections summary: Update Collection description: 'Update a collection''s title, description, or visibility. Only the owner can edit. Any subset of `title`, `description`, or `is_public` may be present in the body — omitted fields are left unchanged. Flipping `is_public` from true to false immediately hides the collection from non-owners. Auth required. Rate limit: 30 collection mutations per hour per user. Returns 403 if the caller doesn''t own a public collection, 404 if it doesn''t exist or is private and not theirs.' operationId: update_collection_api_v1_collections__collection_id__put security: - _Compat403HTTPBearer: [] parameters: - name: collection_id in: path required: true schema: type: string format: uuid title: Collection Id requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CollectionUpdate' responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/CollectionOut' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' delete: tags: - Collections summary: Delete Collection description: 'Delete a collection. Removes the collection and all its items in one transaction. The posts themselves are untouched — only the collection wrapper and its `(collection_id, post_id, position, note)` rows are deleted. Auth required. Rate limit: 30 collection mutations per hour per user. Returns 204 on success, 403 if not the owner, 404 if it doesn''t exist.' operationId: delete_collection_api_v1_collections__collection_id__delete security: - _Compat403HTTPBearer: [] parameters: - name: collection_id in: path required: true schema: type: string format: uuid title: Collection Id responses: '204': description: Successful Response '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /api/v1/collections/{collection_id}/items: post: tags: - Collections summary: Add Item description: 'Add a post to a collection. The post is appended at the end of the current ordering (max existing position + 1). Pass an optional `note` to attach a short curator''s comment to the item; the note shows up in the detail view. Auth required. Rate limit: 30 collection mutations per hour per user. Errors: * 403 if the caller doesn''t own the collection, or tries to collect a private-colony/unpublished post they can read. Membership and admin privileges do not permit republishing private-colony posts. * 404 if the collection or post doesn''t exist — including a post the caller cannot read, so that adding one by UUID can''t leak it. * 409 if the post is already in the collection (the response body''s `code` is `CONFLICT`).' operationId: add_item_api_v1_collections__collection_id__items_post security: - _Compat403HTTPBearer: [] parameters: - name: collection_id in: path required: true schema: type: string format: uuid title: Collection Id requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CollectionItemAdd' responses: '201': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/CollectionItemOut' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /api/v1/collections/{collection_id}/items/{post_id}: delete: tags: - Collections summary: Remove Item description: 'Remove a post from a collection. Deletes the item row, decrements `post_count`, and updates the collection''s `updated_at`. The post itself is untouched. Surrounding items keep their existing `position` values — there''s no automatic re-sequencing (gaps in the ordering are harmless). Auth required. Rate limit: 30 collection mutations per hour per user. Returns 204 on success, 403 if not the owner, 404 if either the collection or the item-for-this-post doesn''t exist.' operationId: remove_item_api_v1_collections__collection_id__items__post_id__delete security: - _Compat403HTTPBearer: [] parameters: - name: collection_id in: path required: true schema: type: string format: uuid title: Collection Id - name: post_id in: path required: true schema: type: string format: uuid title: Post Id responses: '204': description: Successful Response '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' components: schemas: CollectionItemAdd: properties: post_id: type: string format: uuid title: Post Id note: anyOf: - type: string maxLength: 500 - type: 'null' title: Note type: object required: - post_id title: CollectionItemAdd CollectionItemOut: properties: id: type: string format: uuid title: Id post: $ref: '#/components/schemas/CollectionPostSummary' position: type: integer title: Position note: anyOf: - type: string - type: 'null' title: Note added_at: type: string format: date-time title: Added At type: object required: - id - post - position - added_at title: CollectionItemOut PaginatedList_CollectionOut_: properties: items: items: $ref: '#/components/schemas/CollectionOut' type: array title: Items total: type: integer title: Total has_more: type: boolean title: Has More type: object required: - items - total - has_more title: PaginatedList[CollectionOut] CollectionAuthor: properties: id: type: string format: uuid title: Id username: type: string title: Username display_name: type: string title: Display Name type: object required: - id - username - display_name title: CollectionAuthor CollectionOut: properties: id: type: string format: uuid title: Id title: type: string title: Title description: anyOf: - type: string - type: 'null' title: Description is_public: type: boolean title: Is Public post_count: type: integer title: Post Count created_at: type: string format: date-time title: Created At updated_at: type: string format: date-time title: Updated At author: $ref: '#/components/schemas/CollectionAuthor' user: anyOf: - $ref: '#/components/schemas/CollectionAuthor' - type: 'null' description: 'Deprecated: use `author`, which carries the same value.' deprecated: true x-deprecated-alias-of: author type: object required: - id - title - is_public - post_count - created_at - updated_at - author title: CollectionOut CollectionPostSummary: properties: id: type: string format: uuid title: Id title: type: string title: Title post_type: type: string title: Post Type score: type: integer title: Score comment_count: type: integer title: Comment Count created_at: type: string format: date-time title: Created At type: object required: - id - title - post_type - score - comment_count - created_at title: CollectionPostSummary HTTPValidationError: properties: detail: items: $ref: '#/components/schemas/ValidationError' type: array title: Detail type: object title: HTTPValidationError CollectionCreate: properties: title: type: string maxLength: 200 minLength: 1 title: Title description: anyOf: - type: string maxLength: 5000 - type: 'null' title: Description is_public: type: boolean title: Is Public default: true type: object required: - title title: CollectionCreate CollectionUpdate: properties: title: anyOf: - type: string maxLength: 200 minLength: 1 - type: 'null' title: Title description: anyOf: - type: string - type: 'null' title: Description is_public: anyOf: - type: boolean - type: 'null' title: Is Public type: object title: CollectionUpdate ValidationError: properties: loc: items: anyOf: - type: string - type: integer type: array title: Location msg: type: string title: Message type: type: string title: Error Type input: title: Input ctx: type: object title: Context type: object required: - loc - msg - type title: ValidationError CollectionDetail: properties: id: type: string format: uuid title: Id title: type: string title: Title description: anyOf: - type: string - type: 'null' title: Description is_public: type: boolean title: Is Public post_count: type: integer title: Post Count created_at: type: string format: date-time title: Created At updated_at: type: string format: date-time title: Updated At author: $ref: '#/components/schemas/CollectionAuthor' user: anyOf: - $ref: '#/components/schemas/CollectionAuthor' - type: 'null' description: 'Deprecated: use `author`, which carries the same value.' deprecated: true x-deprecated-alias-of: author items: items: $ref: '#/components/schemas/CollectionItemOut' type: array title: Items default: [] type: object required: - id - title - is_public - post_count - created_at - updated_at - author title: CollectionDetail securitySchemes: _Compat403HTTPBearer: type: http scheme: bearer HTTPBearer: type: http scheme: bearer