GraphQL で取り出す
GraphQL の API を使うと、ページに要るものを 1 回の呼び出しで取り出せます。記事の一覧とサイトの設定のように、別のコンテンツタイプのエントリーも一緒に取れます。返るのは、問い合わせに書いたフィールドだけです。
GraphQL のスキーマはスペースのコンテンツタイプから自動で作られます。コンテンツタイプやフィールドを足すと、そのまま問い合わせに使えます。
- [読み取り]の権限のある API キー。発行のしかたは API キーを作る、権限を決める にあります。権限は REST の Content API と同じです
- 取り出すエントリーが[公開中]になっていること。下書きを取るときは、この下の「下書きを取る」を見てください
- コンテンツタイプ ID。コンテンツタイプの画面で[エンドポイント]と出ている値です(例:「posts」)
下の例では、次の値を置き換えてください。
<ホスト名>:あなたの環境のホスト名。管理画面のアドレスhttps://<ホスト名>.hakocms.netの部分です<API キー>:hako_で始まる API キー
例のスペースには、コレクションの「posts」(記事)と「authors」(著者)、シングルの「site-settings」(サイトの設定)があります。記事のフィールドは title(テキスト)、body(リッチテキスト)、tags(セレクト)、author(著者への参照)です。
問い合わせを送る
Section titled “問い合わせを送る”問い合わせは /api/v1/graphql に POST で送ります。本文は JSON で、query に問い合わせを書きます。API キーは REST と同じく Authorization: Bearer で送ります。
記事の数を数え、2 件のタイトルを取り出します。
curl https://<ホスト名>.hakocms.net/api/v1/graphql \ -H "Authorization: Bearer <API キー>" \ -H "Content-Type: application/json" \ -d '{"query": "{ postsCollection(limit: 2) { total items { title } } }"}'次のように返ります。
{ "data": { "postsCollection": { "total": 3, "items": [ { "title": "年末年始のお休み" }, { "title": "GraphQL で読む" } ] } }}本文には query のほかに variables(変数)と operationName(実行する問い合わせの名前)も書けます。
名前の決まり
Section titled “名前の決まり”型とフィールドの名前は、コンテンツタイプ ID とフィールド ID から決まります。
| 取り出すもの | 問い合わせのフィールド | コンテンツタイプ ID が「blog-posts」なら |
|---|---|---|
| コレクションの一覧 | ID をつなげて先頭を小文字にした名前に Collection |
blogPostsCollection |
| コレクションの 1 件 | ID をつなげて先頭を小文字にした名前 | blogPosts(id: "hello") |
| シングル | ID をつなげて先頭を小文字にした名前 | (「site-settings」なら)siteSettings |
- 型の名前は ID をつなげて先頭を大文字にした名前です(
BlogPosts) - フィールドの名前はフィールド ID のままです。GraphQL の名前に使えない
-は_になります(old-fieldはold_field) - どのエントリーにも
sysがあり、id、contentType、createdAt、updatedAt、publishedAt、firstPublishedAt、versionを取り出せます
正確な型はこの下の「スキーマを取る」で、スペースのスキーマを取り出して確かめられます。
一覧とシングルを 1 回で取る
Section titled “一覧とシングルを 1 回で取る”トップページに要る、新しい記事 2 件(タイトル、タグ、著者の名前)と、サイトの名前を 1 回で取り出します。Home は問い合わせの名前で、好きに付けられます。
query Home { postsCollection(limit: 2) { total items { sys { id publishedAt } title tags author { name } } } siteSettings { siteName }}次のように返ります。
{ "data": { "siteSettings": { "siteName": "山田ブログ" }, "postsCollection": { "total": 3, "items": [ { "sys": { "id": "holiday", "publishedAt": "2026-10-21T15:16:12.691Z" }, "title": "年末年始のお休み", "tags": ["news"], "author": { "name": "山田 花子" } }, { "sys": { "id": "graphql", "publishedAt": "2026-10-21T15:16:11.661Z" }, "title": "GraphQL で読む", "tags": ["tech"], "author": { "name": "山田 花子" } } ] } }}- 一覧は既定で公開した日時の新しい順に、20 件までです。
limit(0〜100)とoffsetで区切ります - 参照(
author)は問い合わせに書いた分だけたどります。REST のincludeは要りません。たどれるのは、いちばん上を含めて 4 段までです - 参照先が公開されていないときや消されたときは、参照のフィールドは
nullになります。複数参照なら、配列から除かれます
絞り込む、並べる
Section titled “絞り込む、並べる”一覧のフィールドに where と order を付けます。値は変数で渡せます。タグ「news」の記事を、公開した日時の新しい順に取り出します。
query News($tag: String!) { postsCollection( where: { tags: { contains: $tag } } order: [sys_publishedAt_DESC] ) { items { title } }}変数は本文の variables に書きます。
{ "tag": "news" }次のように返ります。
{ "data": { "postsCollection": { "items": [ { "title": "年末年始のお休み" }, { "title": "サイトを公開しました" } ] } }}whereにはフィールドごとに条件を書きます。使える条件はフィールドの種類で決まります(テキストならeq、contains、startsWithなど、数値と日時ならlt、gteなど)。意味は REST のwhereと同じで、絞り込む、並べる、ページに分ける にあります- 条件を組み合わせるときは、
and、or、notを使います。sysのidや日時でも絞り込めます orderは、<フィールド ID>_ASC(小さい順)か<フィールド ID>_DESC(大きい順)を並べます。並べられるのは、テキスト、テキストエリア、日時、数値のフィールドと、sysのidと日時です- 一覧のフィールドに
qを付けると、全文検索になります。意味は 全文検索を使う と同じです
1 件を取り、リッチテキストを HTML で受け取る
Section titled “1 件を取り、リッチテキストを HTML で受け取る”エントリー ID を id に渡します。リッチテキストのフィールドは、html を選ぶとサーバーで HTML にしたものが、json を選ぶと JSON の形が返ります。
query Post($id: ID!) { posts(id: $id) { title body { html } }}変数に { "id": "hello" } を渡すと、次のように返ります。
{ "data": { "posts": { "title": "サイトを公開しました", "body": { "html": "<p>今日からサイトを公開します。</p>" } } }}エントリーがないときや、公開していないときは、posts が null になります。JSON の形は リッチテキストの形(Hako Rich Text v1) にあります。
サイトのコードから呼ぶ
Section titled “サイトのコードから呼ぶ”JavaScript(ブラウザ、Node.js)では、fetch で送ります。次のコードは上の「絞り込む、並べる」の問い合わせを送り、タイトルを表示します。
const res = await fetch( "https://<ホスト名>.hakocms.net/api/v1/graphql", { method: "POST", headers: { Authorization: "Bearer <API キー>", "Content-Type": "application/json", }, body: JSON.stringify({ query: `query News($tag: String!) { postsCollection(where: { tags: { contains: $tag } }) { items { title } } }`, variables: { tag: "news" }, }), },);const { data, errors } = await res.json();if (errors) throw new Error(errors[0].message);console.log(data.postsCollection.items.map((p) => p.title));どのオリジンからも呼べます(CORS)。ブラウザに渡す API キーは[読み取り]だけの権限にしてください。
下書きを取る
Section titled “下書きを取る”問い合わせのいちばん上のフィールドに preview: true を付けると、公開する前の下書きを取り出せます。その下でたどる参照先も下書きの値になります。
{ posts(id: "hello", preview: true) { title }}下書きを読めるのは、[プレビュー]の権限のある API キーだけです。このキーはサイトのサーバーの中だけで使い、ブラウザに渡さないでください。詳しくは 下書きを取る(プレビュー) にあります。
スキーマを取る
Section titled “スキーマを取る”スペースの GraphQL のスキーマ(SDL)は、次のように取り出せます。イントロスペクションにも答えるので、GraphQL の道具(エディターの補完、GraphQL Code Generator など)をそのままつなげます。
curl https://<ホスト名>.hakocms.net/api/v1/schema/graphql \ -H "Authorization: Bearer <API キー>"次のように始まるテキストが返ります(一部)。コンテンツタイプとフィールドの名前が、説明として入っています。
"""著者(authors)"""type Authors { sys: Sys! """ 名前 """ name: String}フィールドの種類ごとの型は次のとおりです。
| フィールドの種類 | GraphQL の型 | 値がないとき |
|---|---|---|
| テキスト、テキストエリア | String |
null |
| リッチテキスト | RichText(json、html) |
null |
| 画像 | Image(url、width、height、alt) |
null |
| 複数画像 | [Image!]! |
[] |
| ファイル | File(url、fileSize) |
null |
| 日時 | DateTime(RFC 3339 の文字列) |
null |
| 真偽値 | Boolean! |
false |
| 数値 | Float |
null |
| セレクト | [String!]!(選択肢の値) |
[] |
| 参照 | 参照先の型 | null |
| 複数参照 | 参照先の型の配列 | [] |
| カスタム | コンテンツタイプとカスタムフィールドの名前をつなげた型 | null |
| 繰り返し | カスタムの型の配列。カスタムが 2 つ以上なら union の配列 | [] |
重い問い合わせでサイトが遅くならないよう、次の上限があります。
| もの | 上限 |
|---|---|
1 回の一覧の件数(limit) |
0〜100。既定は 20 |
| 1 回の呼び出しで返すエントリーの合計(参照先を含む) | 1,000 |
| 参照のたどり | いちばん上を含めて 4 段 |
| 問い合わせの深さ | 10 |
| 問い合わせの複雑さ(書いたフィールドの数) | 2,000 |
| 本文の大きさ | 64 KB。超えると 413 |
data に、書いたフィールドが返っていれば取り出せています。うまくいかないときは、応答の errors を見てください。GraphQL の誤りは HTTP の 200 と、errors で返ります。
{ "data": null, "errors": [ { "message": "limit must be an integer from 0 to 100", "locations": [{ "line": 2, "column": 3 }], "extensions": { "code": "BAD_REQUEST" } } ]}1 つの問い合わせに書いたフィールドのうち、誤りのあったものだけが data から除かれ、ほかのフィールドは返ります。
| 返ってきたもの | 原因 | 直し方 |
|---|---|---|
401 unauthorized |
API キーがない、違う、または失効している | Authorization: Bearer のあとに、hako_ で始まるキーをそのまま入れているか確かめます |
400 bad_request |
本文が GraphQL の要求の形(query を持つ JSON)でない |
本文を {"query": "…"} の形にし、JSON として正しいか確かめます |
errors の code が FORBIDDEN |
キーに、そのコンテンツタイプを読む権限がない。または preview: true にプレビューの権限がない |
[API キー]の画面で、キーの権限を確かめます |
errors の code が BAD_REQUEST |
引数の値が正しくない(limit が範囲の外、where の条件が合わないなど) |
message に理由が出ます |
errors で Unknown field |
スキーマにないフィールドを書いた | 名前を「名前の決まり」で確かめます。スキーマを取ると、正確な名前が分かります |