---
title: Update a Story
description: Use this endpoint for migrations, updates (new component structure, and more), or bulk actions
url: https://storyblok.com/docs/api/management/stories/update-a-story
---

# Update a Story

PUT

```html
https://mapi.storyblok.com/v1/spaces/:space_id/stories/:story_id
```

Use this endpoint for migrations, updates (new component structure, and more), or bulk actions.

To publish an unpublished story, set the `publish` parameter to `true`.

> [!NOTE]
> Sending `false` for the `publish` parameter does not unpublish a story that is already published. To unpublish a story, use the [Unpublish a Story](/docs/api/management/stories/unpublish-a-story) endpoint.

To define alternate versions of a story, set the `group_id` to the same `group_id` of the story (or stories) that should be the alternate(s).

## Path parameters

-   `:space_id` (required) (number)
    
    Numeric ID of a space
    
-   `:story_id` (required) (number)
    
    Numeric ID of a story
    

## Request body properties

-   `story` (The Story Object)
    
    A [story object](/docs/api/management/stories/the-story-object)
    
-   `group_id` (string)
    
    Group ID (`UUID` string), shared between stories defined as alternates
    
-   `force_update` (string)
    
    Set to `1` to force an update of a locked story.  
    A story is locked when another user edits it. Forcing an update via the API causes a content conflict. `force_update` has no effect if the story is locked as part of a [workflow stage](/docs/manuals/workflows).
    
-   `release_id` (number)
    
    Numeric ID of a release
    
-   `publish` (boolean)
    
    To publish the story, set the parameter to `true`. To save changes without publishing, set it to `false`.
    
-   `lang` (string)
    
    Language code to publish the story individually (must be enabled in **Settings** → **Internationalization**)
    

## Response properties

-   `story` (The Story Object)
    
    A [story object](/docs/api/management/stories/the-story-object)
    

## Examples

-   cURL
    
    ```shellscript
    curl "https://mapi.storyblok.com/v1/spaces/288868932106293/stories/2141" \
      -X PUT \
      -H "Authorization: YOUR_OAUTH_TOKEN" \
      -H "Content-Type: application/json" \
      -d "{\"force_update\":1,\"publish\":true,\"story\":{\"content\":{\"body\":[],\"component\":\"page\"},\"id\":2141,\"name\":\"Updated Story Name\",\"slug\":\"story-name\"}}"
    ```
    
-   JS
    
    ```javascript
    // storyblok-js-client@>=7, node@>=18
    import Storyblok from "storyblok-js-client";
    
    const storyblok = new Storyblok({
      oauthToken: "YOUR_PERSONAL_ACCESS_TOKEN",
    });
    
    try {
      const response = await storyblok.put('spaces/288868932106293/stories/2141', {
        "force_update": 1,
        "publish": true,
        "story": {
          "content": {
            "body": [],
            "component": "page"
          },
          "id": 2141,
          "name": "Updated Story Name",
          "slug": "story-name"
        }
      })
      console.log({ response })
    } catch (error) {
      console.log(error)
    }
    ```
    
-   PHP
    
    ```php
    $client = new \Storyblok\ManagementClient('YOUR_OAUTH_TOKEN');
    
    $payload = ["force_update" => 1,"publish" => true,"story" => ["content" => ["body" => [],"component" => "page"],"id" => 2141,"name" => "Updated Story Name","slug" => "story-name"]];
    
    $client->put('spaces/288868932106293/stories/2141', $payload)->getBody();
    ```
    
-   Java
    
    ```java
    HttpResponse<String> response = Unirest.put("https://mapi.storyblok.com/v1/spaces/288868932106293/stories/2141")
      .header("Content-Type", "application/json")
      .header("Authorization", "YOUR_OAUTH_TOKEN")
      .body({"force_update":1,"publish":true,"story":{"content":{"body":[],"component":"page"},"id":2141,"name":"Updated Story Name","slug":"story-name"}})
      .asString();
    ```
    
