WordPressには「REST API」という機能が標準で組み込まれています。
REST APIを使うと、管理画面を開かずに、外部のプログラムやAIツールからWordPressのデータを取得・作成・更新・削除できます。
この記事では、WordPress REST APIでできることを整理したうえで、実際に接続して使えるようにするまでの構築手順を解説します。
カスタム投稿タイプやカスタムフィールドをAPIに対応させる方法、独自エンドポイントの追加方法、つまずきやすいポイントまでまとめています。
WordPress REST APIとは
WordPress REST APIは、WordPressのデータをHTTP経由で操作するための公式インターフェースです。
WordPress 4.7以降、プラグインなしで標準搭載されています。
投稿の取得結果や更新データは主にJSONを使います。画像アップロードではバイナリなどを送るため、すべてのリクエストがJSONとは限りません。
まずは自分のサイトで有効になっているか確認してみます。
https://example.com/wp-json/このURLにアクセスしてJSONが表示されれば、REST APIは有効です。
投稿一覧を取得する場合は次のURLです。
https://example.com/wp-json/wp/v2/posts標準構成では公開投稿を認証なしで取得できます。ただし、サイトのアクセス制限やプラグイン設定によって応答は異なります。
一方で、下書きの取得や記事の作成・更新には認証が必要になります。
REST APIの基本構造
エンドポイントは次のような構造になっています。
https://example.com/wp-json/{名前空間}/{バージョン}/{リソース}WordPress本体の機能は wp/v2 という名前空間にまとまっています。
プラグインが独自機能を追加する場合は、WooCommerceのwc/v3のように別の名前空間が使われます。認証方式も各APIの仕様を確認します。
操作はHTTPメソッドで指定します。
- GET:取得
- POST:作成・更新
- PUT / PATCH:更新
- DELETE:削除
WordPressの場合、更新はPUTではなくPOSTでも受け付けてくれるため、実務ではPOSTを使うことが多いです。
WordPress REST APIでできること
標準で用意されている主なエンドポイントは以下のとおりです。
/wp/v2/posts:投稿の取得・作成・更新・削除/wp/v2/pages:固定ページの操作/wp/v2/media:画像などメディアのアップロード・編集/wp/v2/categories:カテゴリーの操作/wp/v2/tags:タグの操作/wp/v2/comments:コメントの操作/wp/v2/users:ユーザー情報の取得・編集/wp/v2/taxonomies:登録済みタクソノミーの一覧/wp/v2/types:登録済み投稿タイプの一覧/wp/v2/settings:サイトタイトルなど基本設定の取得・変更/wp/v2/search:横断検索/wp/v2/block-types:ブロックタイプの一覧
各ルートで必要な権限は異なります。たとえば標準のsettingsはmanage_options権限が必要です。一般的には管理者が持ちますが、ロール名だけで判断せず、実際の権限と応答を確認します。
投稿・固定ページで編集できる項目
投稿と固定ページでは、次のような項目をAPI経由で扱えます。
- タイトル
- 本文
- 抜粋
- スラッグ
- 公開状態(publish / draft / private / pending / future)
- 公開日時
- 投稿者
- アイキャッチ画像
- カテゴリー・タグ
- 親ページ・メニュー順(固定ページのみ)
- テンプレート
- コメント許可設定
ブロックエディタで作成した記事も、本文はブロックコメント付きのHTMLとしてそのまま取得・更新できます。
メディアで編集できる項目
画像のアップロードに加えて、次の項目も編集できます。
- タイトル
- 代替テキスト(alt)
- キャプション
- 説明
altの一括修正などをスクリプトで処理したい場合に便利です。
認証方法を決める
外部から記事を編集するには認証が必要です。
WordPress標準の方式と、追加実装が必要な方式を分けて整理します。
アプリケーションパスワード
WordPress 5.6以降に標準搭載されている方式です。
追加のプラグインが不要で、外部ツールから接続する場合はこれが第一候補になります。
外部接続ではHTTPSを使用します。認証されたユーザーの権限で操作するため、発行するユーザーと必要な権限も確認します。
Cookie認証(nonce)
管理画面内のJavaScriptから叩く場合に使う方式です。
WordPressにログインしたブラウザー内の利用を想定した方式です。nonceだけで認証できるわけではなく、有効なログインCookieも必要です。外部の自動処理には、通常アプリケーションパスワードなどの方式を検討します。
JWT認証
プラグインを導入してトークンで認証する方式です。
トークンの有効期限を管理できるため、アプリケーション連携で使われることがあります。
OAuth 2.0
OAuth 2.0を使う場合は、対応するプラグインや認可サーバーなどの追加構成が必要です。WordPress標準の設定だけで利用できる方式としては扱いません。
接続サービスが求める認証方式に合わせ、追加構成の管理方法と許可範囲を確認します。
以下ではアプリケーションパスワードを前提に進めます。
構築手順1:アプリケーションパスワードを発行する
WordPressの管理画面にログインします。
次にプロフィール画面を開きます。
ユーザー > プロフィールページ下部にある「アプリケーションパスワード」の欄に、用途がわかる名前を入力します。
AI連携用「新しいアプリケーションパスワードを追加」を押すと、パスワードが発行されます。

