If a Sora 2 API request fails around size, do not start by changing random dimensions. As rechecked on July 8, 2026, OpenAI still documents the POST /v1/videos workflow for sora-2 and sora-2-pro, but the OpenAI deprecations page also says the Videos API and Sora 2 model aliases are scheduled for removal from the API on September 24, 2026. That means this page should be used as a maintenance and migration checklist, not as a long-term green light for a new Sora 2 integration.
The practical fix is still straightforward: prove that your endpoint is /v1/videos, your model and size pair belongs together, your seconds value is accepted by the current route, and your reference image is not being rejected for a separate policy or file-shape reason. Only after that should you resize assets or retry the render.
Start With The Failure Layer
Most Sora 2 "size errors" are not really one error. They are usually one of five layers being mixed together:
| Layer | Common symptom | First check |
|---|---|---|
| API lifecycle | Old code worked before but now fails or is no longer safe to build on | Check the OpenAI deprecations page for the September 24, 2026 Videos API shutdown |
| Endpoint shape | Request uses an old video job path or a wrapper-only path | Use OpenAI's current POST /v1/videos, then poll GET /v1/videos/{video_id} |
| Model and size | 400, invalid parameter, or model-specific rejection | Match the size value to sora-2 or sora-2-pro before sending |
| Duration | Request validates size but fails on another body field | Validate seconds separately; do not treat every parameter error as a resolution error |
| Reference input | Text-to-video works, image-to-video fails | Separate file upload, image format, human-face policy, and reference-object fields from size |
This order matters. If the endpoint or model is wrong, resizing an image will not help. If the request is blocked because an input image contains a human face, a perfect 1280x720 file will still fail. If you are starting a new product in July 2026, the deprecation date is a product decision, not a small bug.
For broader Sora route ownership, use the Sora 2 API access guide after the immediate size error is isolated. For current OpenAI model naming and lifecycle context, use the OpenAI model map.
Current OpenAI Size Rules To Validate
OpenAI's current Sora documentation keeps size as an explicit API parameter. The prompt can describe "wide", "vertical", "HD", or "short social clip", but the API only obeys the size value you send.
Use this conservative validator for OpenAI direct API requests:
| Model | Safer baseline sizes | Higher-resolution Pro sizes to verify in your project |
|---|---|---|
sora-2 | 720x1280, 1280x720 | Not a Pro route |
sora-2-pro | 720x1280, 1280x720, 1024x1792, 1792x1024 | OpenAI's video guide also references Pro use for 1080x1920 and 1920x1080; test those in your account before depending on them |
Two details prevent many false fixes:
- The format is plain
widthxheight, with no spaces and a lowercasex. sora-2andsora-2-proshould not share one universal resolution table.
Do not copy Azure, wrapper, or old blog-post resolution tables into an OpenAI direct call unless you have verified that the same route, model, and account tier accepts them today. A provider may expose extra presets or hide unsupported sizes behind its own normalization layer. That does not make those values valid for OpenAI's direct endpoint.
Duration Is A Separate Validation Problem
Older guides often hard-coded 4, 8, and 12 seconds as the complete duration set. Current OpenAI Sora guidance has also referenced longer clips up to 20 seconds, while API reference snippets may still show narrower allowed values in some contexts. Treat that as a reason to validate seconds independently instead of assuming a size error.
For production code, keep duration validation configurable:
hljs pythonBASELINE_SECONDS = {"4", "8", "12"}
EXTENDED_SECONDS = {"16", "20"}
def normalize_seconds(value, allow_extended=False):
seconds = str(value)
allowed = BASELINE_SECONDS | (EXTENDED_SECONDS if allow_extended else set())
if seconds not in allowed:
raise ValueError(
f"Unsupported seconds={seconds}. Check the current OpenAI Sora docs "
"and your project access before enabling longer durations."
)
return seconds
If size="1280x720" works with seconds="4" but fails with seconds="20", the resolution table is not the problem. Keep your logs labeled by parameter so a duration or account-tier issue does not get misfiled as image resizing work.
Reference Images Are Not Just A Resolution Issue
The old version of this article treated reference-image failures as if exact resizing was the main fix. That is too narrow for the current API surface. OpenAI's video guide says the API has guardrails and restrictions, including rejection of real people, human likeness in character uploads by default, and input images with human faces. The current API reference also describes video references as a structured reference object, not the older input_reference field shown in many unofficial examples.
Use this decision tree:
| If this happens | Do this before resizing |
|---|---|
| Text-to-video succeeds, image-to-video fails | Check whether the input image includes a human face or restricted content |
| A wrapper accepts your image but OpenAI direct rejects it | Compare the wrapper's transformed request with OpenAI's current reference-object shape |
A generated job enters failed after being queued | Retrieve the job status and error body before changing dimensions |
| A reference-image job produces bad framing | Then inspect crop, aspect ratio, and padding strategy |
Resizing can still be useful, but it should be a controlled preprocessing step. Do not crop client assets silently just to satisfy a preset. When aspect ratio changes, use an explicit policy such as pad-to-fit, center-crop with approval, or reject-and-request-a-new-source-image.
A Safer Preflight Validator
Use a preflight validator to catch route mistakes before you spend render time. Keep it small and easy to update because the API is in a deprecation window.
hljs pythonfrom dataclasses import dataclass
BASELINE_SIZES = {
"sora-2": {"720x1280", "1280x720"},
"sora-2-pro": {"720x1280", "1280x720", "1024x1792", "1792x1024"},
}
PRO_EXTENDED_SIZES = {"1080x1920", "1920x1080"}
@dataclass
class SoraVideoRequest:
model: str
size: str
seconds: str = "4"
allow_extended_pro_size: bool = False
allow_extended_seconds: bool = False
def validate_sora_video_request(req: SoraVideoRequest) -> None:
if req.model not in BASELINE_SIZES:
raise ValueError(f"Unsupported Sora model: {req.model}")
allowed_sizes = set(BASELINE_SIZES[req.model])
if req.model == "sora-2-pro" and req.allow_extended_pro_size:
allowed_sizes |= PRO_EXTENDED_SIZES
if req.size not in allowed_sizes:
raise ValueError(
f"size={req.size} is not enabled for model={req.model}. "
f"Allowed now: {sorted(allowed_sizes)}"
)
seconds = normalize_seconds(
req.seconds,
allow_extended=req.allow_extended_seconds,
)
req.seconds = seconds
This validator intentionally does not promise that every allowed value will work for every account. It prevents known-bad combinations, then leaves room for the live API, account tier, region, and deprecation status to be the final authority.
Current Request Pattern
OpenAI's current video guide describes an asynchronous workflow: create a video job, poll or use webhooks until it completes, then download the final MP4 from the content endpoint. Do not expect a permanent video_url in the initial create response.
hljs pythonimport time
from openai import OpenAI
client = OpenAI()
request = SoraVideoRequest(
model="sora-2-pro",
size="1280x720",
seconds="8",
)
validate_sora_video_request(request)
video = client.videos.create(
model=request.model,
prompt=(
"Wide tracking shot of a teal coupe driving through a desert highway, "
"hard sun overhead, heat ripples visible."
),
size=request.size,
seconds=request.seconds,
)
while video.status in {"queued", "in_progress"}:
time.sleep(10)
video = client.videos.retrieve(video.id)
if video.status != "completed":
raise RuntimeError(f"Sora video failed: {getattr(video, 'error', None)}")
content = client.videos.download_content(video.id, variant="video")
content.write_to_file("sora-output.mp4")
For user-facing apps, use a webhook instead of tight polling. OpenAI's guide notes that render time depends on model, API load, and resolution, and that a single render can take several minutes. Higher resolution and longer duration should be treated as slower jobs in your queue design.
What To Log When It Still Fails
Good logs are the difference between a five-minute fix and a day of guessing. For every failed Sora 2 request, record:
| Field | Why it matters |
|---|---|
model | Confirms whether the request used sora-2 or sora-2-pro |
size | Shows whether the resolution belongs to that model |
seconds | Separates duration failures from size failures |
| endpoint path | Confirms the app is using /v1/videos, not an old or wrapper-only path |
| job status and error body | Distinguishes create-time validation from queued-job failure |
| reference-image metadata | Separates file format, aspect ratio, face/policy rejection, and request-shape problems |
| checked date | Keeps the September 24, 2026 API removal visible to future maintainers |
When To Stop Fixing And Start Migrating
If the failed request is part of an existing production workflow, fixing size validation may be worth it. If the failed request is part of a new integration, the deprecation date changes the answer. Treat the Sora 2 Videos API as a route that needs an exit plan.
Use this cutoff:
| Situation | Better decision |
|---|---|
Existing Sora 2 job fails because 1792x1024 was sent to sora-2 | Fix validation and keep a migration ticket open |
| New product wants to build a video backend in July 2026 | Do not make Sora 2 Videos API the long-term owner without a replacement plan |
| Wrapper claims "stable Sora 2 API" | Ask for current upstream route, shutdown handling, job logs, and refund behavior before routing traffic |
| User only needs prompt structure | Preserve prompt anatomy as portable shot briefs instead of tying it to a sunset API |
For cost-specific decisions, keep the narrower Sora 2 pricing per second guide separate from this size-error page. For consumer workflow steps, use the Sora 2 step-by-step guide only after checking whether that surface still matches the current official route.
Frequently Asked Questions
Why does 1280 x 720 fail when 1280x720 works?
The API parameter is a compact size string. Use widthxheight with no spaces and a lowercase x. Do not send 1280 x 720, 1280*720, 720p, or prose like landscape HD as the size value.
Can sora-2 generate 1080p video?
Do not assume that. Use sora-2 for the baseline 720-oriented sizes. Treat higher-resolution exports as sora-2-pro work, and verify the exact accepted values in your project before depending on 1080x1920 or 1920x1080.
Is every image-to-video failure caused by the image dimensions?
No. Current OpenAI Sora guidance includes content and reference-image restrictions. Human faces, real people, copyrighted characters, unsupported reference-object shape, upload problems, and account access can all fail even when the target size is valid.
Should I keep building on the Sora 2 Videos API?
Only with a migration plan. OpenAI's deprecations page lists the Videos API, sora-2, and sora-2-pro for API removal on September 24, 2026. Maintenance fixes are reasonable; new long-term architecture needs a different owner or a clearly scheduled replacement.
Can a third-party wrapper make unsupported sizes work?
It can normalize, crop, pad, proxy, or reroute the request, but that is a different contract. Before trusting a wrapper, verify the upstream model, accepted dimensions, shutdown plan, logs, billing behavior, and what happens when OpenAI direct support ends.

![Sora 2 API: Complete Guide to Getting Access and Using OpenAI Video Generation API [2026]](/_next/image?url=%2Fblog%2Fen%2Fsora-2-api-access-guide%2Fimg%2Fcover.webp&w=3840&q=76&dpl=dpl_EsdSi5TwnjAcdHmkUBFaoBf1NQoo)

