API 문서

프로그래밍 방식 인코딩 — Ultra 구독자 전용. 계정 → API 키에서 키를 생성하고, 키를 그대로 아래 엔드포인트 URL에 포함시키면 됩니다.

플랜 한도

플랜파일당 상한API 액세스multipart 필요?
Free 5 KB
Pro 100 MB 아니오 (단일 PUT 가능)
Ultra 300 MB 있음 파일 >100 MB는 multipart 필수

Cloudflare 엣지는 단일 request body를 100 MB로 제한합니다. 이 값을 초과하는 파일은 50 MB part로 나누어 아래 multipart 엔드포인트를 사용하세요.

단일 PUT 업로드 (≤100 MB)

POST https://webhook.binaryphp.com/upload/<api_key>
  X-BPHP-Filename: plugin.php          # 필수, 확장자는 .php 또는 .zip
  X-BPHP-Domain:   app.example.com,*.example.com
  X-BPHP-Mac:      aa:bb:cc:dd:ee:ff   # 선택
  X-BPHP-Expire:   2027-12-31          # 선택
  X-BPHP-Webhook:  https://you.example.com/wh    # 선택, 비동기 알림용
  <파일 바이너리를 request body로>

→ 200 {
    "job_id":       "...",
    "download_url": "https://...presigned R2 URL...",
    "expires_at":   "2026-05-09T...",
    "size":         12345,
    "license":      { "domains": [...], ... }
  }

curl 한 줄 버전:

curl -X POST https://webhook.binaryphp.com/upload/$API_KEY \
  -H "X-BPHP-Filename: plugin.php" \
  -H "X-BPHP-Domain: app.example.com" \
  --data-binary @plugin.php

Multipart 업로드 (임의 크기, >100 MB는 필수)

3 단계: init → 각 part를 개별 PUT → complete.

1. Init (초기화)

POST https://webhook.binaryphp.com/upload/<api_key>/init
  X-BPHP-Filename:   bigplugin.zip
  X-BPHP-Total-Size: 200000000

→ 200 {
    "job_id":     "...",
    "upload_id":  "...",                         # R2 multipart 불투명 id
    "r2_key":     "uploads/<job_id>.zip",
    "part_size":  52428800,                      # 권장 50 MB / part
    "part_count": 4,
    "max_part_size": 104857600,                  # 100 MB 하드 리미트
    "parts": [
      { "part_no": 1, "upload_url": "https://...presigned PUT..." },
      { "part_no": 2, "upload_url": "..." },
      { "part_no": 3, "upload_url": "..." },
      { "part_no": 4, "upload_url": "..." }
    ]
  }

2. 각 upload_url에 PUT

이 presigned URL들은 직접 R2로 전송되어 Worker 대역폭을 소비하지 않습니다. 각 PUT 응답의 ETag 헤더는 수집하여, complete 단계에서 함께 전송하세요:

PUT <upload_url>
  <파일의 (part_no-1)*part_size 오프셋에서 part_size 바이트를 읽음>

← 200 OK
  ETag: "abc123def456..."

각 part는 ≥5 MB(마지막 part만 더 작아도 됨), 그리고 ≤100 MB.

3. Complete (완료)

POST https://webhook.binaryphp.com/upload/<api_key>/complete
Content-Type: application/json

{
  "upload_id": "...",
  "r2_key":    "uploads/<job_id>.zip",
  "filename":  "bigplugin.zip",
  "parts": [
    { "part_no": 1, "etag": "\"abc...\"" },
    { "part_no": 2, "etag": "\"def...\"" },
    { "part_no": 3, "etag": "\"ghi...\"" },
    { "part_no": 4, "etag": "\"jkl...\"" }
  ],
  "domain":   "app.example.com",
  "mac":      "",
  "expire":   "2027-12-31",
  "plugin":   "",
  "webhook":  ""
}

→ 200 { "job_id", "download_url", "expires_at", "size", "license" }

Abort (선택)

중간에 part 업로드가 실패한 경우, /upload/<api_key>/abort{ upload_id, r2_key }와 함께 호출하여 R2에 남은 part가 계속 과금되는 것을 방지하세요.

Webhook 알림

X-BPHP-Webhook(또는 complete body의 "webhook")을 설정하면 encode.completed 이벤트를 수신할 수 있습니다. 알림은 Cloudflare 엣지 IP에서 발송되어 우리 호스트 IP가 노출되지 않습니다. Body는 당신의 API key를 공유 비밀로 사용해 HMAC-SHA256으로 서명됩니다:

POST <당신의 webhook URL>
  X-BinaryPHP-Signature: t=1736208000,v1=<hex>
  X-BinaryPHP-Event:     encode.completed
  Content-Type:          application/json

{
  "event":        "encode.completed",
  "job_id":       "...",
  "download_url": "...",
  "expires_at":   "...",
  "size":         12345,
  "license":      { ... }
}

검증 예시 (PHP):

$sig_h = $_SERVER['HTTP_X_BINARYPHP_SIGNATURE'] ?? '';
[$tpart, $vpart] = array_pad(explode(',', $sig_h, 2), 2, '');
$ts  = (int) substr($tpart, 2);
$got = substr($vpart, 3);
if (abs(time() - $ts) > 300) http_response_code(401);
$body = file_get_contents('php://input');
$expected = hash_hmac('sha256', "$ts.$body", $YOUR_API_KEY);
if (!hash_equals($expected, $got)) http_response_code(401);

즉시 사용 가능한 클라이언트

자주 발생하는 오류

상태 코드의미처리 방법
401키 오류 또는 폐기됨 「계정 → API 키」에서 재생성
402플랜이 이 작업 미지원 (예: Free에서 zip 업로드) 플랜 업그레이드
413파일 / Content-Length가 플랜 상한 초과 multipart로 전환, 또는 Pro→Ultra로 업그레이드 (300 MB)
400필드 누락 또는 형식 오류 (filename, parts 등) 응답 body 확인, 누락된 필드가 표시됩니다
502R2 multipart 작업 실패 init 재시도; R2는 가끔 <1% 확률로 실패할 수 있습니다