STORYAIヘルプポータル

APIドキュメント

STORYAI API のエンドポイント、パラメータ、レスポンス、エラーの一覧です。APIキーの発行条件と管理方法は「API機能について」をご覧ください。

概要

作品の登録と分析、版の追加、再分析、分析結果の取得を、お客様のアプリケーションから実行できます。

ベースURL: https://api.storyai.app

認証

すべてのエンドポイントで、APIキーによる認証が必要です。リクエストヘッダーに次を含めてください。

Authorization: Bearer <YOUR_API_KEY>
  • APIキーはブランドに結び付いています。APIで扱える作品は、キーを発行したブランドのすべての作品です。Web画面のプロジェクト権限(管理者・編集者・閲覧者)による絞り込みはかかりません。
  • APIで登録した作品は、キーを発行した人が作成した作品として記録されます。
  • 認証に失敗すると 403 が返ります。ヘッダーが無いときは API key required.、キーが無効・削除済みのときは Invalid API key or associated account not found. です。
  • キーはリクエストのたびに、発行時と同じ条件を満たしているか確認されます。条件を満たさなくなったキーは 403 になり、reason に理由が入ります。
reason原因
api_key_issuer_role_revokedキーを発行した人が、ブランドのオーナー・システム管理者ではなくなった
api_key_plan_not_allowedブランドのプランが、APIを利用できないプランに変わった

発行者の役割やプランを元に戻すと、同じキーを再び使えます。使わせたくない場合は、オーナー・システム管理者がキーを削除してください(「API機能について」)。

  • Web画面のログイン情報では /api/v1/ak/... を呼び出せません。

エンドポイント一覧

エンドポイントメソッド説明
/api/v1/ak/workPOST作品を登録して分析する
/api/v1/ak/workGET作品一覧を取得する
/api/v1/ak/work/:work_idGET作品の情報と分析結果を取得する
/api/v1/ak/work/:work_id/versionPOST既存の作品に版を追加して分析する
/api/v1/ak/work/:work_id/reanalyzePOST最新の版を再分析する
WebSocket(socket.io)-分析状況の更新通知を受け取る

作品の削除やタイトルの変更など、その他の操作はAPIにありません。Web画面で行ってください。


作品の登録と分析

POST /api/v1/ak/work

ファイルまたはテキストを送り、新しい作品を作って分析を始めます。分析は非同期で進みます。完了はWebSocketの通知か、GET /api/v1/ak/work/:work_id で確認してください。

リクエスト形式

multipart/form-data。送るファイルは合計 1000MB までです。超えると 413 になります。

パラメータ

名前型必須説明
titlestring○作品のタイトル(1文字以上)
has_copylightstring ("true")○著作権の確認。"true" 固定で、それ以外は 400
analysis_type_idnumber○分析形式のID(下の表)
category_idnumber○カテゴリのID(下の表)
genre_idnumber○ジャンルのID(下の表)
textstring本文を直接送る場合に使います。分析形式が「テキスト(13)」か「SNS投稿(10)」のときだけ使えます
postsstring(JSON配列)SNS投稿を複数まとめて時系列で分析するときの本文一覧。例: '["1件目","2件目"]'。text と同時には指定できません
post_0, post_1, …fileposts の各投稿に付けるメディア。番号は0始まりで、posts の並び順に対応します。同じ名前で複数送れます
descriptionstring作品の説明
project_idnumber作品を入れるプロジェクトのID。自分のブランドのプロジェクト以外は 404
reading_directionstring ("rl" / "lr")漫画を読む方向。既定は "rl"(右から左)
pdf_unitstring ("page" / "element")PDFの読み取り単位。既定は "page"。page はページを画像として、element は文字要素を取り出して扱います
pdf_spreadstring ("spread_rl" / "spread_lr")PDFを見開きとして扱います。pdf_unit が "page" のときだけ有効です
remove_fillerstring ("true" / "false")音声・動画の書き起こしから「えー」「あの」などのフィラーや言い直しを除きます。既定は false。音声・動画以外で true にすると 400
extract_ocrstring ("true" / "false")動画の画面に映るスライドや文書の文字を読み取り、分析に含めます。既定は false。動画以外で true にすると 400
user_analyze_promptstring分析時にAIへ渡す追加の指示。Web画面の「ユーザープロンプト」と同じです
is_flame_analysisstring ("true" / "false")炎上リスク分析を行います。既定は false
thumbnailfile作品のサムネイル画像(png / jpg / jpeg / webp)
任意のキーfile分析するファイル。キー名は自由です(例: files)。分析形式に合った拡張子だけを受け付けます

分析形式(analysis_type_id)と受け付けるファイル

ID名称拡張子text での直接入力
13テキストtxt, doc, docx, pdf, md, epub○
14ドキュメントdoc, docx, pptx, pdf, md, epub×
8画像(漫画・絵コンテなど)zip, doc, docx, pdf, png, jpg, jpeg, gif, svg, webp×
7動画mp4, mpeg, webm, avi×
12音声wav, mp3, m4a, aac, flac, ogg×
10SNS投稿txt, png, jpg, jpeg, gif, webp, mp4, mov, zip○
4CSV / TSV 形式(ゲーム用の専用フォーマット)csv, tsv, pdf×

ファイルとテキストの組み合わせ

  • text・posts・ファイルのどれも無いときは 400(テキストまたは少なくとも1つのファイルが必要です。)になります。
  • 複数のファイルや、テキストとファイルの併用ができるのは、画像(8)とSNS投稿(10)だけです。他の形式ではファイルを1つだけ送ってください。
  • ZIPファイルは単独で送ります。ZIPと他のファイル、ZIPとテキストは一緒に送れません。

カテゴリ(category_id)

IDカテゴリIDカテゴリ
0あらすじ15Instagram
1筋書き16メールマガジン
2シナリオ17ウェブトゥーン・4コママンガ
4小説18会議
6ブログ19スライド
7ゲーム20広告・宣伝
10映像・動画21パッケージ
11企業向けコンテンツ22絵コンテ
12マンガ23その他
13ウェブサイト24マーケティング・PR
14X(旧Twitter)25音楽・歌詞
26YouTube
27TikTok

ジャンル(genre_id)

エンタメ・物語系

IDジャンルIDジャンル
0アクション21ドキュメンタリー
1ホラー23エンターテインメント
2SF67映画・映像
3ミステリー68演劇・舞台
4スリラー69文学・書籍
5ドラマ71絵本
6アドベンチャー74エッセイ・コラム
7ファンタジー75日記・ブログ
8犯罪76ソーシャルゲーム
9コメディ77ノベルゲーム
10ロマンス78ウェブ小説
11ファミリー79ライトノベル
12伝記
13スポーツ
14音楽
15ミリタリー
16ウエスタン
17歴史
18ミュージカル
19フィルムノワール
20戦争

ビジネス・社会系

IDジャンルIDジャンル
22統合報告書40情報発信
26海外・国際42政治
27エネルギー・環境43選挙
28チャリティ・社会貢献44キャンペーン
30教育52宇宙
31金融72ビジネス・経済
35ステートメント73自己啓発
36採用80情報共有会議
39レポート81意思決定会議
82アイデア出し会議

コンテンツ・メディア系

IDジャンルIDジャンル
37ツイート45ストリーミング
38コメント・レビュー83コミュニケーション
41自社商品・サービスの紹介84メッセージ

生活・文化系

IDジャンルIDジャンル
24不動産55IT・テクノロジー
25ウェルネス56AI・人工知能
29住宅・暮らし57ブロックチェーン・暗号資産
32ヘルスケア58ファッション
33ライフスタイル59コスメ・美容
34イベント60食品・飲料
46リゾート61飲食店
47旅行62料理・レシピ
48遊技機・パチンコ・パチスロ63ペット
49ウェディング64趣味・娯楽
50自動車65アート・デザイン
51航空・鉄道70医療・医者・福祉
54アプリ99その他

表にないIDを指定すると 400(不正なジャンルIDです。 など)になります。

リクエスト例

curl

curl -X POST https://api.storyai.app/api/v1/ak/work \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "title=サンプル小説" \
  -F "description=テスト用の小説です" \
  -F "analysis_type_id=13" \
  -F "category_id=4" \
  -F "genre_id=7" \
  -F "has_copylight=true" \
  -F "files=@story.txt"

Python

import requests

url = "https://api.storyai.app/api/v1/ak/work"
headers = {"Authorization": "Bearer YOUR_API_KEY"}
data = {
    "title": "サンプル小説",
    "description": "テスト用の小説です",
    "analysis_type_id": 13,
    "category_id": 4,
    "genre_id": 7,
    "has_copylight": "true",
}
files = {"files": open("story.txt", "rb")}
response = requests.post(url, headers=headers, data=data, files=files)
print(response.json())

TypeScript

