メインコンテンツへスキップ

APIの概要

Log Query API は、アカウント内で実行されたすべての API 呼び出しの詳細記録を返します。 これには、使用されたモデル、実際に請求された金額、レイテンシ、呼び出しがストリーミングだったかどうか、 および呼び出しが失敗したときのエラーコードが含まれます。 これは 残高照会 API を補完するものです。残高照会では残っているクレジット量がわかり、 ログ照会ではそれがどこに使われたかがわかります。 代表的なユースケースは3つあります:

自動照合

期間ごと、またはモデルごとに実際の支出を集計し、自社の課金と照合する

セルフサービスのトラブルシューティング

失敗したリクエストのエラーコードを確認し、パラメータの問題か上流側の問題かを見分ける

サポートチケット

正確な呼び出しを特定できるよう、request_id をサポートに提供する
ログはコンソールの Logs ページでも確認できます。この API は同じデータへのプログラム用エントリーポイントであり、自動照合、定期エクスポート、または独自の監視への取り込みを目的としています。手動で確認する場合はコンソールを使用してください — 呼び出し記録の確認方法をご覧ください。
推奨される使い方: 1日1回同期し、ログを自分のデータベースに保存してください。この API は、リアルタイムで繰り返し照会する用途ではなく、定期的な増分エクスポート向けに設計されています:
  • 1日1回実行し、前回の同期以降に作成されたレコードだけを自分の データベースまたは CSV ファイルに取り込んでください
  • 1回のリクエストでより多く取得してください: pageSize は 5000 まで対応しています — デフォルトの 10 のままにしないでください。 この落とし穴については下のパラメータ注記を参照してください
  • 一括バックフィルには使わないでください(3か月分を一度に取得するなど)。また、 UI でのライブページネーションにも使わないでください
  • 同時に呼び出さないでください — ページは逐次的に、ページ間隔をおおむね1秒空けて取得してください
  • 各期間は1日以内に抑え、高ボリュームのアカウントでは時間単位で分割してください
その理由は下記の Performance Notes セクションをご覧ください。期間が古いほど、ページネーションが深いほど、 各リクエストのコストは高くなります。サーバー側の制限を超えるとエラーが返り、 同じパラメータで再試行しても速くはなりません。このページの Python の例はすでに このパターンに従っており、そのまま日次の cron ジョブに組み込めます。

パーソナルアクセス token の取得方法

ログクエリ API はパーソナルアクセス token(nap_で始まります)で認証を行いますが、これは API キーとは異なります(本ページ末尾の「重要な注意事項」を参照してください)。
1

Personal Access Tokens を開く

api.apiyi.com/account/profile のプロフィールページに移動します。アカウントオプションで、Personal Access Tokens → Create Token をクリックします。
2

権限を選択する

この API に必要なのは Usage & personal records · Read のみです。日次の定期実行ジョブの場合は、長めの有効期限を選択してください。デフォルトは30日間で、token の有効期限が切れるとスクリプトは 401 を受け取ります。
3

IP許可リストを設定する(任意)

同期スクリプトを固定 IP のサーバーで実行する場合に推奨されます。許可リストは作成後に編集できません。まずは許可リストなしでスクリプトが正常に動作することを確認し、その後、許可リストを設定した本番用 token を別途作成してください。
パーソナルアクセス token の作成:名前、有効期限、IP許可リスト、権限
レガシーのシステム tokens は2026-11-11 (UTC+8)に廃止される予定です。「アカウントオプション - System Token」で生成された AccessTokens はその日まで引き続き動作します。その日付を過ぎると 401 ACCESS_TOKEN_LEGACY_RETIRED を返します。 利用状況を確認した上で期日を延長する可能性もありますが、今すぐパーソナルアクセス token へ切り替えることをお勧めします。APIYI_SYS_TOKEN の値を変更するだけで、以降のスクリプトはそのまま動作します。 パーソナルアクセス token とは?を参照してください。

API情報

