Captioning API · v1
Picute Captioning API
Submit a video URL, receive a captioned MP4, signed SRT, and transcript JSON. The full v1 surface is documented below — Quick Start, interactive reference, and webhook verification.
Quick start
Pick your language. The snippets below submit a caption job using your API key — replace the placeholder before running.
curl -X POST https://picute.net/api/v1/captions \
-H "Authorization: Bearer pk_live_<your_key>" \
-H "Content-Type: application/json" \
-d '{
"video_url": "https://cdn.example.com/clip.mp4",
"language": "auto",
"preset": "default",
"callback_url": "https://api.your-app.com/webhooks/picute"
}'API reference
All endpoints, request schemas, and error codes for v1. Click any operation to expand request and response schemas.
Webhooks
Picute POSTs a signed webhook to your callback URL when a caption job reaches a terminal state. Verify the X-Picute-Signature header before trusting the payload.
Events
caption.completed— Caption job succeeded. data is the full Caption resource with output URLs populated.caption.failed— Caption job failed. data.error has the error code and message.
Verify the signature
Compute HMAC-SHA256 over the raw 'timestamp.body' string with your webhook secret, then constant-time compare against the hex digest in the v1= field of the header.
import hmac, hashlib, time
from flask import Flask, request, abort
app = Flask(__name__)
SECRET = "<your_webhook_secret_from_dashboard>"
TOLERANCE_SECONDS = 5 * 60
def verify(req):
header = req.headers.get("X-Picute-Signature", "")
parts = dict(p.split("=", 1) for p in header.split(",") if "=" in p)
timestamp = int(parts.get("t", "0"))
received = parts.get("v1", "")
if abs(time.time() - timestamp) > TOLERANCE_SECONDS:
return False
signed = f"{timestamp}.{req.get_data(as_text=True)}".encode("utf-8")
expected = hmac.new(SECRET.encode("utf-8"), signed, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, received)
@app.post("/webhooks/picute")
def hook():
if not verify(request):
abort(401)
payload = request.get_json()
print(payload["event"], payload["data"]["id"])
return "", 204