このサイトは非公式の日本語訳です。Cloudflare・EmDashプロジェクトが運営するサイトではありません。

このページで分かること

  • /_emdash/api/ のREST APIの範囲(生成されるOpenAPI 3.1の文書に載っているものが、サポートされる仕様)と、認証・CSRF対策・レスポンスの形式
  • エンドポイントの一覧(コンテンツ、メディア、スキーマ、コメント、タクソノミー、メニュー、セクション、ウィジェット、設定、検索、リダイレクト、ユーザー)
  • コンテンツの更新と _rev、編集ロック、翻訳、メディアのアップロードと使用状況の修復、ページ分割、検索、コメントとリダイレクトの扱い
難易度
上級
読む時間
18分
このページの目次

EmDashは、サポートするアプリケーションプログラミングインターフェース(API)を /_emdash/api/ の下で公開しています。リクエストのパラメーター、ボディ、レスポンスのスキーマ、ステータスコード、クライアントの生成には、生成されるOpenAPI 3.1の文書を使います。

GET /_emdash/api/openapi.json

この文書は、APIが使うのと同じZodのスキーマから生成されます。設定したメディアのアップロードの最大サイズも反映されます。

公開する仕様の範囲

OpenAPIの文書が、サポートするREST APIの範囲です。EmDashには、管理画面やプロトコルの処理のためのルートもあります。ソースコードの中にあってもOpenAPIに載っていないルートは、外部のクライアント向けにサポートされたRESTの操作ではありません。

この区別は、バックアップ、バイラインの管理、リレーションのたどり、プラグインの管理、セットアップ、インポート、認証のルートに当てはまります。バックアップにはバックアップのガイドを、サポートされたバイラインの管理にはMCPのバイラインのツールを使います。OAuthのエンドポイントはプロトコルのエンドポイントです。アプリケーションのRESTエンドポイントとして扱わず、MCPのOAuthの節で説明しているメタデータから見つけます。

認証と認可

ほとんどの操作は、EmDashのセッションのCookieとBearerトークンのどちらでも受け付けます。個人用アクセストークンまたはOAuthのアクセストークンを、Authorization ヘッダーで送ります。

Authorization: Bearer $EMDASH_TOKEN

Bearerトークンでできることは、トークンのスコープと、ひも付いたユーザーのロールで制限されます。セッションのリクエストは、ユーザーのロールを使います。認可の仕組みについては、ユーザーのロールトークンのスコープを参照してください。

GETPOST /_emdash/api/comments/{collection}/{contentId} は公開されています。GET の操作は承認済みのコメントを返し、POST の操作はコメントをモデレーションに送ります。そのほかのコメントのモデレーションの操作には認証が必要です。

クロスサイトリクエストフォージェリ(CSRF)対策

セッションのCookieで認証し、状態を変更するリクエストでは、次のヘッダーを含めます。

X-EmDash-Request: 1

Bearerトークンのリクエストは、ブラウザが自動で送る認証情報を使わないため、このヘッダーは必要ありません。公開されている書き込みの操作へのブラウザからのリクエストは、このヘッダーを送るか、Origin がEmDashのサイトの公開用のオリジンまたはリクエストのオリジンと一致する必要があります。

本サイトの補足 やさしい解説:やさしい解説

WordPressにもREST APIがあるように、EmDashも外部のプログラムからコンテンツを読み書きするためのREST APIを持っています。サポートされているのは、/_emdash/api/openapi.json の一覧に載っている操作だけです。外部のプログラムから使う場合は、管理画面のログイン(Cookie)ではなく、Authorization: Bearer ヘッダーでトークンを送ります。トークンでできることは、トークンのスコープと、そのトークンを作ったユーザーのロールの両方で制限されます。

レスポンスの包み

成功したJSONのレスポンスは、successtrue にし、操作ごとの結果を data に入れます。

{
	"success": true,
	"data": {
		"items": []
	}
}

エラーの場合は、successfalse にし、機械が読める変わらないコードとメッセージを含めます。構造化された details を含むエラーもあります。

{
	"success": false,
	"error": {
		"code": "NOT_FOUND",
		"message": "Content item not found"
	}
}

それぞれのOpenAPIの操作に書かれたステータスコードとエラーのスキーマを使います。よく使われるステータスは、不正な入力の 400、認証情報がないか無効な場合の 401、スコープや権限が足りない場合の 403、リソースが存在しない場合の 404、状態が競合した場合の 409、アップロードが大きすぎる場合の 413、プラグインが保存を拒否した場合の 422、内部の失敗の 500 です。

