# 使用状況詳細のエクスポート

> LMU AI 使用状況エクスポートガイド：ログインして JWT を取得し、ページネーション・期間指定・モデルフィルタリングに対応した /api/v1/usage を呼び出す。3 言語のサンプル付き。

URL: https://docs.lmuai.com/ja/docs/api/usage-export



アカウントとパスワードでログインして JWT を取得し、その JWT で `/api/v1/usage` を呼び出して、&#x2A;*完全なトークン使用状況詳細テーブル（コンソールの `/usage` ページと同一）** を取得します。

エクスポート・照合・エンタープライズ BI への読み込みを自動化する長時間実行のスクリプトに最適です。毎回手動で CSV をダウンロードする必要はありません。

<Callout type="info">
  **なぜ `sk-...` API キーで直接取得できないのか？** このキーはゲートウェイの業務コール（/v1/messages など）専用であり、アカウントレベルの詳細クエリを公開していません。これは意図的なセキュリティ設計です。キーが漏洩しても、請求全体がダンプされることを避けるためです。アカウントレベルのデータにはアカウント認証（JWT）を使用する必要があります。
</Callout>

***

## 1. API の概要 [#1-api-の概要]

| 項目            | 値                                                        |
| ------------- | -------------------------------------------------------- |
| ベース URL       | `https://api.lmuai.com`                                  |
| 認証            | `Authorization: Bearer <access_token>`（アカウントログインで得た JWT） |
| アクセストークンの有効期間 | **86400 秒（24 時間）**、refresh\_token で更新可能                  |
| レスポンス形式       | JSON。`code: 0` は成功、失敗時は `code != 0` で `message` フィールドあり  |
| 推奨用途          | 請求エクスポートの自動化、エンタープライズ BI への読み込み、照合スクリプト                  |

***

## 2. ステップ 1 — ログインして JWT を取得する [#2-ステップ-1--ログインして-jwt-を取得する]

### `POST /api/v1/auth/login` [#post-apiv1authlogin]

```http
POST /api/v1/auth/login HTTP/1.1
Content-Type: application/json

{
  "email": "your@email.com",
  "password": "your-password"
}
```

**レスポンス**（抜粋）：

```json
{
  "code": 0,
  "message": "success",
  "data": {
    "access_token": "eyJhbGc...",
    "refresh_token": "rt_756a220ffa...",
    "expires_in": 86400,
    "token_type": "Bearer",
    "user": { "id": 3, "email": "...", "balance": 1575.13 }
  }
}
```

以降のすべてのリクエストには `Authorization: Bearer <access_token>` を含めるだけです。

***

## 3. ステップ 2 — 使用状況詳細を取得する [#3-ステップ-2--使用状況詳細を取得する]

### `GET /api/v1/usage` [#get-apiv1usage]

```http
GET /api/v1/usage?page=1&page_size=200&start_date=2026-06-01&end_date=2026-06-23&timezone=Asia/Shanghai
Authorization: Bearer <access_token>
```

### クエリパラメータ [#クエリパラメータ]

| パラメータ          | 型      | 必須  | デフォルト        | 説明                                                                    |
| -------------- | ------ | --- | ------------ | --------------------------------------------------------------------- |
| `page`         | int    | いいえ | 1            | ページ番号。1 から開始                                                          |
| `page_size`    | int    | いいえ | 20           | 1 ページあたりの行数。200 を推奨（過大な値は切り詰められる）                                     |
| `start_date`   | string | いいえ | —            | 開始日 `YYYY-MM-DD`。`timezone` に従って解析される                                 |
| `end_date`     | string | いいえ | —            | 終了日（当日を含む）                                                            |
| `timezone`     | string | いいえ | UTC          | 日付パラメータの解析に使うタイムゾーン。例：`Asia/Shanghai`。**強く推奨**。指定しないと境界がローカル時刻と一致しません |
| `api_key_id`   | int    | いいえ | —            | 特定の 1 つのキーの詳細のみを表示（現在のユーザーに属している必要あり）                                 |
| `model`        | string | いいえ | —            | モデル ID でフィルタ（例：`claude-sonnet-5`）                                     |
| `stream`       | bool   | いいえ | —            | `true` でストリーミングのみ、`false` で非ストリーミングのみ                                 |
| `billing_type` | int    | いいえ | —            | 課金タイプ列挙（下記参照）                                                         |
| `sort_by`      | string | いいえ | `created_at` | ソートフィールド                                                              |
| `sort_order`   | string | いいえ | `desc`       | `asc` または `desc`                                                      |