発行されるのは次のような形式の文字列です。
abcd EFGH ijkl MNOP qrst UVWXこのパスワードは一度しか表示されないため、その場で控えておきます。
空白は含めたままでも、削除しても、どちらでも認証は通ります。
項目が表示されない場合は、HTTPS、WordPressの版、ユーザーごとの利用可否、セキュリティ設定や無効化フィルターを順に確認します。HTTPSだけが原因とは限りません。
接続先のAIツールで認証情報の保存方法と実行できる操作を確認し、専用ユーザーで接続します。
認証情報の設定だけで、更新内容や操作権限が自動的に適切になるわけではありません。
自動処理ではアプリケーションパスワードを環境変数やアクセスを制限した設定ファイルから読み取り、会話本文・リポジトリ・ログへ出力しません。
.envを使う場合も共有やGit管理の対象から外します。
構築手順2:接続を確認する
まず認証が必要なusers/meで、接続した専用ユーザーのIDを確認します。
以下のcurl例はPOSIX系シェルの改行・引用符です。
Windows PowerShellではcurl.exeを使い、改行やJSONの渡し方をそのシェルに合わせてください。
-uには専用ユーザー名だけを指定し、表示されるパスワード入力欄へアプリケーションパスワードを入力します。
通常のログインパスワードは使いません。
入力待ちを避ける自動処理には、この対話入力例をそのまま流用しません。
認証情報の扱いはcurlの公式マニュアルも参照してください。
curl -u "専用ユーザー名" \
https://example.com/wp-json/wp/v2/users/meログイン中のユーザー情報がJSONで返ってくれば成功です。
401が返ったら、HTTPステータスに加えてレスポンス本文のcodeとmessageを読みます。ユーザー名・失効したパスワード・認証ヘッダーの扱いなどを切り分けます。
403は権限不足だけでなく、nonceの不正やWAFなどでも返る場合があります。WordPressのJSONエラーか、サーバー/CDNの拒否画面かを区別し、ステータスだけで認証成功とは判断しません。
構築手順3:記事を取得する
公開済みの投稿を5件取得する例です。
curl "https://example.com/wp-json/wp/v2/posts?per_page=5"下書きを含めて取得したい場合は、認証したうえでstatusを指定します。
curl -u "専用ユーザー名" \
"https://example.com/wp-json/wp/v2/posts?status=draft"記事を編集する目的で本文を取得する場合は、context=edit を付けます。
curl -u "専用ユーザー名" \
"https://example.com/wp-json/wp/v2/posts/123?context=edit"これを付けないと、本文はショートコードやブロックが展開された表示用HTMLで返ってきます。
context=edit を付けると content.raw にエディタ上のままのブロックHTMLが入るため、リライト用途ではこちらを使います。
レスポンスが大きすぎる場合は _fields で項目を絞れます。
curl "https://example.com/wp-json/wp/v2/posts?_fields=id,title,slug,link&per_page=100"per_page の上限は100件です。
全件を扱うときは、レスポンスヘッダーの X-WP-Total と X-WP-TotalPages を見ながら page を進めます。
構築手順4:記事を作成・更新する
下書き記事を新規作成する例です。
curl -X POST https://example.com/wp-json/wp/v2/posts \
-u "専用ユーザー名" \
-H "Content-Type: application/json" \
-d '{
"title": "テスト記事",
"content": "<!-- wp:paragraph --><p>本文です。</p><!-- /wp:paragraph -->",
"status": "draft",
"slug": "test-post",
"categories": [3]
}'既存記事は更新前にID・URL・modified_gmt・変更対象の値を保存します。送信直前にも読み戻し、他者の更新があれば差分を確認して作業を止めます。この再取得だけでは同時更新を完全には防げないため、一括処理は担当時間や対象記事を分けて進めます。
既存記事を更新する場合は、URLに投稿IDを付けてPOSTします。
curl -X POST https://example.com/wp-json/wp/v2/posts/123 \
-u "専用ユーザー名" \
-H "Content-Type: application/json" \
-d '{"title": "更新後のタイトル"}'標準APIでは指定した項目を更新しますが、保存フックやプラグインが関連項目を変更する場合もあります。更新後は対象IDを再取得し、指定した値と、保持したい本文・公開状態・URL・分類が意図どおりか確認します。
JavaScriptで下書きを作る最小例です。実運用ではHTTPステータスとエラー本文を確認し、成功したIDを保存して再取得します。タイムアウト時に新規作成を無条件で再送すると、重複投稿になる可能性があります。
const auth = btoa(`${username}:${appPassword}`);
const res = await fetch("https://example.com/wp-json/wp/v2/posts", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Basic ${auth}`,
},
body: JSON.stringify({
title: "テスト記事",
content: "本文です。",
status: "draft",
}),
});
const data = await res.json();
console.log(data.id, data.link);
なお、この書き方はブラウザ上で実行すると認証情報が丸見えになります。
認証を伴う処理は、必ずサーバー側やローカル環境から実行します。
構築手順5:画像をアップロードする
メディアのアップロードはJSONではなくバイナリを送信します。
curl -X POST https://example.com/wp-json/wp/v2/media \
-u "専用ユーザー名" \
-H "Content-Disposition: attachment; filename=sample.jpg" \
-H "Content-Type: image/jpeg" \
--data-binary @sample.jpg返ってきたIDを使えば、アイキャッチ画像として設定できます。
curl -X POST https://example.com/wp-json/wp/v2/posts/123 \
-u "専用ユーザー名" \
-H "Content-Type: application/json" \
-d '{"featured_media": 456}'代替テキストを後から編集する場合はmediaエンドポイントを更新します。
curl -X POST https://example.com/wp-json/wp/v2/media/456 \
-u "専用ユーザー名" \
-H "Content-Type: application/json" \
-d '{"alt_text": "サンプル画像の説明"}'カスタム投稿タイプをREST APIに対応させる
カスタム投稿タイプは、登録時に show_in_rest を有効にしないとAPIに現れません。
functions.php またはプラグイン側で次のように登録します。
add_action('init', function () {
register_post_type('works', [
'label' => '実績',
'public' => true,
'has_archive' => true,
'show_in_rest' => true,
'rest_base' => 'works',
'supports' => ['title', 'editor', 'excerpt', 'thumbnail', 'custom-fields'],
]);
});これで次のエンドポイントが使えるようになります。
https://example.com/wp-json/wp/v2/worksすでに動いているサイトで対応状況を確認したい場合は、typesエンドポイントを見ます。
https://example.com/wp-json/wp/v2/types一覧のrest_baseとrest_namespaceを確認して対象ルートを特定します。掲載されていることだけで、そのユーザーに作成・更新権限があるとは判断しません。
既存のカスタム投稿タイプがテーマやプラグインで登録されていて直接編集できない場合は、フィルターで後から有効化する方法もあります。
add_filter('register_post_type_args', function ($args, $post_type) {
if ($post_type === 'works') {
$args['show_in_rest'] = true;
$args['rest_base'] = 'works';
}
return $args;
}, 10, 2);カスタムタクソノミーをREST APIに対応させる
考え方は投稿タイプと同じです。
add_action('init', function () {
register_taxonomy('works_cat', ['works'], [
'label' => '実績カテゴリー',
'public' => true,
'hierarchical' => true,
'show_in_rest' => true,
'rest_base' => 'works_cat',
]);
});公開されているタクソノミーの一覧はこちらで確認できます。
https://example.com/wp-json/wp/v2/taxonomiesターム一覧の取得や、記事へのターム紐付けもAPIから行えます。
タームIDは一覧から取得した存在するIDを使い、更新後のレスポンスでも保存された配列を確認してください。
存在しないタームIDだけを指定すると、エラーにならず既存の紐付けが外れる場合があります。
curl -X POST https://example.com/wp-json/wp/v2/works/123 \
-u "専用ユーザー名" \
-H "Content-Type: application/json" \
-d '{"works_cat": [5, 8]}'カスタムフィールド・メタディスクリプションを扱う
カスタムフィールドは、標準ではREST APIに公開されていません。
register_post_meta で明示的に登録する必要があります。
function waza_register_rest_note() {
register_post_meta( 'post', 'waza_rest_note', array(
'single' => true,
'type' => 'string',
'sanitize_callback' => 'sanitize_text_field',
'show_in_rest' => array( 'schema' => array(
'type' => 'string',
'context' => array( 'edit' ),
) ),
'auth_callback' => function ( $allowed, $key, $post_id ) {
return current_user_can( 'edit_post', $post_id );
},
) );
}
add_action( 'init', 'waza_register_rest_note' );
この例のキーはwaza_rest_noteです。
投稿別の編集権限を確認し、edit文脈でのみ値を返すため、公開読取用のフィールドにはなりません。
登録すると、レスポンスの meta 内に含まれるようになります。
curl -X POST https://example.com/wp-json/wp/v2/posts/123 \
-u "専用ユーザー名" \
-H "Content-Type: application/json" \
-d '{"meta": {"waza_rest_note": "任意の値"}}'
SEOプラグインの説明文は投稿メタに保存される場合がありますが、独自テーブルを使うものもあります。
プラグインによってキー名が異なり、REST API対応の有無も変わります。
- SEO SIMPLE PACK:
ssp_meta_descriptionなどのメタキー - Rank Math:
rank_math_description - Yoast SEO:
_yoast_wpseo_metadesc - All in One SEO:独自テーブルに保存されるため通常のメタでは扱えない
RESTで利用できない場合は、プラグインが提供する連携方法とデータ構造を確認します。
Rank Mathなど既存プラグインのメタキーは、上の独自キーの例で再登録しないでください。
プラグイン側のREST対応、キー名、保存権限、出力への反映を確認してから連携します。
アンダースコアで始まるメタキーは保護されたメタとして扱われるため、auth_callback の指定が必須になります。
プラグインのアップデートで保存先の仕様が変わることもあるため、更新前に必ずバックアップを取ります。
独自エンドポイントを追加する
標準のエンドポイントで足りない場合は、自分でルートを追加できます。
次の例はサイト全体の公開件数と下書き件数を返すため、edit_others_posts権限を持つ利用者だけに許可します。
通常の著者・寄稿者・購読者には返さず、全体の投稿を管理する編集者や管理者が認証して利用する想定です。
add_action('rest_api_init', function () {
register_rest_route('motoki/v1', '/summary', [
'methods' => 'GET',
'callback' => function (WP_REST_Request $request) {
$count = wp_count_posts('post');
return new WP_REST_Response([
'publish' => (int) $count->publish,
'draft' => (int) $count->draft,
], 200);
},
'permission_callback' => function () {
return current_user_can('edit_others_posts');
},
]);
});呼び出しはこうなります。
https://example.com/wp-json/motoki/v1/summary
permission_callback は省略できません。
省略すると警告が出るうえ、誰でもアクセスできる状態になってしまいます。
読み取り専用で公開したい場合でも、明示的に __return_true を書きます。
ChatGPTなどのAIツールと接続する
接続に必要な情報は次の3つだけです。
WORDPRESS_URL=https://example.com
WORDPRESS_USERNAME=
WORDPRESS_APP_PASSWORD=
これを .env に保存し、.gitignore に .env を追加して公開されないようにします。
AIツール側との接続方法は、大きく3パターンあります。
MCPサーバー経由で接続する
Claude Desktopや対応するAI開発ツールでは、MCPサーバーを介して使う構成を選べます。
WordPress REST APIをラップしたMCPサーバーを用意し、環境変数に上記3つを渡します。
MCPサーバーで公開するツールから削除操作を外せます。
ただし、ツール定義はWordPressの認証情報そのものを操作単位で制限する機能ではありません。
専用ユーザーの権限、WordPress側の投稿別権限、MCPサーバーが許可する操作と対象IDをそれぞれ確認します。
GPTsのActionsとして登録する
ChatGPTのGPTsから使う場合は、OpenAPIスキーマを定義してActionsに登録します。
GPTsのActionsで選べる認証方式は、OpenAIの公式認証資料ではNone・API Key・OAuthです。
WordPressのアプリケーションパスワードはHTTP Basic認証を使いますが、ユーザー名とパスワードをActionsへ入力するだけで接続できるとは限りません。
必要なAuthorizationヘッダーを送れる構成か、サーバー側でWordPressの認証へ変換する中継処理が必要かを確認します。
OpenAPIスキーマはActionsに見せる操作を定義します。
スキーマから操作を省いても、同じ認証情報を別のクライアントで使った場合のWordPress側の権限は変わりません。
実際の許可・拒否は、WordPressのユーザー権限と各ルートのpermission_callbackなどで判定します。
スクリプト経由で処理する
まとまった件数を機械的に処理するなら、Node.jsやPythonのスクリプトが確実です。
文章生成と反映処理を分けると、対象ID・送信項目・更新結果を管理しやすくなります。ただし、スクリプトにしただけで誤更新を防げるわけではありません。差分確認、権限、再試行条件、更新後の検証を実装します。
つまずきやすいポイント
Authorizationヘッダーが届かない
サーバー設定によっては、Authorizationヘッダーが削除されて401になることがあります。
Apache環境で認証ヘッダーの転送が原因と確認できた場合の設定例です。ホスティングの案内と既存設定を確認し、バックアップを取ってから適用可否を判断します。Nginxなどに同じ設定を追加する手順ではありません。
SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1
エックスサーバーなど一部のレンタルサーバーでは、この対応が必要になるケースがあります。
セキュリティプラグインにブロックされる
SiteGuard WP PluginやWordfenceなどが、REST APIやXML-RPCへのアクセスを制限していることがあります。
401や403が解消しない場合は、プラグインの設定も確認します。
権限が足りない
投稿の作成には edit_posts、公開には publish_posts の権限が必要です。
寄稿者権限のユーザーでは公開まで到達できません。
APIの接続元ごとに専用ユーザーを作り、必要最小限の権限を割り当てるのがおすすめです。
本文が意図した形で保存されない
content に生のHTMLを渡すと、ブロックエディタ側では「クラシックブロック」として扱われます。
ブロックとして正しく認識させたい場合は、<!-- wp:paragraph --> などのブロックコメントを含めた形式で送信します。
日時の扱い
date はサイトのタイムゾーン基準、date_gmt はUTC基準です。
予約投稿を作る場合は、status を future にしたうえで date を指定します。
安全に運用するためのルール
編集権限を持つ認証情報を外部ツールに渡すことになるため、運用ルールを決めておきます。
- 接続用のユーザーは専用に作り、管理者権限は避ける
- アプリケーションパスワードは用途ごとに分けて発行する
- 使わなくなったパスワードはすぐに失効させる
- 新規記事は必ず下書きとして作成する
- 公開済み記事の上書きは人の確認を挟む
- 削除系の操作はAIに任せない
.envは絶対にリポジトリに含めない- 一括更新の前にデータベースをバックアップする
まずは読み取りと下書き作成から始めて、問題がないことを確認してから範囲を広げるのが安全です。
独自メタの検証と戻し方
検証用投稿で値を保存し、編集権限のあるedit文脈では読めることと、ログアウトした公開読取では返らないことを確認します。
編集権限のない利用者の更新を拒否することも確認します。
停止する場合は追加した登録関数とフックを外しますが、保存済みの値は自動では削除されません。
既存プラグインのメタを変更してしまった場合は、変更前バックアップから対象値を復元してください。
ローカルWordPressで投稿の作成・更新、投稿別権限、公開用と編集用のレスポンス、カスタム投稿・タクソノミーと集計ルートを確認しました。
2026年10月3日、WordPress 7.1.2の隔離環境でHTTPSのアプリケーションパスワード認証、下書き作成、独自メタの保存とHTMLタグ除去、購読者の更新拒否、著者による集計ルートの拒否と編集者の許可を確認しました。
画像アップロード・代替テキスト・アイキャッチ設定も同じ認証で検証しました。
HTTPの検証にはPythonクライアントを使用しました。
curl例の各シェルでの対話操作、GPTsのActionsやMCPサーバーとの接続は未検証です。
2026年10月20日に本文を再調査し、WordPress公式の認証・投稿APIとWooCommerceのルート仕様を照合しました。上記の隔離環境の記録は過去の検証です。今回、アカウント発行、掲載コードの再実行、全プラグイン・AI接続の動作確認は行っていません。
まとめ
WordPress REST APIでは、対応するルートとユーザー権限の範囲で、投稿・固定ページ・メディア・分類を操作できます。
カスタム投稿タイプやカスタムタクソノミーも、show_in_rest を有効にすれば同じように扱えます。
カスタムフィールドやSEOのメタディスクリプションは、register_post_meta でAPIに公開することで編集可能になります。
さらに register_rest_route を使えば、自分のサイト専用のエンドポイントも追加できます。
WordPressのアプリケーションパスワードで接続する基本情報は、HTTPSのサイトURL・専用ユーザー名・アプリケーションパスワードです。
AIツール側の認証方式や中継処理によって、追加の設定が必要になることがあります。
まずは wp-json/wp/v2/users/me で疎通を確認し、下書き作成から試してみるとイメージがつかみやすいはずです。
1件の読み取り・下書き作成・再取得・表示確認を通してから、対象を増やします。途中で失敗した記事と成功した記事を分けて記録し、再実行で同じ変更を重ねないようにします。
この記事で紹介しているコードは、GitHubのMOTOKI-LLC/WAZA-codeにもまとめています。



