株式会社renue
AI導入・DXの悩みをプロに相談してみませんか?
AIやDXに関する悩みがありましたら、お気軽にrenueの無料相談をご利用ください。 renueのAI支援実績、コンサルティングの方針や進め方をご紹介します。
DocuSign eSignature REST APIは広く利用されている電子署名サービスのAPIだが、「JWT Grant認証をどうPython本番コードに落とし込むか」「デモ/本番の切り替えをどう設計するか」「封筒(Envelope)作成のペイロードをどう構造化するか」といった実装者が本当に詰まるポイントは公式ドキュメントだけでは把握しきれない。本記事では一般的な実装パターンをもとに、JWT Grant認証・アカウントIDパス設計・base_url自動判定・封筒作成・書類ダウンロードを含む本番品質の統合パターンを解説する。
DocuSign APIの基礎とJWT Grant認証の位置付け
DocuSign eSignature APIにはAuthorization Code Grant(ユーザーログイン)とJWT Grant(サーバー間連携)の2種類がある。バッチ/自動化/社内システム組込みではJWT Grantを選ぶのが定石だが、以下の前提を揃える必要がある。
- Integration Key: DocuSign管理画面で発行するアプリ識別子
- RSA鍵ペア: 公開鍵をDocuSign側に登録、秘密鍵はサーバー保管
- User ID (GUID): API操作をそのユーザーの権限で実行するためのユーザーGUID。契約の受信者・署名者の指定とは別である(JWT Grantの対象)
- Account ID: APIコール先のDocuSignアカウントID
- 事前同意(consent): impersonationスコープには対象ユーザーについて同意の付与が必要。個別同意のほか、条件を満たす場合は管理者同意も利用できる
これらを取り違えると「consent_required」「invalid_grant」等の分かりにくいエラーに遭遇する。特に個別同意はブラウザで取得し、管理者同意には別の利用条件がある点を確認する。同意が撤回された場合等は、再取得が必要になる(同意方式、同意の継続条件)。
レイヤー1: デモ/本番環境の自動判定
DocuSignのeSignature APIは開発用のdemo環境(demo.docusign.net)とアカウント別の本番環境(*.docusign.net)を使う。OAuthのホストはそれぞれaccount-d.docusign.comとaccount.docusign.comである(OAuth環境)。切り替えミスが最も多いバグの温床なので、base_urlから自動判定するヘルパーを用意すると事故が減る。
明示指定も許しつつ、未指定時は検証済みの環境設定から判定する2段構えとする。本番のAPI接続先は固定せず、OAuth UserInfoが返す対象アカウントのbase_uriを使い、アカウントIDとの組み合わせを確認する(UserInfoと接続先)。
レイヤー2: JWT Grant認証の実装
JWT Grant認証の核心はRS256署名付きJWTを作ってOAuthエンドポイントに投げ、アクセストークンに交換する流れだ。ペイロードのaud(audience)はデモ/本番で変える必要がある。
JWTペイロードの落とし穴
| フィールド | 値 | よくあるミス |
|---|---|---|
iss | Integration Key | Account IDと混同する |
sub | User GUID | ユーザー名やメールを入れてしまう |
aud | account-d.docusign.com or account.docusign.com | デモ/本番のマッピング間違い |
scope | signature impersonation | スペース区切り必須(カンマ区切りにしてしまう) |
exp | now + 3600 | 長過ぎる値(最大1時間) |
private_keyの改行問題
環境変数にPEM秘密鍵を入れる際、改行が\nにエスケープされているケースが多い。実際の改行に戻す処理が必要だ。
Azure Key Vault/AWS Secrets Manager経由で取得するとこの問題は起きにくいが、.envやaz webapp config appsettingsで設定する場合は必須の前処理。
レイヤー3: アカウントIDを含むURLパス設計
DocuSign REST APIの特徴は封筒等のアカウント配下のエンドポイントはアカウントIDを含む点だ。/v2.1/accounts/{account_id}/envelopesのように。これを毎回呼び出し側で組み立てるのは冗長なので、共通リクエスト処理で一元化する。
呼び出し側は/envelopesと書くだけで済み、アカウントIDやバージョンプレフィックスを意識しなくてよい。バージョンのプレフィックスはここで一元管理できるが、将来のAPI移行はパス変更だけで完了すると決めず、移行先のリクエスト・レスポンス仕様も確認する。
レイヤー4: 封筒作成の型付きヘルパーの設計
DocuSign APIで最も使うのが封筒(Envelope)作成だ。生のAPIは柔軟性が高い代わりにペイロードが複雑なので、型付きラッパーを用意すると呼び出し側のコードが劇的に読みやすくなる。
ファイルから封筒を作成・送信する簡易ヘルパー
PDFファイルと署名者1名を受け取り、文書のBase64エンコード、署名者・署名位置・件名の設定、status=sentでの封筒作成をまとめるヘルパーを設計できる。認証とアカウント設定を済ませたうえで、社内システムからの契約送信フローに組み込む。具体的な要求データの例はDocusign公式の送信例で確認できる。
レイヤー5: 全封筒取得のページネーション(totalSetSize方式)
DocuSignの封筒一覧等では、totalSetSize文字列等のページ情報を使って取得範囲を管理する。nextUriを使うか、endPositionから次の開始位置を計算する。listStatusChangesで対象期間全体を取得する場合は、from_date/to_dateも指定する(公式のページネーション説明)。
ポイントはresultSetSize/totalSetSizeが文字列で返る仕様。数値として比較・加算する場合はint等で変換する。Pythonでは整数と文字列の等値比較はFalseになり、大小比較はTypeError、文字列同士では辞書順比較となる。無限ループになるかは終了条件次第なので、次ページがない場合や取得件数が増えない場合の終了処理も設ける(Pythonの比較規則)。
ダウンロードの特殊ID: "combined" と "certificate"
封筒内のドキュメントIDには予約語がある。
document_id="combined"— 封筒内の全ドキュメントを1つのPDFに結合してダウンロードdocument_id="certificate"— 電子署名証明書(Certificate of Completion)のPDFダウンロードdocument_id="1", "2", ...— 個別ドキュメント
CloudSign vs DocuSign: 設計の違い
| 観点 | CloudSign | DocuSign |
|---|---|---|
| 認証 | client_id → token | JWT Grant (RSA署名) |
| 環境分離 | base_urlのみ | demo/prod OAuth URL分離 |
| URLパス | シンプル(/documents) | アカウントID込み(/v2.1/accounts/{id}/envelopes) |
| ページネーション | page/per_page | start_position/count + totalSetSize(文字列) |
| 証明書取得 | 専用エンドポイント(/certificate) | documentId="certificate" |
| 結合PDF | - | documentId="combined" |
両者を併用するハイブリッドな社内システムを作る場合、この違いを把握しておくと抽象化レイヤー設計が楽になる。
まとめ: DocuSign統合の5つの勘所
- base_urlからデモ/本番を自動判定する実装で環境取り違えを防ぐ
- JWT Grant認証はiss/sub/aud/scopeの取り違えが最頻バグ
- private_keyの改行エスケープ復元を初期化時に必ず実施
- アカウントIDを含むURLは共通処理で一元化して呼び出し側を単純化
- totalSetSizeは文字列 — 数値として扱う場合は変換し、nextUriや終了条件でページネーションを制御
こうした設計は、契約書の送信フロー自動化に応用できる。電子署名APIは一度きちんと組めば長期運用できるため、初回の設計投資を惜しまないことが重要だ。