### レスポンス構造 [#レスポンス構造]

```json
{
  "code": 0,
  "message": "success",
  "data": {
    "items": [ { /* UsageLog */ }, ... ],
    "total": 30423,
    "page": 1,
    "page_size": 200,
    "pages": 153
  }
}
```

<Callout type="warn">
  **ページネーションフィールドは `data` のトップレベルにあり、外側のエンベロープにはありません**。詳細配列は `data.items` にあります。`data` 自体は配列ではありません。
</Callout>

### 単一レコードのフィールドマッピング [#単一レコードのフィールドマッピング]

これらはコンソールの `/usage` ページの各列に厳密に対応します：

| コンソールの列             | JSON フィールド                                                                 | 型              | 説明                                                   |
| ------------------- | -------------------------------------------------------------------------- | -------------- | ---------------------------------------------------- |
| **モデル**             | `model`                                                                    | string         | 実際に課金されたモデル ID                                       |
| **推論の努力度**          | `reasoning_effort`                                                         | string \| null | `low` / `medium` / `high` / `xhigh` / `max`          |
| **インバウンドエンドポイント**   | `inbound_endpoint`                                                         | string \| null | クライアントが呼び出したパス。例：`/v1/messages`                      |
| **アップストリームエンドポイント** | `upstream_endpoint`                                                        | string \| null | 正規化されたアップストリームパス                                     |
| **リクエストタイプ**        | `request_type`                                                             | string         | `chat` / `stream` / `responses` / `messages` など      |
| **ストリーミング**         | `stream`                                                                   | bool           | ストリーミングだったかどうか                                       |
| **課金モード**           | `billing_mode`                                                             | string         | `token` / `per_request` / `image` / `subscription`   |
| **課金タイプ**           | `billing_type`                                                             | int            | 課金タイプ列挙                                              |
| **倍率**              | `rate_multiplier`                                                          | float          | このリクエストに適用されたチャネル倍率                                  |
| **入力トークン**          | `input_tokens`                                                             | int            |                                                      |
| **出力トークン**          | `output_tokens`                                                            | int            |                                                      |
| **キャッシュ作成**         | `cache_creation_tokens`                                                    | int            | すべてのキャッシュ書き込み                                        |
| **キャッシュ作成 5m**      | `cache_creation_5m_tokens`                                                 | int            | Anthropic の一時的な 5 分間ティア                              |
| **キャッシュ作成 1h**      | `cache_creation_1h_tokens`                                                 | int            | Anthropic の 1 時間ティア                                  |
| **キャッシュ読み取り**       | `cache_read_tokens`                                                        | int            |                                                      |
| **入力コスト**           | `input_cost`                                                               | float          | USD                                                  |
| **出力コスト**           | `output_cost`                                                              | float          | USD                                                  |
| **キャッシュ作成コスト**      | `cache_creation_cost`                                                      | float          | USD                                                  |
| **キャッシュ読み取りコスト**    | `cache_read_cost`                                                          | float          | USD                                                  |
| **定価合計**            | `total_cost`                                                               | float          | USD、倍率適用前                                            |
| **実際の課金額**          | `actual_cost`                                                              | float          | **= total\_cost × rate\_multiplier**。残高から実際に差し引かれる金額 |
| **初回トークンレイテンシ**     | `first_token_ms`                                                           | int \| null    | TTFT。ストリーミングで有効                                      |
| **総所要時間**           | `duration_ms`                                                              | int \| null    |                                                      |
| **時刻**              | `created_at`                                                               | ISO8601        | サーバー側の書き込み時刻                                         |
| **リクエスト ID**        | `request_id`                                                               | string         | トラブルシューティングとトレース用                                    |
| **画像生成**            | `image_count` / `image_size` / `image_output_tokens` / `image_output_cost` | —              | マルチモーダルリクエストのみ設定される                                  |
| **API Key**         | `api_key_id` + ネストされた `api_key` オブジェクト                                     | int + obj      |                                                      |
| **グループ**            | `group_id` + ネストされた `group` オブジェクト                                         | int + obj      |                                                      |