const formData = new FormData()
formData.append('title', 'サンプル小説')
formData.append('description', 'テスト用の小説です')
formData.append('analysis_type_id', '13')
formData.append('category_id', '4')
formData.append('genre_id', '7')
formData.append('has_copylight', 'true')

const fileInput = document.getElementById('file') as HTMLInputElement
if (fileInput.files && fileInput.files[0]) {
  formData.append('files', fileInput.files[0])
}

fetch('https://api.storyai.app/api/v1/ak/work', {
  method: 'POST',
  headers: { Authorization: 'Bearer YOUR_API_KEY' },
  body: formData,
})
  .then((response) => response.json())
  .then((data) => console.log(data))

音声を、フィラーを除いて分析する例(curl)

curl -X POST https://api.storyai.app/api/v1/ak/work \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "title=定例会議の録音" \
  -F "analysis_type_id=12" \
  -F "category_id=18" \
  -F "genre_id=80" \
  -F "has_copylight=true" \
  -F "remove_filler=true" \
  -F "files=@meeting.m4a"

SNS投稿を複数まとめて分析する例(curl)

curl -X POST https://api.storyai.app/api/v1/ak/work \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "title=新商品キャンペーン投稿" \
  -F "analysis_type_id=10" \
  -F "category_id=14" \
  -F "genre_id=37" \
  -F "has_copylight=true" \
  -F 'posts=["1件目の投稿本文","2件目の投稿本文","3件目の投稿本文"]' \
  -F "post_0=@image_for_post1.png" \
  -F "post_2=@video_for_post3.mp4"

レスポンス例(200 OK)

{
  "id": 123,
  "title": "サンプル小説",
  "is_flame_analysis": false,
  "work_versions": [
    {
      "id": 456,
      "created_at": "2026-06-10T10:00:00.000Z",
      "user": { "id": 1, "name": "ユーザー名" }
    }
  ],
  "url": "https://storyai.app/your-brand/works/123/detail"
}

url はWeb画面の作品ページです。この時点では、まだ分析結果はありません。

エラー

  • 400: 必須項目の不足、表にないID、対応していない拡張子、組み合わせのルール違反、著作権の未確認。メッセージは 入力値が不正です: {項目}: {内容} の形です
  • 403: APIキーが無い・無効、またはキーの利用条件を満たさなくなった(上の「認証」を参照)
  • 404: project_id のプロジェクトが無い、または他のブランドのもの
  • 413: ファイルが合計1000MBを超えた(reason: upload_size_limit_exceeded)
  • 429: 今月の分析回数の上限に達した(今月の解析上限に達しました。)
  • 500: サーバー内部のエラー

作品一覧の取得

GET /api/v1/ak/work

APIキーのブランドに属する作品の一覧を取得します。

クエリパラメータ

名前型必須既定値説明
limitnumber101ページの件数(1〜100)
pagenumber1ページ番号
order_bystringupdated_at並べ替えの基準(id / created_at / updated_at)
order_directionstringdesc昇順・降順(asc / desc)
searchstringタイトルの部分一致で絞り込む。日本語はURLエンコードして送ります
project_idnumber指定したプロジェクトの作品だけを取得する

リクエスト例

curl -G "https://api.storyai.app/api/v1/ak/work" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  --data-urlencode "limit=20" \
  --data-urlencode "order_by=created_at" \
  --data-urlencode "search=物語"

レスポンス例(200 OK)

{
  "count": 42,
  "works": [
    {
      "id": 123,
      "title": "サンプル小説",
      "analysis_type_id": 13,
      "category_id": 4,
      "genre_id": 7,
      "last_updated_by": { "id": 1, "name": "ユーザー名", "image": null },
      "work_versions": [
        {
          "id": 456,
          "created_at": "2026-06-10T10:00:00.000Z",
          "is_standalone_analysis": false,
          "user": { "id": 1, "name": "ユーザー名", "image": null }
        }
      ],
      "url": "https://storyai.app/your-brand/works/123/detail"
    }
  ]
}
  • count は条件に合う作品の総数です。ページ送りに使ってください。
  • work_versions は新しい版から順に並びます。版ごとの分析状況は含まれません。完了したかどうかは GET /api/v1/ak/work/:work_id かWebSocketの通知で確かめてください。

作品の情報と分析結果の取得

GET /api/v1/ak/work/:work_id

作品の情報と分析結果を取得します。

パスパラメータ

名前型必須説明
work_idnumber○作品のID

クエリパラメータ

