Generative AI API Documentation

The Prospolabs API gives you one endpoint and one auth flow for every frontier image and video generation model — Seedance, Kling V3 / O3, Veo 3.1, GPT Image 2, Nano Banana, and Seedream. Pay USD per generation, no tokens.

Authentication

All API requests require a Bearer token in the Authorization header. Generate API keys from your Dashboard. Keep your keys secret and never expose them in client-side code.

1Authorization: Bearer prsp-your-api-key

Quick Start

One endpoint, every model. Pass the model id and any model-specific parameters.

1curl -X POST https://api.prospolabs.com/v1/generate \
2 -H "Authorization: Bearer prsp-your-api-key" \
3 -H "Content-Type: application/json" \
4 -d '{
5 "model": "veo-3-1-lite",
6 "mode": "text",
7 "params": {
8 "prompt": "A close-up of a hummingbird hovering near a sunlit flower, slow motion",
9 "duration": "8s",
10 "resolution": "720p",
11 "aspect_ratio": "16:9",
12 "generate_audio": true
13 }
14 }'

Generate Endpoint

POST/v1/generate

Run any model in the catalog. Pass the model id (e.g. veo-3-1-lite, seedream-5-lite) and the model-specific parameters listed below.

Shared Request Body

FieldTypeRequiredDescription
modelstringYesModel id from the catalog. e.g. "veo-3-1-lite", "seedream-5-lite", "kling-v3".
modestringNoSelects the input shape for multi-modal models. e.g. "text", "image", "reference" (video) or "generate", "edit" (image). Defaults to the model's first declared mode.
paramsobjectYesPer-model parameters. Schema depends on the chosen model and mode — see the per-model sections below.
webhook_urlstringNoReceive a callback when async generation completes. See Webhooks.
asyncbooleanNoSend true (or pass ?async=true) to skip the synchronous wait. Returns generation_id immediately.

Response

FieldTypeRequiredDescription
generation_idstringYesUnique identifier for the generation (gen_*).
status"queued" | "processing" | "completed" | "failed"YesCurrent state of the generation.
modelstringYesModel id used.
modestringYesMode used for this generation.
output_urlstring | nullYesURL of the generated image or video. Available for 7 days after generation; requests after that return HTTP 410 Gone (code: output_expired). Download anything you want to keep.
cost_usdnumberYesExact USD amount deducted from your balance for this generation.
duration_msnumber | nullYesEnd-to-end processing time in milliseconds.

Response Example

1{
2 "generation_id": "gen_a1b2c3d4e5f6",
3 "status": "completed",
4 "model": "veo-3-1-lite",
5 "mode": "text",
6 "output_url": "https://cdn.prospolabs.com/results/gen_a1b2c3d4e5f6.mp4?token=...",
7 "cost_usd": 0.40,
8 "duration_ms": 28430
9}

Per-Model Parameters

Generate a clip from a text prompt.

Seedance 2.0 Fast — Text → Video

FieldTypeRequiredDescription
promptstringYesPrompt.
resolutionstringNoResolution. One of: 480p, 720p. Default: 720p.
durationnumberNoDuration. Range: 4–15 (s). Default: 5.
aspect_ratiostringNoAspect ratio. One of: 16:9, 9:16, 1:1, 4:3, 3:4, 21:9. Default: 16:9.
generate_audiobooleanNoGenerate audio. Default: true.
seednumberNoSeed. Range: 0–2147483647.

Uploading Files

Any media param — image_url, image_urls, video_urls, audio_urls, mask_url — accepts either a public https:// URL or an opaque upload token minted by POST /v1/uploads/initiate. Use the token flow for large files (videos > 32 MB) or any private file you don't have a public URL for.

Two-step token flow

1. Initiate the upload — get back an opaque token and a PUT target on this domain.

1curl -X POST https://api.prospolabs.com/v1/uploads/initiate \
2 -H "Authorization: Bearer $PROSPOLABS_API_KEY" \
3 -H "Content-Type: application/json" \
4 -d '{"content_type":"video/mp4","file_name":"my-clip.mp4"}'
5
6# Response:
7# {
8# "token": "pl-upload-3d756375a28d44cead027db57565f176",
9# "upload_url": "/v1/uploads/proxy/pl-upload-3d756375a28d44cead027db57565f176",
10# "content_type": "video/mp4"
11# }

2. PUT the raw file bytes to upload_url. Use the same content type you initiated with.

1curl -X PUT "https://api.prospolabs.com/v1/uploads/proxy/pl-upload-3d756375a28d44cead027db57565f176" \
2 -H "Authorization: Bearer $PROSPOLABS_API_KEY" \
3 -H "Content-Type: video/mp4" \
4 --data-binary @my-clip.mp4
5
6# Response: { "status": "uploaded", "bytes": 12345678 }

3. Use the token in any generate request. The server resolves it before dispatching the model.