<Callout type="warn">
  各レコードにはネストされた `user` / `api_key` / `group&#x60; オブジェクトが含まれます（1 行あたり約 +1KB）。**`api_key` オブジェクトには完全なキーテキストが含まれるため、スクリプトのログ／スクリーンショット／CSV では必ずマスキングしてください**。一括エクスポートで、ネストされたオブジェクトが不要な場合は、`jq` を使うか、クライアント側でフィールドマッピングして必要なフィールドだけを残してください。
</Callout>

### 課金タイプ列挙（billing\_type） [#課金タイプ列挙billing_type]

| 値   | 意味                   |
| --- | -------------------- |
| `0` | トークンによる課金（大多数のリクエスト） |
| `1` | サブスクリプションのクォータから差し引き |

`billing_mode` フィールドは文字列版で、具体的な価格モデル（`token` / `per_request` / `image` / `subscription` など）を表します。より読みやすいため、分類には推奨されます。

***

## 4. トークンの更新 [#4-トークンの更新]

アクセストークンは 24 時間後に期限切れになります。更新方法は 2 通りあります：

### refresh\_token で更新する（スクリプト向けに推奨） [#refresh_token-で更新するスクリプト向けに推奨]

```http
POST /api/v1/auth/refresh
Content-Type: application/json

{
  "refresh_token": "rt_756a220ffa..."
}
```

新しい `access_token` を返します（通常は `refresh_token` もローテーションされます）。リフレッシュトークンは 30 日間有効です。

### 再ログインする [#再ログインする]

粗雑ですが単純で、使い捨てスクリプトに適しています。実行のたびに `/auth/login` を再度呼び出します。

***

## 5. コードサンプル [#5-コードサンプル]

### Bash + curl + jq [#bash--curl--jq]

```bash
#!/usr/bin/env bash
set -e

EMAIL="${EMAIL:?set EMAIL env}"
PASSWORD="${PASSWORD:?set PASSWORD env}"
BASE="https://api.lmuai.com"

JWT=$(curl -s -X POST "$BASE/api/v1/auth/login" \
  -H "Content-Type: application/json" \
  -d "{\"email\":\"$EMAIL\",\"password\":\"$PASSWORD\"}" \
  | jq -r '.data.access_token')

[ -n "$JWT" ] && [ "$JWT" != "null" ] || { echo "login failed" >&2; exit 1; }

START="2026-06-01"; END="2026-06-30"; TZ="Asia/Shanghai"; PAGE_SIZE=200

# Fetch page 1 to get total
META=$(curl -s "$BASE/api/v1/usage?page=1&page_size=$PAGE_SIZE&start_date=$START&end_date=$END&timezone=$TZ" \
  -H "Authorization: Bearer $JWT")
PAGES=$(echo "$META" | jq -r '.data.pages')

# CSV header
echo "created_at,model,request_type,input_tokens,output_tokens,cache_read_tokens,total_cost,actual_cost,duration_ms" > usage.csv

# Write page 1
echo "$META" | jq -r '.data.items[] | [.created_at, .model, .request_type, .input_tokens, .output_tokens, .cache_read_tokens, .total_cost, .actual_cost, .duration_ms] | @csv' >> usage.csv

# Fetch remaining pages
for ((p=2; p<=PAGES; p++)); do
  curl -s "$BASE/api/v1/usage?page=$p&page_size=$PAGE_SIZE&start_date=$START&end_date=$END&timezone=$TZ" \
    -H "Authorization: Bearer $JWT" \
    | jq -r '.data.items[] | [.created_at, .model, .request_type, .input_tokens, .output_tokens, .cache_read_tokens, .total_cost, .actual_cost, .duration_ms] | @csv' >> usage.csv
