---
title: "Create a CMS post"
method: POST
path: "/cms/posts"
tags: ["CMS"]
---

# Create a CMS post

`POST /cms/posts`

## Request

- Base URL: `https://next.frase.io/api/v1`
- URL: `https://next.frase.io/api/v1/cms/posts`
- Auth: one of:
  - API key in header `X-API-KEY`
  - HTTP bearer

Create a new post in Frase CMS. CMS must be enabled on the site.

## Request body

- CmsPostInput
  - `site_id` string, uuid, required
  - `title` string, required
  - `content` string, required: HTML content (max 500KB)
  - `slug` string: URL slug. Auto-generated from title if omitted.
  - `status` 'draft' | 'published' | 'scheduled'
  - `type` 'blog_post' | 'page'
  - `excerpt` string
  - `featured_image` string, uri: Must be HTTPS
  - `seo_title` string
  - `seo_description` string
  - `focus_keyword` string
  - `canonical_url` string, uri: Must be HTTPS
  - `published_at` string, date-time
  - `schema_markup` object: JSON-LD structured data for the post. Must include `@context` and `@type`. Additional properties depend on the chosen schema type. See [schema.org](https://schema.org) for full type definitions.
    - `@context` string: Schema.org context URL. Almost always `https://schema.org`.
    - `@type` 'Article' | 'BlogPosting' | 'NewsArticle' | 'FAQPage' | 'HowTo' | 'TechArticle' | 'WebPage': The schema.org type for this content.
    - `headline` string: The headline of the article. Recommended for Article, BlogPosting, NewsArticle.
    - `description` string: A short description or summary of the content.
    - `author` union
      - object: Author as a Person or Organization.
        - `@type` 'Person' | 'Organization'
        - `name` string
        - `url` string, uri
      - object[]: Multiple authors.
        - `@type` 'Person' | 'Organization'
        - `name` string
        - `url` string, uri
    - `datePublished` string, date: Original publication date in ISO 8601 format (e.g., `2026-04-16`).
    - `dateModified` string, date: Last modification date in ISO 8601 format.
    - `image` union: Primary image. Can be a URL string or an ImageObject.
      - string, uri
      - object
        - `@type` 'ImageObject'
        - `url` string, uri
        - `width` integer
        - `height` integer
    - `publisher` object: The publisher of the content.
      - `@type` 'Organization'
      - `name` string
      - `logo` object
        - `@type` 'ImageObject'
        - `url` string, uri
    - `mainEntity` union: Primary entity of the page. Used by FAQPage (array of Question) and HowTo (HowToStep array).
      - object[]: For FAQPage: array of Question objects.
        - `@type` 'Question'
        - `name` string: The question text.
        - `acceptedAnswer` object
          - `@type` 'Answer'
          - `text` string: The answer text.
      - object
    - `step` object[]: For HowTo: ordered list of steps.
      - `@type` 'HowToStep'
      - `name` string: Step title.
      - `text` string: Step instructions.
      - `image` string, uri
  - `meta` object
  - `related_post_ids` string[]: Ordered curated related-post ids (max 3). Every id must be a PUBLISHED blog post on the same site as this post; the list is deduplicated and the post's own id is dropped. More than 3 ids is rejected with a 400. On update, the array REPLACES the existing set; pass [] to clear. Failures to apply are returned as warnings inside data, not an error.

## Response `201`

Post created

- object
  - `data` CmsPost
    - `id` string, uuid
    - `site_id` string, uuid
    - `slug` string
    - `type` 'blog_post' | 'page'
    - `title` string
    - `content` string: HTML content
    - `excerpt` string, nullable
    - `featured_image` string, uri, nullable
    - `seo_title` string, nullable
    - `seo_description` string, nullable
    - `focus_keyword` string, nullable
    - `canonical_url` string, uri, nullable
    - `schema_markup` object, nullable: JSON-LD structured data for the post. Must include `@context` and `@type`. Additional properties depend on the chosen schema type. See [schema.org](https://schema.org) for full type definitions.
      - `@context` string: Schema.org context URL. Almost always `https://schema.org`.
      - `@type` 'Article' | 'BlogPosting' | 'NewsArticle' | 'FAQPage' | 'HowTo' | 'TechArticle' | 'WebPage': The schema.org type for this content.
      - `headline` string: The headline of the article. Recommended for Article, BlogPosting, NewsArticle.
      - `description` string: A short description or summary of the content.
      - `author` union
        - object: Author as a Person or Organization.
          - `@type` 'Person' | 'Organization'
          - `name` string
          - `url` string, uri
        - object[]: Multiple authors.
          - `@type` 'Person' | 'Organization'
          - `name` string
          - `url` string, uri
      - `datePublished` string, date: Original publication date in ISO 8601 format (e.g., `2026-04-16`).
      - `dateModified` string, date: Last modification date in ISO 8601 format.
      - `image` union: Primary image. Can be a URL string or an ImageObject.
        - string, uri
        - object
          - `@type` 'ImageObject'
          - `url` string, uri
          - `width` integer
          - `height` integer
      - `publisher` object: The publisher of the content.
        - `@type` 'Organization'
        - `name` string
        - `logo` object
          - `@type` 'ImageObject'
          - `url` string, uri
      - `mainEntity` union: Primary entity of the page. Used by FAQPage (array of Question) and HowTo (HowToStep array).
        - object[]: For FAQPage: array of Question objects.
          - `@type` 'Question'
          - `name` string: The question text.
          - `acceptedAnswer` object
            - `@type` 'Answer'
            - `text` string: The answer text.
        - object
      - `step` object[]: For HowTo: ordered list of steps.
        - `@type` 'HowToStep'
        - `name` string: Step title.
        - `text` string: Step instructions.
        - `image` string, uri
    - `status` 'draft' | 'published' | 'scheduled'
    - `published_at` string, date-time, nullable
    - `meta` object, nullable
    - `created_at` string, date-time
    - `updated_at` string, date-time
    - `primary_author` object, nullable: Primary/canonical author, or null.
      - `id` string, uuid, required
      - `name` string, required
      - `slug` string, required
      - `avatar_url` string, uri, nullable
      - `bio` string, nullable
      - `role` string, nullable: e.g. "Head of Content". Set on author creation only; a re-import never overwrites an existing author's role.
    - `authors` object[]: Byline authors (incl. the primary), ordered by position.
      - `id` string, uuid, required
      - `name` string, required
      - `slug` string, required
      - `position` integer, required
      - `avatar_url` string, uri, nullable
      - `role` string, nullable: e.g. "Head of Content". Set on author creation only; a re-import never overwrites an existing author's role.
    - `category` object, nullable: Single category, or null.
      - `id` string, uuid, required
      - `name` string, required
      - `slug` string, required
      - `parent_id` string, uuid, nullable
    - `tags` object[]
      - `id` string, uuid, required
      - `name` string, required
      - `slug` string, required

## Other responses

- `401`: Authentication failed
- `403`: Forbidden - action not allowed on this resource
- `409`: Review required. The content type is review-gated and the post is not approved yet.
- `422`: Validation failed
- `429`: Rate limit exceeded

---

[API](https://skmtc.dev/frase/apis/frase-api.md) · [All operations](https://skmtc.dev/frase/apis/frase-api/llms.txt) · [OpenAPI document](https://skmtc.dev/frase/apis/frase-api/revisions/7fb75d89f7a4?raw)
