Sora 2 Generate
Generate videos through the NanoPhoto.AI Sora 2 API.
Prerequisites
- Obtain an API key at: https://nanophoto.ai/settings/apikeys
- Configure
NANOPHOTO_API_KEY before using the skill.
- Do not paste the API key into chat; store it in the platform's secure env setting for this skill.
Preferred OpenClaw setup:
- Open the skill settings for this skill
- Add an environment variable named
NANOPHOTO_API_KEY
- Paste the API key as its value
Equivalent config shape:
{
"skills": {
"entries": {
"sora-2-generate": {
"enabled": true,
"env": {
"NANOPHOTO_API_KEY": "your_api_key_here"
}
}
}
}
}
Other valid ways to provide the key:
- Shell:
export NANOPHOTO_API_KEY="your_api_key_here"
- Tool-specific env config: any runtime that injects
NANOPHOTO_API_KEY
- OpenClaw config fallback: the bundled script also falls back to
~/.openclaw/openclaw.json at skills.entries.sora-2-generate.env.NANOPHOTO_API_KEY
Credential declaration summary:
- Primary credential:
NANOPHOTO_API_KEY
- Resolution order in the bundled script:
--api-key → NANOPHOTO_API_KEY environment variable → ~/.openclaw/openclaw.json skill env
- No unrelated credentials are required
Choose the mode
- Use
textToVideo when the user gives only a prompt.
- Use
imageToVideo when the user provides one or more public image URLs.
- Do not use local image files or base64 images for the API. The API only accepts public
imageUrls.
Recommended workflow
- Collect the prompt.
- Decide
mode: textToVideo or imageToVideo.
- Choose
modelTier, aspectRatio, and videoDuration.
- Default to
sora2.
- Use
sora2-pro-standard or sora2-pro-high only if the user explicitly wants the pro tier or higher resolution output.
- Submit the generation request.
- If the user wants synchronous progress output in the same process, use
submit --follow.
- Wait 120 seconds before the first status check, then check every 20 seconds until
completed or failed.
- Return the final
videoUrl, generation time, and credits used when available.
- Expect real-world wait time to vary from roughly 120 seconds to 480 seconds depending on queue/load, model tier, and prompt complexity; avoid short timeouts.
Preferred commands
Use the single bundled script with subcommands.
Submit only
python3 scripts/sora2_generate.py submit \
--prompt "A golden retriever running on a beach at sunset, cinematic lighting" \
--mode textToVideo \
--model-tier sora2 \
--aspect-ratio landscape \
--video-duration 10
Submit and keep polling in the same process
python3 scripts/sora2_generate.py submit \
--prompt "A golden retriever running on a beach at sunset, cinematic lighting" \
--mode textToVideo \
--model-tier sora2 \
--aspect-ratio landscape \
--video-duration 10 \
--follow
Check status of an existing task
python3 scripts/sora2_generate.py status --task-id task_abc123
Image to video
python3 scripts/sora2_generate.py submit \
--prompt "The person in the painting comes alive, moving naturally and reciting poetry" \
--mode imageToVideo \
--image-url https://static.nanophoto.ai/demo/nano-banana-pro.webp \
--model-tier sora2 \
--aspect-ratio landscape \
--video-duration 10
Script behavior
The bundled script resolves credentials in this order: --api-key, then NANOPHOTO_API_KEY from the environment, then ~/.openclaw/openclaw.json at skills.entries.sora-2-generate.env.NANOPHOTO_API_KEY.
Subcommands:
submit: submit a task
submit --follow: submit and keep polling in the same process
status: check an existing taskId
Cross-platform note:
- Use
python3 on macOS/Linux.
- Use
python on Windows unless python3 is available.
- The script uses Python's standard HTTP client and does not require
curl.
- Use
--json-only when another script/tool needs raw JSON output.
- Use
--initial-status-delay to override the default 120-second wait before the first status check.
- Use
--status-check-interval to override the default 20-second interval between progress checks.
- Default max wait is 1200 seconds.
Manual API calls
Submit generation
curl -X POST "https://nanophoto.ai/api/sora-2/generate" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $NANOPHOTO_API_KEY" \
--data-raw '{
"prompt": "A golden retriever running on a beach at sunset, cinematic lighting",
"mode": "textToVideo",
"modelTier": "sora2",
"aspectRatio": "landscape",
"videoDuration": "10"
}'
Check status
curl -X POST "https://nanophoto.ai/api/sora-2/check-status" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $NANOPHOTO_API_KEY" \
--data-raw '{"taskId": "task_abc123"}'
Parameter guidance
modelTier
sora2: default; lowest cost and fastest turnaround
sora2-pro-standard: 720p pro tier; use only when explicitly requested
sora2-pro-high: 1080p pro tier; use only when explicitly requested
aspectRatio
portrait: vertical/default
landscape: horizontal
videoDuration
Error handling
| errorCode | Cause | Action |
|---|
LOGIN_REQUIRED | Invalid or missing API key | Verify key at https://nanophoto.ai/settings/apikeys |
API_KEY_RATE_LIMIT_EXCEEDED | Rate limit exceeded | Wait and retry |
INSUFFICIENT_CREDITS | Not enough credits | Top up credits |
PROMPT_REQUIRED | Missing prompt | Ask user for a prompt |
IMAGE_REQUIRED | Missing image for image-to-video | Ask for public image URLs |
IMAGE_URLS_REQUIRED | API needs imageUrls | Do not send base64 or local file paths |
TASK_NOT_FOUND | Invalid or expired task ID | Re-submit or verify ownership |
GENERATION_FAILED | Server-side failure | Retry or try a simpler prompt |
Bundled files
scripts/sora2_generate.py: single entry point for submit, status, and optional in-process polling.
references/api.md: condensed API reference, costs, and response shapes.