リクエストの詳細

リクエストヘッダー

Query Parameters

Treat the time window as required.The endpoint does not actually enforce these two parameters — a call without them succeeds. But omitting them tells the server to search your account’s entire history backwards from the newest record, and accounts with a large call history will hit the server-side limit and get an error rather than a slow response.This is the easiest mistake to make on this page and the one with the most direct consequences. We mark it Required not because the server rejects the call, but because the failure mode is hard to recognize: it does not report a missing parameter, it reports a timeout.
pageSize is the only camelCase parameter on this endpoint. Spelling it page_size is silently ignored.Every other parameter (model_name, token_name, start_timestamp, request_id, …) uses snake_case — this one does not. Getting it wrong does not raise an error: the server treats the parameter as absent and falls back to the default of 10 records per page, which is easy to misread as “the cap is 10” or “I only made 10 calls in this period.”
Going above 5000 does raise a clear error rather than truncating silently.
Raising pageSize is the single most effective optimization for this endpoint. At 10 records per page, an account making 500,000 calls a day needs 50,000 requests; at 5000 per page it needs 100. Two orders of magnitude fewer requests, and the pagination offset drops with it — see Performance Notes below.A 5000-record page measures roughly 700 KB gzipped and takes about 2.5 seconds. If bandwidth or memory is tight, 1000 is a comfortable middle ground.

パフォーマンスに関する注意

単一リクエストのコストは固定ではありません。それは 3 つの要素に依存します。これらのルールに従えば API は高速ですが、無視するとサーバー側の 60 秒クエリ制限に達し、エラーが返ります。 実践的なルールは 4 つあります。
  1. start_timestamp と end_timestamp を必ず渡してください。 ウィンドウを省略するのは、この API を呼び出すうえで最も高くつく方法です。
  2. pageSize を引き上げてください。 これは簡単です。1ページあたり 10 件から 1000〜5000 件にすると、リクエスト数を 2 桁減らせて、オフセットもそれに伴って小さくなります。
  3. オフセットを深くするのではなく、ウィンドウを狭めてください。 コストがかかるのは「どのページか」ではなく、「そこにたどり着くまでに何件スキップしたか」であり、それは超線形に増えます。1つの大きなウィンドウを最後までページングするのではなく、24 個の 1 時間ウィンドウに分割し、各ウィンドウを offset 0 から再開するようにしてください。
  4. 履歴は一度だけバックフィルして保存し、その後は増分だけを同期してください。 古いデータは最新データよりクエリコストがはるかに高いため、同じ履歴を何度も読み直すのは完全な無駄です。
pageSize=1000 でもウィンドウが数十ページかかるなら、その期間の呼び出し量は多いということです — ウィンドウを半分に分け、それぞれを別々に取得してください。これは、さらに深くページングするよりずっと速いです。下の Python 例にある MAX_PAGES 定数は、まさにこれを行っています。

60 秒は厳格な上限で、それを超えるとエラーが返ります

サーバーは単一クエリを 60 秒 に制限しています。それを過ぎると遅い応答が返るのではなく、 エラーが返り、そこまでに費やした時間ではデータは一切得られません。 次の 3 つのパターンは、これを引き起こしやすいです。再試行して期待するのではなく、最初から避けてください。 同じパラメータで再試行しても速くはなりません。単にさらに 60 秒かかるだけです。 正しい対応は、時間ウィンドウを狭めるか、pageSize を引き上げてページングを減らすことです — どちらにしても、1 回の呼び出しでサーバーが処理するデータ量を減らしてください。

ログタイプ

支出額を計算する際は、必ず type=2 を渡してください。 これを指定しない場合、チャージおよびシステム付与の記録も 返されます。これらの quota は0ですが、model_name と token_name も空であるため、単純に 合計したりモデルごとにグループ化したりすると、誤った結果になります。アカウントで非同期動画モデル(Seedance など)を使用している場合は、type=11 も取得してください。タスクが失敗すると、その事前課金分が負の返金エントリとして戻されるため、type=2 だけを合計すると、その事前課金分が支出としてカウントされます。

