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

# Refine a post

> <Info>This API is in beta. Endpoints, fields, and behavior may still change, so avoid depending on it in production.</Info>

Rewrites a single post in the content plan according to your request, and returns the whole updated plan.

Take `post_id` from a post in the plan. Only that post changes. Every other post is returned unchanged. To replace a post's text yourself instead of having it rewritten, use [Update post content](/api-reference/update-post-content).

This request costs 1 credit and fails with a 402 when the workspace is out of quota. It calls a language model, so expect it to take a few seconds.

<Warning>Editing the same post while a refinement is in flight discards the refinement, and the request fails with a **500**, not a 409. Retrying is the right response, but check the post's current `content` first, because your edit is the version that survived. A 409 here means something different. It signals repeated write conflicts on the plan that did not settle.</Warning>

This endpoint shares a limit of 15 requests per minute with the other social content endpoints.

<Note>This endpoint accepts a personal API key. Workspace API keys are not authorized for it and are rejected with a 403.</Note>

<Warning>The response includes fields beyond the ones documented here. Don't rely on undocumented response fields, as they can change at any time. Send only the fields documented here. Other request fields are not supported and their behavior can change.</Warning>



## OpenAPI

````yaml /developers/references/app-management/app-management-openapi.json post /api/apps/{app_id}/virality/posts/{post_id}/refine
openapi: 3.1.0
info:
  title: Base44 App Management API
  version: 1.0.0
servers:
  - url: https://app.base44.com
security:
  - ApiKeyAuth: []
paths:
  /api/apps/{app_id}/virality/posts/{post_id}/refine:
    post:
      summary: Refine a post
      description: >-
        <Info>This API is in beta. Endpoints, fields, and behavior may still
        change, so avoid depending on it in production.</Info>


        Rewrites a single post in the content plan according to your request,
        and returns the whole updated plan.


        Take `post_id` from a post in the plan. Only that post changes. Every
        other post is returned unchanged. To replace a post's text yourself
        instead of having it rewritten, use [Update post
        content](/api-reference/update-post-content).


        This request costs 1 credit and fails with a 402 when the workspace is
        out of quota. It calls a language model, so expect it to take a few
        seconds.


        <Warning>Editing the same post while a refinement is in flight discards
        the refinement, and the request fails with a **500**, not a 409.
        Retrying is the right response, but check the post's current `content`
        first, because your edit is the version that survived. A 409 here means
        something different. It signals repeated write conflicts on the plan
        that did not settle.</Warning>


        This endpoint shares a limit of 15 requests per minute with the other
        social content endpoints.


        <Note>This endpoint accepts a personal API key. Workspace API keys are
        not authorized for it and are rejected with a 403.</Note>


        <Warning>The response includes fields beyond the ones documented here.
        Don't rely on undocumented response fields, as they can change at any
        time. Send only the fields documented here. Other request fields are not
        supported and their behavior can change.</Warning>
      operationId: refine_post_api_api_apps__app_id__virality_posts__post_id__refine_post
      parameters:
        - name: post_id
          in: path
          required: true
          schema:
            type: string
            description: ID of the post, as returned in the content plan. Must be a UUID.
            title: Post Id
          description: ID of the post, as returned in the content plan. Must be a UUID.
          example: 3f2504e0-4f89-11d3-9a0c-0305e82c3301
        - name: app_id
          in: path
          required: true
          schema:
            type: string
            description: ID of the app.
            title: App Id
          description: ID of the app.
          example: 6820f3a4e7b91d003c45a1f2
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RefinePostPayload'
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ContentPlanResponse'
        '400':
          description: The `post_id` is not a UUID, or `request` is empty.
        '401':
          description: Missing or invalid credentials.
        '402':
          description: The workspace is out of credits.
        '403':
          description: >-
            You don't have editor access to this app, or you used a workspace
            API key.
        '404':
          description: >-
            App not found, the app has no content plan, the post isn't in it, or
            the social content feature is not enabled for your account.
        '409':
          description: >-
            Repeated write conflicts on this plan did not settle, or a content
            plan is currently generating. Retry the request.
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
        '429':
          description: Rate limit exceeded (15 requests per minute).
        '500':
          description: >-
            The post was edited while refining and the refinement was discarded,
            or the model returned no usable change. Retry the request.
components:
  schemas:
    RefinePostPayload:
      properties:
        request:
          type: string
          maxLength: 5000
          title: Request
          description: What to change about the post, in your own words. Can't be empty.
          example: Make it shorter and drop the emoji.
      type: object
      required:
        - request
      title: RefinePostPayload
    ContentPlanResponse:
      properties:
        plan:
          anyOf:
            - $ref: '#/components/schemas/ContentPlan'
            - type: 'null'
          description: The app's content plan, or `null` if it has none.
      type: object
      title: ContentPlanResponse
      description: The app's social content plan after the change.
    HTTPValidationError:
      properties:
        detail:
          items:
            $ref: '#/components/schemas/ValidationError'
          type: array
          title: Detail
      type: object
      title: HTTPValidationError
    ContentPlan:
      properties:
        id:
          anyOf:
            - type: string
            - type: 'null'
          title: Id
          description: ID of the content plan.
          example: 8c1f9a2e-3b7d-4c5e-9f01-2a3b4c5d6e7f
        app_id:
          anyOf:
            - type: string
            - type: 'null'
          title: App Id
          description: ID of the app the plan belongs to.
          example: 6820f3a4e7b91d003c45a1f2
        strategy:
          anyOf:
            - $ref: '#/components/schemas/ContentStrategy'
            - type: 'null'
          description: The strategy and the per-platform posts.
        created_at:
          anyOf:
            - type: string
            - type: 'null'
          title: Created At
          description: Time the plan was created, as an ISO 8601 timestamp.
          example: '2026-08-24T09:15:00+00:00'
        updated_at:
          anyOf:
            - type: string
            - type: 'null'
          title: Updated At
          description: Time the plan last changed, as an ISO 8601 timestamp.
          example: '2026-08-24T10:02:00+00:00'
      type: object
      title: ContentPlan
    ValidationError:
      properties:
        loc:
          items:
            anyOf:
              - type: string
              - type: integer
          type: array
          title: Location
        msg:
          type: string
          title: Message
        type:
          type: string
          title: Error Type
      type: object
      required:
        - loc
        - msg
        - type
      title: ValidationError
    ContentStrategy:
      properties:
        app_summary:
          anyOf:
            - type: string
            - type: 'null'
          title: App Summary
          description: Short summary of what the app does.
          example: A CRM for freelancers who want to track leads without a spreadsheet.
        marketing_approach:
          anyOf:
            - type: string
            - type: 'null'
          title: Marketing Approach
          description: >-
            The approach the content takes, extracted from the accepted
            strategy. Empty if the strategy text was empty when the plan was
            generated.
          example: Lead with the spreadsheet pain, then show the app solving it.
        platforms:
          items:
            $ref: '#/components/schemas/PlatformContentPlan'
          type: array
          title: Platforms
          description: One entry per platform you approved, in the order you sent them.
      type: object
      title: ContentStrategy
    PlatformContentPlan:
      properties:
        platform:
          anyOf:
            - $ref: '#/components/schemas/Platform'
            - type: 'null'
          description: Platform these posts are written for.
          example: instagram
        mode:
          anyOf:
            - $ref: '#/components/schemas/ContentMode'
            - type: 'null'
          description: >-
            How to read the posts. A `series` is a sequence to publish in order,
            and a `selection` is a set of alternatives to pick one from.
          example: series
        reasoning:
          anyOf:
            - type: string
            - type: 'null'
          title: Reasoning
          description: Why the content for this platform takes the shape it does.
          example: Instagram rewards a consistent series, so these build on each other.
        posts:
          items:
            $ref: '#/components/schemas/SocialPost'
          type: array
          title: Posts
          description: The generated posts for this platform.
      type: object
      title: PlatformContentPlan
    Platform:
      type: string
      enum:
        - x
        - instagram
        - tiktok
        - linkedin
        - reddit
        - facebook
      title: Platform
    ContentMode:
      type: string
      enum:
        - series
        - selection
      title: ContentMode
    SocialPost:
      properties:
        id:
          anyOf:
            - type: string
            - type: 'null'
          title: Id
          description: >-
            ID of the post. Pass it as `post_id` to [Refine a
            post](/api-reference/refine-a-post), [Update post
            content](/api-reference/update-post-content), and [Generate a post
            image](/api-reference/generate-a-post-image).
          example: 3f2504e0-4f89-11d3-9a0c-0305e82c3301
        platform:
          anyOf:
            - $ref: '#/components/schemas/Platform'
            - type: 'null'
          description: Platform the post is written for.
          example: instagram
        angle:
          anyOf:
            - $ref: '#/components/schemas/PostAngle'
            - type: 'null'
          description: Editorial angle the post takes.
          example: pain_point
        angle_label:
          anyOf:
            - type: string
            - type: 'null'
          title: Angle Label
          description: Human-readable label for the angle.
          example: Pain point
        post_number:
          anyOf:
            - type: integer
            - type: 'null'
          title: Post Number
          description: Position of this post within its platform's set, starting at 1.
          example: 1
        total_posts:
          anyOf:
            - type: integer
            - type: 'null'
          title: Total Posts
          description: Number of posts generated for this platform.
          example: 5
        suggested_day:
          anyOf:
            - type: integer
            - type: 'null'
          title: Suggested Day
          description: Suggested day to publish on, counted from the start of the campaign.
          example: 1
        rationale:
          anyOf:
            - type: string
            - type: 'null'
          title: Rationale
          description: Why this post works for this platform and angle.
          example: Opens on the spreadsheet frustration the audience already has.
        content:
          anyOf:
            - type: string
            - type: 'null'
          title: Content
          description: >-
            The post text, ready to publish. Change it with [Update post
            content](/api-reference/update-post-content).
          example: >-
            Still tracking leads in a spreadsheet? I built the thing I wanted
            instead.
        image_url:
          anyOf:
            - type: string
            - type: 'null'
          title: Image Url
          description: >-
            URL of the post image, or `null` if no image was generated yet.
            Create one with [Generate a post
            image](/api-reference/generate-a-post-image).
          example: https://storage.base44.com/virality/3f2504e0.png
        image_prompt:
          anyOf:
            - type: string
            - type: 'null'
          title: Image Prompt
          description: >-
            Prompt used to generate the post image, or `null` if the post has
            none.
          example: A freelancer closing a laptop at a tidy desk, warm morning light
        hashtags:
          anyOf:
            - items:
                type: string
              type: array
            - type: 'null'
          title: Hashtags
          description: Suggested hashtags, without the leading `#`.
          example:
            - freelance
            - buildinpublic
        post_title:
          anyOf:
            - type: string
            - type: 'null'
          title: Post Title
          description: >-
            Title for platforms that use one, such as Reddit and LinkedIn, or
            `null` elsewhere.
          example: I built a CRM because spreadsheets kept losing my leads
        suggested_subreddits:
          anyOf:
            - items:
                type: string
              type: array
            - type: 'null'
          title: Suggested Subreddits
          description: Subreddits to consider for a Reddit post. Empty for other platforms.
          example:
            - r/freelance
            - r/SideProject
        launch_comment:
          anyOf:
            - type: string
            - type: 'null'
          title: Launch Comment
          description: >-
            First comment to post under the main post, or `null` if none was
            generated.
          example: Happy to answer questions about how it works.
        option_label:
          anyOf:
            - type: string
            - type: 'null'
          title: Option Label
          description: >-
            Label for this post when the platform's `mode` is `selection`, so
            you can tell the alternatives apart, or `null` in `series` mode.
          example: Direct and personal
        best_for_context:
          anyOf:
            - type: string
            - type: 'null'
          title: Best For Context
          description: >-
            When to prefer this option over the others, or `null` if not
            applicable.
          example: Best if your audience already knows you
      type: object
      title: SocialPost
    PostAngle:
      type: string
      enum:
        - pain_point
        - feature_demo
        - social_proof
        - trending_hook
        - user_story
        - before_after
      title: PostAngle
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: api_key
      description: Personal API key.

````