Skip to main content

Overview

The Stories endpoints provide full CRUD (Create, Read, Update, Delete) operations for web stories. Stories are the main content type in the Web Stories plugin. Base Path: /wp-json/web-stories/v1/web-story

List Stories

Retrieves a collection of stories.
GET /web-stories/v1/web-story
curl https://yoursite.com/wp-json/web-stories/v1/web-story

Query Parameters

context
string
default:"view"
Scope under which the request is made: view or edit
page
integer
default:"1"
Current page of the collection
per_page
integer
default:"10"
Maximum number of items to return (max 100)
Search stories by title or content
author
integer
Filter stories by author user ID
status
string
default:"publish"
Filter by post status: publish, draft, pending, future, private, auto-draft
orderby
string
default:"date"
Sort by: date, modified, title, story_author, relevance
order
string
default:"desc"
Sort order: asc or desc
_embed
boolean
default:"false"
Include embedded resources (author, featured media, etc.)
_web_stories_envelope
boolean
default:"false"
Wrap response in envelope for preloading
web_stories_demo
boolean
default:"false"
Load demo data for auto-draft stories

Response

[
  {
    "id": 123,
    "date": "2024-03-15T10:30:00",
    "date_gmt": "2024-03-15T10:30:00",
    "guid": {
      "rendered": "https://example.com/?post_type=web-story&p=123"
    },
    "modified": "2024-03-15T12:45:00",
    "modified_gmt": "2024-03-15T12:45:00",
    "slug": "my-awesome-story",
    "status": "publish",
    "type": "web-story",
    "link": "https://example.com/web-stories/my-awesome-story/",
    "title": {
      "rendered": "My Awesome Story"
    },
    "content": {
      "rendered": "<html>...</html>",
      "protected": false
    },
    "excerpt": {
      "rendered": "An exciting web story",
      "protected": false
    },
    "author": 1,
    "featured_media": 456,
    "template": "",
    "story_data": {
      "version": 1,
      "pages": [
        {
          "id": "page-1",
          "elements": []
        }
      ]
    },
    "story_poster": {
      "id": 456,
      "url": "https://example.com/wp-content/uploads/2024/03/poster.jpg",
      "width": 640,
      "height": 853,
      "needsProxy": false
    },
    "preview_link": "https://example.com/web-stories/my-awesome-story/",
    "edit_link": "https://example.com/wp-admin/post.php?post=123&action=edit",
    "_links": {
      "self": [
        {"href": "https://example.com/wp-json/web-stories/v1/web-story/123"}
      ],
      "author": [
        {"href": "https://example.com/wp-json/web-stories/v1/users/1"}
      ]
    }
  }
]

Response Headers

X-WP-Total: 42
X-WP-TotalPages: 5
X-WP-TotalByStatus: {"all":42,"publish":30,"draft":10,"pending":2}

Get Story

Retrieves a single story by ID.
GET /web-stories/v1/web-story/:id
curl https://yoursite.com/wp-json/web-stories/v1/web-story/123

Path Parameters

id
integer
required
Unique identifier for the story

Query Parameters

context
string
default:"view"
Scope: view, edit, or embed
_embed
boolean
default:"false"
Include embedded resources

Response

id
integer
Unique identifier for the story
date
string
Publication date in ISO 8601 format
date_gmt
string
Publication date in GMT
modified
string
Last modified date
slug
string
URL-friendly slug
status
string
Post status: publish, draft, pending, private, future, auto-draft
title
object
Story title
content
object
Story HTML content
story_data
object
JSON representation of the story structure (edit context only)
author
integer
Author user ID
Featured media attachment ID (poster image)
story_poster
object
Story poster image details
Preview URL for the story (edit context only)
Admin edit URL (edit context only)
embed_post_link
string
Link to embed story in a post (edit context, if user can edit posts)
style_presets
object
Global style presets (edit context only)

Create Story

Creates a new story.
POST /web-stories/v1/web-story
curl -X POST https://yoursite.com/wp-json/web-stories/v1/web-story \
  -H "Content-Type: application/json" \
  -u "username:password" \
  -d '{
    "title": "My New Story",
    "status": "draft",
    "content": "<html>...</html>",
    "story_data": {
      "version": 1,
      "pages": []
    }
  }'

Request Body

title
string
required
Story title (plain text or object with raw property)
content
string
required
Story HTML content (base64 encoded for special characters)
story_data
object
required
JSON story structure with pages and elements
status
string
default:"draft"
Post status: publish, draft, pending, private, future
excerpt
string
Story excerpt/description
author
integer
Author user ID (defaults to current user)
Featured media ID (poster image)
meta
object
Post meta fields
original_id
integer
Original story ID to duplicate from

Response

Returns the created story object (same format as Get Story response) with HTTP 201 status.

Update Story

Updates an existing story.
PUT /web-stories/v1/web-story/:id
curl -X PUT https://yoursite.com/wp-json/web-stories/v1/web-story/123 \
  -H "Content-Type: application/json" \
  -u "username:password" \
  -d '{
    "title": "Updated Title",
    "status": "publish",
    "content": "<html>...</html>",
    "story_data": {...}
  }'

Path Parameters

id
integer
required
Unique identifier for the story

Request Body

Accepts the same parameters as Create Story. All fields are optional - only include fields you want to update.
Important: When updating a story, content and story_data must be updated together. Updating one without the other will result in a 412 error (except for auto-draft status).
style_presets
object
Update global style presets (affects all stories)

Response

Returns the updated story object with HTTP 200 status.

Delete Story

Deletes a story.
DELETE /web-stories/v1/web-story/:id
curl -X DELETE https://yoursite.com/wp-json/web-stories/v1/web-story/123?force=true \
  -u "username:password"

Path Parameters

id
integer
required
Unique identifier for the story

Query Parameters

force
boolean
default:"false"
Whether to bypass trash and force deletion

Response

{
  "deleted": true,
  "previous": {
    "id": 123,
    "title": {
      "rendered": "Deleted Story"
    }
  }
}

Duplicate Story

Create a copy of an existing story by using the original_id parameter.
POST /web-stories/v1/web-story
curl -X POST https://yoursite.com/wp-json/web-stories/v1/web-story \
  -H "Content-Type: application/json" \
  -u "username:password" \
  -d '{
    "original_id": 123
  }'
The duplicate will have ” (Copy)” appended to the title and will copy:
  • Story content and story_data
  • Story excerpt
  • Featured media
  • Publisher logo and other metadata

Common Errors

rest_cannot_create
error
Status 403: You don’t have permission to create storiesRequired capability: edit_web-stories
rest_cannot_edit
error
Status 403: You don’t have permission to edit this storyRequired capability: edit_web-story or edit_others_web-stories
rest_post_invalid_id
error
Status 404: Story with the specified ID does not exist
rest_empty_content
error
Status 412: content and story_data must be updated togetherBoth fields are required when updating story content

Story Locking

Stories support post locking to prevent concurrent edits. Lock information is included in the _links response:
{
  "_links": {
    "https://api.w.org/lock": [{
      "href": "https://example.com/wp-json/web-stories/v1/web-story/123/lock",
      "embeddable": true
    }],
    "https://api.w.org/lockuser": [{
      "href": "https://example.com/wp-json/web-stories/v1/users/2",
      "embeddable": true
    }]
  }
}
The lock endpoint is documented in /includes/REST_API/Stories_Lock_Controller.php:14191.

Build docs developers (and LLMs) love