レスポンス詳細

成功レスポンスの例

主要レスポンスフィールド

otherフィールドにはネストされたオブジェクトではなくJSON文字列が格納されるため、2回目のパースが必要です (Pythonではjson.loads()、JavaScriptではJSON.parse())。これにはbilling_type、 request_path(実際に呼び出されたエンドポイント)、group_ratio、model_ratio、およびusageが含まれます。非同期動画タスクの精算エントリには、final_quota(タスクの最終合計)、original_quota (送信時に行われた事前課金)、adjustment_quota(このエントリの差額)およびactual_tokensも含まれます。詳細は以下のFAQを参照してください。

クォータ換算

換算ルール

500,000クォータ = $1.00 USD
計算式: USD金額 = quota ÷ 500,000 例:
  • quota: 7500 → $0.015 USD
  • quota: 22500 → $0.045 USD
  • quota: 18 → $0.000036 USD
これは残高照会APIで使用される換算と同じです。 そのため、両者は直接対応します。

エラーレスポンス

HTTP 401 - 認証失敗

原因: tokenが無効、期限切れ、または削除されているか、APIキー(sk-で始まるもの)が誤ってパーソナルアクセス tokenとして使用されています。アカウントのパスワード、2要素認証、またはパスキーを変更すると、すべてのパーソナルアクセス tokenが無効化されます。 解決策: コンソールで新しいパーソナルアクセス tokenを作成してください。 他の2つの401レスポンスには明示的なメッセージが含まれています:

HTTP 403 - 権限拒否

原因: パーソナルアクセス tokenに Usage & personal records · Read がありません。その権限を持つ新しい tokenを作成してください。権限は作成後に変更できません。

コード例

cURLの例(単一ページ、クイック確認)

--compressedオプションは必須です。APIがgzip圧縮されたコンテンツを返すためです。 これがないと文字化けした出力になります。
これを使用してtokenが機能することを確認してください。本格的な照合を行う場合は、以下の日次同期スクリプトを使用してください。

Python の例: 日次の増分同期(cron ジョブとしてすぐ使えます)

これは 推奨される標準的な使い方 です。1日1回実行し、前回の同期以降に新しくなったものだけを取得して、 ローカルの SQLite データベースに書き込みます。再実行しても安全です(レコードは request_id で重複排除されます)。また、途中で中断された実行は停止したところから再開されます。
サンプル出力:
データがローカルにあれば、モデル別、日別、token 別など、必要なあらゆる集計はすべて ご自身のデータベースに対して実行されるため、そのために再び API に問い合わせる必要はありません。これははるかに高速で、 すでに保持期間を過ぎて消えたデータが欲しくなる問題も回避できます。

Node.js の例(単一の時間枠)

考え方は同じです。1時間ごとに分割し、順番にページングし、ページネーションが深くなりすぎたら時間枠を縮小します。
Python の requests ライブラリと Node.js の fetch API はどちらも gzip を自動的に展開するため、 その場合は追加の設定は不要です。明示的な --compressed フラグが必要なのは curl のみです。

Common Scenarios

日次照合(推奨される方法)

上の Python スクリプトを 1 日に 1 回実行するようにスケジュールし、ログをローカルデータベースに保存します。必要な内訳——総支出、モデル別、token別——はすべて、自分のデータベースに対する SQL クエリで取得できます。 これが適切な形である理由は 3 つあります。ローカルのクエリは高速であること、ログの保持期間の影響を受けないこと、そして古い履歴を繰り返し読み直すことで API の速度を落とさずに済むことです。 1 つの model のレコードだけを同期するには、リクエストに model_name パラメータを追加します。

失敗した呼び出しの見つけ方

