Magic Asset Manager

API の使い方

画面でできることは、すべて API でもできます。API は JSON で読み書きし、登録と更新のたびに判定と検査をして、その結果を応答に入れて返します。

認証

  1. 「APIトークン」でトークンを発行します。トークンの文字列は、発行したときに一度だけ表示されます。
  2. リクエストのたびに、Authorization ヘッダーにトークンを付けます。
curl https://assets.magichtml.dev/api/v2/assets \
  -H "Authorization: Bearer $TOKEN" -H "Accept: application/json"
  • トークンは発行したアカウントのもので、そのアカウントのアセット(持ち主 user:<アカウントの番号>)だけを読み書きできます。
  • 事務局が用意するフォント(持ち主 system:magic)は、誰でも読めます。書き込むことはできません。
  • 有効期間は 90 日です。失効したトークンや期限の切れたトークンは 401 になります。
  • 1 分あたりの回数に上限があり、超えると 429 になります。
  • 応答はキャッシュされません(Cache-Control: private, no-store)。

書き込みの約束

  • request_key:書き込みには、毎回新しい UUID を付けます。同じ request_key で送り直すと、最初の結果をそのまま返し、二重に登録されません。同じキーで中身を変えると 409 です。
  • base_revision:ファイルを変える書き込みには、元にしたリビジョンの番号を付けます。その間にほかの書き込みが入っていると 409 になり、応答に今の番号が入ります。
  • ファイル:{"path", "json"}・{"path", "text"}・{"path", "blob"} のどれかで指定します。画像などのバイナリは、先に POST /api/v2/blobs に本文として送り、返ってきた sha256 を blob に入れます。blob は 1 日で消えます。
  • スキーマ:{"path", "json", "schema": "magic://schemas/..."} のようにスキーマを付けると、そのスキーマで検査します。

エンドポイント

パスはすべて /api/v2 の下です。

メソッドとパス 内容
GET /assets 一覧。q(名前の部分一致)、kind(カンマ区切り)、medium、state(active・archived・deleted。既定は active)、verdict(passed・failed・unchecked)、sort(updated・title)、page・per_page
POST /assets 登録。{request_key, kind, title, files}。1 ファイルの種類は、multipart の file でも送れる
POST /assets(制作物) {request_key, kind: "production", title, medium: {id, version}, media_contract}
GET /assets/{id} 今のリビジョンを、ファイルの一覧と検査の結果つきで返す。?revision=<n> で番号を指定
PATCH /assets/{id} {request_key, title}。名前だけを変える。リビジョンは増えない
GET /assets/{id}/revisions リビジョンの一覧。それぞれの検査の結果つき
POST /assets/{id}/revisions ファイルを変える。{request_key, base_revision, put: [ファイル…], remove: [パス…]}。新しいリビジョンを作って検査する
GET /assets/{id}/files/{path} ファイルの中身。?revision=<n>、Range ヘッダー、?download=1
POST /assets/{id}/duplicates 丸ごと複製する。{request_key, title, revision?}
POST /assets/{id}/copies ほかのアセットを制作物の references/ にコピーする。{request_key, base_revision, source: {asset, revision?}, to}
PUT /assets/{id}/state {request_key, state}。archived(アーカイブ)・deleted(ゴミ箱。30 日後に完全に削除)・active(戻す)
DELETE /assets/{id} {request_key}。ゴミ箱のアセットを、すべてのリビジョンとともに完全に削除する
DELETE /assets/{id}/revisions/{n}/content {request_key, reason?}。そのリビジョンの中身だけを消す。以後、そのリビジョンのファイルは 410 になる
POST /blobs 本文にファイルのバイト列を送る。{sha256, size} を返す
GET /schemas・GET /schemas/{kind}/{version} スキーマの一覧と本文

例:画像を登録する

curl https://assets.magichtml.dev/api/v2/assets \
  -H "Authorization: Bearer $TOKEN" -H "Accept: application/json" \
  -F request_key=$(uuidgen | tr A-Z a-z) -F kind=image -F title="春の OGP" -F file=@ogp.png

応答(抜粋):

{
  "asset": {
    "id": "0b6f…",
    "kind": "image",
    "title": "春の OGP",
    "revision": {
      "number": 1,
      "ref": "0b6f…@1",
      "files": [{"path": "image.png", "media_type": "image/png", "size": 48213, "sha256": "…"}],
      "inspection": {
        "verdict": "passed",
        "media": [{"id": "ogp", "version": 1, "label": "OGP画像", "type": "banner", "basis": "1200×630 px が形式「1200 × 630 px」の寸法"}],
        "checks": [
          {"standard": "names", "contract": "media-contract", "version": "0.2.0", "target": null, "verdict": "passed", "violations": [], "details": {"files": 1}},
          {"standard": "formats", "contract": "asset-manager", "version": null, "target": null, "verdict": "passed", "violations": [], "details": {"files": […]}}
        ],
        "contracts": {"media-contract": "0.2.0", "magic-contract": "0.4.0"},
        "inspected_at": "2026-10-10T09:00:00.000000Z"
      }
    }
  }
}

例:制作物にファイルを足す

# 1. 画像を blob として送る
SHA=$(curl -s https://assets.magichtml.dev/api/v2/blobs -H "Authorization: Bearer $TOKEN" \
  --data-binary @front.png -H "Content-Type: application/octet-stream" | jq -r .sha256)

# 2. リビジョン 1 を元に、canvas/front.png を足す
curl https://assets.magichtml.dev/api/v2/assets/$ID/revisions \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -H "Accept: application/json" \
  -d '{"request_key": "'$(uuidgen | tr A-Z a-z)'", "base_revision": 1, "put": [{"path": "canvas/front.png", "blob": "'$SHA'"}]}'

画像の寸法が媒体の CANVAS と違うと、応答の inspection.verdict は failed になります。checks の canvas に canvas.size の違反が入り、expected と actual で寸法の違いがわかります。

検査の結果(inspection)

フィールド 内容
verdict passed(合格)・failed(不合格)・unchecked(実行できなかった検査がある)
media 判定した媒体。id・version・label・type・basis(根拠)
checks 規格ごとの結果。standard・contract・version・target(対象のパスやフォルダ、全体は null)・verdict・violations(code・path・message・expected・actual)・details(根拠)
contracts 検査に使った規格の版
inspected_at 検査した日時

一覧(GET /assets)とリビジョンの一覧では、verdict と media だけを返します。規格の中身は判定と検査を見てください。

エラー

コード 場面
401 トークンがない、または無効
403 system: のアセットへの書き込み
404 ほかのアカウントのアセット、または存在しないアセット
409 base_revision の競合、許されていない状態の移り変わり、ゴミ箱にないアセットの完全な削除、request_key の使い回し
410 中身を消したリビジョンのファイル
422 入力の誤り(名前の規則・ファイル形式・スキーマ・媒体など)。errors にフィールドごとの理由が入る
429 回数の上限を超えた