EmDashは/_emdash/api/にREST APIを公開しており、コンテンツ管理、メディアアップロード、スキーマ操作に使用できます。
認証
APIリクエストにはAuthorizationヘッダーのBearerトークンによる認証が必要です:
Authorization: Bearer <token>
管理画面またはプログラムでトークンを生成してください。
レスポンス形式
すべてのレスポンスは一貫した形式に従います。成功レスポンスは結果をdataでラップします:
{
"success": true,
"data": { ... }
}
エラーレスポンスにはコード、メッセージ、およびオプションの詳細が含まれます:
{
"success": false,
"error": {
"code": "ERROR_CODE",
"message": "Human-readable message",
"details": { ... }
}
}
コンテンツエンドポイント
コンテンツ一覧
GET /_emdash/api/content/:collection
パラメータ
| パラメータ | 型 | 説明 |
|---|---|---|
collection | string | コレクションスラッグ(パス) |
cursor | string | ページネーションカーソル(クエリ) |
limit | number | ページあたりの項目数(クエリ、デフォルト: 50) |
status | string | ステータスでフィルタ(クエリ) |
orderBy | string | ソートフィールド(クエリ) |
order | string | ソート方向: ascまたはdesc(クエリ) |
レスポンス
{
"success": true,
"data": {
"items": [
{
"id": "01HXK5MZSN...",
"type": "posts",
"slug": "hello-world",
"data": { "title": "Hello World", ... },
"status": "published",
"createdAt": "2025-01-24T12:00:00Z",
"updatedAt": "2025-01-24T12:00:00Z"
}
],
"nextCursor": "eyJpZCI6..."
}
}
コンテンツ取得
GET /_emdash/api/content/:collection/:id
レスポンス
{
"success": true,
"data": {
"item": {
"id": "01HXK5MZSN...",
"type": "posts",
"slug": "hello-world",
"data": { "title": "Hello World", ... },
"status": "published",
"createdAt": "2025-01-24T12:00:00Z",
"updatedAt": "2025-01-24T12:00:00Z"
}
}
}
コンテンツ作成
POST /_emdash/api/content/:collection
Content-Type: application/json
リクエストボディ
{
"data": {
"title": "New Post",
"content": [...]
},
"slug": "new-post",
"status": "draft"
}
レスポンス
{
"success": true,
"data": {
"item": { ... }
}
}
コンテンツ更新
PUT /_emdash/api/content/:collection/:id
Content-Type: application/json
リクエストボディ
{
"data": {
"title": "Updated Title"
},
"status": "published"
}
コンテンツ削除
DELETE /_emdash/api/content/:collection/:id
レスポンス
{
"success": true,
"data": {
"success": true
}
}
メディアエンドポイント
メディア一覧
GET /_emdash/api/media?includeUsage=1
パラメータ
| パラメータ | 型 | 説明 |
|---|---|---|
cursor | string | 不透明なページネーションカーソル |
limit | number | ページあたりの項目数、1〜100(デフォルト: 50) |
mimeType | string | カンマ区切りの1つ以上のMIMEタイプでフィルタ |
q | string | 大文字小文字を区別しないファイル名検索 |
includeUsage | 1 | 返される各項目にカバレッジ対応のusageサマリーを含める |
レスポンス
{
"data": {
"items": [
{
"id": "01HXK5MZSN...",
"filename": "photo.jpg",
"mimeType": "image/jpeg",
"size": 102400,
"width": 1920,
"height": 1080,
"url": "/_emdash/api/media/file/uploads/photo.jpg",
"createdAt": "2025-01-24T12:00:00Z",
"usage": {
"count": 3,
"coverage": {
"scope": "all_content_collections",
"status": "complete"
}
}
}
],
"nextCursor": "eyJpZCI6..."
}
}
メディア取得
GET /_emdash/api/media/:id?includeUsage=1
includeUsageは一覧取得と個別取得の両方でオプションです。受け入れられる唯一の値は1です。省略すると、
usageプロパティは省略され、サーバーは使用状況クエリを実行しません。
使用状況サマリー
usage.countは、選択された現在のインデックスソースがメディアアイテムを参照している、EmDashの個別のアクティブなコンテンツ行またはロケールの数です。同じコンテンツエントリに対する繰り返しの参照と複数のソースバリアントは1回としてカウントされます。ゴミ箱のコンテンツはカウントされません。
数値カウントは下書きのようなコンテンツを明らかにする可能性があります。セッションユーザーが
content:read_draftsを持っている場合、またはAPIトークンがadminスコープを持ち、関連ユーザーもそのパーミッションを持っている場合にのみ返されます。他のメディアリーダーはusage.count: nullを受け取ります。これは成功した編集済みレスポンスであり、エラーではありません。
リクエストされた各サマリーには、現在登録されているすべてのコンテンツコレクションの集計カバレッジが含まれます:
| ステータス | 意味 |
|---|---|
complete | 登録されたすべてのコレクションが最新の完了した使用状況カバレッジを持っている |
never | 登録されたコレクションのいずれも初期使用状況修復を完了していない |
running | 使用状況修復が現在実行中 |
partial | カバレッジが混在しているか、登録範囲の一部のみがインデックスされている |
failed | 登録範囲全体でカバレッジが失敗した |
stale | インデックスされたカバレッジが古くなっている |
unknown | 保存されたカバレッジにこのバージョンが認識しない状態が含まれている |
completeのみが、以下に説明するEmDash管理フィールド内でのスコープ付き完全ゼロステートメントをサポートします。他のステータスのカウントはインデックスされた投影であり、過大報告または過小報告する可能性があります。完全な結果でさえ、同時書き込み中は参考情報です。使用状況読み取りはトランザクションロックではなく、削除保証として使用してはなりません。
メディア使用状況詳細取得
GET /_emdash/api/media/:id/usage?limit=50&cursor=...
このエンドポイントにはmedia:readとcontent:read_draftsが必要です。トークン認証の呼び出し元も
adminスコープが必要です。トークンスコープは関連ユーザーのパーミッションをバイパスしません。
limitはページあたりのコンテンツエントリグループを制御し、1〜100(デフォルト: 50)です。ページネーションは
返されるエントリグループのソースまたはオカレンスを分割することはありません。
{
"data": {
"items": [
{
"collection": "posts",
"contentId": "01CONTENT...",
"title": "Launch notes",
"slug": "launch-notes",
"locale": "en",
"status": "published",
"scheduledAt": null,
"deletedAt": null,
"sources": [
{
"variant": "columns",
"occurrences": [
{
"fieldSlug": "hero",
"fieldPath": "hero",
"occurrenceIndex": 0,
"referenceType": "image_field"
}
]
}
]
}
],
"nextCursor": "eyJvcmRlclZhbHVlIjoicG9zdHMiLCJpZCI6IjAxLi4uIn0",
"coverage": {
"scope": "all_content_collections",
"status": "complete"
}
}
}
承認された詳細にはアクティブなエントリとゴミ箱のエントリが含まれます。null以外のdeletedAtはゴミ箱のエントリを識別します。ソースはcolumnsまたはdraft_overlayです。オカレンスは内部インデックスメタデータを公開せずに、サポートされるフィールドとパスを識別します。
メディア使用状況は、EmDashコンテンツコレクションが管理するトップレベルの画像とファイルフィールド、リピーター画像フィールド、Portable Text画像ブロックのローカルメディア参照をカバーします。カスタムコード、レンダリングされたHTML、設定、メニュー、ウィジェット、プラグインプライベートデータ、外部サイト、プロバイダー専用アセットはスキャンしません。
メディア作成
POST /_emdash/api/media
Content-Type: application/json
リクエストボディ
{
"filename": "photo.jpg",
"mimeType": "image/jpeg",
"size": 102400,
"width": 1920,
"height": 1080,
"storageKey": "uploads/photo.jpg"
}
メディア更新
PUT /_emdash/api/media/:id
Content-Type: application/json
リクエストボディ
{
"alt": "Photo description",
"caption": "Photo caption"
}
メディア削除
DELETE /_emdash/api/media/:id
メディア使用状況修復
POST /_emdash/api/admin/media-usage/repair
Content-Type: application/json
X-EmDash-Request: 1
1つのコレクションまたはすべてのコンテンツコレクションのコンテンツメディア使用状況インデックスを修復します。これは管理者/オペレーターエンドポイントです:セッション認証の呼び出し元はschema:manageが必要で、ルートが/_emdash/api/adminの下にあるため、Bearerトークンはadminスコープが必要です。
全コンテンツ修復は現在のバージョンでは同期的かつ順次的に実行されます。大規模サイトではコストが高くなる可能性があるため、呼び出し元は意図的にトリガーしてレスポンスを待つ必要があります。
リクエストボディ
1つのコレクションを修復:
{
"scope": "collection",
"collection": "posts"
}
すべてのコンテンツコレクションを修復:
{
"scope": "all"
}
リクエストボディは必須です。無効なスラッグ、未知のリクエストキー、scopeの欠如、ボディなしのリクエストは、全コンテンツ修復をデフォルトにする代わりに400を返します。
レスポンス
修復呼び出しが構造化された結果を生成すると、エンドポイントは200を返します。data.statusを確認してください:failedとstaleは修復ドメインのステータスであり、トランスポートエラーではありません。
{
"data": {
"status": "complete",
"indexedSourceCount": 12,
"failedSourceCount": 0,
"skippedSourceCount": 0,
"deletedSourceCount": 1,
"collections": [
{
"collection": "posts",
"status": "complete",
"indexedSourceCount": 12,
"failedSourceCount": 0,
"skippedSourceCount": 0,
"deletedSourceCount": 1,
"lastErrorCode": null,
"startedAt": "2026-07-07T12:00:00.000Z",
"completedAt": "2026-07-07T12:00:01.000Z"
}
]
}
}
トップレベルのレスポンスフィールド:
| フィールド | 型 | 説明 |
|---|---|---|
status | complete | partial | failed | stale | 集計修復ステータス |
indexedSourceCount | number | 修復中にインデックスされたソース |
failedSourceCount | number | 修復中に失敗したソース |
skippedSourceCount | number | スキップされたソース(古い競合を含む) |
deletedSourceCount | number | 修復中に削除された古い使用状況行 |
collections | array | コレクションごとの修復サマリー |
コレクションサマリーフィールド:
| フィールド | 型 | 説明 |
|---|---|---|
collection | string | コレクションスラッグ |
status | complete | partial | failed | stale | コレクション修復ステータス |
indexedSourceCount | number | このコレクションでインデックスされたソース |
failedSourceCount | number | このコレクションで失敗したソース |
skippedSourceCount | number | このコレクションでスキップされたソース |
deletedSourceCount | number | このコレクションで削除された古い使用状況行 |
lastErrorCode | string | null | 最後のコレクション修復エラー(利用可能な場合) |
startedAt | string | 修復開始時刻 |
completedAt | string | null | 完了時刻、または古い結果の場合はnull |
不明なコレクションは200を返し、data.status: "failed"とコレクションごとのlastErrorCode(COLLECTION_NOT_FOUNDなど)が含まれます。トランスポートエラーは400、401、403、413、500を含む標準エラーエンベロープを引き続き使用します。
メディアファイル取得
GET /_emdash/api/media/file/:key
実際のファイルコンテンツを提供します。ローカルストレージのみ。
リビジョンエンドポイント
リビジョン一覧
GET /_emdash/api/content/:collection/:entryId/revisions
パラメータ
| パラメータ | 型 | 説明 |
|---|---|---|
limit | number | 返すリビジョンの最大数(デフォルト: 50) |
レスポンス
{
"success": true,
"data": {
"items": [
{
"id": "01HXK5MZSN...",
"collection": "posts",
"entryId": "01HXK5MZSN...",
"data": { ... },
"createdAt": "2025-01-24T12:00:00Z"
}
],
"total": 5
}
}
リビジョン取得
GET /_emdash/api/revisions/:revisionId
リビジョン復元
POST /_emdash/api/revisions/:revisionId/restore
コンテンツをこのリビジョンの状態に復元し、新しいリビジョンを作成します。
スキーマエンドポイント
コレクション一覧
GET /_emdash/api/schema/collections
レスポンス
{
"success": true,
"data": {
"items": [
{
"id": "01HXK5MZSN...",
"slug": "posts",
"label": "Posts",
"labelSingular": "Post",
"supports": ["drafts", "revisions", "preview"]
}
]
}
}
コレクション取得
GET /_emdash/api/schema/collections/:slug
パラメータ
| パラメータ | 型 | 説明 |
|---|---|---|
includeFields | boolean | フィールド定義を含める(クエリ) |
コレクション作成
POST /_emdash/api/schema/collections
Content-Type: application/json
リクエストボディ
{
"slug": "products",
"label": "Products",
"labelSingular": "Product",
"description": "Product catalog",
"supports": ["drafts", "revisions"]
}
コレクション更新
PUT /_emdash/api/schema/collections/:slug
Content-Type: application/json
コレクション削除
DELETE /_emdash/api/schema/collections/:slug
パラメータ
| パラメータ | 型 | 説明 |
|---|---|---|
force | boolean | コレクションにコンテンツがあっても削除(クエリ) |
フィールド一覧
GET /_emdash/api/schema/collections/:slug/fields
フィールド作成
POST /_emdash/api/schema/collections/:slug/fields
Content-Type: application/json
リクエストボディ
{
"slug": "price",
"label": "Price",
"type": "number",
"required": true,
"validation": {
"min": 0
}
}
フィールド更新
PUT /_emdash/api/schema/collections/:collectionSlug/fields/:fieldSlug
Content-Type: application/json
フィールド削除
DELETE /_emdash/api/schema/collections/:collectionSlug/fields/:fieldSlug
フィールド並べ替え
POST /_emdash/api/schema/collections/:slug/fields/reorder
Content-Type: application/json
リクエストボディ
{
"fieldSlugs": ["title", "content", "author", "publishedAt"]
}
スキーマエクスポート
スキーマエクスポート(JSON)
GET /_emdash/api/schema
Accept: application/json
スキーマエクスポート(TypeScript)
GET /_emdash/api/schema?format=typescript
Accept: text/typescript
すべてのコレクションのTypeScriptインターフェースを返します。
プラグインエンドポイント
プラグイン一覧
GET /_emdash/api/admin/plugins
プラグイン取得
GET /_emdash/api/admin/plugins/:id
プラグイン有効化
POST /_emdash/api/admin/plugins/:id/enable
プラグイン無効化
POST /_emdash/api/admin/plugins/:id/disable
エラーコード
| コード | HTTPステータス | 説明 |
|---|---|---|
NOT_FOUND | 404 | リソースが見つからない |
VALIDATION_ERROR | 400 | 無効な入力データ |
UNAUTHORIZED | 401 | トークンが欠落または無効 |
FORBIDDEN | 403 | 権限不足 |
CONTENT_LIST_ERROR | 500 | コンテンツ一覧取得失敗 |
CONTENT_CREATE_ERROR | 500 | コンテンツ作成失敗 |
CONTENT_UPDATE_ERROR | 500 | コンテンツ更新失敗 |
CONTENT_DELETE_ERROR | 500 | コンテンツ削除失敗 |
MEDIA_LIST_ERROR | 500 | メディア一覧取得失敗 |
MEDIA_CREATE_ERROR | 500 | メディア作成失敗 |
SCHEMA_CREATE_ERROR | 500 | スキーマ操作失敗 |
SLUG_CONFLICT | 409 | スラッグが既に存在する |
RESERVED_SLUG | 400 | スラッグは予約済み |
検索エンドポイント
グローバル検索
GET /_emdash/api/search?q=hello+world
パラメータ
| パラメータ | 型 | 説明 |
|---|---|---|
q | string | 検索クエリ(必須) |
collections | string | カンマ区切りのコレクションスラッグ |
status | string | ステータスでフィルタ(デフォルト: published) |
limit | number | 最大結果数(デフォルト: 20) |
cursor | string | ページネーションカーソル |
レスポンス
{
"success": true,
"data": {
"items": [
{
"collection": "posts",
"id": "01HXK5MZSN...",
"slug": "hello-world",
"locale": "en",
"title": "Hello World",
"snippet": "...this is a <mark>hello</mark> <mark>world</mark> example...",
"score": 0.95
}
],
"nextCursor": "eyJvZmZzZXQiOjIwfQ"
}
}
検索サジェスト
GET /_emdash/api/search/suggest?q=hel&limit=5
オートコンプリート用のプレフィックス一致タイトルを返します。
検索インデックス再構築
POST /_emdash/api/search/rebuild
すべてまたは特定のコレクションのFTSインデックスを再構築します。
検索統計
GET /_emdash/api/search/stats
コレクションごとのインデックス済みドキュメント数を返します。
セクションエンドポイント
セクション一覧
GET /_emdash/api/sections
GET /_emdash/api/sections?source=theme
GET /_emdash/api/sections?search=newsletter
セクション取得
GET /_emdash/api/sections/:slug
セクション作成
POST /_emdash/api/sections
Content-Type: application/json
{
"slug": "my-section",
"title": "My Section",
"keywords": ["keyword1"],
"content": [...]
}
セクション更新
PUT /_emdash/api/sections/:slug
セクション削除
DELETE /_emdash/api/sections/:slug
設定エンドポイント
すべての設定を取得
GET /_emdash/api/settings
設定を更新
POST /_emdash/api/settings
Content-Type: application/json
{
"siteTitle": "My Site",
"tagline": "A great site",
"postsPerPage": 10
}
メニューエンドポイント
メニュー一覧
GET /_emdash/api/menus
メニュー取得
GET /_emdash/api/menus/:name
メニュー作成
POST /_emdash/api/menus
Content-Type: application/json
{
"name": "main",
"label": "Main Navigation",
"items": []
}
メニュー更新
PUT /_emdash/api/menus/:name
メニュー削除
DELETE /_emdash/api/menus/:name
メニュー項目追加
POST /_emdash/api/menus/:name/items
Content-Type: application/json
{
"label": "About",
"url": "/about",
"position": 0
}
メニュー項目並べ替え
POST /_emdash/api/menus/:name/reorder
Content-Type: application/json
{
"itemIds": ["item_1", "item_2", "item_3"]
}
タクソノミーエンドポイント
タクソノミー定義一覧
GET /_emdash/api/taxonomies
タクソノミー作成
POST /_emdash/api/taxonomies
Content-Type: application/json
{
"name": "categories",
"label": "Categories",
"hierarchical": true,
"collections": ["posts"]
}
ターム一覧
GET /_emdash/api/taxonomies/:name/terms
ターム作成
POST /_emdash/api/taxonomies/:name/terms
Content-Type: application/json
{
"slug": "tutorials",
"label": "Tutorials",
"parentId": "term_abc",
"description": "How-to guides"
}
ターム更新
PUT /_emdash/api/taxonomies/:name/terms/:slug
ターム削除
DELETE /_emdash/api/taxonomies/:name/terms/:slug
エントリタームの設定
POST /_emdash/api/content/:collection/:id/terms/:taxonomy
Content-Type: application/json
{
"termIds": ["term_news", "term_featured"]
}
ウィジェットエリアエンドポイント
ウィジェットエリア一覧
GET /_emdash/api/widget-areas
ウィジェットエリア取得
GET /_emdash/api/widget-areas/:name
ウィジェットエリア作成
POST /_emdash/api/widget-areas
Content-Type: application/json
{
"name": "sidebar",
"label": "Main Sidebar",
"description": "Appears on posts"
}
ウィジェットエリア削除
DELETE /_emdash/api/widget-areas/:name
ウィジェット追加
POST /_emdash/api/widget-areas/:name/widgets
Content-Type: application/json
{
"type": "content",
"title": "About",
"content": [...]
}
ウィジェット更新
PUT /_emdash/api/widget-areas/:name/widgets/:id
ウィジェット削除
DELETE /_emdash/api/widget-areas/:name/widgets/:id
ウィジェット並べ替え
POST /_emdash/api/widget-areas/:name/reorder
Content-Type: application/json
{
"widgetIds": ["widget_1", "widget_2", "widget_3"]
}
ユーザー管理エンドポイント
ユーザー一覧
GET /_emdash/api/admin/users
GET /_emdash/api/admin/users?role=40
GET /_emdash/api/admin/users?search=john
ユーザー取得
GET /_emdash/api/admin/users/:id
ユーザー更新
PUT /_emdash/api/admin/users/:id
Content-Type: application/json
{
"name": "John Doe",
"role": 40
}
ユーザー有効化
POST /_emdash/api/admin/users/:id/enable
ユーザー無効化
POST /_emdash/api/admin/users/:id/disable
認証エンドポイント
セットアップ状態
GET /_emdash/api/setup/status
セットアップが完了しているかどうか、およびユーザーが存在するかどうかを返します。
Passkeyログイン
POST /_emdash/api/auth/passkey/options
WebAuthn認証オプションを取得します。
POST /_emdash/api/auth/passkey/verify
Content-Type: application/json
{
"id": "credential-id",
"rawId": "...",
"response": {...},
"type": "public-key"
}
Passkeyを検証してセッションを作成します。
マジックリンク
POST /_emdash/api/auth/magic-link/send
Content-Type: application/json
{
"email": "[email protected]"
}
GET /_emdash/api/auth/magic-link/verify?token=xxx
ログアウト
POST /_emdash/api/auth/logout
現在のユーザー
GET /_emdash/api/auth/me
ユーザー招待
POST /_emdash/api/auth/invite
Content-Type: application/json
{
"email": "[email protected]",
"role": 30
}
Passkey管理
GET /_emdash/api/auth/passkey
ユーザーのPasskeyを一覧表示します。
POST /_emdash/api/auth/passkey/register/options
POST /_emdash/api/auth/passkey/register/verify
新しいPasskeyを登録します。
PATCH /_emdash/api/auth/passkey/:id
Content-Type: application/json
{
"name": "MacBook Pro"
}
Passkeyの名前を変更します。
DELETE /_emdash/api/auth/passkey/:id
Passkeyを削除します。
インポートエンドポイント
WordPressエクスポート分析
POST /_emdash/api/import/wordpress/analyze
Content-Type: multipart/form-data
file: <WXR file>
WordPressインポート実行
POST /_emdash/api/import/wordpress/execute
Content-Type: application/json
{
"analysisId": "...",
"options": {
"includeMedia": true,
"includeTaxonomies": true,
"includeMenus": true
}
}
レート制限
APIエンドポイントはデプロイメント設定に基づいてレート制限される場合があります。レート制限時のレスポンスには以下が含まれます:
HTTP/1.1 429 Too Many Requests
Retry-After: 60
CORS
APIはブラウザリクエスト用のCORSをサポートしています。デプロイメントで許可されるオリジンを設定してください。