Webharu CMS Docs BETA llms-full.txt

Webharu CMS 開発者ドキュメント

記事の作成・公開・管理をプログラムとAIから。日本語サイト運用のために作られた、AI最適化ヘッドレスCMSのAPI & MCPリファレンス。

REST APIとMCPサーバーの2つの入口から、同じ公開パイプラインに接続します。記事を published にすると、静的サイトへのビルド・デプロイまで自動で完了します。

ベースURLhttps://cms.webharu.com API/api/ext/v1 MCP/mcp 認証Bearer(APIキー)

Webharu CMSとは

Webharu CMSは、株式会社Web春が運営するサイト運用基盤のヘッドレスCMSです。ブラウザの記事エディタ(noteライクなWYSIWYG)に加えて、この開発者向けAPIとMCPサーバーを提供します。

  • 公開まで全自動 — APIで status: "published" にした瞬間、サイトのビルド・デプロイが走り、数分で本番URLに反映されます(Git連携テナント)。Webhookの組み立てやCI設定は不要です。
  • Markdownファースト — 本文は body_md(Markdown)だけ送ればOK。HTML変換はサーバー側で行います。
  • AI最適化 — MCPサーバー同梱・llms.txt 提供・削除やレート等の安全設計込み。AIエージェントがそのまま運用に参加できます。
  • エディタと同一パイプライン — API経由の操作もブラウザのエディタと同じ検証・履歴・監査ログを通ります。どちらで編集しても一貫します。
BETA現在は招待制ベータです。APIキーはマイページからご自身で発行できます。仕様は互換性を保ちながら拡張されますが、変更時は変更履歴に記載します。

クイックスタート

APIキーを発行してから、最初の記事を公開するまでの最短手順です。

0. APIキーを発行する

マイページ(cms.webharu.com/my/)にログイン →「AIツール連携(APIキー)」→ 用途がわかる名前を入れて発行。 キーの値が表示されるのは発行時の一度だけです(サーバーにはハッシュのみ保存)。1サイトあたり5本まで発行でき、停止・削除も同じ画面からいつでもできます。

1. 接続を確認する

curl https://cms.webharu.com/api/ext/v1/me \
  -H "Authorization: Bearer whk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
const BASE = "https://cms.webharu.com/api/ext/v1";
const KEY = process.env.WEBHARU_API_KEY;

const res = await fetch(`${BASE}/me`, {
  headers: { Authorization: `Bearer ${KEY}` },
});
console.log(await res.json());
import os, requests

BASE = "https://cms.webharu.com/api/ext/v1"
KEY = os.environ["WEBHARU_API_KEY"]

r = requests.get(f"{BASE}/me", headers={"Authorization": f"Bearer {KEY}"})
print(r.json())
// レスポンス
{
  "ok": true,
  "data": {
    "tenant_name": "あなたのサイト名",
    "site_url": "https://example.com",
    "collections": [{ "key": "news", "label": "お知らせ" }]
  }
}

2. 下書きを作る

curl -X POST "$BASE/posts" \
  -H "Authorization: Bearer $KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "夏季休業のお知らせ",
    "body_md": "## 休業期間\n\n8月13日〜16日はお休みをいただきます。",
    "category": "お知らせ"
  }'

status を省略すると必ず下書き(draft)として作成されます。サイトには載りません。

3. 公開する

curl -X PUT "$BASE/posts/夏季休業記事のidまたはslug" \
  -H "Authorization: Bearer $KEY" \
  -H "Content-Type: application/json" \
  -d '{ "status": "published" }'
公開の仕組みGit連携テナントでは、公開と同時にサイトリポジトリへ記事ファイルがコミットされ、ビルド・デプロイが自動実行されます。本番URLへの反映まで通常2〜3分です。

認証とAPIキー

すべてのリクエストに以下のヘッダーが必要です。

ヘッダー必須
AuthorizationBearer whk_...(発行されたAPIキー)はい
Content-Typeapplication/json(ボディがある場合)POST / PUT

キーの性質

  • キーはサイト(テナント)ごとに発行され、そのサイトのコンテンツだけを操作できます。
  • サーバー側にはキーのハッシュのみ保存されます。値が見られるのは発行時の一度だけです。紛失した場合はマイページで削除して再発行してください。
  • キーの停止・削除は即時に反映されます(停止後の全リクエストは 401)。
  • すべての操作は監査ログに記録されます(いつ・どのキーが・何をしたか)。
