APIリファレンス
SignFastAiのテンプレートからプログラムで文書を送信します。
SignFastAiの公開APIを使うと、保存済みのテンプレート(ダッシュボードの「マイテンプレート」)から文書を作成・送信したり、文書の署名状況を確認したり、最終的な署名済みPDFをダウンロードしたりできます——ブラウザを開く必要はありません。これは自動化(Zapierのようなスクリプトや独自のツール)から他システム経由で署名リクエストをトリガーするために作られています。
概要
利用条件
公開APIは Pro / Lifetime 限定の機能です。すべてのエンドポイントは、これらいずれかのプランのアカウントの有効なAPIキーを必要とします。
ベースURL
すべてのエンドポイントは次の配下にあります。
https://<your-domain>/api/v1<your-domain> は、あなたがSignFastAiにアクセスしているドメインに置き換えてください。
クイック例
curl https://<your-domain>/api/v1/presets \
-H "x-api-key: YOUR_API_KEY"対応していない範囲
これは意図的に最小限に絞ったAPIです——作成/送信、ステータス確認、ダウンロードのみ。テンプレートやクライアント、対面署名セッション自体を管理するエンドポイントは(今のところ)ありません。これらは引き続きダッシュボードからのみ操作できます。
認証
キーの作成
- サインインして 設定 → APIキー(
/settings/apikeys)を開きます。このページはProまたはLifetimeプランが必要です——無料プランのアカウントにはアップグレードの案内が表示されます。 - APIキーを作成をクリックし、名前を付けます。
- ダイアログに表示されたキーの値をコピーします。あとからでもAPIキー一覧(キー列の目のアイコンとコピーアイコン)でいつでも再表示・コピーできるため、先に別の場所へ保存しておく必要はありません。キーが漏えいした場合は、削除して新しく作成してください。
キーの使い方
すべてのリクエストで x-api-key ヘッダーにキーを設定して送信します。
curl https://<your-domain>/api/v1/presets \
-H "x-api-key: YOUR_API_KEY"Authorization: Bearer には対応していません——必ず x-api-key を使用してください。
レート制限
各キーは24時間のローリングウィンドウで1000リクエストまでに制限されています。これは実際の送信上限ではなく、あくまで不正利用防止のための下限です——1か月に実際に送信できる文書数はプランによって決まり(送信上限を参照)、このリクエストレート上限とは独立しています。上限を超えると 429 が返されます——詳細はエラーを参照してください。
認証エラー
| ステータス | コード | 意味 |
|---|---|---|
| 401 | MISSING_API_KEY | x-api-key ヘッダーが送信されていません |
| 401 | INVALID_API_KEY(またはその他のキー関連コード) | キーが存在しない、無効化されている、または不正な形式です |
| 403 | UPGRADE_REQUIRED | キーは有効ですが、所有者のプランにAPIアクセス権がありません |
| 429 | RATE_LIMITED | 現在の24時間ウィンドウ内のリクエストが多すぎます |
テンプレート
テンプレート一覧を取得する
GET /api/v1/presetsアカウントに保存されているすべてのテンプレート(内部では「preset」と呼びます)を、その署名者ロールとともに返します。POST /api/v1/documents を呼び出す前にこのエンドポイントが必要です——受信者はロールの表示ラベルではなく id でロールに割り当てられるため、先にここでIDを確認する必要があります。
なぜ表示名ではなくロールIDで照合するのですか? 同じテンプレート内の2つのロールが同じ表示ラベルを持つことがあります(例:2つとも「署名者」というロール)。IDは常に一意なので、どの受信者がどのロールに割り当てられているかが曖昧になることはありません。
テンプレートのレスポンス
{
"success": true,
"data": {
"presets": [
{
"id": "b3f6b6b0-...",
"title": "Freelance Agreement",
"roles": [
{
"id": "0e2b0f2e-...",
"role": "Client",
"requireAccessCode": false
},
{
"id": "9a1c9d3f-...",
"role": "Witness",
"requireAccessCode": true
}
]
}
]
}
}rolesはテンプレートの署名順と同じ順序で並びます。requireAccessCode: trueは、そのロールに割り当てられた受信者が文書送信時にaccessCodeも一緒に指定する必要があることを意味します——アクセスコードを参照してください。
ページネーションはありません——1アカウントあたりのテンプレート数は少ないためです(無料プランの上限は1件、このエンドポイント自体もPro/Lifetimeが必要です)。
文書
作成して送信する
POST /api/v1/documentsテンプレートから1つの文書を作成し、即座に送信します——このコールの一部として、各受信者に署名リンクのメールが送られます(テンプレートで順序署名が有効な場合を除く。その場合は最初の署名者にのみ通知され、残りの署名者は前の署名者が完了するたびに自動的に通知されます。これはダッシュボードから送信した場合と同じ挙動です)。
リクエストボディ
{
"presetId": "b3f6b6b0-...",
"title": "Freelance Agreement — Acme Corp",
"recipients": [
{
"roleId": "0e2b0f2e-...",
"name": "Jane Client",
"email": "jane@acme.example"
},
{
"roleId": "9a1c9d3f-...",
"name": "Bob Witness",
"email": "bob@acme.example",
"accessCode": "4471"
}
]
}| フィールド | 必須 | 備考 |
|---|---|---|
presetId | 必須 | GET /api/v1/presets から取得 |
title | 任意 | この文書についてテンプレートの保存済みタイトルを上書きします |
recipients | 必須 | テンプレートのロールごとに1件 — 詳細は下記 |
recipients[].roleId | 必須 | presetId に属するロールIDである必要があります |
recipients[].name | 必須 | |
recipients[].email | 必須 | |
recipients[].accessCode | 条件付き | そのロールが requireAccessCode: true の場合は必須 |
テンプレート上のすべてのロールに、過不足なくちょうど1人の受信者が必要です。APIは何かを作成する前に次を検証します。
presetIdに属さないroleId→UNKNOWN_ROLE_ID- 同じ
roleIdが2回使われている →DUPLICATE_ROLE_ID - 受信者がいないロールがある →
MISSING_ROLE_RECIPIENT requireAccessCodeのロールにaccessCodeがない(または空) →ACCESS_CODE_REQUIRED
それぞれの完全なレスポンス形式はエラーを参照してください。
アクセスコード
シングルロールのテンプレートのみに対応し、アクセスコードが必要なテンプレートは拒否するダッシュボードの一括送信機能とは異なり、APIはマルチロールのテンプレートに対応しており、各受信者のアクセスコードを直接指定できます——これを収集するUI手順がないため、あなた自身が指定する必要があります。
送信上限
文書を作成する前に、APIはプランの月間送信上限をチェックします(ダッシュボードから送信する際に適用されるものと同じです)。この文書の送信が上限を超える場合、409 SIGN_LIMIT_EXCEEDED が返され、何も作成されません。
作成のレスポンス
{
"success": true,
"data": {
"documentId": "c1d2e3f4-...",
"status": "sent",
"signers": [
{
"id": "...",
"name": "Jane Client",
"email": "jane@acme.example",
"role": "Client",
"status": "sent",
"signingUrl": "https://<your-domain>/sign/s/..."
},
{
"id": "...",
"name": "Bob Witness",
"email": "bob@acme.example",
"role": "Witness",
"status": "pending",
"signingUrl": null
}
]
}
}signingUrl はこの呼び出しで通知された署名者に対してのみ設定されます——順序署名テンプレートでまだ順番待ちの署名者は null になります(順番が来ると実際のリンクが発行され、通知されます)。
ステータスを確認する
GET /api/v1/documents/:id文書の現在のステータスと各署名者のステータス/タイムスタンプを返します。文書が存在しない場合、または別のアカウントに属している場合のいずれも404(DOCUMENT_NOT_FOUND)が返されます——APIはどちらであるかを明かしません。
{
"success": true,
"data": {
"id": "c1d2e3f4-...",
"title": "Freelance Agreement — Acme Corp",
"status": "sent",
"sentAt": "2026-09-23T09:00:00.000Z",
"completedAt": null,
"signers": [
{
"id": "...",
"name": "Jane Client",
"email": "jane@acme.example",
"role": "Client",
"status": "viewed",
"viewedAt": "2026-09-23T09:05:00.000Z",
"signedAt": null,
"declinedAt": null,
"declineReason": null
}
]
}
}署名済みPDFをダウンロードする
GET /api/v1/documents/:id/downloadstatus が completed になって初めて利用できます。最終PDFを直接返します(Content-Type: application/pdf)。JSONのレスポンス形式ではありません。それより前に呼び出すと 409 DOCUMENT_NOT_COMPLETED が返されます。
署名済みPDFは、元の文書の末尾に完了証明書のページを追加したものです。レスポンスヘッダー:
Content-Disposition—— 元のファイル名(ファイル名にASCII以外の文字が含まれる場合は、filename*にUTF-8のファイル名が入ります)。X-Document-Sha256—— ファイルのSHA-256。ダウンロード内容が改ざん・欠損していないか確認できます。
ストレージからのファイル取得は、まれに一時的に失敗することがあります(502 STORAGE_FETCH_FAILED、または 500)——そのまま再試行して問題ありません。
Webhook
GET /documents/{id} をポーリングする代わりに、URLを登録しておけば、文書(API、ダッシュボード、
一括送信のいずれで作成したものでも)に動きがあるたびにイベントをPOSTします。
設定 → APIキー → Webhook で管理します。エンドポイントは最大5件まで追加でき、 エンドポイントごとに受け取るイベントを選べます。テストイベントの送信や、30日間のすべての送信履歴 (相手先の応答を含む)の確認もできます。Webhookは Pro / Lifetime プランの機能です。
イベント
| イベント | 送信されるタイミング |
|---|---|
document.sent | 文書が署名依頼として送信された |
signer.viewed | 署名者が文書を開いた |
signer.signed | 署名者が署名を完了した |
document.completed | 全員の署名が完了し、最終PDFをダウンロードできる |
document.declined | 署名者が署名を拒否した |
document.completed は最終PDFが作成された後にのみ送信されるため、受信後すぐに
GET /documents/{id}/download を呼び出せます。
ペイロード
各リクエストはJSON本文を持つ POST です。
{
"id": "evt_2f6c1b0e-7a1d-4a55-9a52-2f7c0f8f1a11",
"type": "document.signed",
"createdAt": "2026-09-24T09:15:02.000Z",
"data": {
"document": {
"id": "0b0c7a4e-...",
"title": "業務委託契約書 — Acme",
"status": "sent",
"createdVia": "api",
"sentAt": "2026-09-24T09:10:00.000Z",
"completedAt": null,
"finalFileHash": null,
"signers": [
{ "id": "…", "name": "Ada Lovelace", "email": "ada@example.com", "status": "signed" }
]
},
"signer": { "id": "…", "name": "Ada Lovelace", "email": "ada@example.com", "status": "signed" }
}
}data.signer は signer.* イベントにのみ含まれます。同じイベントが複数回送信されることがある
(再試行後など)ため、id を冪等キーとして扱ってください。
署名の検証
すべてのリクエストに次のヘッダーが付きます。
| ヘッダー | 値 |
|---|---|
X-SignFast-Signature | t=<UNIX秒>,v1=<16進のHMAC-SHA256> |
X-SignFast-Event | イベント種別(例:document.completed) |
X-SignFast-Delivery | この送信の一意なID |
署名は HMAC-SHA256(secret, "<t>.<生のリクエスト本文>") です。secret はエンドポイントの署名シークレット
(作成時に表示され、その後も一覧からいつでも確認できます)。生の本文に対して計算し、
定数時間で比較し、数分以上ずれたタイムスタンプは拒否してください。
import { createHmac, timingSafeEqual } from 'node:crypto';
function verify(secret, header, rawBody) {
const parts = Object.fromEntries(header.split(',').map((p) => p.split('=')));
if (Math.abs(Date.now() / 1000 - Number(parts.t)) > 300) return false;
const expected = createHmac('sha256', secret)
.update(`${parts.t}.${rawBody}`)
.digest('hex');
const a = Buffer.from(expected);
const b = Buffer.from(parts.v1 ?? '');
return a.length === b.length && timingSafeEqual(a, b);
}送信と再試行
8秒以内に任意の 2xx ステータスを返して受信を通知してください。それ以外(またはタイムアウト)は失敗として扱い、
約5秒後と約30秒後に再試行し、その後その送信を失敗としてマークします。失敗した送信はダッシュボードから
再送できます。リダイレクトには従いません。
エンドポイントのURLは https:// で公開アクセス可能である必要があります。プライベートネットワーク、
localhost、クラウドのメタデータ用アドレスは拒否されます。
リクエストログ
APIキーで行われたすべてのリクエスト(メソッド、パス、ステータスコード、エラーコード、所要時間)が記録され、 設定 → APIキー → リクエストログ に表示されます。キーや成功/エラーで絞り込めます。保存期間は30日間です。 APIキーの一覧には各キーの最終使用時刻と過去30日のリクエスト数も表示され、API経由で作成した文書は文書一覧で「API」と表示されます。
利用状況タブでは、リクエスト数を時間別(過去24時間)または日別(7日・30日)のグラフで確認でき、成功・クライアントエラー・サーバーエラーに分けて表示されます。応答時間やエンドポイント別・キー別の内訳も見られます。リクエストログはCSVでエクスポートでき、エラーアラートを有効にすると、過去1時間の失敗率が設定したしきい値を超えたときにメールでお知らせします(6時間に最大1通)。
エラー
レスポンス形式
すべてのJSONレスポンス(PDFダウンロードを除く)は同じ形式を使用します。
{ "success": true, "data": { /* ... */ } }{
"success": false,
"error": {
"code": "MISSING_ROLE_RECIPIENT",
"message": "Every template role needs a recipient",
"details": { "missingRoleIds": ["9a1c9d3f-..."] }
}
}details は、プログラムで対処できる有用な情報がある場合(どのロールIDが問題だったか、プランの上限は何かなど)にのみ含まれます——message の解析にフォールバックする前に、まず details を確認してください。
エラーコード一覧
| ステータス | コード | 対象 | 意味 |
|---|---|---|---|
| 401 | MISSING_API_KEY | 全エンドポイント | x-api-key ヘッダーが送信されていません |
| 401 | INVALID_API_KEY(または類似コード) | 全エンドポイント | キーが存在しない、無効化されている、または不正な形式です |
| 403 | UPGRADE_REQUIRED | 全エンドポイント | キーは有効ですが、アカウントがPro/Lifetimeではありません |
| 429 | RATE_LIMITED | 全エンドポイント | このキーで過去24時間のリクエストが1000件を超えました |
| 400 | INVALID_BODY | POST /documents | リクエストボディがスキーマ検証に失敗しました |
| 404 | PRESET_NOT_FOUND | POST /documents | presetId が存在しないか、あなたのものではありません |
| 400 | UNKNOWN_ROLE_ID | POST /documents | roleId がこのテンプレートに属していません |
| 400 | DUPLICATE_ROLE_ID | POST /documents | 同じ roleId が2人の受信者に使われました |
| 400 | MISSING_ROLE_RECIPIENT | POST /documents | テンプレートのロールに受信者がいません |
| 400 | ACCESS_CODE_REQUIRED | POST /documents | requireAccessCode のロールの受信者に accessCode がありません |
| 409 | SIGN_LIMIT_EXCEEDED | POST /documents | 送信するとプランの月間送信上限を超えます |
| 404 | DOCUMENT_NOT_FOUND | GET /documents/:id、.../download | 文書が存在しないか、あなたのものではありません |
| 409 | DOCUMENT_NOT_COMPLETED | GET /documents/:id/download | まだ全員の署名が完了していません |
| 502 | STORAGE_FETCH_FAILED | GET /documents/:id/download | ストレージの一時的なエラーです——再試行してください |
| 500 | INTERNAL_ERROR | 全エンドポイント | サーバーで予期しないエラーが発生しました |