エンドポイントの一覧

操作ID(Operation)は、生成される仕様の中で変わらず、OpenAPIのクライアント生成ツールではメソッド名としてよく使われます。次の一覧は、生成されたOpenAPIの文書と照合しています。

コンテンツ

メソッド パス 操作 概要
GET /_emdash/api/content/{collection} listContent コンテンツのアイテムを一覧にします
POST /_emdash/api/content/{collection} createContent コンテンツのアイテムを作成します
GET /_emdash/api/content/{collection}/{id} getContent コンテンツのアイテムを取得します
PUT /_emdash/api/content/{collection}/{id} updateContent コンテンツのアイテムを更新します
DELETE /_emdash/api/content/{collection}/{id} deleteContent コンテンツのアイテムを削除します(論理削除)
POST /_emdash/api/content/{collection}/{id}/publish publishContent コンテンツのアイテムを公開します
POST /_emdash/api/content/{collection}/{id}/unpublish unpublishContent コンテンツのアイテムを非公開にします
POST /_emdash/api/content/{collection}/{id}/schedule scheduleContent コンテンツを予約公開します
DELETE /_emdash/api/content/{collection}/{id}/schedule unscheduleContent 予約公開を取り消します
POST /_emdash/api/content/{collection}/{id}/duplicate duplicateContent コンテンツのアイテムを複製します
POST /_emdash/api/content/{collection}/{id}/restore restoreContent コンテンツのアイテムをゴミ箱から元に戻します
DELETE /_emdash/api/content/{collection}/{id}/permanent permanentDeleteContent コンテンツのアイテムを完全に削除します
GET /_emdash/api/content/{collection}/{id}/compare compareContent 公開中のリビジョンと下書きのリビジョンを比較します
POST /_emdash/api/content/{collection}/{id}/discard-draft discardDraft 下書きの変更を破棄します
GET /_emdash/api/content/{collection}/{id}/lock getEntryLock エントリーの編集ロックを読み取ります
POST /_emdash/api/content/{collection}/{id}/lock acquireEntryLock エントリーの編集ロックを取得または延長します
DELETE /_emdash/api/content/{collection}/{id}/lock releaseEntryLock 呼び出し元の編集ロックを解放します
GET /_emdash/api/content/{collection}/{id}/translations getContentTranslations コンテンツのアイテムの翻訳を取得します
GET /_emdash/api/content/{collection}/{id}/terms/{taxonomy} getContentTerms コンテンツのアイテムに割り当てられたタクソノミーのタームを取得します
POST /_emdash/api/content/{collection}/{id}/terms/{taxonomy} setContentTerms コンテンツのアイテムにタクソノミーのタームを設定します
GET /_emdash/api/content/{collection}/authors listContentAuthors コレクションのコンテンツの執筆者を重複なく一覧にします
GET /_emdash/api/content/{collection}/trash listTrashedContent ゴミ箱にあるコンテンツのアイテムを一覧にします

メディア

メソッド パス 操作 概要
GET /_emdash/api/media listMedia メディアのアイテムを一覧にします
POST /_emdash/api/media uploadMedia メディアのアイテムをアップロードします
GET /_emdash/api/media/folders listMediaFolders メディアのフォルダーを一覧にします
POST /_emdash/api/media/folders createMediaFolder メディアのフォルダーを作成します
GET /_emdash/api/media/folders/{id} getMediaFolder メディアのフォルダーを取得します
PUT /_emdash/api/media/folders/{id} updateMediaFolder メディアのフォルダーを更新します
DELETE /_emdash/api/media/folders/{id} deleteMediaFolder メディアのフォルダーを削除します
GET /_emdash/api/media/{id} getMedia メディアのアイテムを取得します
PUT /_emdash/api/media/{id} updateMedia メディアのメタデータを更新します
DELETE /_emdash/api/media/{id} deleteMedia メディアのアイテムを削除します
GET /_emdash/api/media/{id}/usage getMediaUsage メディアの使用状況の詳細を取得します
PUT /_emdash/api/media/{id}/replace replaceMediaImage メディアの画像を置き換えます
POST /_emdash/api/admin/media-usage/repair repairMediaUsage メディアの使用状況のインデックスを修復します
GET /_emdash/api/admin/media-usage/progress getMediaUsageProgress メディアの使用状況のインデックス作成の進み具合を取得します
POST /_emdash/api/admin/media-usage/progress advanceMediaUsageProgress メディアの使用状況のインデックス作成を進めます
GET /_emdash/api/admin/media-usage/work listMediaUsageWork 永続化されたメディアの使用状況の作業を一覧にします
GET /_emdash/api/admin/media-usage/activation getMediaUsageActivation メディアの使用状況の有効化の状態を取得します
POST /_emdash/api/admin/media-usage/activation advanceMediaUsageActivation メディアの使用状況の有効化を進めます
POST /_emdash/api/admin/media-usage/work/retry retryMediaUsageWork 永続化されたメディアの使用状況のジョブを1件再試行します
GET /_emdash/api/admin/media-usage/collection-deletions listMediaUsageCollectionDeletions 永続化されたコレクションの削除を一覧にします
POST /_emdash/api/admin/media-usage/collection-deletions/retry retryMediaUsageCollectionDeletion コレクションの削除を1件再試行します
POST /_emdash/api/media/upload-url getMediaUploadUrl メディアのアップロード先を取得します
POST /_emdash/api/media/{id}/confirm confirmMediaUpload メディアのアップロードを確定します
PUT /_emdash/api/media/{id}/upload uploadPendingMedia 保留中のメディアのファイルをEmDash経由でアップロードします