名前型必須説明
work_version_idnumber取得する版のID。省略すると最新の版です
includestring追加で取得するデータをカンマ区切りで指定します(下の表)。知らないキーを指定すると 400

include で指定できるキーは次のとおりです。

種類キー
分析データemotion_analysis, co_occurrence_analysis, correspondence_analysis, wordcloud_analysis, network_analysis, timeline_analysis
グラフ画像のURLemotion_chart_image(感情曲線), co_occurrence_chart_image(共起ネットワーク), character_network_images(人物相関図)
  • 分析データは キー:項目1:項目2 の形で、必要な項目だけに絞れます。入れ子の項目は . でつなぎます(例: emotion_analysis:summary:scores.final_story_evaluation)。
  • include を指定しないと、感情の時系列データなど大きな結果は返りません。必要なものだけを指定してください。
  • グラフ画像は { "url", "expires_in", "content_type" } の形で返ります。url は1時間だけ有効です。画像がまだ作られていない作品では null になります。
  • character_network_images は { "overall": 全体図, "timeline": [期間ごとの図] } の形です。

リクエスト例

curl -X GET "https://api.storyai.app/api/v1/ak/work/123?work_version_id=456&include=emotion_analysis:summary,emotion_chart_image" \
  -H "Authorization: Bearer YOUR_API_KEY"

レスポンス例(200 OK)

{
  "id": 123,
  "work_version_id": 456,
  "project": { "id": 1, "name": "プロジェクト名" },
  "user": { "id": 1, "name": "ユーザー名" },
  "title": "サンプル小説",
  "description": "テスト用の小説です",
  "thumbnail": "https://...(1時間有効のURL)",
  "analysis_type_id": 13,
  "category_id": 4,
  "genre_id": 7,
  "comment": "版のコメント",
  "is_diff": false,
  "is_standalone_analysis": false,
  "created_at": "2026-06-10T10:00:00.000Z",
  "updated_at": "2026-06-10T10:20:00.000Z",
  "sns_metrics": null,
  "work_analysis_result": {
    "ai_summary": "作品全体の要約…",
    "final_evaluation_summary": "総合評価の説明…",
    "total_point": 72,
    "rank": "B",
    "indicators": [
      {
        "key": "…",
        "group": "…",
        "status": "…",
        "value": 0.81,
        "percentage": 81,
        "summary": "…"
      }
    ]
  },
  "additional_tools_status": {
    "status": 2,
    "tools": { "word_cloud": 2, "cooccurrence": 2, "correspondence": 2, "network": 2 }
  },
  "url": "https://storyai.app/your-brand/works/123/detail",
  "emotion_analysis": { "summary": "…" },
  "emotion_chart_image": {
    "url": "https://...",
    "expires_in": 3600,
    "content_type": "image/svg+xml"
  }
}
  • work_analysis_result は、分析が終わるまで null です。
  • additional_tools_status は追加の分析(ワードクラウド・共起・コレスポンデンス・ネットワーク)の状況です。値は 0 未分析、1 分析中、2 完了、3 失敗です。
  • include で指定した結果は同じ名前のキーで追加されます。まだ作られていないときは null です。

エラー

  • 400: include に知らないキーを指定した
  • 404: 作品が無い、または他のブランドの作品(Work does not exist.)。指定した版が無い(Work Version does not exist.)

版の追加

POST /api/v1/ak/work/:work_id/version

既存の作品に新しい版を追加して分析します。分析形式・カテゴリ・ジャンルは元の作品のものを引き継ぎます。Web画面の「新しい版を追加」と同じ操作で、追加した版は「版の比較」で見比べられます。

リクエスト形式

multipart/form-data(ファイルは合計1000MBまで。超えると 413)。ファイルとテキストの組み合わせのルールは作品の登録と同じです。

パラメータ

名前型必須説明
has_copylightstring ("true")○著作権の確認("true" 固定)
textstring本文(テキスト・SNS投稿の形式だけ)
commentstringこの版のコメント。Web画面の版の一覧に表示されます
reading_direction / pdf_unit / pdf_spread / remove_filler / extract_ocr作品の登録と同じです
任意のキーfile分析するファイル

リクエスト例

curl -X POST https://api.storyai.app/api/v1/ak/work/123/version \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "has_copylight=true" \
  -F "comment=第2稿。中盤の展開を修正" \
  -F "files=@story_v2.txt"

レスポンス例(200 OK)