1curl -X POST https://api.prospolabs.com/v1/generate \
2 -H "Authorization: Bearer $PROSPOLABS_API_KEY" \
3 -H "Content-Type: application/json" \
4 -d '{
5 "model": "seedance-2",
6 "mode": "reference",
7 "params": {
8 "prompt": "animate the product on a beach at golden hour",
9 "image_urls": ["pl-upload-3d756375a28d44cead027db57565f176"],
10 "duration": 6,
11 "resolution": "720p"
12 }
13 }'

Limits

  • Images: JPEG / PNG / WebP, up to 30 MB per file.
  • Videos: MP4 / MOV, up to 50 MB per file.
  • Audio: MP3 / WAV, up to 15 MB per file.
  • Token lifetime: 1 hour pre-PUT, 24 hours after upload completes. Tokens are single-account — only the API key that minted them can redeem them.

Sync vs Async API

Use the standard endpoint for synchronous processing, or pass ?async=true for asynchronous processing. Recommended for video generations longer than 5 seconds.

POST /v1/generate

Blocks until processing completes. Best for image generation and short video clips.

Timeout: 180 seconds. For longer generations, use async mode.

Response

1{
2 "generation_id": "gen_a1b2c3d4e5f6",
3 "status": "completed",
4 "model": "veo-3-1-lite",
5 "mode": "text",
6 "output_url": "https://cdn.prospolabs.com/results/gen_a1b2c3d4e5f6.mp4?token=...",
7 "cost_usd": 0.40,
8 "duration_ms": 28430
9}

Webhooks

Configure a webhook URL in your dashboard or pass it per-request via the webhook_url field.

Event Types

EventDescription
generation.completedGeneration completed successfully. Includes output_url and cost_usd.
generation.failedGeneration failed. The corresponding cost has been refunded automatically.

Payload Format

1{
2 "event": "generation.completed",
3 "generation_id": "gen_a1b2c3d4e5f6",
4 "data": {
5 "model": "veo-3-1",
6 "mode": "text",
7 "output_url": "https://cdn.prospolabs.com/results/gen_a1b2c3d4e5f6.mp4?token=...",
8 "cost_usd": 3.22,
9 "duration_ms": 42180
10 },
11 "timestamp": "2026-05-02T14:33:27.000Z"
12}

Verifying Webhook Signatures

Every webhook includes an X-Prospo-Signature header containing an HMAC-SHA256 signature. Verify it against your webhook secret.

1import crypto from 'crypto';
2
3function verifyWebhook(payload, signature, secret) {
4 const expected = crypto
5 .createHmac('sha256', secret)
6 .update(payload)
7 .digest('hex');
8 return crypto.timingSafeEqual(
9 Buffer.from(signature),
10 Buffer.from(expected)
11 );
12}
13
14app.post('/api/webhook', (req, res) => {
15 const signature = req.headers['x-prospo-signature'];
16 const isValid = verifyWebhook(JSON.stringify(req.body), signature, process.env.WEBHOOK_SECRET);
17 if (!isValid) return res.status(401).send('Invalid signature');
18
19 const { event, data } = req.body;
20 if (event === 'generation.completed') {
21 console.log('Output ready:', data.output_url, 'cost:', data.cost_usd);
22 }
23 res.status(200).send('OK');
24});

Retry Policy

If your endpoint returns a non-2xx status code, we'll retry delivery with exponential backoff:

  • 1First retry: 30 seconds after initial attempt
  • 2Second retry: 2 minutes after first retry
  • 3Third retry: 10 minutes after second retry
  • 4Final retry: 1 hour after third retry
  • 5After 4 failed attempts the webhook is marked as failed and surfaced in the dashboard

Check Balance

Returns your current USD credit balance. Useful for budget alerts, dashboards, or deciding whether to top up before a large batch run. Authenticates with the same Bearer token as any other endpoint.

GET/v1/balance

Returns { balance_usd, currency } for the authenticated user. No body, no query params.

Example

1curl https://api.prospolabs.com/v1/balance \
2 -H "Authorization: Bearer $PROSPOLABS_API_KEY"
3
4# Response:
5# {
6# "balance_usd": 12.345,
7# "currency": "USD"
8# }

Rate Limits

Default: 60 requests per minute. Monitor your usage via the response headers X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset.

Need higher rate limits, dedicated capacity, or SLA guarantees? Contact us with your expected volume and we'll work with you directly.

Contact us for higher limits →

Error Handling

The API uses standard HTTP status codes. All error responses include a JSON body with a machine-readable code and human-readable message.

StatusNameDescription
400Bad RequestInvalid request body, unknown model id, unknown mode, or missing required field
401UnauthorizedMissing or invalid API key / Bearer token
403ForbiddenInsufficient balance or account suspended
404Not FoundGeneration not found (for polling endpoint)
429Too Many RequestsRate limit exceeded. Check X-RateLimit-* headers
500Internal Server ErrorUnexpected server error. Your balance is automatically refunded
504Gateway TimeoutProvider unavailable or generation exceeded model timeout

Error Response Example

1{
2 "detail": "Insufficient balance. Please top up to continue."
3}