スキーマ

メソッド パス 操作 概要
GET /_emdash/api/schema/collections listCollections すべてのコレクションを一覧にします
POST /_emdash/api/schema/collections createCollection コレクションを作成します
GET /_emdash/api/schema/collections/{slug} getCollection コレクションを取得します
PUT /_emdash/api/schema/collections/{slug} updateCollection コレクションを更新します
DELETE /_emdash/api/schema/collections/{slug} deleteCollection コレクションを削除します
GET /_emdash/api/schema/collections/{slug}/fields listFields コレクションのフィールドを一覧にします
POST /_emdash/api/schema/collections/{slug}/fields createField フィールドを作成します
GET /_emdash/api/schema/collections/{slug}/fields/{fieldSlug} getField フィールドを取得します
PUT /_emdash/api/schema/collections/{slug}/fields/{fieldSlug} updateField フィールドを更新します
DELETE /_emdash/api/schema/collections/{slug}/fields/{fieldSlug} deleteField フィールドを削除します
POST /_emdash/api/schema/collections/reorder reorderCollections 管理画面のサイドバーでのコレクションの並び順を変えます
POST /_emdash/api/schema/collections/{slug}/fields/reorder reorderFields コレクションのフィールドの並び順を変えます
GET /_emdash/api/schema/orphans listOrphanedTables 孤立したコンテンツのテーブルを一覧にします
POST /_emdash/api/schema/orphans/{slug} registerOrphanedTable 孤立したテーブルをコレクションとして登録します

コメント

メソッド パス 操作 概要
GET /_emdash/api/comments/{collection}/{contentId} listPublicComments コンテンツの承認済みのコメントを一覧にします
POST /_emdash/api/comments/{collection}/{contentId} createComment 新しいコメントを送信します
GET /_emdash/api/admin/comments listAdminComments モデレーションのためにコメントを一覧にします
GET /_emdash/api/admin/comments/counts getCommentCounts コメントのステータスごとの件数を取得します
POST /_emdash/api/admin/comments/bulk bulkCommentAction コメントをまとめて承認、スパム、ゴミ箱、削除にします
GET /_emdash/api/admin/comments/{id} getComment 1件のコメントを取得します
DELETE /_emdash/api/admin/comments/{id} deleteComment コメントを完全に削除します
PUT /_emdash/api/admin/comments/{id}/status updateCommentStatus コメントのステータスを変更します

タクソノミー