done

echo "saved $(wc -l < usage.csv) lines to usage.csv"
```

### Python [#python]

```python
import os, csv, requests

BASE = "https://api.lmuai.com"
EMAIL = os.environ["EMAIL"]
PASSWORD = os.environ["PASSWORD"]

def login() -> str:
    r = requests.post(f"{BASE}/api/v1/auth/login",
                      json={"email": EMAIL, "password": PASSWORD},
                      timeout=15)
    r.raise_for_status()
    data = r.json()
    if data["code"] != 0:
        raise RuntimeError(data.get("message", "login failed"))
    return data["data"]["access_token"]

def fetch_usage(jwt: str, **params):
    """Yield each row from paginated /usage endpoint."""
    page = 1
    while True:
        r = requests.get(f"{BASE}/api/v1/usage",
                         headers={"Authorization": f"Bearer {jwt}"},
                         params={**params, "page": page, "page_size": 200},
                         timeout=30)
        r.raise_for_status()
        d = r.json()["data"]
        for row in d.get("items", []):
            yield row
        if page >= d.get("pages", 1):
            return
        page += 1

if __name__ == "__main__":
    jwt = login()
    cols = ["created_at","model","request_type","input_tokens","output_tokens",
            "cache_read_tokens","total_cost","actual_cost","duration_ms"]
    with open("usage.csv", "w", newline="") as f:
        w = csv.writer(f); w.writerow(cols)
        for row in fetch_usage(jwt, start_date="2026-06-01", end_date="2026-06-30",
                               timezone="Asia/Shanghai"):
            w.writerow([row.get(c) for c in cols])
    print("done")
```

### Node.js [#nodejs]

```js
import fs from 'node:fs'

const BASE = 'https://api.lmuai.com'
const { EMAIL, PASSWORD } = process.env

async function login() {
  const r = await fetch(`${BASE}/api/v1/auth/login`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ email: EMAIL, password: PASSWORD }),
  })
  const j = await r.json()
  if (j.code !== 0) throw new Error(j.message || 'login failed')
  return j.data.access_token
}

async function* fetchUsage(jwt, params) {
  for (let page = 1; ; page++) {
    const q = new URLSearchParams({ ...params, page, page_size: '200' })
    const r = await fetch(`${BASE}/api/v1/usage?${q}`, {
      headers: { Authorization: `Bearer ${jwt}` },
    })
    const j = await r.json()
    for (const row of j.data.items) yield row
    if (page >= j.data.pages) return
  }
}

const jwt = await login()
const cols = ['created_at','model','request_type','input_tokens','output_tokens',
              'cache_read_tokens','total_cost','actual_cost','duration_ms']
