API Reference
Opera Video API
Generate personalized patient education videos programmatically.
Base URL: https://getopera.ai
Quick Start
Generate a video in 3 steps.
1. Start generation
curl -X POST /api/v1/video/generate \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"patient_name":"Sarah","doctor_name":"Dr. Martinez","clinic_name":"Bright Smiles","treatment":"crown"}'2. Poll until ready
curl /api/v1/video/JOB_ID \
-H "Authorization: Bearer YOUR_API_KEY"
# Response when done:
# { "status": "completed", "video_url": "https://...mp4" }3. Use the video
# Direct link — plays in browser, embed in app, send to patient https://opera-ai-videos.s3.amazonaws.com/videos/patient-video-xxx.mp4
Authentication
All endpoints require a Bearer token.
Authorization: Bearer opk_a1b2c3d4e5f6...
Generate Video
POST /api/v1/video/generate
patient_namestringrequired
Patient's full name.
doctor_namestringrequired
Doctor's name (include "Dr." prefix).
clinic_namestringrequired
Practice name.
treatmentstringrequired
Treatment type. See supported list below.
treatment_notesstring
Clinical notes, e.g. "MOD composite #14".
video_goalstring
educate, reassure, convince, prepare, follow_up, celebrate. Default:
educatepatient_statusstring
undecided, hesitant, accepted, scheduled, in_treatment, post_treatment. Default:
undecidedcontent_modestring
template (fastest), template_ai, full_ai (custom). Default:
templateconcernsstring
Patient concerns, e.g. "afraid of needles".
financingstring
Financing info, e.g. "accepts CareCredit".
urgency_levelstring
routine, moderate, urgent. Default:
routinebrand_primary_colorstring
Hex color for clinic branding. Default:
#7c3aedResponse — 202 Accepted
{
"id": "uuid-job-id",
"status": "processing",
"poll_url": "/api/v1/video/uuid-job-id",
"created_at": "2026-01-15T10:30:00.000Z"
}Check Status
GET /api/v1/video/:id
Poll every 3-5 seconds.
// Processing
{ "status": "processing", "progress": 0.65, "step": "Rendering video" }
// Completed
{ "status": "completed", "video_url": "https://...s3.amazonaws.com/videos/...",
"download_url": "/api/v1/video/.../download" }
// Failed
{ "status": "failed", "error": "Description of what went wrong" }Download
GET /api/v1/video/:id/download
Redirects (302) to the MP4 file.
Supported Treatments
crown
filling
root_canal
implant
extraction
bridge
veneers
whitening
gum_treatment
dentures
full_mouth_rehab
braces
invisalign
ceramic_braces
lingual_braces
expander
retainer
jaw_surgery
Code Examples
Python
import requests, time
API_KEY = "opk_your_key"
job = requests.post("/api/v1/video/generate",
headers={"Authorization": f"Bearer {API_KEY}"},
json={"patient_name": "Sarah", "doctor_name": "Dr. Martinez",
"clinic_name": "Bright Smiles", "treatment": "crown"}).json()
while True:
s = requests.get(f"/api/v1/video/{job['id']}",
headers={"Authorization": f"Bearer {API_KEY}"}).json()
if s["status"] == "completed":
print("Video:", s["video_url"])
break
time.sleep(3)Node.js
const KEY = "opk_your_key";
const { id } = await fetch("/api/v1/video/generate", {
method: "POST",
headers: { Authorization: `Bearer ${KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({ patient_name: "Sarah", doctor_name: "Dr. Martinez",
clinic_name: "Bright Smiles", treatment: "crown" })
}).then(r => r.json());
while (true) {
const s = await fetch(`/api/v1/video/${id}`,
{ headers: { Authorization: `Bearer ${KEY}` } }).then(r => r.json());
if (s.status === "completed") { console.log(s.video_url); break; }
await new Promise(r => setTimeout(r, 3000));
}Errors
400
invalid_jsonRequest body is not valid JSON.401
unauthorizedMissing or invalid API key.404
not_foundJob ID does not exist.422
validation_errorInput validation failed. Check details array.429
rate_limitedRate limit exceeded. Check Retry-After header.500
internal_errorUnexpected server error.Default rate limits: 10 req/min, 500 req/day. Contact us for higher limits.