メソッド パス 操作 概要
GET /_emdash/api/taxonomies listTaxonomies すべてのタクソノミーの定義を一覧にします
GET /_emdash/api/taxonomies/{name} getTaxonomy タクソノミーの定義を取得します
PUT /_emdash/api/taxonomies/{name} updateTaxonomy タクソノミーの定義を更新します
DELETE /_emdash/api/taxonomies/{name} deleteTaxonomy タクソノミー、そのターム、コンテンツへのタームの割り当てを削除します
GET /_emdash/api/taxonomies/{name}/translations listTaxonomyTranslations タクソノミーの定義のすべてのロケール別の版を一覧にします
POST /_emdash/api/taxonomies/{name}/reorder reorderTerms 同じ親を持つタームのグループ1つについて、手動の並び順を設定します
GET /_emdash/api/taxonomies/{name}/terms listTerms タクソノミーのタームを一覧にします
POST /_emdash/api/taxonomies/{name}/terms createTerm タームを作成します
GET /_emdash/api/taxonomies/{name}/terms/{slug} getTerm スラッグでタームを取得します
PUT /_emdash/api/taxonomies/{name}/terms/{slug} updateTerm タームを更新します
DELETE /_emdash/api/taxonomies/{name}/terms/{slug} deleteTerm タームを削除します
メソッド パス 操作 概要
GET /_emdash/api/menus listMenus すべてのメニューを項目数とともに一覧にします
POST /_emdash/api/menus createMenu メニューを作成します
GET /_emdash/api/menus/{name} getMenu メニューをすべての項目とともに取得します
PUT /_emdash/api/menus/{name} updateMenu メニューを更新します
DELETE /_emdash/api/menus/{name} deleteMenu メニューとその項目を削除します
POST /_emdash/api/menus/{name}/items createMenuItem メニューに項目を追加します
PUT /_emdash/api/menus/{name}/items/{id} updateMenuItem メニューの項目を更新します
DELETE /_emdash/api/menus/{name}/items/{id} deleteMenuItem メニューの項目を削除します
POST /_emdash/api/menus/{name}/reorder reorderMenuItems メニューの項目の並び順をまとめて変えます

セクション

メソッド パス 操作 概要
GET /_emdash/api/sections listSections セクションを一覧にします
POST /_emdash/api/sections createSection セクションを作成します
GET /_emdash/api/sections/{slug} getSection スラッグでセクションを取得します
PUT /_emdash/api/sections/{slug} updateSection セクションを更新します
DELETE /_emdash/api/sections/{slug} deleteSection セクションを削除します

ウィジェット

メソッド パス 操作 概要
GET /_emdash/api/widget-areas listWidgetAreas すべてのウィジェットエリアを一覧にします
POST /_emdash/api/widget-areas createWidgetArea ウィジェットエリアを作成します
GET /_emdash/api/widget-areas/{name} getWidgetArea ウィジェットエリアをウィジェットとともに取得します
DELETE /_emdash/api/widget-areas/{name} deleteWidgetArea ウィジェットエリアとそのウィジェットを削除します
POST /_emdash/api/widget-areas/{name}/widgets createWidget エリアにウィジェットを追加します
PUT /_emdash/api/widget-areas/{name}/widgets/{id} updateWidget ウィジェットを更新します
DELETE /_emdash/api/widget-areas/{name}/widgets/{id} deleteWidget ウィジェットを削除します
POST /_emdash/api/widget-areas/{name}/reorder reorderWidgets エリアのウィジェットの並び順を変えます

設定

メソッド パス 操作 概要
GET /_emdash/api/settings getSettings サイト設定を取得します
PUT /_emdash/api/settings updateSettings サイト設定を更新します
メソッド パス 操作 概要
GET /_emdash/api/search search コレクションをまたいで全文検索します
GET /_emdash/api/search/suggest searchSuggest 検索の入力補完の候補を返します
POST /_emdash/api/search/rebuild rebuildSearchIndex コレクションの検索インデックスを作り直します
POST /_emdash/api/search/enable enableSearch コレクションの検索を有効または無効にします
GET /_emdash/api/search/stats getSearchStats 検索インデックスの統計を取得します

リダイレクト

メソッド パス 操作 概要
GET /_emdash/api/redirects listRedirects リダイレクトを一覧にします
POST /_emdash/api/redirects createRedirect リダイレクトのルールを作成します
GET /_emdash/api/redirects/{id} getRedirect リダイレクトを取得します
PUT /_emdash/api/redirects/{id} updateRedirect リダイレクトを更新します
DELETE /_emdash/api/redirects/{id} deleteRedirect リダイレクトを削除します
GET /_emdash/api/redirects/404s listNotFoundEntries 404のログの項目を一覧にします
POST /_emdash/api/redirects/404s pruneNotFoundLog 古い404のログの項目を削除します
DELETE /_emdash/api/redirects/404s clearNotFoundLog 404のログの項目をすべて消去します
GET /_emdash/api/redirects/404s/summary getNotFoundSummary パスごとにまとめた404の集計を取得します

ユーザー

メソッド パス 操作 概要
GET /_emdash/api/admin/users listUsers ユーザーを一覧にします
GET /_emdash/api/admin/users/{id} getUser ユーザーの詳細を取得します
PUT /_emdash/api/admin/users/{id} updateUser ユーザーを更新します
POST /_emdash/api/admin/users/{id}/disable disableUser ユーザーのアカウントを無効にします
POST /_emdash/api/admin/users/{id}/enable enableUser ユーザーのアカウントを有効にします
GET /_emdash/api/admin/allowed-domains listAllowedDomains 許可したメールのドメインを一覧にします
POST /_emdash/api/admin/allowed-domains createAllowedDomain 許可するメールのドメインを追加します
PUT /_emdash/api/admin/allowed-domains/{domain} updateAllowedDomain 許可したドメインを更新します
DELETE /_emdash/api/admin/allowed-domains/{domain} deleteAllowedDomain 許可したドメインを削除します