キーの取り扱いキーはコードにハードコードせず、環境変数やシークレットマネージャに保管してください。公開リポジトリへのコミットは厳禁です。漏えいが疑われる場合はマイページで該当キーを停止または削除してください(即時失効します)。

コンテンツモデル

Webharu CMSのコンテンツは「記事(post)」です。記事は「コレクション」に属します(例: news = お知らせ、blog = ブログ)。使えるコレクションは GET /me で確認できます。

記事のフィールド

フィールド説明
idstring記事ID(post_で始まる。システム発行)
slugstringURLになる識別子。省略時は自動採番。テナント内で一意
titlestring記事タイトル
body_mdstring本文(Markdown)。これが原稿の正
body_htmlstring本文HTML。未指定なら body_md からサーバーが生成
excerptstring | null要約(一覧・OGP・検索結果用。80字目安)
cover_imagestring | null表紙画像URL(画像APIの返すURL)
categorystring | nullカテゴリ名(自由入力。既存一覧と表記を揃えると◎)
statusstringdraft(下書き)/ published(公開)/ scheduled(予約)
collectionstring所属コレクション。既定 news
publish_atstring | null予約公開日時(scheduled のとき必須・ISO 8601)
published_atstring | null公開日時(公開時に自動設定)
authorstring | null投稿者表示名(API経由はキー名が入る)
updated_atstring最終更新日時

公開ステータスの遷移

status挙動
draft下書き。サイトには一切表示されない(既定値)
published即時公開。サイトへの反映(ビルド・デプロイ)が自動で走る
scheduled予約公開。publish_at の時刻を過ぎると5分以内に自動公開

公開中の記事を draft に戻すと、サイトからも取り下げられます。

GET/api/ext/v1/me

キーが指すサイトの情報を返します。接続テストと、使えるコレクションの確認に使います。

curl "$BASE/me" -H "Authorization: Bearer $KEY"

// 200
{ "ok": true, "data": { "tenant_name": "サイト名", "site_url": "https://example.com",
  "collections": [{ "key": "news", "label": "お知らせ" }] } }
GET/api/ext/v1/posts

記事一覧を新しい順に返します(本文は含みません。全文は GET /posts/:id)。

クエリ説明
collectionstring任意既定 news
statusstring任意draft / published / scheduled で絞り込み
limitnumber任意件数上限(既定50・最大200)
curl "$BASE/posts?status=published&limit=10" -H "Authorization: Bearer $KEY"

// 200
{ "ok": true, "data": [
  { "id": "post_...", "slug": "summer-notice", "title": "夏季休業のお知らせ",
    "excerpt": "...", "cover_image": null, "category": "お知らせ",
    "status": "published", "collection": "news",
    "publish_at": null, "published_at": "2026-07-30 06:38:19",
    "author": "連携アプリ", "updated_at": "2026-07-30 06:38:19" }
] }
GET/api/ext/v1/posts/:id

記事1件の全文(body_md / body_html 含む)を返します。:id には記事IDでもslugでも指定できます

curl "$BASE/posts/summer-notice" -H "Authorization: Bearer $KEY"
POST/api/ext/v1/posts

記事を作成します。

