Encodage programmatique — réservé aux abonnés Ultra. Créez une clé sur Compte → Clés API, puis insérez-la directement dans les URLs des endpoints ci-dessous.
| Plan | Max par fichier | Accès API | Multipart requis ? |
|---|---|---|---|
| Free | 5 Ko | — | — |
| Pro | 100 Mo | — | Non (PUT unique suffit) |
| Ultra | 300 Mo | Oui | Fichiers >100 Mo doivent passer en multipart |
L'edge Cloudflare limite un body de requête à 100 Mo. Les fichiers plus gros doivent être découpés en parts de 50 Mo et passer par les endpoints multipart ci-dessous.
POST https://webhook.binaryphp.com/upload/<api_key>
X-BPHP-Filename: plugin.php # requis, extension .php ou .zip
X-BPHP-Domain: app.example.com,*.example.com
X-BPHP-Mac: aa:bb:cc:dd:ee:ff # facultatif
X-BPHP-Expire: 2027-12-31 # facultatif
X-BPHP-Webhook: https://you.example.com/wh # facultatif, pour notification asynchrone
<binaire du fichier en request body>
→ 200 {
"job_id": "...",
"download_url": "https://...presigned R2 URL...",
"expires_at": "2026-05-09T...",
"size": 12345,
"license": { "domains": [...], ... }
}
curl en une ligne :
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
Trois étapes : init → PUT individuel pour chaque part → complete.
POST https://webhook.binaryphp.com/upload/<api_key>/init
X-BPHP-Filename: bigplugin.zip
X-BPHP-Total-Size: 200000000
→ 200 {
"job_id": "...",
"upload_id": "...", # ID opaque R2 multipart
"r2_key": "uploads/<job_id>.zip",
"part_size": 52428800, # recommandé 50 Mo / part
"part_count": 4,
"max_part_size": 104857600, # limite dure 100 Mo
"parts": [
{ "part_no": 1, "upload_url": "https://...presigned PUT..." },
{ "part_no": 2, "upload_url": "..." },
{ "part_no": 3, "upload_url": "..." },
{ "part_no": 4, "upload_url": "..." }
]
}
upload_urlCes URLs presigned visent directement R2 et ne consomment pas
la bande passante du Worker. Le header ETag de chaque réponse PUT
doit être collecté et renvoyé à l'étape complete :
PUT <upload_url>
<lire part_size octets à l'offset (part_no-1)*part_size du fichier>
← 200 OK
ETag: "abc123def456..."
Chaque part doit faire ≥5 Mo (sauf la dernière qui peut être plus petite) et ≤100 Mo.
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" }
Si l'upload d'un part échoue en cours de route, appelez
/upload/<api_key>/abort avec { upload_id, r2_key }
pour éviter que les parts restants ne soient facturés sur R2.
Définissez X-BPHP-Webhook (ou "webhook" dans le body de complete)
pour recevoir des événements encode.completed. Les notifications partent
d'IPs Cloudflare edge, sans révéler notre IP d'hôte. Le body est signé en HMAC-SHA256
avec votre clé API comme secret partagé :
POST <votre URL webhook>
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": { ... }
}
Exemple de vérification (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);
ext-curl. Choisit automatiquement single ou multipart selon la taille
du fichier ; en cas d'échec, abort le multipart R2 pour éviter les parts résiduels facturés.
API_KEY=bphp_live_xxx php upload.php big.zip --domain=app.example.com
requests. Détection automatique + cleanup d'abort identique.
| Code | Signification | Que faire |
|---|---|---|
| 401 | Clé erronée ou révoquée | Recréez-en une dans « Compte → Clés API » |
| 402 | Plan ne supporte pas cette opération (ex. Free + upload zip) | Mettez votre plan à niveau |
| 413 | Fichier / Content-Length dépasse la limite du plan | Passez en multipart, ou Pro→Ultra (300 Mo) |
| 400 | Champ manquant ou format incorrect (filename, parts, etc.) | Consultez le body de la réponse, il indique le champ manquant |
| 502 | Opération multipart R2 échouée | Réessayez init ; R2 échoue parfois (<1%) |