コンテンツのライフサイクルとバイライン

コンテンツを読み込むと、利用できる場合は中身を解釈しない前提の _rev トークンが返されます。PUT /content/{collection}/{id}_rev を付けて送ると、読み込んだあとに加えられた変更を上書きすることを防げます。トークンが古い場合は競合になります。アイテムを読み込み直してから再試行します。CLIでは content update でこの確認が必須ですが、RESTのフィールドは、あえて無条件で書き込むことを選ぶクライアントのために任意のままです。

エントリーの読み込みと更新

変更する前に、エントリーを読み込みます。

GET /_emdash/api/content/articles/01JARTICLE0000000000000000
Authorization: Bearer $EMDASH_TOKEN

レスポンスには、フィールド、公開の状態、リビジョンのトークンが含まれます。

{
	"success": true,
	"data": {
		"item": {
			"id": "01JARTICLE0000000000000000",
			"type": "articles",
			"slug": "launch-notes",
			"status": "published",
			"data": { "title": "Launch notes" }
		},
		"_rev": "opaque-revision-token"
	}
}

変更が必要なフィールドだけを、その読み込みで得たトークンと一緒に送ります。

PUT /_emdash/api/content/articles/01JARTICLE0000000000000000
Authorization: Bearer $EMDASH_TOKEN
Content-Type: application/json

{
	"data": { "title": "Updated launch notes" },
	"_rev": "opaque-revision-token"
}

公開済みのエントリーを変更すると、前の版が公開されたまま、下書きが作られます。compareの操作を呼び出して両方の版を確認してから、下書きを公開するか破棄します。非公開にすると、コンテンツと公開日は残りますが、公開中のサイトからは取り除かれます。

作成と更新のボディはバイラインのクレジットを受け付け、コンテンツのレスポンスには主なバイラインと順序付きのクレジットが含まれます。コンテンツの一覧は、保存されたバイラインのIDで絞り込むことができ、執筆者から推定したバイラインを含めることもできます。バイラインのレコードそのものの作成と管理は、公開のRESTの仕様ではなく、MCPのバイラインのツールで扱えます。

ライフサイクルの操作は、論理削除と完全な削除を区別します。元に戻す操作(restore)はゴミ箱にあるコンテンツに対して働きます。完全な削除は、ゴミ箱にあるアイテムを取り除き、元に戻せません。公開、非公開、予約公開、予約の解除、比較、下書きの破棄、複製はそれぞれ別の操作のため、クライアントは状態の変更を1つずつ要求できます。

エントリーの編集ロック

コレクションは、編集者がエントリーを開いたときに、7分間の編集ロックを取得できます。/content/{collection}/{id}/lock の3つの操作で、ロック(リース)の読み取り、取得または延長、解放をします。

読み取りまたは取得のレスポンスは、ロックが有効かどうか、呼び出し元がリースを持っているかどうか、現在誰が持っているかを示します。

{
	"success": true,
	"data": {
		"enabled": true,
		"heldByCaller": false,
		"holder": {
			"userId": "01JUSER000000000000000000",
			"userName": "Ada",
			"acquiredAt": "2026-05-01T09:12:04.117Z",
			"expiresAt": "2026-05-01T09:19:04.117Z"
		}
	}
}

コレクションで編集ロックが無効な場合、enabledfalse で、リースは取得されません。同じロックをもう一度取得することと、エントリーを保存することは、どちらも呼び出し元が持つリースを延長します。

取得のボディには、1つの編集セッションを識別する、中身を解釈しない前提の token と、ユーザーが別の編集者のリースを置き換えることを選んだ場合の takeover: true を含められます。ロックを解放するときは、同じトークンをクエリパラメーターとして渡します。これにより、同じアカウントの2つ目のタブが、誤って1つ目のタブのリースを解放することはなくなります。

別のユーザーがリースを持っている場合、保護されたコンテンツへの書き込みは 409 ENTRY_LOCKED を返します。エラーの詳細には、リースを持っている人と期限が含まれます。ロックを無視して書き込むには、ボディのある書き込みではJSONのボディに "overrideLock": true を、ボディのない DELETE の操作では ?overrideLock=true を送ります。

