> ## Documentation Index
> Fetch the complete documentation index at: https://docs.member.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Publish Discussion

> Publish a draft discussion (author only).

Transitions a draft (is_published=False) discussion to published state.
Idempotent: re-publishing an already-published discussion returns 200 with
no side-effects.

Auth order: active-member gate → ownership → space posting gate → idempotency.
A stale draft cannot be published if the author has since lost segment access
or the space became admins_only.

Returns 200 with the JSON:API discussion resource on success.
Returns 403 when the caller is not the author, is banned, or the space gate
blocks posting.  Returns 404 when the discussion or space does not exist.



## OpenAPI

````yaml /openapi/mio-openapi.json post /api/v1/discussions/{discussion_id}/publish
openapi: 3.1.0
info:
  description: >-
    Production API reference for Membership.io. Use the authored guides for
    workflows and the generated endpoint pages for exact parameters and schemas.
  title: Membership.io API
  version: 0.1.0
servers:
  - description: Production
    url: https://api.member.dev
security:
  - bearerAuth: []
paths:
  /api/v1/discussions/{discussion_id}/publish:
    post:
      tags:
        - community-discussions
      summary: Publish Discussion
      description: >-
        Publish a draft discussion (author only).


        Transitions a draft (is_published=False) discussion to published state.

        Idempotent: re-publishing an already-published discussion returns 200
        with

        no side-effects.


        Auth order: active-member gate → ownership → space posting gate →
        idempotency.

        A stale draft cannot be published if the author has since lost segment
        access

        or the space became admins_only.


        Returns 200 with the JSON:API discussion resource on success.

        Returns 403 when the caller is not the author, is banned, or the space
        gate

        blocks posting.  Returns 404 when the discussion or space does not
        exist.
      operationId: >-
        community_discussions.post_community_discussions_post_discussions_by_discussion_id_publish
      parameters:
        - in: path
          name: discussion_id
          required: true
          schema:
            title: Discussion Id
            type: string
        - in: query
          name: hub_id
          required: true
          schema:
            title: Hub Id
            type: string
      responses:
        '200':
          content:
            application/vnd.api+json:
              schema:
                $ref: >-
                  #/components/schemas/JsonApiResponse_DiscussionResponseAttributes_
          description: Successful Response
        '422':
          content:
            application/vnd.api+json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
          description: Validation Error
      security:
        - HTTPBearer: []
