Typle API
アプリのAPI
API(Go)
OpenAPI
GitHub
アプリのAPI
API(Go)
OpenAPI
GitHub
  • アプリのAPI(/api/*)

    • 概要と共通事項
    • ワークスペースと記録
    • パックの共有
    • ログイン
    • 管理画面

概要と共通事項

Typle 本体(Web版と iPad・Mac・Android・Windows 版)が使う、アプリ自身のバックエンドです。Go の server/internal/web で、本番では Vercel の Go の関数(リポジトリ直下の api/index.go → server/vercel)として動きます。手元では server/cmd/typle-web(既定 127.0.0.1:8081)で起動し、npm run dev と E2E が使います。

スクリプトや別のアプリから読み書きする手元専用の /api/v1 は API(Go) を見てください。2つは internal/store・internal/workspace・internal/auth を共有します。

エンドポイント

メソッドとパスログイン内容
GET /api/health不要DB に5秒以内につながれば 200 { "status": "ok" }、だめなら 503 databaseUnavailable
GET /api/workspace要ワークスペース全体
PUT /api/workspace要ワークスペースを保存する
POST /api/workspace/records要記録を1件追加する
DELETE /api/workspace/records要記録を1件削除する
GET /api/shares要共有中のパックの一覧
PUT /api/shares要パックを共有する(共有中なら中身を取り直す)
DELETE /api/shares?pack=<パックのID>要共有をやめる
GET /api/shared?id=<共有のID>不要共有されたパックのファイル
GET /api/auth/session任意ログイン中のユーザーと、使えるログイン方法
GET /api/auth/signin—ログインを始める
GET /api/auth/callback/github・/api/auth/callback/ffpf—ログインから戻る先
POST /api/auth/token—アプリのログインのコードをトークンに換える
POST /api/auth/signout—ログアウト
POST /api/auth/local—開発用のログイン(有効なときだけ)
POST /api/auth/admin/signout—管理画面からログアウト
GET /api/admin/dashboard管理者管理画面の集計
GET /api/admin/users管理者ユーザーの一覧

共通事項

  • 本文はJSON(Content-Type: application/json; charset=utf-8)で、Cache-Control: private, no-store・Vary: Cookie を付けます。/api/shared だけは Cache-Control: no-store です。
  • エラーは { "error": "<キー>" } です。キーはアプリの errors のメッセージのキーで、画面が利用者の言語で表示します。
  • すべての応答に Content-Security-Policy: frame-ancestors 'none'; base-uri 'self'; object-src 'none'・X-Frame-Options: DENY・X-Content-Type-Options: nosniff・Referrer-Policy: strict-origin-when-cross-origin を付けます(Vercel では next.config.mjs のヘッダーが Go の関数に届かないため)。
  • HEAD は GET と同じに答えます(本文なし)。

エラー

ステータスキー状況
400emptyRequest書き込みに本文がない
400invalidWorkspace・invalidRecord・levelsConflict・listLimit など本文が不正(各エンドポイントを参照)
401loginRequiredログインしていない、またはセッションが無効にされた
401loginAccountChanged本文の accountId がログイン中のアカウントと違う(別の画面で別のアカウントにログインした)
403forbiddenRequest書き込みの Origin がアプリのものでない、または Content-Type が application/json でない
404notFound未知のパス
405methodNotAllowedそのパスで使えないメソッド。Allow に使えるメソッドを付ける
409conflict保存の revision が古い
413workspaceTooLarge本文が 1MiB を超える、または保存後が大きすぎる
503databaseUnavailableDBの障害(読み取り)
503workspaceSaveFailedDBの障害(書き込み)
503authUnavailableログインの設定がない、またはログインを始められない

503 で答えた失敗は、操作名(workspace.read など)を付けて Sentry に送ります(docs/sentry.md)。

認証

アカウントは github:<GitHubのユーザーID>、または FFPF ID でログインしたときのアカウントです。ログインの流れは ログイン を見てください。

  • Authorization ヘッダーがあるリクエストは、アプリ(iPad・Mac・Android・Windows)のものとして Authorization: Bearer <トークン> だけで判断し、Cookie は見ません。トークンは POST /api/auth/token で受け取ります。
  • ないリクエストはセッションの Cookie で判断します。名前は HTTPS では __Host- 付きで、HttpOnly・SameSite=Lax・Path=/ です。セッションはログインから30日で切れ、使っても延びません。
  • データを読み書きするリクエストは、そのたびにセッションが無効にされていないか(POST /api/auth/signout?everywhere=1 の後のログインか)をDBで確かめます。無効なら 401 loginRequired で、Cookie を消します。確かめられなければ 503 databaseUnavailable です。

書き込みの制限(CSRF 対策)

Cookie で書き込むリクエストは、Origin がアプリの origin(AUTH_URL。小文字、既定のポートなし)と同じで、Content-Type の ; より前が application/json のときだけ受け付けます。違えば 403 forbiddenRequest です。

ヒント

ほかのサイトのフォームはこの Content-Type を送れないため、他サイトから Cookie で保存されることはありません。アプリのトークンはブラウザーが勝手に送らないため、トークンのリクエストに Origin は要りません(Content-Type は要ります)。

コードの構成

場所内容
api/index.goVercel の Go の関数(1つだけ)。vercel.json の rewrites がバックエンドのパスをすべてここへ送り、server/vercel が元のパスで振り分ける
server/vercel環境変数から internal/web を組み立てる。/api/auth はセッションの応答が DB を待たないよう、DB を開かずに組み立てる
server/cmd/typle-web手元でこの API を起動するコマンド
server/internal/webHTTPハンドラー(web.go がパスの一覧)
server/internal/sessionCookie・トークン・ログイン途中の状態の署名
server/internal/authGitHub の OAuth と FFPF ID のクライアント
server/internal/storetyple_workspaces・typle_records・typle_shared_packs・typle_admins などの読み書き
server/internal/operation記録の追加・変更・削除(/api/v1 と共通)
GitHub でこのページを編集
次のページ
ワークスペースと記録