翻訳とリレーション

公開のRESTの仕様では、コンテンツの翻訳と、タクソノミーの定義の翻訳を扱えます。コンテンツの作成は translationOf を受け付け、タクソノミーの作成も同じフィールドでロケール別の版を追加します。コンテンツのタームの操作は、ロケールを考慮した割り当てを返します。

GET /taxonomies/{name} は、locale を省略すると、サイトの既定のロケールの定義を返します。既定のロケールに定義がない場合にだけ、ロケールコードが最も小さいものを返します。更新の動作は異なり、locale を省略すると、ロケールコードが最も小さい定義を変更します。翻訳されたタクソノミーの更新を目的の定義に反映させるには、locale を渡します。そのロケールに定義がない場合、更新は別のロケールに切り替えずに NOT_FOUND を返します。translationsの操作は、共通のグループにあるすべての定義を返し、translationOf に指定できるIDを提供します。

タクソノミーを削除すると、その定義のすべてのロケール、すべてのターム、コンテンツへのそれらのタームのすべての割り当てが削除されます。コンテンツのエントリーそのものは削除されません。

タームの並べ替えの操作は、同じ親を持つ1つのグループを変更します。ids の配列には、そのグループの一部だけを入れることもできます。指定したタームは既存の位置を互いに入れ替え、指定しなかったタームはその位置に残ります。たとえば、[A, B, C]ids: ["C", "A"] で並べ替えると、[C, B, A] になります。並べ替えで親子関係は変わらず、1つのタームの並び順は、その翻訳グループのすべてのロケールに適用されます。

メニュー、タクソノミーのターム、バイラインの翻訳のルートは、公開のRESTの仕様に含まれていません。サポートされた翻訳の一覧は、MCPサーバーmenu_translationstaxonomy_term_translationsbyline_translations で取得できます。

EmDashには、管理画面でのリレーションの編集を支える内部のルートがありますが、OpenAPIには載っていません。外部のRESTクライアントは、それらの内部のルートを呼び出さず、コレクションのスキーマに記述されたリレーションと参照のフィールドを使います。

メディアのエンドポイント

メディアの操作は、一覧、アップロード、メタデータの更新、画像の置き換え、フォルダー、使用状況の情報、使用状況のインデックスの保守を扱います。ユーザーから見た作業の流れと、使用状況の網羅範囲(カバレッジ)の意味は、メディアライブラリのガイドで説明しています。

メディアの一覧と確認

GET /media は、カーソルまたは番号付きのページによるページ分割、MIMEタイプとファイル名の絞り込み、フォルダー、任意の使用状況の概要をサポートします。すべてのフォルダーを含めるには folderId を省略し、メインのライブラリだけを返すには folderId=unfiled を渡します。使用状況の情報を含めるには、一覧または1件の読み込みで includeUsage=1 を設定します。それ以外の値は無効です。

usage.count は、現在インデックスされている内容がそのメディアのアイテムを参照している、有効なコンテンツの行またはロケールの数を重複なく数えます。1つのエントリーの中で繰り返し参照していても1回と数え、ゴミ箱にあるエントリーは数えません。この数は、下書きを読める呼び出し元にだけ表示されます。数から下書きの内容が分かってしまう可能性があるため、それ以外のメディアを読む権限を持つ呼び出し元には count: null が返されます。

使用状況の結果には、必ず網羅範囲のステータスが含まれます。

ステータス 意味
complete 登録されたすべてのコレクションに、最新の使用状況の網羅範囲があります。
never 登録されたコレクションのどれも、最初の使用状況の修復を完了していません。
running 修復の実行中です。
partial 登録されたコレクションの一部だけに、最新の網羅範囲があります。
failed 登録されたコレクション全体で、網羅範囲の作成に失敗しました。
stale インデックスが、それが表すコンテンツより古くなっています。
unknown 保存された状態を、このバージョンのEmDashが認識できません。

インデックスの対象のフィールドの型の範囲で、数が0であることを網羅的な結果として扱えるのは、complete の場合だけです。同時に書き込みがある間、数は目安です。メディアのアイテムをロックしたり、削除しても安全であることを保証したりはしません。使用状況のインデックスは、EmDashのコレクションの画像とファイルのフィールド、リピーターの画像のフィールド、Portable Textの画像のブロックを対象にします。アプリケーションのコード、描画されたHTML、設定、メニュー、ウィジェット、プラグインのデータ、外部のサイト、プロバイダーにだけあるアセットは調べません。

マルチパートでの直接のアップロード