-   C#
    
    ```csharp
    var client = new RestClient("https://mapi.storyblok.com/v1/spaces/288868932106293/stories/2141");
    var request = new RestRequest(Method.PUT);
    
    request.AddHeader("Content-Type", "application/json");
    request.AddHeader("Authorization", "YOUR_OAUTH_TOKEN");
    request.AddParameter("application/json", "{\"force_update\":1,\"publish\":true,\"story\":{\"content\":{\"body\":[],\"component\":\"page\"},\"id\":2141,\"name\":\"Updated Story Name\",\"slug\":\"story-name\"}}", ParameterType.RequestBody);
    IRestResponse response = client.Execute(request);
    ```
    
-   Python
    
    ```python
    import requests
    
    url = "https://mapi.storyblok.com/v1/spaces/288868932106293/stories/2141"
    
    querystring = {}
    
    payload = {"force_update":1,"publish":true,"story":{"content":{"body":[],"component":"page"},"id":2141,"name":"Updated Story Name","slug":"story-name"}}
    headers = {
      'Content-Type': "application/json",
      'Authorization': "YOUR_OAUTH_TOKEN"
    }
    
    response = requests.request("PUT", url, data=payload, headers=headers, params=querystring)
    
    print(response.text)
    ```
    
-   Ruby
    
    ```ruby
    require 'storyblok'
    client = Storyblok::Client.new(oauth_token: 'YOUR_OAUTH_TOKEN')
    
    payload = {"force_update" => 1,"publish" => true,"story" => {"content" => {"body" => [],"component" => "page"},"id" => 2141,"name" => "Updated Story Name","slug" => "story-name"}}
    
    client.put('spaces/288868932106293/stories/2141', payload)
    ```
    
-   Swift
    
    ```swift
    let storyblok = URLSession(storyblok: .mapi(accessToken: .oauth("YOUR_OAUTH_TOKEN")))
    var request = URLRequest(storyblok: storyblok, path: "spaces/288868932106293/stories/2141")
    request.httpMethod = "PUT"
    request.httpBody = try JSONSerialization.data(withJSONObject: [
        "force_update": 1,
        "publish": true,
        "story": [
            "content": [
                "body": [ ],
                "component": "page",
            ],
            "id": 2141,
            "name": "Updated Story Name",
            "slug": "story-name",
        ],
    ])
    let (data, _) = try await storyblok.data(for: request)
    print(try JSONSerialization.jsonObject(with: data))
    ```
    
-   Kotlin
    
    ```kotlin
    val client = HttpClient {
        install(Storyblok(MAPI)) {
            accessToken = OAuth("YOUR_OAUTH_TOKEN")
        }
    }
    
    val response = client.put("spaces/288868932106293/stories/2141") {
        setBody(buildJsonObject {
            put("force_update", 1)
            put("publish", true)
            putJsonObject("story") {
                putJsonObject("content") {
                    putJsonArray("body") { }
                    put("component", "page")
                }
                put("id", 2141)
                put("name", "Updated Story Name")
                put("slug", "story-name")
            }
        })
    }
    
    println(response.body<JsonElement>())
    ```

Request for updating assets in a specific story.

> [!TIP]
> To add an asset to a story or change an existing asset’s values using this endpoint, the asset object sent as part of the request body must include a specific set of parameters. Omitting any required parameters disables the **Edit asset** dialog in the UI.

Example Asset Object

```json
{
"component": "image",
"image_file": {
  "alt": "Image alt text",
  "copyright": null,
  "fieldtype": "asset",
  "filename": "<https://a.storyblok.com/f/656/9c40e5/image_file_name.jpg>",
  "focus": null,
  "id": 123456789,
  "name": "",
  "title": null
}
}
```

## Pagination

-   [Previous: Duplicate a Story](/docs/api/management/stories/duplicate-a-story)
-   [Next: Publish a Story](/docs/api/management/stories/publish-a-story)
