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

# Pages & Blog

> List, read, create, update, and delete custom pages and blog posts on your job board

Custom pages and blog posts are the same content type on Kardow: a blog post is a page flagged as a blog article. These endpoints let another system (or an AI assistant via the MCP connector) manage them programmatically.

<Info>
  Authenticate every request with your API key in the `x-api-key` header. A valid key can manage its own organization's content. Create keys under **Settings > API** in the dashboard.
</Info>

## Content format

Send the body in the `content` field as **HTML** (recommended, easiest to produce). It is stored as rich-text and rendered on your live site. You may also send TipTap JSON directly if you already have it.

These elements render on the live site:

| Element               | HTML                                                                                           |
| --------------------- | ---------------------------------------------------------------------------------------------- |
| Headings              | `<h1>` through `<h6>`                                                                          |
| Paragraph, line break | `<p>`, `<br>`                                                                                  |
| Emphasis              | `<strong>`, `<em>`, `<s>`, inline `<code>`                                                     |
| Lists                 | `<ul>` / `<ol>` with `<li>`                                                                    |
| Quote                 | `<blockquote>`                                                                                 |
| Code block            | `<pre><code>...</code></pre>`                                                                  |
| Divider               | `<hr>`                                                                                         |
| Link                  | `<a href="...">`                                                                               |
| Image                 | `<img src="...">`                                                                              |
| Table                 | `<table>` / `<tr>` / `<th>` / `<td>` (colspan/rowspan supported)                               |
| Text alignment        | any block with `style="text-align:center"` (or right/justify)                                  |
| Text color            | `<span style="color:#2563eb">...</span>`                                                       |
| YouTube               | `<div data-youtube-video><iframe src="https://www.youtube.com/embed/VIDEO_ID"></iframe></div>` |
| Embed (iframe)        | `<iframe src="https://..." width="100%" height="600px">`                                       |

Wide tables render inside a horizontal scroller on the live site, so real data tables with many columns are fine. Generic iframes cover embeds like Tableau dashboards, maps, calendars, or booking widgets: use the provider's embed or share URL as the `src`. Embeds render sandboxed on the live site.

Interactive builder blocks (pricing tables, contact/subscribe forms, section templates) are managed in the dashboard editor and are not authored through the API. Any HTML you send outside the list above is cleaned out, so stick to these tags for predictable results.

For images, do not hard-link an external URL inside `content`. Upload it first with the [Assets API](/docs/api-reference/content/assets) so it is hosted on your board, then use the returned `cdn.kardow.com` URL as the `cover_image` or inside the HTML.

***

## List pages

```http theme={null}
GET https://api.kardow.com/pages
```

<ParamField query="kind" type="string">
  `blog_post` (blog articles), `page` (standalone pages), or `all` (default).
</ParamField>

<ParamField query="status" type="string">
  Filter by `draft`, `published`, or `archived`.
</ParamField>

<ParamField query="search" type="string">
  Match against the title.
</ParamField>

<ParamField query="page" type="number" default="1">Page number.</ParamField>
<ParamField query="per_page" type="number" default="20">Records per page, up to 100.</ParamField>

```bash cURL theme={null}
curl --url "https://api.kardow.com/pages?kind=blog_post&status=published" \
  --header "x-api-key: your-api-key-here"
```

Each item includes `id`, `title`, `slug`, `kind` fields (`type`, `is_blog_article`), `status`, the full public `url`, `cover_image` (a cdn.kardow\.com URL), `meta_title`, `meta_description`, `author_id`, `published_at`, `created_at`, and `updated_at`. The list is metadata only; fetch a single page to get its body.

***

## Get a page

```http theme={null}
GET https://api.kardow.com/pages/{id}
```

Returns everything from the list shape plus `content` (TipTap JSON), `content_html` (the body rendered as HTML, easiest to read and revise), `content_text` (plain text), `og_image`, and `custom_fields`.

```bash cURL theme={null}
curl --url "https://api.kardow.com/pages/4d1b6fe8-688f-467c-b233-b5d6a51ce1cb" \
  --header "x-api-key: your-api-key-here"
```

***

## Create a page or blog post

```http theme={null}
POST https://api.kardow.com/pages
```

<ParamField body="title" type="string" required>Page or article title.</ParamField>
<ParamField body="content" type="string">Body as HTML (or TipTap JSON). Empty is allowed.</ParamField>
<ParamField body="kind" type="string" default="page">`blog_post` to create a blog article, `page` for a standalone page.</ParamField>
<ParamField body="status" type="string" default="draft">`published` to make it live immediately, or `draft` to keep it hidden.</ParamField>
<ParamField body="slug" type="string">URL slug. Auto-generated from the title (and de-duplicated) if omitted.</ParamField>
<ParamField body="cover_image" type="string">Cover/hero image URL, ideally a `cdn.kardow.com` URL from the Assets API. Shown on blog cards.</ParamField>
<ParamField body="meta_title" type="string">SEO title.</ParamField>
<ParamField body="meta_description" type="string">SEO description; also used as the blog card summary.</ParamField>
<ParamField body="author_id" type="string">Optional author UUID for blog posts.</ParamField>
<ParamField body="published_at" type="string">Optional publish date (ISO 8601). Defaults to now when `status` is `published`.</ParamField>

```bash cURL theme={null}
curl --request POST \
  --url "https://api.kardow.com/pages" \
  --header "Content-Type: application/json" \
  --header "x-api-key: your-api-key-here" \
  --data '{
    "title": "5 Remote Hiring Trends for 2026",
    "kind": "blog_post",
    "status": "published",
    "cover_image": "https://cdn.kardow.com/abc123/storage/v1/object/public/org-assets/42/library/cover.png",
    "meta_description": "What we learned about remote hiring this year.",
    "content": "<h2>The shift to async</h2><p>Teams increasingly hire across time zones...</p><ul><li>Point one</li><li>Point two</li></ul>"
  }'
```

The response returns the full page including its public `url`.

***

## Update a page

```http theme={null}
PATCH https://api.kardow.com/pages/{id}
```

Send only the fields you want to change. Accepts the same fields as create (`title`, `content`, `status`, `slug`, `cover_image`, `meta_title`, `meta_description`, `author_id`, `published_at`). Passing `content` replaces the body. Setting `status` to `published` stamps `published_at` automatically the first time.

```bash cURL theme={null}
curl --request PATCH \
  --url "https://api.kardow.com/pages/4d1b6fe8-688f-467c-b233-b5d6a51ce1cb" \
  --header "Content-Type: application/json" \
  --header "x-api-key: your-api-key-here" \
  --data '{ "status": "published" }'
```

***

## Delete a page

```http theme={null}
DELETE https://api.kardow.com/pages/{id}
```

```bash cURL theme={null}
curl --request DELETE \
  --url "https://api.kardow.com/pages/4d1b6fe8-688f-467c-b233-b5d6a51ce1cb" \
  --header "x-api-key: your-api-key-here"
```