EmDashを通してファイルを送るには、マルチパートのリクエストの file フィールドとしてPOSTします。

curl --request POST \
	--header "Authorization: Bearer $EMDASH_TOKEN" \
	--form "file=@./cover.jpg;type=image/jpeg" \
	https://example.com/_emdash/api/media

マルチパートの境界は curl が追加します。Content-Type ヘッダーは手動で設定しません。OpenAPIの MediaDirectUploadBody スキーマに任意のメタデータのフィールドが載っており、レスポンスのスキーマは、新しいアップロードと、重複を除いた既存のアイテムを区別します。

マルチパートのボディには、画像の widthheight、MIMEタイプの許可リストを適用する fieldId、低画質のプレースホルダーを作るための縮小した thumbnail も含められます。新しいファイルは 201 Created を返し、すぐに使える状態になります。同じバイト列の場合は、既存のメディアのアイテムを 200 OKdeduplicated: true とともに返します。

アップロード先を使う流れ

クライアントがS3互換のストレージに直接アップロードできる場合は、アップロード先を使う流れを使います。確定が成功するまで、メディアのアイテムは保留中のままで、通常のライブラリには表示されません。

  1. アップロード先を要求します

    POST /_emdash/api/media/upload-url
    Authorization: Bearer $EMDASH_TOKEN
    Content-Type: application/json
    
    {
    	"filename": "cover.jpg",
    	"contentType": "image/jpeg",
    	"size": 102400
    }
    

    レスポンスは、uploadUrlmethodheadersmediaIdstorageKey と有効期限を返します。contentHash が、MIMEタイプとサイズが同じ既存のファイルと一致する場合、レスポンスは代わりに existing: true を設定します。その場合は、そのメディアのアイテムを使い、別のコピーをアップロードしたり確定したりしません。

  2. バイト列をアップロードします

    返されたメソッドとヘッダーを使います。ルートからの相対URLはEmDashのサイトを基準に解決し、Bearerトークンを含めます。別のオリジンの絶対URLには、返されたアップロード用のヘッダーだけを送ります。

  3. アップロードを確定します

    POST /_emdash/api/media/01JMEDIA000000000000000000/confirm
    Authorization: Bearer $EMDASH_TOKEN
    Content-Type: application/json
    
    {
    	"size": 102400,
    	"width": 1920,
    	"height": 1080
    }
    

    確定の操作は、保存されたオブジェクトを検証し、アイテムを pending から ready に変えます。指定したサイズと寸法は、アップロードしたファイルと一致する必要があります。

ローカルのストレージとネイティブのR2は、同じオリジンのEmDashのアップロード先を返します。S3互換のストレージは、署名付きの外部のURLを返すことがあります。保留中のアイテムは、確定が成功するまで通常のメディアの一覧に表示されません。

アップロードのエラー

次のエラーは、それぞれ異なる対処が必要です。

ステータス コード 対処
400 NO_FILE マルチパートのリクエストに file フィールドを追加するか、足りないアップロードのボディを送ります。
400 INVALID_TYPE 保留中のメディアのアイテムと一致する、許可されたMIMEタイプを使います。
400 VALIDATION_ERROR 設定したサイズの上限を超える値も含め、足りない、または不正なメタデータを直します。
400 FILE_NOT_FOUND 確定する前に、返されたアップロード先にオブジェクトをアップロードします。
400 UPLOAD_SIZE_MISMATCH 正しいサイズで流れを最初からやり直します。申告したサイズ、アップロードしたサイズ、確定したサイズが一致する必要があります。
400 または 409 INVALID_STATE 再試行する前に、メディアのアイテムを読み込みます。すでに保留中でなくなっているか、確定の間に別のリクエストが変更した可能性があります。
404 NOT_FOUND 存在する保留中のメディアのIDを使います。
413 PAYLOAD_TOO_LARGE 次のアップロードを始める前に、ファイルのサイズを小さくするか、maxUploadSizeを大きくします。

メディアのフォルダー

フォルダー名は前後の空白が取り除かれ、200文字までに制限され、Unicodeの正規化と小文字への変換をしてから比較されます。そのため、PhotosphotosPHOTOS のような名前は競合します。フォルダーを削除すると、その中のメディアはメインのライブラリに戻ります。メディアを削除したり、メディアのIDやURL、使用状況の記録を変えたりはしません。

メディアの使用状況の修復

メディアの使用状況の有効化、進み具合、作業キュー、削除の後片付け、修復は、/_emdash/api/admin/media-usage/ の下にある運用者向けの操作です。セッションのユーザーには schema:manage が必要で、Bearerトークンにはさらに admin スコープも必要です。