{
  "id": 123,
  "title": "サンプル小説",
  "work_version_id": 457,
  "work_version": {
    "id": 457,
    "created_at": "2026-06-11T09:00:00.000Z",
    "user": { "id": 1, "name": "ユーザー名" }
  },
  "analysis_type_id": 13,
  "category_id": 4,
  "genre_id": 7,
  "url": "https://storyai.app/your-brand/works/123/detail"
}

エラー

  • 400: 入力値やファイル形式が正しくない
  • 404: 作品が無い、または他のブランドの作品
  • 413: ファイルが合計1000MBを超えた
  • 429: 今月の分析回数の上限に達した

再分析

POST /api/v1/ak/work/:work_id/reanalyze

作品の最新の版をもう一度分析します。分析に失敗したときや、古い結果を今の仕組みで分析し直したいときに使います。版は増えず、結果は上書きされます。分析回数は使いません。

リクエスト形式

application/json

名前型必須説明
only_nlp_analysisboolean○true: 追加自然言語分析(ワードクラウド・共起・コレスポンデンス)だけをやり直します。false: 感情分析を含めてすべてやり直します

Web画面の「再分析する」で「追加自然言語分析のみを再分析する」にチェックを入れた操作が true にあたります。

リクエスト例

curl -X POST https://api.storyai.app/api/v1/ak/work/123/reanalyze \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"only_nlp_analysis": false}'

レスポンス例(200 OK)

{ "message": "Re-analysis has been requested successfully." }

エラー

  • 400: only_nlp_analysis が真偽値でない
  • 404: 作品か最新の版が無い、または他のブランドの作品

分析状況の通知(WebSocket)

分析の完了や失敗を、問い合わせを繰り返さずに受け取れます。socket.io-client でベースURLに接続します。APIキーを渡せば、ほかのヘッダーは要りません。

import { io } from 'socket.io-client'

const socket = io('https://api.storyai.app', {
  auth: { apiKey: 'YOUR_API_KEY' },
})

socket.on('notification', (data) => {
  if (data.type === 'ANALYSIS_STATUS_UPDATE') {
    // data.id: 版(work_version)のID
    // data.status: 1 分析中 / 2 完了 / 3 失敗
    console.log(`WorkVersion ${data.id} status: ${data.status}`)
  }
})
  • 接続時にも、キーの利用条件(発行者の役割・ブランドのプラン)を確認します。満たさない場合は接続が拒否され、connect_error の err.data.reason に api_key_issuer_role_revoked か api_key_plan_not_allowed が入ります。接続中に条件が変わった場合は、次に接続するときから拒否されます。
  • 通知が届くのは、キーを発行した人がWeb画面で見られる作品だけです。APIで登録した作品は発行した人の作品になるため、通知が届きます。
  • 通知に含まれるのは版のIDと状況だけで、本文は含まれません。
  • 完了(status: 2)を受け取ったら、GET /api/v1/ak/work/:work_id で結果を取得してください。

エラーレスポンスの形

エラーのときは次の形で返ります。

{
  "error": "BADREQUEST",
  "message": "入力値が不正です: title: タイトルは必須です。"
}
ステータスerror主な原因
400BADREQUEST / VALIDATION_ERRORパラメータの誤り、対応していないファイル、組み合わせのルール違反
403FORBIDDENAPIキーが無い・無効・削除済み。発行者の役割やブランドのプランが利用条件を満たさない(reason 付き)
404NOTFOUND作品・版・プロジェクトが無い、または他のブランドのもの
413PAYLOADTOOLARGEファイルが合計1000MBを超えた(reason: upload_size_limit_exceeded)
429TOOMANYREQUESTS今月の分析回数の上限(今月の解析上限に達しました。)
500INTERNAL_SERVER_ERRORサーバー内部のエラー

413 のレスポンス例:

{
  "error": "PAYLOADTOOLARGE",
  "message": "Uploaded file exceeds the size limit.",
  "reason": "upload_size_limit_exceeded"
}

利用の制限

  • 月間の分析回数: 作品の登録と版の追加で1回ずつ使います。Web画面での分析と同じ回数(ブランド全体で共通)です。上限に達すると 429 になります。再分析と結果の取得では使いません。上限は契約内容によって異なります。
  • ファイルサイズ: 1回のリクエストで合計1000MBまでです。超えると 413 になります。
  • 分析にかかる時間: 分析は非同期で進みます。たくさんまとめて送ると、完了まで時間がかかります。

お問い合わせ

APIについてのご質問は、左メニューの「お問い合わせ」からご連絡ください。

関連記事