const out = fs.createWriteStream('usage.csv')
out.write(cols.join(',') + '\n')
for await (const row of fetchUsage(jwt, {
  start_date: '2026-06-01', end_date: '2026-06-30', timezone: 'Asia/Shanghai',
})) {
  out.write(cols.map(c => JSON.stringify(row[c] ?? '')).join(',') + '\n')
}
console.log('done')
```

***

## 6. 実践上の注意 [#6-実践上の注意]

1. **大量のページ送りの間にディレイを入れる** — N ページを連続でめくる場合、レート制限を回避するために `sleep(0.1~0.3s)` を推奨します。
2. **一度に長すぎる期間を取得しない** — 数か月にまたがり数百万行にわたると遅くなります。月単位でスライスするほうが安定します。
3. **`page_size` は 200 を推奨** — サーバーは過大な値を切り詰めます。
4. **帯域を節約する** — ネストされた `user` / `api_key` / `group` オブジェクトは大きいため、詳細行だけが必要なら `jq` でクライアント側でフィルタしてください。
5. **よくあるエラー**：
   * `401` JWT 期限切れ → `refresh_token` で更新するか再ログイン
   * `403` 権限のないアクセス（例：`api_key_id` で他人のキーをクエリ）→ そのキーが現在のユーザーに属していることを確認
   * `400` パラメータ不正（例：`start_date` の形式）→ `YYYY-MM-DD` + `timezone` が有効か確認

***

## 7. セキュリティに関する推奨事項（必読） [#7-セキュリティに関する推奨事項必読]

<Callout type="warn">
  **あなたのアカウントパスワード + JWT は、アカウントへのフルアクセスと同等です。** エクスポートをスクリプト化する前に、以下を確認してください：
</Callout>

| 項目           | 推奨事項                                                                                                                        |
| ------------ | --------------------------------------------------------------------------------------------------------------------------- |
| 認証情報の管理      | password / access\_token / refresh\_token を git や CI ログに**絶対に**コミットしないこと。環境変数、シークレットマネージャー、または `.env`（`.gitignore` 付き）を使用する |
| アカウントのセキュリティ | **TOTP 二要素認証**の有効化を強く推奨します（アカウント設定で有効化）。この API はログイン時の TOTP 検証に対応しています                                                      |
| 定期的なローテーション  | アカウントパスワードを定期的に変更し、refresh\_token は期限切れ後すぐにローテーションする                                                                        |
| 異常の監視        | アカウントの「最終ログイン時刻／IP」を監視し、見慣れないデバイスを見つけたらすぐにパスワードを変更する                                                                        |
| フィールドのマスキング  | レスポンス内のネストされた `api_key.key`（完全な sk-... テキスト）、`user.email`、`refresh_token` はすべて機密フィールドです。**出力／ログ／CSV の前にマスキングしてください**        |
| 最小権限         | 分離できるなら、エクスポートスクリプト専用のサブアカウントを使用し（組織がマルチアカウント構成の場合）、メインアカウントの長期的な露出を避ける                                                     |
| エラーリトライ      | ログイン失敗時に無限にリトライしないこと。リスク管理を容易にトリガーします。指数バックオフを推奨します                                                                         |

***

## 8. フィールドクイックリファレンス [#8-フィールドクイックリファレンス]

CSV の列マッピングに便利です：

| ラベル             | フィールド                         | 単位           |
| --------------- | ----------------------------- | ------------ |
| モデル             | `model`                       | —            |
| 推論の努力度          | `reasoning_effort`            | —            |
| インバウンドエンドポイント   | `inbound_endpoint`            | path         |
| アップストリームエンドポイント | `upstream_endpoint`           | path         |
| リクエストタイプ        | `request_type`                | enum         |
| ストリーミング         | `stream`                      | bool         |
| 課金モード           | `billing_mode`                | enum         |
| 課金タイプ           | `billing_type`                | int          |
| 倍率              | `rate_multiplier`             | float        |
| 入力トークン          | `input_tokens`                | int          |
| 出力トークン          | `output_tokens`               | int          |
| キャッシュ読み取りトークン   | `cache_read_tokens`           | int          |
| キャッシュ書き込みトークン   | `cache_creation_tokens`       | int          |
| キャッシュ書き込み 5m    | `cache_creation_5m_tokens`    | int          |
| キャッシュ書き込み 1h    | `cache_creation_1h_tokens`    | int          |
| 入力コスト           | `input_cost`                  | USD          |
| 出力コスト           | `output_cost`                 | USD          |
| キャッシュ作成コスト      | `cache_creation_cost`         | USD          |
| キャッシュ読み取りコスト    | `cache_read_cost`             | USD          |
| 定価合計            | `total_cost`                  | USD          |
| 実際の課金額          | `actual_cost`                 | USD          |
| 初回トークン          | `first_token_ms`              | ms           |
| 総所要時間           | `duration_ms`                 | ms           |
| 時刻              | `created_at`                  | ISO8601      |
| リクエスト ID        | `request_id`                  | string       |
| グループ            | `group_id` / `group.name`     | int / string |
| API Key         | `api_key_id` / `api_key.name` | int / string |
