一覧APIは本文を含まない — 軽量な一覧取得

入門 約5分 最終更新 2026-09-08

公開APIの投稿一覧(posts.list())は、意図的に本文を含まない軽量なレスポンスになっています。このガイドでは、その理由と、一覧・詳細を使い分けるパターンを短くまとめます。

1. なぜ一覧は軽いのか

一覧の各要素(PostSummary)には、本文(body・ProseMirror JSON)を含めていません。本文は装飾や画像を含むと数KB〜数十KBになることもあり、それを一覧に全件含めると投稿数に比例してペイロードが膨らみます。一覧はタイトルやカテゴリなど、一覧表示に必要な項目だけに絞ることで、投稿数が増えても応答サイズがほぼ変わりません。

2. 一覧レスポンスの形

cms.posts.list() は items と meta(ページング情報)だけを返します。

GET /posts/news (list)
{
  "items": [
    {
      "slug": "2026-autumn-sale",
      "title": "秋の新商品キャンペーンを開始しました",
      "published_at": "2026-09-01T10:00:00+09:00",
      "pinned": true,
      "category": { "name": "お知らせ", "slug": "info" },
      "tags": ["キャンペーン", "新商品"],
      "eyecatch_image": {
        "url": "https://cdn.example.com/eyecatch/2026-autumn-sale.jpg",
        "thumbnail_url": "https://cdn.example.com/eyecatch/2026-autumn-sale_thumb.jpg",
        "width": 1200,
        "height": 630
      }
    }
  ],
  "meta": {
    "current_page": 1,
    "last_page": 3,
    "per_page": 20,
    "total": 54
  }
}

一方 cms.posts.get() は同じ項目に加えて、本文・関連URL・メタタグ設定を含みます。一覧より情報が多い分、1件あたりの応答は大きくなります。

GET /posts/news/{slug} (detail)
{
  "slug": "2026-autumn-sale",
  "title": "秋の新商品キャンペーンを開始しました",
  "published_at": "2026-09-01T10:00:00+09:00",
  "pinned": true,
  "category": { "name": "お知らせ", "slug": "info" },
  "tags": ["キャンペーン", "新商品"],
  "eyecatch_image": {
    "url": "https://cdn.example.com/eyecatch/2026-autumn-sale.jpg",
    "thumbnail_url": "https://cdn.example.com/eyecatch/2026-autumn-sale_thumb.jpg",
    "width": 1200,
    "height": 630
  },
  "body": {
    "type": "doc",
    "content": [
      {
        "type": "paragraph",
        "content": [{ "type": "text", "text": "本文はここに入ります。" }]
      }
    ]
  },
  "related_urls": [{ "label": "特設ページ", "url": "https://example.com/campaign" }],
  "meta": {
    "meta_title": null,
    "meta_description": "2026年秋の新商品キャンペーンについて",
    "og_image_url": null
  }
}

3. 本文が要るときだけ詳細を引く

このため、実装も一覧と詳細で呼び分けます。一覧ページ(index)は list() の結果だけで表示し、詳細ページはスラッグごとに get() を呼んで本文を取得します。SSGなら getStaticPaths(Astro)や generateStaticParams(Next.js)で一覧からスラッグを列挙し、各ページのビルド時にだけ詳細を取得するのが基本形です(Astroで作るガイド参照)。

  • 一覧ページ:list() のみ呼ぶ。本文は取得しない。
  • 詳細ページ:スラッグごとに get() を呼び、そのときだけ本文をレンダリングする。

4. ページングと件数

1リクエストの per_page 上限は100件です。pageで改ページし、meta.last_page / meta.total で残りページ・全件数を把握できます。投稿数が100件を超えるサイトで全件を扱いたい場合は、ページ送りループで取得します。

src/lib/fetchAllPosts.ts
import { cms } from '../lib/cms';

async function fetchAllPosts(postType: string) {
  const items = [];
  let page = 1;

  while (true) {
    const res = await cms.posts.list(postType, { page, perPage: 100 });
    items.push(...res.items);
    if (page >= res.meta.last_page) break;
    page += 1;
  }

  return items;
}
多言語(オプション):list() も get() も localeを受け取り、言語別の公開版を返します(一覧の軽さは変わりません)。未翻訳は原文を返し、各要素に translation_available が付きます。詳しくは多言語サイトを作るを参照してください。
ヒント:一覧の軽さはあくまで一覧表示のためのものです。全文検索やタグでの横断検索が必要な場合は、公開APIの一覧を都度舐めるのではなく、ビルド時に取得した内容を自前の検索インデックス(例:Pagefind、Algolia)に投入する構成にしてください。
FEEDBACK

このページはお役に立ちましたか?

改善要望・不具合・ドキュメントの分かりにくい点など、お気軽にお寄せください。いただいた内容は今後の改善に役立てます。

返信をご希望の場合のみご記入ください。

スパム対策(レートリミット・ハニーポット・送信速度チェック)はサーバ側で自動適用されます。