Skip to content

Media generation (video, images, music)

NordRouter can generate images, video and music — with the same sk-nr-… key and the same balance as the text models. Pay per use, no tokens or packs.

How it works

Generation is asynchronous (video and music take from seconds to a couple of minutes):

  1. Create a taskPOST /media/generate with a model and parameters.
  2. Wait for the result — poll GET /media/job/:id until status is done.
  3. Fetch the file — from result_url (a link on nordrouter.com).

1. Create a task

bash
curl https://nordrouter.com/media/generate \
  -H "Authorization: Bearer sk-nr-YOUR-KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "image/nano-banana-2",
    "input": { "prompt": "a cozy cabin in a winter forest, watercolor", "resolution": "2K" }
  }'

Response:

json
{ "id": "beefb531-…", "model": "image/nano-banana-2", "status": "processing",
  "poll": "https://nordrouter.com/media/job/beefb531-…" }

2. Wait for the result

bash
curl https://nordrouter.com/media/job/beefb531-…
json
{ "id": "beefb531-…", "status": "done",
  "result_url": "https://nordrouter.com/media/file/beefb531-…",
  "cost_usd": 0.052, "error": null }

status: processingdone (or failed). The finished file is at result_url.

🎵 Suno generates two tracks per task: the first is at result_url, the second at result_url_2 (same link format). You pay per task — both tracks are included.

Webhooks (instead of polling)

Don't want to poll — pass a callback_url to POST /media/generate and we'll push the result with a POST when the task finishes:

bash
curl https://nordrouter.com/media/generate \
  -H "Authorization: Bearer sk-nr-YOUR-KEY" -H "Content-Type: application/json" \
  -d '{
    "model": "image/nano-banana-2",
    "input": { "prompt": "…" },
    "callback_url": "https://your-server.com/webhooks/nordrouter",
    "callback_secret": "your-secret"
  }'

When the task reaches done/failed, a POST hits your callback_url with the same body as GET /media/job/:id plus an event field:

json
{ "event": "media.completed", "id": "beefb531-…", "status": "done",
  "result_url": "https://nordrouter.com/media/file/beefb531-…", "cost_usd": 0.052, "error": null }

event: media.completed or media.failed.

Verify the signature. If you set callback_secret, the X-NR-Signature header carries sha256=<hmac> — HMAC-SHA256 of the raw request body keyed by your secret. Verify it to confirm the request is from us:

python
import hmac, hashlib
expected = "sha256=" + hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
assert hmac.compare_digest(expected, request.headers["X-NR-Signature"])

Requirements & reliability:

  • callback_url must be https:// and a public address (internal/private IPs are rejected with 400).
  • Up to 4 delivery attempts with increasing backoff; respond 2xx or we'll retry.
  • Webhooks don't replace polling — combine them, or use GET /media/job/:id as a fallback.

More detail

The job lifecycle, signature verification with examples, and delivery reliability — on the Jobs and webhooks page.

3. Models and pricing

GET /media/models returns available models, their parameters and a price estimate:

json
{ "models": [
    { "id": "image/nano-banana-2", "type": "image",
      "fields": [ {"name":"prompt","type":"textarea"}, {"name":"resolution","type":"select","options":["1K","2K","4K"]} ],
      "est_usd": 0.052 }
  ], "retention_days": 14 }

Full reference

Every model with its input parameters and price — on the Media: all models & billing page.

Models

95 models are available — the always-current list with parameters and prices lives in GET /media/models. Main families:

TypeFamilyModes≈ price
🖼 ImagesNano Banana / 2 / Pro (image/nano-banana*)text→image, edit, up to 4Kfrom $0.025
🖼Imagen 4 Fast / Ultra (image/imagen4*)text→imagefrom $0.025
🖼GPT Image 1.5 / 2 (image/gpt-image-*)text→image, edit, up to 4Kfrom $0.025
🖼Flux 2 Pro / Flex (image/flux2-*)text→image, editfrom $0.03
🖼Seedream v4 / 4.5 / 5 Lite (image/seedream-*)text→image, editfrom $0.04
🖼Ideogram v3 / Character (image/ideogram-*)text, remix, characterfrom $0.02
🖼Qwen / Wan Image / Grok / Z-Imagetext→image, editfrom $0.01
🛠 UtilsTopaz / Recraft (image/*upscale*, image/recraft-remove-bg)upscale up to 8K, background removalfrom $0.01
🎬 VideoVeo 3.1 Lite / Fast / Quality (video/veo-3.1-*)text/image→videofrom $0.19
🎬Kling 2.1 → 3.0 (video/kling-*)text/image→video, motion, avatars, up to 4K & 15sfrom $0.16
🎬Wan 2.2 → 2.7 (video/wan-*)text/image/video→video, speech-to-videofrom $0.25
🎬Seedance 1.5 / 2 / Fast / Mini (video/seedance-*)text/image→video, up to 4K, audiofrom $0.06
🎬Hailuo 02 / 2.3 (video/hailuo-*)text/image→videofrom $0.08
🎬HappyHorse 1.0 / 1.1 (video/happyhorse-*)text/image/reference→video, video editfrom $0.70
🎬Grok Video / 1.5 (video/grok-*)text/image→video, up to 30sfrom $0.06
🎬Gemini Omni (video/gemini-omni)video with audio, up to 4Kfrom $0.39
🗣 AvatarsKling Avatar, OmniHuman, InfiniteTalk, Lip Syncphoto+audio→talking videofrom $0.19
🎵 MusicSuno V4–V5.5 (music/suno-v5)text/style→2 tracks~$0.08
🎙 SpeechElevenLabs Turbo / Multilingual (audio/elevenlabs-*)text→speech, vocal isolationfrom $0.04 / 1000 chars

Parameters

Parameters depend on the model — the exact list is in /media/models (the fields array: name, type, options, default). Common ones:

  • prompt — description (for all generative models).
  • resolution1K/2K/4K (images) or 480p/720p/1080p/4k (video). Price depends on resolution.
  • aspect_ratio1:1, 16:9, 9:16, etc.
  • duration — video length in seconds (most models 5/10, Kling 3.0 & Wan 2.7 up to 15, Grok up to 30). Video is billed per second.
  • sound / generate_audio — audio track (Kling, Seedance). Audio costs more — /media/estimate accounts for it.
  • mode / quality / rendering_speed — quality tier (Kling 3.0 std/pro/4K, GPT Image medium/high, Ideogram TURBO/BALANCED/QUALITY).
  • image — source image (edit, image→video; pass a direct link or upload via /media/upload).
  • video_url / audio_url — source video/audio (video-edit, lip sync, avatars).
  • For music: title, style, instrumental, version (V4V5_5).

POST /media/estimate with the same model + input returns the exact price of a specific configuration before you commit.

Cost and storage

  • Charged to your USD balance by the actual generation cost — the exact amount is in cost_usd after completion.
  • Failed generations (provider errors) are not charged — the reserve is refunded automatically.
  • Files are kept on our servers for a limited time (see retention_days in /media/models) — download to keep them.