Trimix API — 利用上の注意事項
Trimix API を安全・安定して利用するための注意事項をまとめています。すべての API に共通する内容です。
目次
1. APIキーの安全な管理(最重要)
APIキーが漏洩すると、第三者があなたのプランを消費したり不正なリクエストを送ったりする可能性があります。以下のルールを必ず守ってください。
BFFパターンの推奨(最重要)
フロントエンド(ブラウザ)に直接 APIキーを埋め込まないでください。
React・Vue・Next.js などのクライアントサイドコードに APIキーを書くと、ブラウザの開発者ツールやソースコードから誰でも取得できてしまいます。
推奨する構成(BFF パターン):
ブラウザ ─── あなたのサーバー(APIキーを保持) ─── Trimix API
サーバーサイドで APIキーを保持し、フロントエンドはあなた自身のサーバーを経由して Trimix API を呼び出す構成を取ってください。
コードサンプル: Next.js API Routes(TypeScript)
// pages/api/invoice/[registrationNumber].ts
// このファイルはサーバーサイドで実行されるため、APIキーを安全に扱えます
import type { NextApiRequest, NextApiResponse } from "next";
const TRIMIX_API_KEY = process.env.TRIMIX_API_KEY;
const TRIMIX_API_BASE_URL = "https://api.trimix-data.io";
export default async function handler(
req: NextApiRequest,
res: NextApiResponse,
) {
if (!TRIMIX_API_KEY) {
return res.status(500).json({ error: "APIキーが設定されていません" });
}
const { registrationNumber } = req.query;
try {
const response = await fetch(
`${TRIMIX_API_BASE_URL}/v1/invoice-issuers/${registrationNumber}`,
{
headers: {
"x-api-key": TRIMIX_API_KEY,
"Content-Type": "application/json",
},
signal: AbortSignal.timeout(10_000), // 10秒タイムアウト
},
);
if (!response.ok) {
const error = await response.json();
return res.status(response.status).json(error);
}
const data = await response.json();
return res.status(200).json(data);
} catch (error) {
return res.status(500).json({ error: "APIリクエストに失敗しました" });
}
}
フロントエンドからは /api/invoice/T1234567890123 のように自分のサーバーを経由して呼び出すだけで、APIキーをブラウザに渡す必要がありません。
コードサンプル: Python(FastAPI)
# main.py
# サーバーサイドで動作する FastAPI アプリケーション
import os
import httpx
from fastapi import FastAPI, HTTPException
app = FastAPI()
TRIMIX_API_KEY = os.environ["TRIMIX_API_KEY"] # 環境変数から取得
TRIMIX_API_BASE_URL = "https://api.trimix-data.io"
@app.get("/invoice/{registration_number}")
async def get_invoice_issuer(registration_number: str):
async with httpx.AsyncClient(timeout=10.0) as client:
response = await client.get(
f"{TRIMIX_API_BASE_URL}/v1/invoice-issuers/{registration_number}",
headers={"x-api-key": TRIMIX_API_KEY},
)
if response.status_code != 200:
raise HTTPException(
status_code=response.status_code,
detail=response.json(),
)
return response.json()
コードサンプル: curl(動作確認用)
# curl はローカル開発・動作確認用途に限定してください
# スクリプトに APIキーをハードコードしないこと
export TRIMIX_API_KEY="your_api_key_here"
curl -s \
-H "x-api-key: ${TRIMIX_API_KEY}" \
-H "Content-Type: application/json" \
"https://api.trimix-data.io/v1/invoice-issuers/T1234567890123"
環境変数での管理
APIキーは環境変数で管理してください。ソースコードへのハードコードは禁止です。
# .env(ローカル開発用)
TRIMIX_API_KEY=your_api_key_here
// Node.js での読み込み
const apiKey = process.env.TRIMIX_API_KEY;
if (!apiKey) {
throw new Error("TRIMIX_API_KEY が設定されていません");
}
本番環境では AWS Secrets Manager・Vault・各クラウドの Secret Manager などを使って安全に管理してください。
Git へのコミット禁止
.env ファイルや APIキーを含むファイルを Git リポジトリにコミットしないでください。
# .gitignore に必ず追加する
.env
.env.local
.env.*.local
*.secret
誤ってコミットした場合は、APIキーが漏洩したと見なしてすぐにローテーションしてください(履歴から削除しても安全とは言えません)。
ログへの出力禁止
APIキーをログに出力しないでください。ログ集約サービス(Datadog・CloudWatch 等)に送信されると、閲覧権限のある全員にキーが露出します。
// 悪い例
console.log(`APIキー: ${apiKey}`);
logger.info({ apiKey }, "リクエスト送信");
// 良い例
logger.info("Trimix API リクエスト送信");
APIキーのローテーション
定期的なローテーション(3〜6ヶ月を推奨)と、漏洩の疑いが生じた際の即時ローテーションを実施してください。
ダッシュボードから新しいキーの発行・旧キーの失効ができます: https://trimix-data.io/dashboard
他者との共有禁止
APIキーは発行したアカウントのプランに紐づいています。チームで利用する場合はメンバーごとに個別のアカウントを作成し、それぞれのキーを使ってください。
2. レート制限
制限超過時の挙動
レート制限を超えたリクエストには HTTP 429 が返ります。レスポンスには Retry-After ヘッダーと RFC 7807 形式のエラーボディが含まれます。
HTTP/1.1 429 Too Many Requests
Retry-After: 30
Content-Type: application/problem+json
{
"type": "https://api.trimix-data.io/errors/rate-limit-exceeded",
"title": "レート制限を超過しました",
"status": 429,
"detail": "リクエスト数が上限を超えました。30秒後に再試行してください。",
"instance": "/v1/invoice-issuers/T1234567890123"
}
レート制限の上限値はプランによって異なります。詳細は ダッシュボード を参照してください。
指数バックオフの実装
429 を受け取った場合は、Retry-After ヘッダーの秒数を待機してから再試行してください。Retry-After がない場合は指数バックオフを使ってください。
// 指数バックオフ付きリトライ(TypeScript)
async function fetchWithRetry(
url: string,
options: RequestInit,
maxRetries = 3,
): Promise<Response> {
for (let attempt = 0; attempt <= maxRetries; attempt++) {
const response = await fetch(url, options);
if (response.status === 429) {
if (attempt === maxRetries) {
throw new Error("レート制限: 最大リトライ回数に達しました");
}
// Retry-After ヘッダーがあればその秒数、なければ指数バックオフ
const retryAfter = response.headers.get("Retry-After");
const waitMs = retryAfter
? parseInt(retryAfter, 10) * 1000
: Math.min(1000 * 2 ** attempt, 30_000); // 最大30秒
await new Promise((resolve) => setTimeout(resolve, waitMs));
continue;
}
return response;
}
throw new Error("予期しないエラーが発生しました");
}
バッチ処理時の注意
複数の T番号を一括検証する場合など、大量のリクエストを送る際は並列数を制限してください。
// 並列数を制限したバッチ処理(TypeScript)
async function batchFetch(
registrationNumbers: string[],
concurrency = 5, // 同時リクエスト数を絞る
): Promise<unknown[]> {
const results: unknown[] = [];
for (let i = 0; i < registrationNumbers.length; i += concurrency) {
const chunk = registrationNumbers.slice(i, i + concurrency);
const chunkResults = await Promise.all(
chunk.map((num) =>
fetchWithRetry(
`https://api.trimix-data.io/v1/invoice-issuers/${num}`,
{
headers: { "x-api-key": process.env.TRIMIX_API_KEY! },
},
).then((r) => r.json()),
),
);
results.push(...chunkResults);
}
return results;
}
3. エラーハンドリング
エラーレスポンス形式
Trimix API のエラーレスポンスは RFC 7807 (Problem Details for HTTP APIs) 形式に準拠しています。
{
"type": "https://api.trimix-data.io/errors/not-found",
"title": "リソースが見つかりません",
"status": 404,
"detail": "登録番号 T9999999999999 の適格請求書発行事業者は登録されていません。",
"instance": "/v1/invoice-issuers/T9999999999999"
}
| フィールド | 説明 |
|---|---|
type | エラーの種類を示す URI |
title | エラーの概要(人間が読める文字列) |
status | HTTP ステータスコード |
detail | エラーの詳細説明 |
instance | エラーが発生したリクエストパス |
リトライ可否の判断基準
| ステータスコード | 種別 | 対応方法 |
|---|---|---|
5xx | サーバーエラー | 指数バックオフでリトライ可(一時的な障害の可能性) |
429 | レート制限 | Retry-After ヘッダーの秒数待機後にリトライ |
4xx(429除く) | クライアントエラー | リトライ不可。リクエスト内容(パラメータ・認証情報等)を修正する |
// リトライ判断ロジック(TypeScript)
function shouldRetry(statusCode: number): boolean {
// 5xx はリトライ可
if (statusCode >= 500) return true;
// 429 はリトライ可(Retry-After を守ること)
if (statusCode === 429) return true;
// その他の 4xx はリトライ不可
return false;
}
タイムアウト設定の推奨
ネットワーク遅延やサーバー負荷を考慮し、タイムアウトは 10秒以上 を推奨します。タイムアウトを設定しないと、リクエストがハングしてアプリケーション全体に影響が出る場合があります。
// fetch API(タイムアウト付き)
const response = await fetch(url, {
signal: AbortSignal.timeout(10_000), // 10秒
});
# Python httpx(タイムアウト付き)
async with httpx.AsyncClient(timeout=10.0) as client:
response = await client.get(url, headers=headers)
# curl(タイムアウト付き)
curl --max-time 10 -H "x-api-key: ${TRIMIX_API_KEY}" \
"https://api.trimix-data.io/v1/invoice-issuers/T1234567890123"
4. キャッシュの推奨
キャッシュを活用してください
Trimix API が提供する国税庁データは 日次更新(毎日 JST 04:00 頃)です。同じデータを短時間に繰り返し取得しても結果は変わらないため、キャッシュを利用することを強く推奨します。
推奨 TTL: 1時間〜1日
キャッシュのメリット
- コスト削減: APIの呼び出し回数を減らすことでプランのリクエスト消費を抑えられます
- レート制限対策: キャッシュヒット時はリクエストが発生しないため、レート制限に達しにくくなります
- レスポンス高速化: キャッシュから返すほうがAPIリクエストより高速です
キャッシュ実装例
// シンプルなメモリキャッシュ(TypeScript)
// 本番環境では Redis 等の外部キャッシュを推奨します
const cache = new Map<string, { data: unknown; expiresAt: number }>();
async function getCachedInvoiceIssuer(
registrationNumber: string,
ttlMs = 3_600_000, // デフォルト1時間
): Promise<unknown> {
const cached = cache.get(registrationNumber);
if (cached && cached.expiresAt > Date.now()) {
return cached.data; // キャッシュヒット
}
// キャッシュミス: APIを呼び出す
const response = await fetch(
`https://api.trimix-data.io/v1/invoice-issuers/${registrationNumber}`,
{
headers: { "x-api-key": process.env.TRIMIX_API_KEY! },
signal: AbortSignal.timeout(10_000),
},
);
const data = await response.json();
cache.set(registrationNumber, { data, expiresAt: Date.now() + ttlMs });
return data;
}
5. データ・利用規約
国税庁データの利用規約への準拠
Trimix API が提供するデータは、国税庁「適格請求書発行事業者公表サイト」の公開データに基づいています。利用にあたっては国税庁の利用規約への準拠が必要です。
利用規約: https://www.nta.go.jp/about/organization/ntc/sozei/jirei.htm(国税庁 適格請求書発行事業者公表サイトの利用規約として参照)
商用利用する場合は、必ず自身で最新の利用規約を確認してください。 Trimix は利用規約の変更を常時追跡することを保証しません。
データの二次配布・再販禁止
Trimix API から取得したデータを第三者に再配布・再販することは禁止されています。データはあなた自身のアプリケーション内での利用にのみ使用してください。
6. サービス変更への対応
APIバージョニング
Trimix API はパスベースのバージョニング(/v1/)を採用しています。
- 後方互換性: v1 は後方互換性を維持しながら継続提供します。既存のレスポンスフィールドの削除・型変更などの破壊的変更は行いません
- 新バージョン: 破壊的変更が必要な場合は
/v2/として新バージョンを提供します。v1 は一定期間並行稼働します - フィールド追加: レスポンスへの新フィールド追加は破壊的変更とみなしません。未知のフィールドを無視するよう実装してください
// 未知のフィールドを無視する実装例(TypeScript)
// 型定義にないフィールドが追加されても動作するように
interface InvoiceIssuer {
registrationNumber: string;
name: string;
address: string;
// 将来のフィールドは自動的に無視される
[key: string]: unknown;
}
変更通知
API の重要な変更(新バージョンのリリース、旧バージョンの廃止予告等)はダッシュボードおよび登録メールアドレス宛に通知します。
- ダッシュボード: https://trimix-data.io/dashboard
- メールアドレスを最新の状態に保つことを推奨します
最終更新: 2026-06-01