データがローカルにあれば、自分のテーブルを直接クエリします:
ゲートウェイによって拒否されたリクエスト(無効なパラメータなど)は、quota が 0 であり、 課金されません。ログ内の error_code を使うと、「呼び出しが失敗した」のか 「呼び出しは成功したが、結果が気に入らなかった」のかを分けられます。

サポートに渡すリクエスト ID の指定

ログ内で問題のある呼び出しを見つけ、サポートに request_id を伝えてください。これにより、 エンドツーエンドで正確なリクエストを特定できるため、「ある model への呼び出しが ある時刻の前後で失敗した」と説明するより、はるかに効率的です。

よくある質問

まず次の3点を確認してください。遅いクエリのほとんどは、これらのいずれかが原因です。
  1. start_timestamp と end_timestamp を渡していますか? 時間範囲を省略することは、この API を呼び出すうえで 最もコストの高い方法です。サーバーが履歴全体を検索します。
  2. 範囲が古すぎる、または広すぎませんか? 1か月前のデータをクエリするコストは、 昨日のデータをクエリするよりはるかに高くなります。範囲は1日未満に保ち、大量の場合は時間単位で分割してください。
  3. p が数千に達していませんか? ページネーションのコストは超線形に増加します。対処方法は、 各時間範囲が数十ページだけで済むよう時間範囲を縮小することであり、1つの大きな範囲内で さらに深くページングすることではありません。
同じパラメータで再試行しても速くなりません。 タイムアウトした場合は、同一のリクエストを繰り返すのではなく、 上記のようにパラメータを調整してください。単純な再試行では、再び待つだけです。
10回中9回は、パラメータが snake_case の page_size として記述されています。正しいスペルは camelCase の pageSize です。これはこの エンドポイントで唯一の camelCase パラメータです。ほかのすべて(model_name、token_name、start_timestamp、…)は snake_case であるため、間違えやすくなっています。エラーは発生せず、サーバーはこの パラメータが存在しないものとして扱い、1ページあたり10レコードにフォールバックします。
最大値は5000で、これを超えると明確なエラーが返されます。大量の場合でも、レスポンスが空の配列を返すまで ページネーション(p=0、p=1、…)を行う必要があります。上記の Python と Node.js の例では、すでにこの処理がカプセル化されています。
はい。request_id を渡すと、そのレコードのみが返されます。
特定の1件の呼び出しを調査する場合、これは時間範囲を取得して 自分でフィルタリングするよりはるかに高速です。
いいえ。一部のフィールドにはプラットフォーム内部の情報が格納されており、通常の アカウントの観点では空またはゼロになります。これは想定どおりであり、照合やトラブルシューティングに必要な フィールドには影響しません。quota、model_name、error_code、および request_id はすべて完全に設定されています。
API はグループの識別子を返しますが、コンソールにはグループのラベルが表示されます。 これらは異なる場合があります。たとえば、API は default を返しますが、コンソールには Default と表示されます。完全なマッピングは、公開エンドポイント https://api.apiyi.com/api/pricing の usable_group フィールドから取得できます。このフィールドは識別子をラベルにマッピングします。レポートを コンソールと一致させたい場合は、このマッピングを自身で適用してください。
quota を使用してください。これは呼び出しに対して実際に差し引かれた金額であり、 照合に適した唯一のフィールドです。画像生成や動画生成などの呼び出しごとに価格設定されるモデルでは、 レスポンス内の token 数が価格設定に関与しないプレースホルダー値である場合があります。 これらのモデルは、other.billing_type に by_count を報告します。
直近30日間のみクエリ可能であることを前提に、同期ロジックを設計してください。実際にはクエリ可能な範囲は通常もっと長いですが、保持については一切保証しません。 これはログクリーンアップポリシーに応じて変更され、その変更は個別に告知されません。30日間を 計画上の下限として扱えば、そのポリシーが変わっても照合処理は壊れません。また、範囲が古いほどクエリのコストは高くなります。データがまだ存在していても、 取得にははるかに時間がかかります。したがって、適切なパターンは1日に1回、自身のデータベースへ同期することであり、履歴分析は ローカルで実行してください。長期間保持する必要があるものは、自身でアーカイブしてください。この API から後で取得できることに依存しないでください。
理由: API は gzip 圧縮されたコンテンツ(Content-Encoding: gzip)を返しますが、curl が それを展開していません。解決策: --compressed フラグを追加してください。
Python の requests ライブラリと Node.js の fetch API は自動的に展開します。
非同期動画タスク(Seedance など)は「送信時に事前チャージし、完了時に差額を精算する」方式で課金されるため、 1本の動画につき2件のエントリが残ります。事前チャージ(completion_tokens が0で、request_id が存在)と精算 (completion_tokens が実際の使用量、request_id は空、quota は差額のみ)です。 どちらのエントリにも task_id は含まれないため、この API ではエントリをタスクに対応付けられません。動画の実際のコストを取得するには、task_id でタスク API をクエリしてください。その quota は2件のエントリの合計です。
そのページングパラメータは snake_case の page_size であり、p は1から始まる点に注意してください。これはこの API と逆です。 失敗したタスクでも quota には事前チャージが表示されますが、実際のコストは0です(ログには負の type=11 の返金エントリが含まれます)。 詳しい手順:task_id で Seedance 動画の実際のコストを検索する方法。
いいえ。ログクエリのエンドポイントはクォータを消費しません。

