REST・CLI・OpenAPI

SingleFax APIドキュメントとCLI

APIキーと前払いクレジットを使用。npmの公式CLI、またはcurl・Node・Python・Go・PHPのRESTサンプルを利用できます。チャットアプリはMCPを使ってください。

CLI

npx @singlefax/cli send FILE --to +E164。Word・Excel・PDF・画像は元の形式で渡し、先にPDFに変換しないでください。

REST

POST /api/v1/faxesにBearer sf_live_…とIdempotency-Keyを指定。

チャット用MCP

Cursor・Claude・Codex・ChatGPT。APIキーではなくOAuthを使用。MCPをインストール。

クイックスタート

  1. APIキーでスコープを設定したキーを作成(fax:send、fax:read、inbox:read、credits:read)。
  2. 管理画面でクレジットを前払い、またはnpx @singlefax/cli credits buy。
  3. 下のCLIで送信するか、POST /api/v1/faxes。

ベースURLはhttps://api.singlefax.com(https://singlefax.comも同じパス)。sf_test_キーで実送信はできません。キーをブラウザーに置かないでください。

CLI

Node 20以上。設定:SINGLEFAX_API_KEYまたは~/.config/singlefax/config.json。元のファイル(Word、Excel、PowerPoint、PDF、テキスト、画像)を渡してください。先にPDFへ変換しないでください。MCP OAuthやStripe MPP用ではありません。

terminal
export SINGLEFAX_API_KEY=sf_live_…

npx @singlefax/cli send ./document.docx --to +14155552671
npx @singlefax/cli send ./document.pdf --to +14155552671 --wait --json
quote, status, credits
npx @singlefax/cli quote --to +14155552671 --pages 12
npx @singlefax/cli status <id>
npx @singlefax/cli list
npx @singlefax/cli numbers
npx @singlefax/cli numbers buy
npx @singlefax/cli credits
npx @singlefax/cli credits buy --dollars 20

ファクスを送信

1回のリクエストで、base64形式の文書と宛先を送ります。PDF、Word、Excel、PowerPoint、テキスト、画像に対応。Idempotency-Keyが必須です。同じキーで異なる本文を再送すると409を返します。

terminal
PDF_B64="$(base64 < document.pdf | tr -d '\n')"

curl -sS https://api.singlefax.com/api/v1/faxes \
  -H "Authorization: Bearer $SINGLEFAX_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d "{\"to\":\"+14155552671\",\"base64\":\"$PDF_B64\"}"

大きいファイルはアップロードして送信

CLIはアップロードトークンを作成し、バイト列をPUTしてからuploadTokenで送信します。PUTにもBearerトークンが必要です。大きなファイルをJSONに詰め込むより、この方法を推奨します。先にPDFへ変換しないでください。

terminal
UPLOAD=$(curl -sS https://api.singlefax.com/api/v1/uploads \
  -H "Authorization: Bearer $SINGLEFAX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"contentType":"application/pdf"}')

UPLOAD_URL=$(printf '%s' "$UPLOAD" | python3 -c "import json,sys; print(json.load(sys.stdin)['uploadUrl'])")
TOKEN=$(printf '%s' "$UPLOAD" | python3 -c "import json,sys; print(json.load(sys.stdin)['uploadToken'])")

curl -sS -X PUT "$UPLOAD_URL" \
  -H "Authorization: Bearer $SINGLEFAX_API_KEY" \
  -H "Content-Type: application/pdf" \
  --data-binary @document.pdf

curl -sS https://api.singlefax.com/api/v1/faxes \
  -H "Authorization: Bearer $SINGLEFAX_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d "{\"to\":\"+14155552671\",\"uploadToken\":\"$TOKEN\"}"

REST APIリファレンス

方法パス認証備考
POST/api/v1/faxesfax:sendIdempotency-Key required. JSON { to, base64 | uploadToken } or multipart file.
GET/api/v1/faxesfax:readList. Query limit, offset.
GET/api/v1/faxes/{id}fax:readStatus including latest delivery attempt.
POST/api/v1/faxes/quotefax:read{ to, pages? | base64? }, quote without charging.
POST/api/v1/uploadsfax:sendReturns uploadToken + uploadUrl. PUT the bytes, then send with uploadToken.
GET/api/v1/creditscredits:readPrepaid balance.
POST/api/v1/credits/checkoutcredits:checkout{ amountCents }. Stripe Checkout for a credit pack.
GET/api/v1/received-faxesinbox:readInbound inbox list. Query limit, cursor. No transcripts in list.
GET/api/v1/received-faxes/{id}inbox:readInbound detail with bounded transcript slice. HIPAA Secure content is omitted.
GET/api/v1/numbersfax:readActive fax numbers.
POST/api/v1/numberscredits:checkout{ sku?, country?, state? }, default inbound_30day. Returns checkoutUrl + reserved phoneNumber.
GET/api/v1/skuspublicCatalog. Same shape as MCP list_skus.
POST/api/v1/checkoutcredits:checkout{ sku }, credit_pack, inbound, subscriptions, lifetime.

完全なスキーマ:openapi.json。互換性を損なう変更:バージョン管理ポリシー(Sunsetは90日後)。このクレジットAPIでのHTTP 402は残高不足です。MPPの402はPOST /api/v1/machine/faxesのみです。

Webhook

署名付きのfax.queued、fax.delivered、fax.failed、credits.low_balanceイベント。生の本文に対してSingleFax-Signature(t=,v1=)を検証してください。timestamp.payloadのHMAC-SHA256です。管理画面のWebhookでエンドポイントを追加します。

verify.mjs
import { createHmac, timingSafeEqual } from 'node:crypto'

export function verifySingleFaxSignature(rawBody, signatureHeader, secret, toleranceSeconds = 300) {
  const parts = Object.fromEntries(signatureHeader.split(',').map((kv) => kv.split('=')))
  const timestamp = Number(parts.t)
  if (!Number.isFinite(timestamp) || !parts.v1) return false
  if (Math.abs(Math.floor(Date.now() / 1000) - timestamp) > toleranceSeconds) return false
  const expected = createHmac('sha256', secret).update(`${timestamp}.${rawBody}`).digest('hex')
  const a = Buffer.from(parts.v1)
  const b = Buffer.from(expected)
  return a.length === b.length && timingSafeEqual(a, b)
}

制約事項

  • APIキーはサーバーで管理し、sf_live_をウェブページに埋め込まないでください。
  • PHIは送らないでください。対象機関は、電子BAA付きのウェブサイトのHIPAA Secureモードを利用してください。
  • 有効なE.164形式の宛先。PDF、Word、Excel、PowerPoint、RTF、テキスト、画像に対応します。MIMEタイプはOpenAPIをご覧ください。先にPDF変換しないでください。送信前に当社で変換します。
  • チャット用MCPとStripe MPP:/agents、mpp.md、MPPと即時決済の違い。

よくあるご質問

機械可読ドキュメント

クローラー・コーディングエージェント向けのMarkdownとOpenAPI。内容はこのページと同じです。