追跡がオフの場合は、有効化の前に、データベースに直接書き込む処理を止めます。セットアップの実行中、EmDashはAPIを通したコンテンツとスキーマの書き込みを一時的に止めますが、データベースに直接書き込む別のプロセスは止められません。

  1. データベースに直接書き込む処理を止め、実行中の書き込みが終わるのを待ちます。
  2. 有効化の状態を読み取ります。expanded は追跡がオフ、activating はEmDashがコレクションを準備中、active は新しいメディアの参照の変更が追跡されていることを意味します。
  3. { "writersDrained": true } を付けて、有効化のリクエストを1回送ります。
  4. 有効化が active になるまで、進み具合のリクエストを1つずつ送ります。それぞれ、返された nextRequestInMs だけ待ちます。
  5. データベースへの直接の書き込みを再開します。
  6. 過去の分のインデックス作成が ready になり、nextRequestInMsnull になるまで、進み具合のリクエストを続けます。

書き込みのリクエストがタイムアウトした場合や、409 または 500 を返した場合は、再試行の前に有効化と進み具合の状態を読み取ります。完了したバッチは記録されたままです。lastErrorCode が設定されている場合は、直接の書き込みを止めたまま、報告された問題を解決し、確認のうえで再試行を1回送ります。有効化は、始めたあとに取り消したりリセットしたりできません。この手順はステージング用のコピーで試し、最新のデータベースのバックアップを取っておきます。

作業の一覧の操作は、失敗したり遅れたりしているエントリーのインデックス作成を示しますが、コンテンツ、メディアの参照、リースのトークン、データベースのそのままのエラー、正確な未処理の件数は返しません。1件の再試行は、何度実行しても同じ結果になります(冪等)。409 WORK_LEASE_ACTIVE は、ワーカーがまだそのアイテムを処理中であることを意味します。レスポンスには details.leaseExpiresAt が含まれるため、その時刻まで待ち、アイテムを読み込み直してから再試行します。409 WORK_CHANGED は、別のリクエストが作業のアイテムを変更したことを意味します。新しい作業を上書きせず、現在の状態を読み込みます。

修復の操作は、{ "scope": "collection", "collection": "articles" }{ "scope": "all" } のどちらかを受け付けます。すべてのコレクションの修復は同期的に順番に実行されるため、大きなサイトでは長い時間がかかることがあります。200 のレスポンスでも partialfailedstale を報告することがあります。修復が完了したと扱う前に、data.status、コレクションごとのステータス、ソースの件数を確認します。

ページ分割

一覧の操作は、ページ分割のパラメーターをOpenAPIに記述しています。カーソルでページ分割する操作の多くは、中身を解釈しない前提の cursor と、1〜100の limit(既定値50)を受け付けます。前のレスポンスの nextCursor を変えずにそのまま返します。中身を調べたり、自分で組み立てたりはしません。一部のメディアの操作は番号付きのページもサポートし、一部の特殊な一覧は異なる上限を使うため、生成したクライアントはそれぞれの操作のスキーマに従います。

検索のトークナイザー

検索を有効にする操作は、コレクションごとにトークナイザーを保存します。有効なコレクションでトークナイザーを変更すると、そのコレクションのインデックスが作り直されます。

用途
porter unicode61 Porterのステミング(語幹の抽出)が役立つ英語のコンテンツ向けの既定値。
unicode61 単語を区切る記号を使うが、英語のステミングを適用しない言語。
trigram 日本語、中国語、タイ語、クメール語、ラオ語、ビルマ語など、スペースのないテキスト、または部分一致の検索が必要なコレクション。3文字(Unicodeの文字数)より短いクエリは何も一致しません。

検索を無効にしても、保存されたトークナイザーは次に有効にするときのために残ります。作り直しの操作は、コレクションに保存されたトークナイザーとフィールドの重みを使います。

コメントとリダイレクト

公開された経路から送信されたコメントは、モデレーションの待ち行列に入ります。管理用のコメントの操作は、すべてのステータスの一覧、件数、1件のステータスの更新、まとめてのモデレーション、コメントの完全な削除を扱います。429 のレスポンスは、送信の回数の上限に達したことを意味します。

リダイレクトの操作は、リダイレクトのルールと、記録された404のログを別々に管理します。整理(prune)はリクエストのボディで選んだ項目を削除し、DELETE /redirects/404s はログ全体を消去します。どちらの操作も、リダイレクトのルールは削除しません。