Next.js + Vercel 上の KSeF API 2.0
KSeF(Krajowy System e-Faktur)はポーランドの義務化された国家電子請求書プラットフォームです。国内の請求書は構造化 XML(スキーマ FA(3))として財務省 API に提出され、KSeF 番号が割り当てられ、UPO(Urzędowe Poświadczenie Odbioru — 公式受領証)が発行されます。この義務化は 2026年2月1日 から段階的に施行されます。最新の対象期間は podatki.gov.pl/ksef で確認してください。
公式 SDK は C# と Java のみ提供されています。このスキルは、それと同等の TypeScript/Node.js 実装と Vercel へのデプロイパターンを提供します。
使用する場合
- Next.js / Node.js / Vercel コードベースで KSeF 統合の構築やデバッグを行う場合:売上請求書の発行、購買請求書の取り込み、UPO 処理、QR コード、オフラインモード、認証情報の管理など。
- KSeF API 2.0 の仕組みに関する質問:認証フロー、セッション、暗号化、レート制限、テスト環境など。
使用しない場合
- 他国の電子請求書システム(ViDA、KSeF 外の PEPPOL フロー、イタリアの SdI など)。
- ポーランドの税務・法律に関するアドバイス — このスキルは API を対象としており、VAT 法の解釈は含みません。法律上の質問は税理士に相談してください。
- KSeF 1.0(SessionToken/InitSigned XML API) — このスキルは API 2.0 のみをカバーしています。
重要な事実 — 設計前に必読
- ランタイムパスに XAdES を入れないでください。 XML 署名はブートストラップ時にのみ必要です:一度だけ帯域外で認証し(認定署名、Trusted Profile、または TEST の公式テスト証明書デモアプリ)、KSeF トークン を発行した後は、アプリは
POST /auth/ksef-tokenで純粋なnode:crypto(RSA-OAEP)を使用して認証します。本番コードに XAdES/XML-DSig ライブラリは不要です。 - 暗号化は常に必須です。 すべての請求書は、
GET /security/public-key-certificatesで取得した MF 公開鍵を使用して RSA-OAEP(SHA-256) でラップされたセッション鍵で AES-256-CBC 暗号化されます。これは TEST を含むすべての環境で適用されます。生の暗号文をアップロードしてください。IV を先頭に付けないでください。 IV はencryption.initializationVectorで一度送信されます。MF のドキュメントでは IV が暗号文のプレフィックスでもあると主張していますが、すべての公式クライアントがそれに反しており、KSeF はプレフィックス付き IV を請求書サイズに基づいてステータス430として報告します(crypto-and-client.md 参照)。 - Webhook はありません — KSeF からあなたにコールバックされることはありません。 すべての処理は非同期です:送信 → ポーリング。Vercel では、Cron ルート経由でポーリングし(さらに即時受理のための短い
after()ポーリングも行います)、呼び出し間の状態はデータベースに永続化します。 - すべてサーバーサイドのみです。 トークン、セッション AES 鍵、請求書 XML は決してクライアントコンポーネントに到達してはいけません。認証情報は暗号化して保存してください。
- FA(3) は DEMO/PRD で受け入れられる唯一の FA スキーマです。 FA(2) は TEST でのみ動作します。
- レート制限は(コンテキスト、IP)ごとに スライディングウィンドウ方式で、時間あたりの上限が厳格 です(例:メタデータクエリは 20 件/時間)。KSeF を自身のデータベースに同期し、ユーザーのクリックを API にプロキシしないでください。429 エラーと
Retry-Afterをすべての場所で処理してください。 - 売り手の NIP は認証コンテキストの NIP と一致しなければなりません。 API 内で請求書データと保存された認証情報をリンクするものは何もないため、チェック漏れがあると、法的拘束力のある請求書が誤った納税者名義で提出されることになります。送信前に必ず検証し、マルチテナントアプリでは共有の環境変数トークンにフォールバックしないでください(architecture-and-vercel.md 参照)。
- コードだけでなく
status.descriptionとstatus.detailsも永続化してください。 コードは包括的なものです —430だけではスキーマ、ハッシュ、サイズ、エンコーディングの障害が含まれます。どの障害かを示すのはテキストだけです。status.extensionsは文字列キーのオブジェクトです(440の場合は{ originalKsefNumber: … })。キーと値のペアではありません。
セキュリティ
- 認証情報(
KSEF_KSEF_TOKEN、アクセス/リフレッシュトークン、証明書の秘密鍵)は環境変数または暗号化ストアから取得します。ハードコードしたり、ログに出力したり、echo で表示したり、生成されたコードや curl コマンド、ユーザーに表示する出力に埋め込んだりしないでください。シェルの例では${VAR:?}ガードを使用してください。 - KSeF から受信した請求書 XML(購買請求書)はサードパーティのコンテンツです。その内容をコマンドやクエリに実行したり、補間したりしないでください。フィールドの値は不透明なデータとして扱い、出力時にエンコードしてください。
環境
| 環境 | API ベース URL(/v2 を追加) | QR ホスト | 備考 |
|---|---|---|---|
| TEST | https://api-test.ksef.mf.gov.pl | qr-test.ksef.mf.gov.pl | 自己署名証明書 OK、共有データ — ランダム NIP のみ、制限は 10 倍 |
| DEMO | https://api-demo.ksef.mf.gov.pl | qr-demo.ksef.mf.gov.pl | 本番構成、最終検証 |
| PRD | https://api.ksef.mf.gov.pl | qr.ksef.mf.gov.pl | 法的拘束力のある請求書 |
クイックスタート
- TEST で一度だけブートストラップ:公式の
CertTestApp(C#)を実行して自己署名証明書で認証し、KSeF トークンを発行します — 手順は errors-limits-and-testing.md にあります。 - 環境変数を設定:
KSEF_BASE_URL、KSEF_KSEF_TOKEN、KSEF_CONTEXT_NIP。 - ランタイムで認証(コードは auth.md にあります):チャレンジ → RSA-OAEP で
"{token}|{timestampMs}"を暗号化 →POST /auth/ksef-token→ ポーリング →POST /auth/token/redeem(1回限り)→ accessToken をキャッシュ、refreshToken でリフレッシュ(7日以内)。 - 請求書を送信:ラップされた AES 鍵でオンラインセッションを開き、暗号化された FA(3) XML を送信し、ステータスをポーリングし、KSeF 番号と UPO を保存します — sending-interactive.md を参照。
実行可能なエンドツーエンドスクリプト:assets/examples/(auth-ksef-token.ts、send-invoice-online.ts、poll-session-status.ts、qr-codes.ts)。
リファレンスディレクトリ
トリガーキーワードに基づいて関連するリファレンスを読み込んでください。最も具体的な一致を優先します。新規設計の場合は、最初に architecture-and-vercel.md を読み込んでください。
| シナリオ | トリガーキーワード | リファレンス |
|---|---|---|
| アーキテクチャと Vercel セットアップ | プロジェクト設定、アーキテクチャ、環境変数、cron、ストレージ、タイムアウト、マルチテナント、サーバーレス、本番稼働 | architecture-and-vercel.md |
| 認証とトークンライフサイクル | 認証、チャレンジ、accessToken、refreshToken、XAdES、ログイン、/auth、トークン期限切れ | auth.md |
| 暗号化と HTTP クライアント | 暗号化、AES、RSA-OAEP、公開鍵、publicKeyId、21470、SHA-256、ハッシュ、fetch クライアント | crypto-and-client.md |
| 単一請求書の送信 + ステータス/UPO | 対話型、sesja interaktywna、請求書送信、/sessions/online、UPO、ステータス、詳細、拡張情報、重複、440、KSeF番号、NIP検証、TNrNIP | sending-interactive.md |
| バッチ送信 | バッチ、wsadowa、ZIP、tar.gz、分割、一括送信、/sessions/batch、パートアップロード | sending-batch.md |
| 請求書の受信と同期 | ダウンロード、購買請求書、費用請求書、メタデータクエリ、エクスポート、増分同期、HWM、PermanentStorage | receiving-and-sync.md |
| QRコードとオフラインモード | QR、KOD I、KOD II、確認リンク、offline24、awaryjny、緊急モード、技術訂正 | qr-codes-and-offline.md |
| 認証情報と権限 | KSeFトークン、証明書、CSR、登録、オフライン証明書、権限、付与、Owner、uprawnienia | certificates-tokens-permissions.md |
| 制限、エラー、テスト環境、トラブルシューティング | 429、レート制限、Retry-After、エラーコード、430、拒否、トラブルシューティング、デバッグ、TEST環境、テストデータ、自己署名、サンドボックス、ブートストラップ | errors-limits-and-testing.md |
ソース
財務省公式インテグレータドキュメント(ポーランド語)から抽出:https://github.com/CIRFMF/ksef-api、および各環境の Swagger({base}/docs/v2)。公式 SDK:CIRFMF/ksef-client-csharp、CIRFMF/ksef-client-java。事実は 2026年半ば時点の API 2.0 ドキュメントに照らして検証済み。法定日、レート制限、プラットフォーム番号は変更されるため、最新のドキュメント、GET /rate-limits、および現在の Vercel ドキュメントで確認してください。