Skip to content

Support OpenRouter's async video generation endpoints (/api/v1/videos job lifecycle) #261

@tombeckenham

Description

@tombeckenham

Context

TanStack AI just added an openRouterVideo adapter targeting OpenRouter's dedicated async video API (TanStack/ai#740, docs). aimock 1.29's video handler mocks the OpenAI-shaped /v1/videos resource (status/progress/url on the video object), but OpenRouter uses a different path prefix and a different job-lifecycle wire shape, so the adapter's E2E coverage currently has to stay unit-test-only (feature-support.ts exclusion).

What OpenRouter's API looks like (live-verified)

SubmitPOST /api/v1/videos (JSON):

{
  "model": "bytedance/seedance-2.0",
  "prompt": "",
  // optional:
  "duration": 8, "resolution": "720p", "aspect_ratio": "16:9", "size": "1280x720",
  "seed": 42, "generate_audio": true, "callback_url": "https://…",
  "frame_images": [{ "type": "image_url", "image_url": { "url": "" }, "frame_type": "first_frame" }],
  "input_references": [{ "type": "image_url", "image_url": { "url": "" } }],
  "provider": { "options": { "<slug>": { /* passthrough */ } } }
}

Response: { "id": "<jobId>", "polling_url": "…/api/v1/videos/<jobId>", "status": "pending" }

PollGET /api/v1/videos/{jobId}:

  • status: pending → in_progress → completed | failed (also cancelled, expired)
  • on completion adds "unsigned_urls": ["…/api/v1/videos/<jobId>/content?index=0"] and "usage": { "cost": 0.05 }
  • on failure adds "error": "<message>"

DownloadGET /api/v1/videos/{jobId}/content?index=0:

  • requires the Authorization: Bearer <key> header (401 without it)
  • serves the bytes with Content-Type: video/mp4

Model listGET /api/v1/videos/models (nice-to-have): { "data": [{ "id", "name", "supported_durations", "supported_resolutions", "supported_aspect_ratios", "supported_frame_images", "supported_sizes", "generate_audio", "seed", "pricing_skus" }] } — video models do not appear in the plain /api/v1/models listing.

Ask

Route POST /api/v1/videos + GET /api/v1/videos/{jobId} (+ /content) on the OpenRouter mock surface with the shape above — fixture matching on prompt/model like the existing OpenAI video handler, with the same staged status progression. That would let TanStack AI's video-gen / image-to-video matrix rows add openrouter and run the submit→poll→download lifecycle end-to-end against fixtures.

One client-behavior note: the @openrouter/sdk (Speakeasy-generated) sends Accept: application/octet-stream for the content download but the real endpoint replies video/mp4 — TanStack AI's adapter fetches the unsigned URL directly, so the mock should serve video/mp4 to match production.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions