Face swap request in Python: validate the video URL before you send
A Python snippet that rejects non-HTTPS, localhost and private-IP video URLs locally, then submits a Sume face-swap beta run with a quality and idempotency key.

Sume's face-swap beta refuses localhost, private-network, non-HTTPS, signed or private URLs and provider task URLs, so a cheap local check saves a round trip. The snippet below tests the cases it can see from the string alone, then submits the run (Face swap (Beta)).
The script
Needs requests. The final request carries all three required fields: avatar_handle, video_url and quality.
import ipaddress, os, requests
from urllib.parse import urlparse
def url_problem(url):
u = urlparse(url)
if u.scheme != "https":
return "not https"
host = u.hostname or ""
if host == "localhost" or host.endswith(".local"):
return "local host"
try:
ip = ipaddress.ip_address(host)
if ip.is_private or ip.is_loopback:
return "private address"
except ValueError:
pass
return None
video = "https://example.com/source-12s.mp4"
if (why := url_problem(video)):
raise SystemExit(f"fix the URL: {why}")
r = requests.post(
"https://api.sume.com/v1/models/sume/avatar-face-swap/v1.0/runs",
headers={"Authorization": "Bearer " + os.environ["SUME_API_KEY"], "Idempotency-Key": "swap-py-001"},
json={"avatar_handle": "reference_presenter", "video_url": video, "quality": "standard"},
timeout=30,
)
print(r.status_code, r.json())What this cannot catch
A signed URL or a provider task URL looks like a normal HTTPS link, so only Sume can reject those. Use a stable, public file URL, not an expiring link from another tool.
What to budget
Quality is required, and the reservation uses the 15-second beta maximum at the tier rate.
| quality | Reserved for 15 s |
|---|---|
| standard | $2.76 |
| plus | $3.675 |
| max | $8.25 |
After the submit
Keep the job id from the response. Poll GET /v1/jobs/{id}/status, then /result. The beta also supports sync, subscribe and webhook communication modes like other generation submits.
Constraints from the docs
The Beta endpoint is narrow on purpose. Checking these before you submit saves a failed round trip.
- Source video: approximately 4 to 15 seconds with usable audio (the current Beta plan).
- No prompt, transcript, duration, aspect ratio, avatar id in the body or provider fields: the endpoint does not take them.
- The avatar must already be ready; for script-driven talking video use Avatar videos instead.
Sources
Related posts
More in Developers
- Failed Sume video job: resubmit or stop? Read retryable, next_action
Sora said failed and little else. A failed Sume job carries an error with category, retryable, retry_after_seconds and next_action. A small decision function.
- FastAPI 0.142 native OpenTelemetry: tag spans with a Sume job id
FastAPI 0.142.0 added native OpenTelemetry. Put the Sume job_id on the current span in a webhook route so a failed render shows up next to the HTTP trace.
- FastAPI background poll of a Sume job: use next_poll_after_seconds
Poll a Sume job from an asyncio task in a FastAPI 0.142 app, wait for the server-provided interval, stop at terminal, and never resubmit after a timeout.
- Fastify: verify a Sume video webhook where Sora's video.completed was
Swap the Sora video.completed handler for Sume's job.completed in Fastify. Keep the raw string body, verify sume-v1 with the SDK, and refuse an empty secret.
Written by Sume