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

# Update Blog Post via Write API

> Partially update an existing blog post via the Write API with support for flexible field modification and status changes.

Update an existing blog post using partial updates, allowing you to modify specific fields while preserving all other content. This endpoint is perfect for content updates, SEO optimization, or adding new media to existing posts.

**Partial Update Flexibility**: All fields in the request body are optional - include only the fields you want to modify. Any omitted fields will retain their current values, making it safe to update specific content without affecting the entire post structure.

> **Important**: The URL must append a trailing slash to the blog post slug in the URL path (`/v2/posts/your-post-slug/`). This is required for the endpoint to function correctly.

**Localization**: Use the `locale` query parameter to target a specific locale variant (e.g. `?locale=es`). When omitted, updates the post in its current locale. If the locale variant does not yet exist, a new locale variant is created and linked to the original post — this is the primary way to create translations of existing blog posts.

**Scheduling Limitations**: Blog post scheduling is not available through the Write API. Any scheduled parameters in your request will be silently ignored (not treated as errors), allowing you to safely update posts that are currently scheduled without affecting their publication timing.

**Media Integration**: Include `upload_images_to_media_library=true` in your request to automatically download and upload any image URLs within the post body to your ButterCMS media library. This ensures reliable hosting and CDN performance for your content images.

**Asynchronous Processing**: This endpoint returns `202 Accepted` immediately to ensure fast response times for your application. The actual update processing, including media uploads, content validation, and webhook notifications, happens in the background processing queue.


## OpenAPI

````yaml /api/openapi/write_api.yaml patch /posts/{slug}/
openapi: 3.1.0
info:
  title: ButterCMS Write API
  version: 2.0.0
  description: >
    Write endpoints for the ButterCMS API — create, update, and delete Pages,
    Collections, and Blog Posts.
  contact:
    email: support@buttercms.com
  license:
    name: ButterCMS Terms of Service
    url: https://buttercms.com/terms/
servers:
  - url: https://api.buttercms.com/v2
    description: ButterCMS API v2
security:
  - writeTokenAuth: []
tags:
  - name: Pages
    description: >
      Create new pages using ButterCMS Write API. Programmatically create
      content to enable powerful use cases and scale your content faster.


      Note: For Pages, PUT behaves like PATCH (partial update). Use either
      method to perform partial updates.
  - name: Collections
    description: >
      Create, update, and delete Collection items using ButterCMS Write API.
      Collections are user-defined content structures with completely
      customizable field schemas.
  - name: Blog posts
    description: >
      Create, update, and delete blog posts using ButterCMS Write API. Blog
      posts support rich content including HTML body, categories, tags, featured
      images, and SEO metadata.
