成分 / Seibun

認証

成分 API のデータルート(/v1/foods*/v1/food-groups/v1/nutrients)は 認証必須です。認証手段は用途に応じて 3 系統あります。

系統用途渡し方
セッション認証ダッシュボード / API キー管理Cookie(Better Auth)
API キー認証実 API コール(本利用)X-API-Key ヘッダ
お試しトークン認証なしで試す(お試し利用)Authorization: Bearer ヘッダ

公開のままなのは GET /v1/meta/healthz と発行エンドポイント POST /v1/trial-token だけです。 その他のデータルートは、API キーかお試しトークンが無いと一律 401 を返します。

セッション認証(Better Auth)

アカウント登録・ログインは Better Auth のメール+パスワードで行い、 /api/auth/* にマウントされています。API キーの発行・一覧・失効はセッションが必須です。

# サインアップ(成功すると即ログイン状態の Cookie が Set-Cookie で返る)
curl -i -X POST https://api.example.com/api/auth/sign-up/email \
  -H 'content-type: application/json' \
  -d '{"email":"[email protected]","password":"password1234","name":"me"}'
 
# サインイン
curl -i -X POST https://api.example.com/api/auth/sign-in/email \
  -H 'content-type: application/json' \
  -d '{"email":"[email protected]","password":"password1234"}'

サインイン/サインアップは IP 単位でブルートフォース対策のレート制限を受けます (クライアント IP は CF-Connecting-IP)。超過時は 429 を返します。

API キー認証(X-API-Key)

本利用では、セッションで発行した API キーをリクエストの X-API-Key ヘッダに付けます。 キーの tier は free で、レート制限の対象になります(レート制限)。

curl "https://api.example.com/v1/foods/01001" \
  -H "X-API-Key: fnk_xxxxxxxxxxxxxxxx"

キーの発行・一覧・失効

# 発行:平文キーはこの応答にのみ含まれる(保存されず、再表示もできない)
curl -X POST https://api.example.com/v1/keys -b cookies.txt \
  -H 'content-type: application/json' -d '{"name":"my key"}'
#   → { "id": "...", "name": "my key", "keyPrefix": "fnk_xxxx", "tier": "free", "key": "fnk_<平文>" }
 
# 一覧(平文は含まない)
curl https://api.example.com/v1/keys -b cookies.txt
 
# 失効(本人のキーのみ)
curl -X DELETE https://api.example.com/v1/keys/{id} -b cookies.txt

平文キーは保存されません。 発行時の応答に 1 度だけ含まれ、サーバ側は SHA-256 ハッシュのみを保持します。 控え忘れたら失効して再発行してください。他人のキーへの操作・存在しないキーへの失効は 404(存在を秘匿)です。

お試しトークン(Turnstile → Bearer)

認証なしで試したいときは、Cloudflare Turnstile を 1 回解いて短命トークン(HMAC 署名・有効 24 時間/生涯 30 リクエスト)を得ます。 得たトークンは Authorization: Bearer で渡します。tier は anon です。

# 1) お試しトークンを得る(Turnstile のウィジェットトークンを渡す)
curl -X POST https://api.example.com/v1/trial-token \
  -H 'content-type: application/json' -d '{"turnstileToken":"<widget token>"}'
#   → { "token": "<payload>.<sig>", "expiresAt": "..." }
 
# 2) トークンでデータルートを叩く
curl https://api.example.com/v1/food-groups \
  -H 'Authorization: Bearer <payload>.<sig>'

失敗は一律 401(理由秘匿)

認証の検証失敗は、理由(不在 / 失効 / 期限切れ / 形式不正など)を問わず HTTP では一律 401 に潰します。これは「どのキーが存在するか」といった情報を 攻撃者に与えないための設計です。エラーの形は エラー を参照してください。