重要な注意事項

パーソナルアクセス token は API キーではなく、両者に互換性はありません
  • API キー(sk- で始まるもの)は /v1/* の推論エンドポイント用です。これを /api/log/self に対して使用すると 401 が返されます。
  • パーソナルアクセス token(nap_ で始まるもの)は /api/* の管理エンドポイント用であり、モデルを呼び出すことはできません。
照合スクリプトの token には**「Usage & personal records · Read」のみ**を付与してください。設定できるからといって、他の権限を追加しないでください。コード内ではなくシークレットマネージャーに保管し、リポジトリには絶対にコミットせず、有効期限が切れる前に置き換えてください。
ログのレスポンスにはご自身の API キーが平文で含まれています各ログレコードには、呼び出しを行った token に関する情報が含まれています。生のログレスポンスを公開の場に貼り付けたり、スクリーンショットを共有したり、第三者に渡したりしないでください — エクスポートする前に機密フィールドを削除してください。特に、この平文には sk- プレフィックスが含まれていないため、一般的なシークレットスキャナーでは検出されない可能性があります。自動チェックに頼って検出を任せきりにしないでください。
推奨される呼び出しパターン
  • 1日1回同期する — より頻繁に実行する必要はありません。各実行では新規データのみを取得します
  • デフォルトの 10 ではなく、1000〜5000 の pageSize を使用する — これは他の要素すべてを合わせたものよりも重要です
  • ページ間は約1秒の間隔を空けてシリアルに呼び出し、決して同時に実行しないでください
  • クライアントのタイムアウトは 60 秒に設定してください(サーバー側のクエリ制限も 60 秒です)
  • 各時間ウィンドウは 1 日以下に抑えてください。データ量が多いアカウントの場合は、1時間ごとに分割してください
  • タイムアウトが発生した場合は、再試行する前にウィンドウを狭めてください — 同じ条件で再試行しても処理速度は上がりません
これらは厳格なクォータではありません。単にご自身のデータを最速で取り出すための方法です。このパターンに従うことで、一般的なアカウントであれば 1 日分のログ全体を 1 分未満で同期でき、1 日に数十万回の呼び出しを行う大規模なアカウントであっても、わずか約 100 回のリクエストで済みます。
将来的に、このエンドポイントにレート制限を導入する権利を留保します。現時点ではレート制限は設定されていませんが、「無制限」を前提とした定期ジョブの設計は行わないでください。上記のパターン(1 日 1 回、シリアル実行、大きな pageSize)に従っていれば、将来レート制限が導入されても影響を受けることはありません。

関連ドキュメント