ボディ説明
titlestring必須記事タイトル(25〜30字目安)
body_mdstring必須本文Markdown。見出しは ## から
categorystring任意カテゴリ名
excerptstring任意要約(80字目安)
cover_imagestring任意表紙画像URL
statusstring任意既定 draft
publish_atstring任意scheduled のとき必須(例 2026-08-01T10:00:00+09:00
collectionstring任意既定 news
slugstring任意英小文字とハイフン。省略で自動採番
body_htmlstring任意通常は送らない(サーバーが body_md から生成)
curl -X POST "$BASE/posts" \
  -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{
    "title": "新メニューのご案内",
    "body_md": "## 夏の新メニュー\n\n7月から新メニューが始まりました。\n\n- 冷やし担々麺\n- すだちそば",
    "category": "お知らせ",
    "excerpt": "7月からの新メニューを2品ご紹介します"
  }'
const res = await fetch(`${BASE}/posts`, {
  method: "POST",
  headers: { Authorization: `Bearer ${KEY}`, "Content-Type": "application/json" },
  body: JSON.stringify({
    title: "新メニューのご案内",
    body_md: "## 夏の新メニュー\n\n7月から新メニューが始まりました。",
    category: "お知らせ",
  }),
});
const { data } = await res.json(); // data.id, data.slug, data.status === "draft"
r = requests.post(f"{BASE}/posts",
    headers={"Authorization": f"Bearer {KEY}"},
    json={
        "title": "新メニューのご案内",
        "body_md": "## 夏の新メニュー\n\n7月から新メニューが始まりました。",
        "category": "お知らせ",
    })
post = r.json()["data"]  # post["status"] == "draft"
PUT/api/ext/v1/posts/:id

記事を部分更新します。渡したフィールドだけが変わります(:id はIDでもslugでも可)。公開・非公開の切り替えもこのエンドポイントです。

# 公開する
curl -X PUT "$BASE/posts/post_abc123" -H "Authorization: Bearer $KEY" \
  -H "Content-Type: application/json" -d '{ "status": "published" }'

# 明日の朝10時に予約公開へ変更
curl -X PUT "$BASE/posts/post_abc123" -H "Authorization: Bearer $KEY" \
  -H "Content-Type: application/json" \
  -d '{ "status": "scheduled", "publish_at": "2026-07-31T10:00:00+09:00" }'
DELETE/api/ext/v1/posts/:id

記事を削除します。公開中の記事はサイトからも取り下げられます。取り消せません。

curl -X DELETE "$BASE/posts/post_abc123" -H "Authorization: Bearer $KEY"

// 200
{ "ok": true, "data": { "id": "post_abc123" } }
GET/api/ext/v1/categories

そのサイトで使われている既存カテゴリの一覧です。表記ゆれ(「お知らせ」と「おしらせ」など)を防ぐため、記事作成前の確認を推奨します。

{ "ok": true, "data": ["イベント", "お知らせ", "キャンペーン"] }
POST/api/ext/v1/media

画像をアップロードし、記事で使えるURLを返します。multipart/form-datafile フィールドで送信します(image/*・10MBまで)。

curl -X POST "$BASE/media" -H "Authorization: Bearer $KEY" \
  -F "file=@./photo.jpg"

// 200
{ "ok": true, "data": { "id": "med_...", "filename": "photo.jpg",
  "url": "https://cms.webharu.com/media/..." } }

返ってきた urlcover_image や本文の ![alt](url) に使います。

POST/api/ext/v1/media-from-url

外部URLの画像を取り込みます(https・image/*・10MBまで)。ファイルを扱えない環境(AIエージェント等)向けです。

curl -X POST "$BASE/media-from-url" -H "Authorization: Bearer $KEY" \
  -H "Content-Type: application/json" \
  -d '{ "url": "https://example.com/images/photo.jpg" }'

エラーとレート制限

エラーは共通フォーマット { "error": "日本語のメッセージ" } で返ります。

ステータス意味対処
400リクエスト不正メッセージに従い修正(必須フィールド不足・不正な日時など)
401認証失敗キーの値・Bearer プレフィックス・キーが停止されていないか確認
404記事が見つからないid / slug を確認
409slug重複別のslugにするか、slugを省略して自動採番
429レート制限間隔を空けて再試行(下記)
5xxサーバーエラー時間を置いて再試行。続く場合はサイト担当者へ

レート制限

APIキーごとに 120リクエスト/分 です。超過すると 429 が返ります。バッチ処理は1秒に1〜2リクエスト程度に抑えるのが安全です。

再試行の指針4295xx は指数バックオフ(1秒→2秒→4秒…)での再試行を推奨します。4xx(429以外)はリクエスト自体の問題なので再試行しても解決しません。

MCPサーバー

MCP(Model Context Protocol)は、AIアシスタントに外部ツールを安全に接続するための標準プロトコルです。Webharu CMSはリモートMCPサーバーを同梱しており、Claude・Cursor等のAIから記事の作成・公開を直接指示できます。コードを書く必要はありません。

項目
エンドポイントhttps://cms.webharu.com/mcp
トランスポートStreamable HTTP(ステートレス)
認証APIキー(RESTと同じ)を Authorization: Bearer ヘッダーで

Claude Code(CLI)

claude mcp add --transport http webharu-cms \
  https://cms.webharu.com/mcp \
  --header "Authorization: Bearer whk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

登録後、Claudeに「サイトにお知らせを1本書いて下書きにして」のように話すだけで動きます。

Claude Desktop

設定 → コネクタ → 「カスタムコネクタを追加」で上記URLを入力し、ヘッダーに Authorization: Bearer whk_... を設定します。

Cursor / その他のMCPクライアント

// mcp.json(Cursor: .cursor/mcp.json)
{
  "mcpServers": {
    "webharu-cms": {
      "url": "https://cms.webharu.com/mcp",
      "headers": { "Authorization": "Bearer whk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }
    }
  }
}

MCPツールリファレンス

ツール説明主な引数
get_site_infoサイト情報・コレクション一覧(接続確認)
list_posts記事一覧(新しい順)collection status limit
get_post記事1件の全文id(IDかslug)
create_post記事作成(既定は下書き)title body_md category status ほか
update_post部分更新・公開/非公開の切替id +変更フィールド
delete_post記事削除(公開中はサイトからも消える)id
list_categories既存カテゴリ一覧
upload_image_from_url外部URLの画像を取り込みURLを返すurl

安全設計

  • 既定は下書きstatus を明示しない作成は必ず下書きになります。AIが会話の流れで勝手に公開することはありません。
  • スコープはサイト単位 — キーは1サイト分の権限しか持ちません。他サイト・管理機能には一切アクセスできません。
  • 全操作が監査ログに記録 — いつ・どのキーが・どの記事に何をしたかをサイト担当者が確認できます。
  • 即時失効 — キーを停止すればその瞬間からすべての操作が拒否されます。
運用の推奨AIに公開まで任せる場合も、まず create_post(下書き)→内容確認→update_post で公開、の2段階を推奨します。

AIエージェントで導入する

このドキュメントの全文はAIが読み込みやすいプレーンテキストでも提供しています。AIエージェント(Claude Code等)に以下を渡すだけで、連携コードの実装やMCPセットアップを自動で行えます。

https://cms.webharu.com/docs/llms-full.txt を読んで、
Webharu CMSとの連携をセットアップしてください。
APIキー: (発行されたキーを環境変数 WEBHARU_API_KEY に設定済み)
やりたいこと: (例)毎週月曜にブログ下書きを自動生成する

例えばこんな依頼がそのまま動きます:

  • 「MCPで接続して、今公開中の記事一覧を見せて」
  • 「この議事録を要約してお知らせ記事の下書きにして」
  • 「予約投稿で来週月曜9時に公開される記事を作って」
  • 「Webhookは無いので、RSS代わりに published 一覧をポーリングするスクリプトを書いて」

llms.txt

AI向けのドキュメントインデックスと全文を公開しています。

ファイル内容
/docs/llms.txtインデックス(このドキュメントの目次と要点)
/docs/llms-full.txt全文(API仕様・MCP仕様・コード例のすべて)。AIにはこちらを読ませてください

FAQ

Webhookはありますか?

ベータ版では未提供です。公開済み記事の検知は GET /posts?status=published のポーリング(数分間隔)で代替できます。要望が多ければ正式版で検討します。

記事の取得だけしたい(読み取り専用キー)

ベータ版のキーは読み書き両方の権限を持ちます。読み取り専用スコープは今後のロードマップにあります。取得だけの用途でも現状のキーをそのまま使えます。

body_htmlを直接送ってもいい?

可能ですが推奨しません。body_md だけ送る方が、エディタとの相互編集・将来のデザイン変更に強くなります。

予約公開の精度は?

5分間隔のスケジューラが処理するため、指定時刻から最大5分程度の遅延があります。

1つのキーを複数のツールで使い回してもいい?

動作はしますが、ツールごとにキーを分けることを推奨します(監査ログでの区別・漏えい時に該当ツールだけ止められるため)。マイページから5本まで発行できます。

料金は?

ベータ期間中、契約クライアントは追加費用なしで利用できます。

変更履歴

日付内容
2026-08-06APIキーをマイページから自分で発行・停止・削除できるようになりました(1サイト5本まで)
2026-07-30ベータ公開。REST API v1(記事CRUD・カテゴリ・画像)・MCPサーバー(8ツール)・llms.txt