paths:
  /posts/{slug}/:
    patch:
      tags:
        - Blog posts
      summary: Update Blog Post via Write API
      description: >
        Update an existing blog post using partial updates, allowing you to
        modify specific fields while preserving all other content. This endpoint
        is perfect for content updates, SEO optimization, or adding new media to
        existing posts.


        **Partial Update Flexibility**: All fields in the request body are
        optional - include only the fields you want to modify. Any omitted
        fields will retain their current values, making it safe to update
        specific content without affecting the entire post structure.


        > **Important**: The URL must append a trailing slash to the blog post
        slug in the URL path (`/v2/posts/your-post-slug/`). This is required for
        the endpoint to function correctly.


        **Localization**: Use the `locale` query parameter to target a specific
        locale variant (e.g. `?locale=es`). When omitted, updates the post in
        its current locale. If the locale variant does not yet exist, a new
        locale variant is created and linked to the original post — this is the
        primary way to create translations of existing blog posts.


        **Scheduling Limitations**: Blog post scheduling is not available
        through the Write API. Any scheduled parameters in your request will be
        silently ignored (not treated as errors), allowing you to safely update
        posts that are currently scheduled without affecting their publication
        timing.


        **Media Integration**: Include `upload_images_to_media_library=true` in
        your request to automatically download and upload any image URLs within
        the post body to your ButterCMS media library. This ensures reliable
        hosting and CDN performance for your content images.


        **Asynchronous Processing**: This endpoint returns `202 Accepted`
        immediately to ensure fast response times for your application. The
        actual update processing, including media uploads, content validation,
        and webhook notifications, happens in the background processing queue.
      operationId: updateBlogPost
      parameters:
        - name: slug
          in: path
          required: true
          description: >
            The slug of the blog post to update.


            **Important**: The URL must end with a trailing slash
            (`/v2/posts/your-slug/`).
          schema:
            type: string
            maxLength: 100
          example: this-is-a-blog-post
        - name: locale
          in: query
          description: >
            Target a specific locale variant (e.g. `en`, `es`). When omitted,
            updates the post in its current locale. If the locale variant does
            not exist, a new one is created and linked to the original post.
          required: false
          schema:
            type: string
            maxLength: 10
          example: en
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateBlogPostRequest'
            examples:
              partial_update:
                summary: Partial update (only specified fields changed)
                value:
                  slug: the-new-post-slug
                  body: <h1>Updated</h1><p>This blog post was updated via API</p>
              content_update:
                summary: Update content and SEO fields
                value:
                  title: Updated Blog Post Title
                  body: >-
                    <h1>Fresh Content</h1><p>Completely new content for this
                    post.</p>
                  summary: Updated summary of the post.
                  seo_title: Updated SEO Title
                  meta_description: Updated meta description for better SEO.
              category_tag_update:
                summary: Update categories and tags
                value:
                  categories:
                    - Updated Category
                    - New Category
                  tags:
                    - updated
                    - refresh
                    - api
              status_update:
                summary: Change post status
                value:
                  status: published
              media_library_update:
                summary: Update with media library upload
                value:
                  body: >-
                    <h1>Updated with Images</h1><p><img
                    src='https://example.com/new-image.jpg' alt='New image'></p>
                  upload_images_to_media_library: true
              scheduled_ignored:
                summary: Scheduled fields ignored (with warnings)
                value:
                  title: Updated Title
                  scheduled: '2024-12-25T10:00:00Z'
                  status: scheduled
      responses:
        '202':
          description: >
            **Accepted - Post Update Initiated**


            The update request has been accepted and will be processed
            asynchronously. The response may include warning messages if certain
            fields were ignored (such as scheduling-related fields).


            **Warning Messages**: If you provided `scheduled` timestamp or
            `status: "scheduled"`, these will be ignored and warning messages
            will be included in the response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BlogPostUpdateSuccessResponse'
              examples:
                simple_update:
                  summary: Simple update without warnings
                  value:
                    status: pending
                update_with_scheduled_warning:
                  summary: Update with scheduled field ignored
                  value:
                    status: pending
                    'warning: scheduled field': >-
                      Scheduled timestamps cannot be created or altered via
                      write API. This field will be ignored.
                update_with_status_warning:
                  summary: Update with scheduled status ignored
                  value:
                    status: pending
                    'warning: status field': >-
                      A blog post's status cannot be set as `scheduled` via
                      write API at this time. This field will be ignored.
                update_with_both_warnings:
                  summary: Update with both scheduling warnings
                  value:
                    status: pending
                    'warning: scheduled field': >-
                      Scheduled timestamps cannot be created or altered via
                      write API. This field will be ignored.
                    'warning: status field': >-
                      A blog post's status cannot be set as `scheduled` via
                      write API at this time. This field will be ignored.
        '400':
          description: >
            **Bad Request - Validation Error**


            The API will return HTTP status code 400 if your data does not pass
            validation. This may happen if:


            - Invalid field values provided

            - The remote URL for a media field returns a 404

            - Invalid author email or slug provided

            - Malformed request data


            Error explanations will be returned in a single JSON array.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ValidationErrorResponse'
              examples:
                invalid_featured_image:
                  summary: Invalid featured image URL
                  value:
                    featured_image:
                      - Could not retrieve image from URL.
                invalid_author_email:
                  summary: Author with email not found
                  value:
                    author:
                      - Author with email 'nonexistent@email.com' not found.
                invalid_status:
                  summary: Invalid status value
                  value:
                    status:
                      - >-
                        Select a valid choice. 'invalid_status' is not one of
                        the available choices.
        '401':
          $ref: '#/components/responses/UnauthorizedWriteResponse'
        '403':
          description: >
            **Forbidden - Insufficient Permissions**


            Your API token does not have write permissions or you don't have
            permission to update this blog post.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                detail: Your API token does not allow writes.
        '404':
          description: >
            **Not Found - Blog Post Does Not Exist**


            The blog post with the specified slug was not found or you don't
            have access to it.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                detail: Not found.
      security:
        - writeTokenAuth: []