components:
  schemas:
    JsonApiResponse_DiscussionResponseAttributes_:
      properties:
        data:
          $ref: '#/components/schemas/JsonApiResource_DiscussionResponseAttributes_'
        included:
          anyOf:
            - items: {}
              type: array
            - type: 'null'
          title: Included
        links:
          anyOf:
            - $ref: '#/components/schemas/JsonApiLinks'
            - type: 'null'
        meta:
          anyOf:
            - additionalProperties: true
              type: object
            - type: 'null'
          title: Meta
      required:
        - data
      title: JsonApiResponse[DiscussionResponseAttributes]
      type: object
    HTTPValidationError:
      properties:
        detail:
          items:
            $ref: '#/components/schemas/ValidationError'
          title: Detail
          type: array
      title: HTTPValidationError
      type: object
    JsonApiResource_DiscussionResponseAttributes_:
      properties:
        attributes:
          $ref: '#/components/schemas/DiscussionResponseAttributes'
        id:
          title: Id
          type: string
        links:
          anyOf:
            - $ref: '#/components/schemas/JsonApiLinks'
            - type: 'null'
        meta:
          anyOf:
            - additionalProperties: true
              type: object
            - type: 'null'
          title: Meta
        relationships:
          anyOf:
            - additionalProperties: true
              type: object
            - type: 'null'
          title: Relationships
        type:
          title: Type
          type: string
      required:
        - id
        - type
        - attributes
      title: JsonApiResource[DiscussionResponseAttributes]
      type: object
    JsonApiLinks:
      properties:
        self:
          anyOf:
            - type: string
            - type: 'null'
          title: Self
      title: JsonApiLinks
      type: object
    ValidationError:
      properties:
        ctx:
          title: Context
          type: object
        input:
          title: Input
        loc:
          items:
            anyOf:
              - type: string
              - type: integer
          title: Location
          type: array
        msg:
          title: Message
          type: string
        type:
          title: Error Type
          type: string
      required:
        - loc
        - msg
        - type
      title: ValidationError
      type: object
    DiscussionResponseAttributes:
      properties:
        attachments:
          anyOf:
            - items:
                $ref: '#/components/schemas/RenderableAttachment'
              type: array
            - type: 'null'
          title: Attachments
        author_contact_id:
          anyOf:
            - type: string
            - type: 'null'
          title: Author Contact Id
        author_display_name:
          anyOf:
            - type: string
            - type: 'null'
          title: Author Display Name
        author_membership_status:
          anyOf:
            - enum:
                - active
                - banned
                - soft_banned
                - left
              type: string
            - type: 'null'
          title: Author Membership Status
        author_photo_thumbnail_url:
          anyOf:
            - type: string
            - type: 'null'
          title: Author Photo Thumbnail Url
        author_photo_thumbnail_url_expires_at:
          anyOf:
            - format: date-time
              type: string
            - type: 'null'
          title: Author Photo Thumbnail Url Expires At
        author_photo_url:
          anyOf:
            - type: string
            - type: 'null'
          title: Author Photo Url
        author_photo_url_expires_at:
          anyOf:
            - format: date-time
              type: string
            - type: 'null'
          title: Author Photo Url Expires At
        author_role:
          anyOf:
            - enum:
                - owner
                - admin
                - moderator
                - member
              type: string
            - type: 'null'
          title: Author Role
        body:
          anyOf:
            - type: string
            - type: 'null'
          title: Body
        comment_count:
          anyOf:
            - type: integer
            - type: 'null'
          title: Comment Count
        created_at:
          anyOf:
            - type: string
            - type: 'null'
          title: Created At
        deleted_at:
          anyOf:
            - type: string
            - type: 'null'
          title: Deleted At
        external_video_embeds:
          anyOf:
            - items:
                additionalProperties: true
                type: object
              type: array
            - type: 'null'
          title: External Video Embeds
        hub_id:
          anyOf:
            - type: string
            - type: 'null'
          title: Hub Id
        is_broadcast:
          anyOf:
            - type: boolean
            - type: 'null'
          title: Is Broadcast
        is_locked:
          anyOf:
            - type: boolean
            - type: 'null'
          title: Is Locked
        is_pinned:
          anyOf:
            - type: boolean
            - type: 'null'
          title: Is Pinned
        is_published:
          anyOf:
            - type: boolean
            - type: 'null'
          title: Is Published
        last_activity_at:
          anyOf:
            - type: string
            - type: 'null'
          title: Last Activity At
        poll:
          anyOf:
            - $ref: '#/components/schemas/PollAttributes'
            - type: 'null'
        published_at:
          anyOf:
            - type: string
            - type: 'null'
          title: Published At
        reaction_count:
          anyOf:
            - type: integer
            - type: 'null'
          title: Reaction Count
        reactions:
          anyOf:
            - items: {}
              type: array
            - type: 'null'
          title: Reactions
        report_count:
          default: 0
          description: >-
            Number of moderation reports on this resource, across ALL statuses
            (pending, dismissed, actioned). Present ONLY for an active,
            non-banned hub owner/admin/moderator — the key is omitted entirely
            for any other viewer. Clients MUST treat absence as 'not authorized
            / not supplied', never as zero.
          minimum: 0
          title: Report Count
          type: integer
        reported_by_me:
          default: false
          description: >-
            True when the requesting member has already filed a report against
            this resource. Present for any authenticated member; omitted
            entirely for an anonymous viewer. Clients MUST treat absence as
            'unknown', never as false.
          title: Reported By Me
          type: boolean
        repost:
          anyOf:
            - $ref: '#/components/schemas/RepostBlockAttributes'
            - type: 'null'
        repost_count:
          anyOf:
            - type: integer
            - type: 'null'
          title: Repost Count
        scheduled_at:
          anyOf:
            - type: string
            - type: 'null'
          title: Scheduled At
        space_id:
          anyOf:
            - type: string
            - type: 'null'
          title: Space Id
        status:
          anyOf:
            - type: string
            - type: 'null'
          title: Status
        team_id:
          anyOf:
            - type: string
            - type: 'null'
          title: Team Id
        title:
          anyOf:
            - type: string
            - type: 'null'
          title: Title
        updated_at:
          anyOf:
            - type: string
            - type: 'null'
          title: Updated At
      title: DiscussionResponseAttributes
      type: object
    RenderableAttachment:
      properties:
        asset_kind:
          anyOf:
            - type: string
            - type: 'null'
          title: Asset Kind
        file_id:
          anyOf:
            - type: string
            - type: 'null'
          title: File Id
        filename:
          anyOf:
            - type: string
            - type: 'null'
          title: Filename
        id:
          title: Id
          type: string
        media_id:
          title: Media Id
          type: string
        mime_type:
          anyOf:
            - type: string
            - type: 'null'
          title: Mime Type
        role:
          title: Role
          type: string
        size_bytes:
          anyOf:
            - type: integer
            - type: 'null'
          title: Size Bytes
        status_upload:
          anyOf:
            - type: string
            - type: 'null'
          title: Status Upload
        thumbnail_url:
          anyOf:
            - type: string
            - type: 'null'
          title: Thumbnail Url
        thumbnail_url_expires_at:
          anyOf:
            - type: string
            - type: 'null'
          title: Thumbnail Url Expires At
        url:
          anyOf:
            - type: string
            - type: 'null'
          title: Url
        url_expires_at:
          anyOf:
            - type: string
            - type: 'null'
          title: Url Expires At
      required:
        - id
        - media_id
        - role
      title: RenderableAttachment
      type: object
    PollAttributes:
      description: >-
        A single-choice poll attached to a discussion.


        Built field-by-field by ``app.community.poll_read`` (member scope) —

        never via ``model_dump()`` of the ORM rows. ``viewer_voted`` /

        ``viewer_option_id`` are member-scope only; the anon read path

        (``app.community.anon_read.AnonPollAttributes``) omits both entirely,
        not

        just nulls them, since an anonymous request has no viewer identity.
      properties:
        closed:
          title: Closed
          type: boolean
        deadline_at:
          format: date-time
          title: Deadline At
          type: string
        id:
          title: Id
          type: string
        options:
          items:
            $ref: '#/components/schemas/PollOptionAttributes'
          title: Options
          type: array
        total_votes:
          title: Total Votes
          type: integer
        viewer_option_id:
          anyOf:
            - type: string
            - type: 'null'
          title: Viewer Option Id
        viewer_voted:
          anyOf:
            - type: boolean
            - type: 'null'
          title: Viewer Voted
      required:
        - id
        - deadline_at
        - closed
        - total_votes
        - options
      title: PollAttributes
      type: object
    RepostBlockAttributes:
      additionalProperties: false
      properties:
        author_display_name:
          anyOf:
            - type: string
            - type: 'null'
          title: Author Display Name
        author_photo_thumbnail_url:
          anyOf:
            - type: string
            - type: 'null'
          title: Author Photo Thumbnail Url
        author_photo_url:
          anyOf:
            - type: string
            - type: 'null'
          title: Author Photo Url
        body:
          anyOf:
            - type: string
            - type: 'null'
          title: Body
        id:
          anyOf:
            - type: string
            - type: 'null'
          title: Id
        published_at:
          anyOf:
            - type: string
            - type: 'null'
          title: Published At
        space_name:
          anyOf:
            - type: string
            - type: 'null'
          title: Space Name
        space_slug:
          anyOf:
            - type: string
            - type: 'null'
          title: Space Slug
        state:
          enum:
            - visible
            - locked
            - deleted
            - unavailable
          title: State
          type: string
        title:
          anyOf:
            - type: string
            - type: 'null'
          title: Title
      required:
        - state
      title: RepostBlockAttributes
      type: object
    PollOptionAttributes:
      description: >-
        A single selectable option on a poll.


        ``vote_count`` is documentation-only here (this model drives OpenAPI

        generation, not runtime field filtering — see
        ``RepostBlockAttributes``'s

        docstring for why: the routes that carry this shape return a raw

        ``JSONResponse``). The ACTUAL omit-vs-present gating —

        ``vote_count`` present only when the viewer has voted or the poll is

        closed — is implemented field-by-field in

        ``app.community.poll_read.build_poll_attrs_member``.
      properties:
        id:
          title: Id
          type: string
        label:
          title: Label
          type: string
        position:
          title: Position
          type: integer
        vote_count:
          anyOf:
            - type: integer
            - type: 'null'
          title: Vote Count
      required:
        - id
        - label
        - position
      title: PollOptionAttributes
      type: object
  securitySchemes:
    bearerAuth:
      bearerFormat: JWT or mio_sk API key
      description: >-
        Send platform JWTs, contact JWTs, or team API keys as `Authorization:
        Bearer <token>`.
      scheme: bearer
      type: http
    HTTPBearer:
      scheme: bearer
      type: http

````