Runware compatibility
What Parsec serves of Runware's task API: models, parameters, transports and errors.
To move a Runware client over, see Migrating from Runware. This page is the reference for what is served.
Parsec serves Runware’s task API at https://platform.parseclab.ai/v1 for
the image and video models it hosts. Requests keep Runware’s shape (a JSON
array of tasks with taskType and taskUUID), Runware’s model ids keep
working, and answers come back as {"data": […], "errors": […]}.
| Runware model id | Parsec model | Task |
|---|---|---|
google:4@3 | nano-banana-2 | imageInference |
google:nano-banana@2.1 | nano-banana-2.1 | imageInference |
google:4@2 | nano-banana-pro | imageInference |
google:nano-banana@2-lite | nano-banana-2-lite | imageInference |
xai:grok-imagine@image | grok-imagine-image | imageInference |
xai:grok-imagine@image-2.0 | grok-imagine-image-2 | imageInference |
xai:grok-imagine@image-quality | grok-imagine-image-quality | imageInference |
xai:grok-imagine@video | grok-imagine-1 | videoInference |
xai:grok-imagine@video-1.5 | grok-imagine-1.5 | videoInference |
Either name works in model. Prices are on the
models page.
SDK
Runware’s SDKs default to a WebSocket, which Parsec serves at
wss://platform.parseclab.ai/v1:
import { createClient } from "@runware/sdk";
const runware = await createClient({
apiKey: process.env.PARSEC_API_KEY,
wsBaseUrl: "wss://platform.parseclab.ai/v1",
});
await runware.connect();
const [image] = await runware.run({
model: "google:4@3",
positivePrompt: "A watercolor lighthouse at dusk",
width: 1344,
height: 768,
});
console.log(image.imageURL);
For REST instead, set transport: "rest" and
httpBaseUrl: "https://platform.parseclab.ai/v1". Either way the SDK’s async
default works as it does on Runware: it starts the task, then polls
getResponse until the result is ready.
Over the WebSocket, the first message authenticates
([{"taskType": "authentication", "apiKey": …}]), ping answers pong, and
each task answers on its own as soon as it is done. Idle connections close
after 120 seconds, as on Runware. Results of a dropped connection are not
replayed; async tasks are kept, so getResponse still finds them.
HTTP
curl https://platform.parseclab.ai/v1 \
-H "Authorization: Bearer $PARSEC_API_KEY" \
-H "Content-Type: application/json" \
-d '[{
"taskType": "imageInference",
"taskUUID": "a770f077-f413-47de-9dac-be0b26a35da6",
"model": "google:4@3",
"positivePrompt": "A watercolor lighthouse at dusk",
"resolution": "1K",
"includeCost": true
}]'
The key can also go in a leading {"taskType": "authentication", "apiKey": …}
task, as on Runware.
Video
videoInference is always asynchronous. Send the task, then poll with
getResponse and the same taskUUID:
curl https://platform.parseclab.ai/v1 \
-H "Authorization: Bearer $PARSEC_API_KEY" \
-d '[{"taskType": "videoInference", "taskUUID": "4f5b…", "model": "xai:grok-imagine@video-1.5",
"positivePrompt": "An otter surfing at sunset", "duration": 6, "resolution": "720p"}]'
curl https://platform.parseclab.ai/v1 \
-H "Authorization: Bearer $PARSEC_API_KEY" \
-d '[{"taskType": "getResponse", "taskUUID": "4f5b…"}]'
The poll answers "status": "processing" until the video is ready, then
"status": "success" with videoURL. A video is charged once, when a poll
first finds it done; failed videos cost nothing.
Webhooks
Set webhookURL on an imageInference or videoInference task and the task
runs in the background; each result is POSTed to that URL as it finishes,
the same item getResponse would return. A task that fails POSTs its error
object ("status": "error", code, taskUUID). Put any token you check in
the URL’s query string, as on Runware.
- Answer with a 2xx. Anything else is retried with backoff (250 ms doubling to 8 s) for up to 30 minutes.
- A delivery can arrive more than once: dedupe on
taskUUIDandimageUUID/videoUUID. - The URL must be https and resolve to a public address; redirects are not followed.
What is served
| Parameter | |
|---|---|
positivePrompt | Required. |
width, height | Mapped to the nearest aspect ratio the model supports, and to a size. |
resolution | Nano Banana: 0.5K, 1K, 2K, 4K. Grok Imagine images: 1K, 2K. Video: 480p, 720p, 1080p. |
duration | Video, 1 to 15 seconds. Default 6, as on Runware. |
inputs.referenceImages | URLs, data URIs or base64. Up to 14 for Nano Banana, 1 for Grok Imagine images (an edit), 7 for Grok Imagine 1.5 video. |
inputs.frameImages | Video: a first frame, and a last frame on Grok Imagine 1.5. |
seed | Nano Banana. With numberResults, each result uses the next seed. |
numberResults | Images, 1 to 4. One video per task. |
outputType | Images: URL (default), base64Data, dataURI. Video: URL. |
outputFormat | Images: JPG (default), PNG, WEBP (lossless). Video: MP4. |
outputQuality | JPG, 20 to 99. |
ttl | How long output URLs work, 60 seconds to 30 days. Default 7 days. |
includeCost | Adds cost in USD to each result. |
deliveryMethod | Images: sync (default) or async. Video: async. |
webhookURL | See Webhooks. |
settings | Nano Banana: systemPrompt, temperature, topP. Grok Imagine Image 2: quality. |
Not served yet, and refused with unsupportedParameter rather than ignored:
uploadEndpoint, providerSettings, advancedFeatures, speech,
inputs.referenceVideos, model auto, and images uploaded to Runware by
UUID (send the image itself or a URL instead). Task types other than
imageInference, videoInference, getResponse, authentication and
ping are not served either.
Errors
Errors use Runware’s shape, one entry per failed task, with the HTTP status of the first failure when no task succeeded:
{"errors": [{"code": "unsupportedModel", "message": "…", "parameter": "model",
"taskType": "imageInference", "taskUUID": "…", "status": "error"}]}
| Code | Status | |
|---|---|---|
missingApiKey, invalidApiKey | 401 | |
insufficientCredits | 402 | Top up in the console. |
invalidParameter, unsupportedParameter | 400 | parameter names the field. |
unsupportedModel, unsupportedTaskType | 400 | The message lists what is served. |
contentModeration | 400 | The provider’s safety filter took the output. |
providerRejected, noOutput | 400 | |
taskNotFound | 404 | getResponse for an unknown task, or another account’s. |
rateLimitExceeded, providerRateLimited | 429 | Wait for Retry-After, or retry later. |
providerError, timeoutProvider | 502, 504 | Safe to retry. |
Decisions
If you call TypeSafe’s decisions API through Runware (/v1/decisions),
Parsec serves the same request at
POST /v1/decisions with its own model,
tod-picker. Leave model out or set it to tod-picker; other model names
are refused.