components:
  schemas:
    UpdateBlogPostRequest:
      type: object
      description: >
        Request schema for updating an existing blog post. All fields are
        optional for partial updates.


        **Note**: If `scheduled` timestamp or `status: "scheduled"` are
        provided, they will be ignored and warning messages will be included in
        the response.
      properties:
        title:
          type: string
          description: The title of the blog post
          maxLength: 200
          example: Updated Blog Post Title
        slug:
          type: string
          description: >
            The slug of the blog post.


            **Auto-Slugification**: The API automatically converts your input to
            a valid slug format using unicode slugification.
          maxLength: 100
          example: updated-blog-post-slug
        status:
          type: string
          description: >
            The status of the post.


            **Note**: `"scheduled"` status will be ignored and a warning message
            will be included in the response.
          enum:
            - draft
            - published
            - scheduled
          example: published
        author: f900807d-66ee-4116-b844-e063ae5c6e92
        categories:
          type: array
          description: >-
            Array of category names. Categories will be created if they don't
            exist.
          items:
            type: string
          example:
            - Updated Category
            - New Category
        tags:
          type: array
          description: Array of tag names. Tags will be created if they don't exist.
          items:
            type: string
          example:
            - updated
            - refresh
            - api
        featured_image:
          type: string
          format: uri
          description: >
            Can be a remote URL to an image.


            The image will always be uploaded to the media library (the value of
            `upload_images_to_media_library` is ignored for featured images).
          example: https://example.com/updated-featured-image.jpg
        featured_image_alt:
          type: string
          description: Alt text for the featured image
          maxLength: 250
          example: Updated featured image alt text.
        body:
          type: string
          description: >
            Should be a string of escaped HTML.


            In case it contains any remote URLs to images, the
            `upload_images_to_media_library` flag controls the behavior.
          example: <h1>Updated Content</h1><p>This blog post was updated via API</p>
        summary:
          type: string
          description: Plain-text summary of the blog post
          maxLength: 2000
          example: Updated summary of the blog post.
        seo_title:
          type: string
          description: SEO title for HTML title tag
          maxLength: 100
          example: Updated SEO Title
        meta_description:
          type: string
          description: Meta description for SEO and social sharing
          example: Updated meta description for better SEO.
        upload_images_to_media_library:
          type: boolean
          description: >
            Defaults to `false`.


            If set to `true`, any image URLs in the `body` property will be
            uploaded to the Butter Media Library and the original URL will be
            replaced with the media library URL.


            **Note**: Featured images are always uploaded regardless of this
            setting.
          default: false
          example: true
        scheduled:
          type: string
          format: date-time
          description: >
            **Note**: This field will be ignored - scheduled timestamps cannot
            be created or altered via write API.


            If provided, this field will be removed from the request and a
            warning message will be included in the response.
          example: '2024-12-25T10:00:00Z'
    BlogPostUpdateSuccessResponse:
      type: object
      description: >
        Success response for blog post updates (202 Accepted). May include
        warning messages for ignored fields.
      properties:
        status:
          type: string
          enum:
            - pending
          description: >-
            Indicates that the blog post update is being processed
            asynchronously
          example: pending
        'warning: scheduled field':
          type: string
          description: Warning message when scheduled field is ignored
          example: >-
            Scheduled timestamps cannot be created or altered via write API.
            This field will be ignored.
        'warning: status field':
          type: string
          description: Warning message when scheduled status is ignored
          example: >-
            A blog post's status cannot be set as `scheduled` via write API at
            this time. This field will be ignored.
      additionalProperties:
        type: string
        description: Additional warning messages for other ignored fields
    ValidationErrorResponse:
      type: object
      description: >-
        Response for validation errors (400 Bad Request) - supports both
        field-specific errors and general error messages
      oneOf:
        - type: object
          description: >-
            Field-specific validation errors (used by Pages, Blog Posts, and
            Collections)
          additionalProperties:
            type: array
            items:
              type: string
          example:
            title:
              - You must specify a page title.
            slug:
              - You must specify a page slug.
        - type: object
          description: General error message (used for organization limits, etc.)
          properties:
            error:
              type: string
              description: Error message
          example:
            error: >-
              Cannot create a new Collection Item. Collection Item Limit
              Reached.
    ErrorResponse:
      type: object
      properties:
        detail:
          type: string
          description: Error message describing what went wrong
          example: Authentication credentials were not provided
  responses:
    UnauthorizedWriteResponse:
      description: >
        **Unauthorized - Invalid or Missing Write API Token**


        No valid write API key provided. The API token you use for reading from
        the ButterCMS API

        will not allow you to create content. You need a different write-enabled
        token.

        Contact support@buttercms.com to get yours.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            detail: Authentication credentials were not provided
  securitySchemes:
    writeTokenAuth:
      type: apiKey
      in: header
      name: Authorization
      description: >
        Write-enabled API token required for creating content.


        The API token you use for reading from the ButterCMS API will not allow
        you to create content in the API. For this you will need to use a
        different write-enabled token. Chat or email support@buttercms.com to
        get yours.


        Set the `Authorization` header to `Token your_write_api_token`.


        Example: `Authorization: Token abc123def456`


        Your write-enabled token should never be used anywhere it would be
        exposed, e.g. in client-side JavaScript.

````