Love API Reference

ゲーム世界観ドキュメント管理システム「Love」のREST API。

基本情報

  • Base URL: https://love.stagbeetle.group/api/v1
  • Format: JSON (UTF-8必須、Shift_JISは400で拒否)
  • レスポンス形式: {"data": ...}(204は空)
  • エラー形式: {"error": "message"}
  • 認証: なし(IPアロー方式、現在は全許可)
  • 姉妹システム: Fudo(https://box.stagbeetle.group/)と同じVPS上で稼働、別バイナリ

概念

Title (タイトル) ─┬─ Worldview Pages (世界観ページ)
                 ├─ Chronology Events (年代史)
                 ├─ Glossary Terms (用語集)
                 ├─ Characters (登場人物) ─┬─ Relationships (相関)
                 │                         └─ History Events (人物史)
                 └─ [Phase 4: Songs / BGM / SE]

各タイトルが独立した世界観を持ち、配下に複数カテゴリのデータを管理する。


Titles (タイトル)

Method Path Description Body
GET /titles タイトル一覧
POST /titles タイトル作成 {slug, name, description?, cover_image_url?}
GET /titles/{slug} タイトル取得
PUT /titles/{slug} タイトル更新 {name, description, cover_image_url}
DELETE /titles/{slug} タイトル削除(カスケード削除)

Title オブジェクト

{
  "id": 1,
  "slug": "test-game",
  "name": "テストゲーム",
  "description": "テスト用タイトル",
  "cover_image_url": "/uploads/covers/abc.png",
  "sort_order": 0,
  "created_at": "2026-04-09 02:57:40",
  "updated_at": "2026-04-09 02:57:40"
}

Worldview (世界観)

タイトル配下の世界観ページ群。Markdownで自由記述。

Method Path Description Body
GET /titles/{slug}/worldview ページ一覧
POST /titles/{slug}/worldview ページ作成 {slug, name, content?}
PUT /titles/{slug}/worldview/{pageId} ページ更新 {name, content}
DELETE /titles/{slug}/worldview/{pageId} ページ削除

WorldviewPage オブジェクト

{
  "id": 1,
  "title_id": 1,
  "slug": "geography",
  "name": "地理",
  "content": "# 大陸\n\n広大な大陸が広がっている...",
  "sort_order": 0,
  "created_at": "...",
  "updated_at": "..."
}

Chronology (年代史)

時系列イベント。架空の暦に対応するため year/month/day はすべて文字列。

Method Path Description Body
GET /titles/{slug}/chronology イベント一覧
POST /titles/{slug}/chronology イベント作成 {era?, year?, month?, day?, event_name, description?, sort_order?}
PUT /titles/{slug}/chronology/{eventId} イベント更新 同上
DELETE /titles/{slug}/chronology/{eventId} イベント削除

ChronologyEvent オブジェクト

{
  "id": 1,
  "title_id": 1,
  "era": "第一紀",
  "year": "100",
  "month": "3",
  "day": "15",
  "event_name": "王国建国",
  "description": "初代国王が王国を建てる",
  "sort_order": 1,
  "created_at": "...",
  "updated_at": "..."
}

Glossary (用語集)

Method Path Description Body
GET /titles/{slug}/glossary 用語一覧
POST /titles/{slug}/glossary 用語作成 {term, reading?, category?, description?}
PUT /titles/{slug}/glossary/{termId} 用語更新 同上
DELETE /titles/{slug}/glossary/{termId} 用語削除

GlossaryTerm オブジェクト

{
  "id": 1,
  "title_id": 1,
  "term": "マナ",
  "reading": "まな",
  "category": "魔法",
  "description": "魔法エネルギーの源",
  "created_at": "...",
  "updated_at": "..."
}

Characters (登場人物)

Method Path Description Body
GET /titles/{slug}/characters キャラ一覧
POST /titles/{slug}/characters キャラ作成 Character 全フィールド (slug, name 必須)
PUT /titles/{slug}/characters/{characterId} キャラ更新 Character 全フィールド
DELETE /titles/{slug}/characters/{characterId} キャラ削除(相関・人物史もカスケード)

Character オブジェクト

{
  "id": 1,
  "title_id": 1,
  "slug": "hero",
  "name": "勇者アルト",
  "name_kana": "ゆうしゃあると",
  "role": "主人公",
  "age": "17",
  "gender": "男",
  "affiliation": "冒険者ギルド",
  "occupation": "騎士",
  "avatar_url": "/uploads/characters/abc123.png",
  "description": "## 背景\n小さな村出身の若き騎士...",
  "sort_order": 0,
  "created_at": "...",
  "updated_at": "..."
}

description は Markdown 対応。


Character Relationships (相関関係)

Method Path Description Body
GET /titles/{slug}/character-relationships タイトル内全相関一覧(from/to名前付き)
POST /titles/{slug}/character-relationships 相関作成 {from_character_id, to_character_id, relation_type, description?}
PUT /titles/{slug}/character-relationships/{relId} 相関更新 {relation_type, description}
DELETE /titles/{slug}/character-relationships/{relId} 相関削除

CharacterRelationship オブジェクト

{
  "id": 1,
  "title_id": 1,
  "from_character_id": 1,
  "to_character_id": 2,
  "relation_type": "宿敵",
  "description": "幼少期からのライバル",
  "from_name": "勇者アルト",
  "from_slug": "hero",
  "to_name": "魔王ザード",
  "to_slug": "villain",
  "created_at": "..."
}

from_name, from_slug, to_name, to_slug はGET時のみ含まれるJOIN結果。


Character History Events (人物史)

各キャラクターの人生イベント。

Method Path Description Body
GET /titles/{slug}/characters/{characterId}/history 人物史一覧
POST /titles/{slug}/characters/{characterId}/history イベント作成 {era?, year?, month?, day?, event_name, description?, sort_order?}
PUT /titles/{slug}/characters/{characterId}/history/{eventId} イベント更新 同上
DELETE /titles/{slug}/characters/{characterId}/history/{eventId} イベント削除

CharacterHistoryEvent オブジェクト

ChronologyEvent と同じ構造で character_id フィールドを持つ。


Image Upload (画像アップロード)

Method Path Description Body
POST /upload/image?dir={subdir} 画像アップロード multipart/form-data (file フィールド)
  • 上限: 10MB
  • 対応形式: jpg / jpeg / png / gif / webp
  • dir クエリ: 保存サブディレクトリ(英数字・ハイフン・アンダースコアのみ)。例: characters, covers
  • 戻り値: {"data": {"url": "/uploads/{dir}/{random}.ext"}}
  • アップロード後のURLはそのままブラウザでアクセス可能(https://love.stagbeetle.group/uploads/...

エラーレスポンス

{"error": "title not found"}
Code 意味
200 取得成功
201 作成成功
204 更新/削除成功(ボディ無し)
400 リクエスト不正(必須フィールド欠落、UTF-8でない等)
404 リソース未発見
500 サーバーエラー

使用例

タイトル作成 → キャラ作成 → 相関設定の流れ

# 1. タイトル作成
curl -X POST https://love.stagbeetle.group/api/v1/titles \
  -H 'Content-Type: application/json' \
  -d '{"slug":"my-game","name":"My RPG","description":"自作RPG"}'

# 2. キャラ2人作成
curl -X POST https://love.stagbeetle.group/api/v1/titles/my-game/characters \
  -H 'Content-Type: application/json' \
  -d '{"slug":"hero","name":"勇者","role":"主人公","age":"17"}'

curl -X POST https://love.stagbeetle.group/api/v1/titles/my-game/characters \
  -H 'Content-Type: application/json' \
  -d '{"slug":"villain","name":"魔王","role":"敵"}'

# 3. 相関設定
curl -X POST https://love.stagbeetle.group/api/v1/titles/my-game/character-relationships \
  -H 'Content-Type: application/json' \
  -d '{"from_character_id":1,"to_character_id":2,"relation_type":"宿敵"}'

# 4. 用語追加
curl -X POST https://love.stagbeetle.group/api/v1/titles/my-game/glossary \
  -H 'Content-Type: application/json' \
  -d '{"term":"魔法","reading":"まほう","category":"基本","description":"マナを使った技術"}'

画像アップロード → キャラに設定

# 1. 画像アップロード
curl -X POST 'https://love.stagbeetle.group/api/v1/upload/image?dir=characters' \
  -F 'file=@hero.png'
# レスポンス: {"data":{"url":"/uploads/characters/abc123.png"}}

# 2. キャラ更新でavatar_urlに設定
curl -X PUT https://love.stagbeetle.group/api/v1/titles/my-game/characters/1 \
  -H 'Content-Type: application/json' \
  -d '{"slug":"hero","name":"勇者","avatar_url":"/uploads/characters/abc123.png"}'

注意事項

UTF-8必須

リクエストボディは厳密にUTF-8でないと拒否される(400エラー)。Windows等のシェルから日本語を送る場合は文字コードに注意。

文字列フィールドの空値

PUT時、未指定フィールドは空文字で上書きされる。部分更新は未対応(全フィールドを送る必要あり)。

slug の制約

URL-safe な英数字とハイフンを推奨。重複は同一title_id内で不可(UNIQUE制約)。

ファイルパス

  • アップロードされたファイルは /opt/love/uploads/{dir}/ に保存
  • DBには相対URL /uploads/{dir}/{filename} で記録
  • ブラウザからは https://love.stagbeetle.group/uploads/... でアクセス可能
  • タイトル削除時、関連ファイルは自動削除されない(手動削除が必要)