Summary
videoGeneration.getVideoContent() throws on a successful download. The video-content endpoint returns 200 with Content-Type: video/mp4 and a valid MP4 body, but the generated client only accepts application/octet-stream, so the response fails to match and the call errors instead of returning the stream.
This is the TypeScript counterpart of OpenRouterTeam/python-sdk#175 (get_video_content raise error because of the mismatch Content-Type) — same root cause, both SDKs generated from the same spec.
Version
@openrouter/sdk@0.12.79
Reproduction
import { OpenRouter } from '@openrouter/sdk'
const client = new OpenRouter({ apiKey: process.env.OPENROUTER_API_KEY })
// 1. Submit + poll to completion
const job = await client.videoGeneration.generate({
videoGenerationRequest: {
model: 'bytedance/seedance-2.0-fast',
prompt: 'A red balloon rising in a blue sky',
duration: 4,
},
})
let s = await client.videoGeneration.getGeneration({ jobId: job.id })
while (s.status !== 'completed' && s.status !== 'failed') {
await new Promise((r) => setTimeout(r, 5000))
s = await client.videoGeneration.getGeneration({ jobId: job.id })
}
// 2. Download the completed content — throws
const stream = await client.videoGeneration.getVideoContent({ jobId: job.id })
Observed
Unexpected Status or Content-Type: Status 200 Content-Type video/mp4
Body: ftypisom�isomiso2avc1mp41 ...
The body is a valid MP4 — note the ftypisom signature. Downloading the same unsigned_urls[0] manually confirms it:
GET <unsigned_urls[0]> (Authorization: Bearer <key>)
→ 200, content-type: video/mp4, 1,497,720 bytes, starts with `ftypisom`
Root cause
In esm/funcs/videoGenerationGetVideoContent.js:
- the request sends
Accept: "application/octet-stream", and
- the response is matched with
M.stream(200, …) keyed to the octet-stream content type,
while the upstream provider (Seedance 2.0, and presumably all video models) serves Content-Type: video/mp4. The spec types the content response as application/octet-stream; the live endpoint does not honor that, so the generated matcher rejects every real download.
Suggested fix
Have the video-content operation accept the actual media content types (video/mp4, ideally video/* / any 2xx body) as a passthrough stream, rather than only application/octet-stream — matching what the endpoint returns. Same change is needed in python-sdk (#175).
Context / downstream impact
Surfaced while building an OpenRouter video adapter for TanStack AI (TanStack/ai#740). We work around it by downloading unsigned_urls[0] directly with the Authorization header instead of using getVideoContent; filing here so the SDK path can eventually be used.
Refs: OpenRouterTeam/python-sdk#175
Summary
videoGeneration.getVideoContent()throws on a successful download. The video-content endpoint returns200withContent-Type: video/mp4and a valid MP4 body, but the generated client only acceptsapplication/octet-stream, so the response fails to match and the call errors instead of returning the stream.This is the TypeScript counterpart of OpenRouterTeam/python-sdk#175 (
get_video_content raise error because of the mismatch Content-Type) — same root cause, both SDKs generated from the same spec.Version
@openrouter/sdk@0.12.79Reproduction
Observed
The body is a valid MP4 — note the
ftypisomsignature. Downloading the sameunsigned_urls[0]manually confirms it:Root cause
In
esm/funcs/videoGenerationGetVideoContent.js:Accept: "application/octet-stream", andM.stream(200, …)keyed to the octet-stream content type,while the upstream provider (Seedance 2.0, and presumably all video models) serves
Content-Type: video/mp4. The spec types the content response asapplication/octet-stream; the live endpoint does not honor that, so the generated matcher rejects every real download.Suggested fix
Have the video-content operation accept the actual media content types (
video/mp4, ideallyvideo/*/ any 2xx body) as a passthrough stream, rather than onlyapplication/octet-stream— matching what the endpoint returns. Same change is needed in python-sdk (#175).Context / downstream impact
Surfaced while building an OpenRouter video adapter for TanStack AI (TanStack/ai#740). We work around it by downloading
unsigned_urls[0]directly with theAuthorizationheader instead of usinggetVideoContent; filing here so the SDK path can eventually be used.Refs: OpenRouterTeam/python-sdk#175