# microfeed API This is a self-contained API reference. It includes every endpoint, parameter, request body, response status, response schema, and reusable schema. You do not need to fetch another document to understand or use the API. Use this API to build integrations that create and manage content in this microfeed instance. Send an API key using Bearer authentication: Authorization: Bearer YOUR_API_KEY The API base path is /api/v1/. Operation paths in the contract are relative to that base path. API access may be disabled by the instance owner. ## Operations GET /feed/ — Get the feed POST /items/ — Create an item GET /items/{itemId}/ — Get an item PUT /items/{itemId}/ — Update an item DELETE /items/{itemId}/ — Delete an item PUT /channels/{channelId}/ — Update the primary channel POST /media_files/presigned_urls/ — Prepare a media upload ## Pagination Use sort=created_at|updated_at|published_at and order=asc|desc. Follow next_url and prev_url when present. Legacy newest_first and oldest_first sort values remain supported. ## Media uploads Prepare an upload, PUT the raw bytes to presigned_url, then save media_url on the item or channel. The server does not read full_local_file_path; it uses that value only to preserve the file extension. ## Complete endpoint contract The OpenAPI 3.1.1 document below is the complete contract for this instance. References such as `#/components/schemas/Item` resolve to definitions contained later in this same document. ```yaml openapi: 3.1.1 info: title: microfeed API version: 1.0.1 description: Create, read, update, and delete content in this microfeed instance. Send an API key using Bearer authentication. license: name: GNU Affero General Public License v3.0 identifier: AGPL-3.0-only servers: - url: /api/v1/ description: This microfeed instance API tags: - name: Feed description: Read the complete feed. - name: Items description: Create and manage feed items. - name: Channel description: Update the primary channel. - name: Media description: Prepare same-origin media uploads. security: - bearerAuth: [] paths: /feed/: get: operationId: getFeed summary: Get the feed tags: - Feed parameters: - in: query name: limit schema: type: integer minimum: 1 maximum: 300 - in: query name: next_cursor schema: type: string - in: query name: order schema: type: string enum: - asc - desc - in: query name: prev_cursor schema: type: string - in: query name: sort schema: type: string enum: - created_at - updated_at - published_at - newest_first - oldest_first responses: "200": description: Successful response. content: application/json: schema: $ref: "#/components/schemas/Feed" "401": description: The API key is missing or invalid. content: application/json: schema: $ref: "#/components/schemas/Error" /items/: post: operationId: createItem summary: Create an item tags: - Items requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/ItemInput" responses: "201": description: Successful response. content: application/json: schema: type: object properties: id: type: string required: - id additionalProperties: false "400": description: The request body is invalid. content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: The API key is missing or invalid. content: application/json: schema: $ref: "#/components/schemas/Error" /items/{itemId}/: get: operationId: getItem summary: Get an item tags: - Items parameters: - in: path name: itemId schema: type: string minLength: 1 description: The microfeed item ID or an item-page slug ending in that ID. example: 0HGJLSML3P1 required: true description: The microfeed item ID or an item-page slug ending in that ID. responses: "200": description: Successful response. content: application/json: schema: $ref: "#/components/schemas/Feed" "401": description: The API key is missing or invalid. content: application/json: schema: $ref: "#/components/schemas/Error" "404": description: The item does not exist. content: application/json: schema: $ref: "#/components/schemas/Error" put: operationId: updateItem summary: Update an item description: Only provided fields are changed. Attachments, GUIDs, dates, and omitted fields are preserved. tags: - Items parameters: - in: path name: itemId schema: type: string minLength: 1 description: The microfeed item ID or an item-page slug ending in that ID. example: 0HGJLSML3P1 required: true description: The microfeed item ID or an item-page slug ending in that ID. requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/ItemInput" responses: "200": description: Successful response. content: application/json: schema: $ref: "#/components/schemas/Item" "400": description: The request body or item ID is invalid. content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: The API key is missing or invalid. content: application/json: schema: $ref: "#/components/schemas/Error" "404": description: The item does not exist. content: application/json: schema: $ref: "#/components/schemas/Error" delete: operationId: deleteItem summary: Delete an item tags: - Items parameters: - in: path name: itemId schema: type: string minLength: 1 description: The microfeed item ID or an item-page slug ending in that ID. example: 0HGJLSML3P1 required: true description: The microfeed item ID or an item-page slug ending in that ID. responses: "200": description: Successful response. content: application/json: schema: type: object properties: {} additionalProperties: false "400": description: The item ID is invalid. content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: The API key is missing or invalid. content: application/json: schema: $ref: "#/components/schemas/Error" "404": description: The item does not exist. content: application/json: schema: $ref: "#/components/schemas/Error" /channels/{channelId}/: put: operationId: updatePrimaryChannel summary: Update the primary channel tags: - Channel parameters: - in: path name: channelId schema: type: string const: primary description: microfeed currently exposes one primary channel. required: true description: microfeed currently exposes one primary channel. requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/ChannelInput" responses: "200": description: Successful response. content: application/json: schema: type: object properties: {} additionalProperties: false "400": description: The request body or channel ID is invalid. content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: The API key is missing or invalid. content: application/json: schema: $ref: "#/components/schemas/Error" /media_files/presigned_urls/: post: operationId: prepareMediaUpload summary: Prepare a media upload description: Creates a short-lived same-origin upload URL. PUT the raw file bytes to presigned_url, then save media_url on an item or channel. tags: - Media requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/UploadRequest" responses: "201": description: Successful response. content: application/json: schema: $ref: "#/components/schemas/UploadResponse" "400": description: The upload request is invalid. content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: The API key is missing or invalid. content: application/json: schema: $ref: "#/components/schemas/Error" "503": description: Media storage is unavailable. content: application/json: schema: $ref: "#/components/schemas/Error" components: schemas: ItemInput: type: object properties: _microfeed: type: object propertyNames: type: string additionalProperties: {} attachment: $ref: "#/components/schemas/Attachment" attachments: maxItems: 1 type: array items: $ref: "#/components/schemas/Attachment" content_html: type: string date_published: type: string format: date-time pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ date_published_ms: type: integer minimum: 0 maximum: 9007199254740991 guid: type: string id: type: string image: type: string format: uri status: anyOf: - type: string enum: - published - unlisted - unpublished - type: integer minimum: 1 maximum: 4 description: The item visibility. Names are preferred; numeric values are retained for compatibility. example: published title: type: string url: type: string format: uri additionalProperties: {} Attachment: type: object properties: category: type: string enum: - audio - video - document - image - external_url duration_in_seconds: type: number minimum: 0 mime_type: type: string size_in_byte: deprecated: true description: Deprecated singular spelling. Use size_in_bytes. type: integer minimum: 0 maximum: 9007199254740991 size_in_bytes: type: integer minimum: 0 maximum: 9007199254740991 url: type: string format: uri required: - category - url additionalProperties: {} ChannelInput: type: object properties: _microfeed: type: object propertyNames: type: string additionalProperties: {} authors: type: array items: type: object properties: name: type: string required: - name description: type: string expired: type: boolean home_page_url: deprecated: true type: string format: uri homepage_url: type: string format: uri icon: type: string format: uri language: type: string title: type: string additionalProperties: {} UploadRequest: type: object properties: category: type: string enum: - image - audio - video - document full_local_file_path: type: string minLength: 1 description: A filename or local path used to preserve the extension. The server never reads this path. example: /tmp/episode.mp3 item_id: description: Required for audio, video, and document uploads. type: string size: description: Expected upload size in bytes. type: integer minimum: 0 maximum: 9007199254740991 type: description: Expected media type, such as audio/mpeg. type: string required: - category - full_local_file_path Feed: type: object properties: _microfeed: type: object propertyNames: type: string additionalProperties: {} description: type: string favicon: type: string feed_url: type: string home_page_url: type: string icon: type: string items: type: array items: $ref: "#/components/schemas/Item" language: type: string next_url: type: string title: type: string version: type: string required: - items - version additionalProperties: {} Item: type: object properties: _microfeed: type: object propertyNames: type: string additionalProperties: {} attachment: $ref: "#/components/schemas/Attachment" attachments: type: array items: $ref: "#/components/schemas/AttachmentOutput" content_html: type: string date_published: type: string format: date-time pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ date_published_ms: type: integer minimum: 0 maximum: 9007199254740991 guid: type: string id: type: string image: type: string status: anyOf: - type: string enum: - published - unlisted - unpublished - type: integer minimum: 1 maximum: 4 description: The item visibility. Names are preferred; numeric values are retained for compatibility. example: published title: type: string url: type: string date_modified: type: string format: date-time pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ required: - id additionalProperties: {} AttachmentOutput: type: object properties: category: type: string enum: - audio - video - document - image - external_url duration_in_seconds: type: number minimum: 0 mime_type: type: string size_in_byte: deprecated: true description: Deprecated singular spelling. Use size_in_bytes. type: integer minimum: 0 maximum: 9007199254740991 size_in_bytes: type: integer minimum: 0 maximum: 9007199254740991 url: type: string minLength: 1 required: - url additionalProperties: {} Error: type: object properties: error: type: string required: - error additionalProperties: false UploadResponse: type: object properties: media_url: type: string format: uri description: The URL to save in the item or channel after the upload succeeds. presigned_url: type: string format: uri description: Send the file bytes to this same-origin URL using HTTP PUT before saving media_url. required: - media_url - presigned_url additionalProperties: false securitySchemes: bearerAuth: type: http scheme: bearer description: An API key sent using Bearer authentication. ```