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

팩스 보내기

요청 하나에 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 참조

메서드경로인증메모
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. 하위 호환되지 않는 변경: 버전 관리 정책(90일 Sunset). 이 크레딧 API의 HTTP 402는 잔액 부족입니다. MPP 402는 POST /api/v1/machine/faxes에만 적용됩니다.

웹훅

서명된 fax.queued, fax.delivered, fax.failed, credits.low_balance 이벤트입니다. 원시 본문으로 SingleFax-Signature(t=,v1=)를 검증하세요. timestamp.payload의 HMAC-SHA256입니다. 대시보드 웹훅에 엔드포인트를 추가하세요.

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입니다. 이 페이지와 같은 정보를 담고 있습니다.