Reference
API reference
Every endpoint, parameter and response.
https://qulture-webapi-staging-381114038302.us-central1.run.app. Fields marked * are required.Account
Who the key belongs to and its API balance.
Returns the key's owner, which key was used, who pays (payer) and the API balance (billing.balance_usd). The quickest way to test a key. credits and plan are the Studio plan (used by connector keys).
curl https://qulture-webapi-staging-381114038302.us-central1.run.app/api/v1/developer/me \
-H "Authorization: Bearer $QULTURE_API_KEY"{
"success": true,
"message": "OK",
"data": {
"success": true,
"message": "OK",
"data": {
"user": {
"id": "172a9b77-06a8-491e-967c-8c245368de28",
"username": "studiotest",
"name": "Studio Test"
},
"credits": 6,
"plan": "free",
"key": {
"id": "1a976eb1-46bf-44a6-b49a-6254abb5b4ad",
"name": "My app",
"prefix": "qk_live_ULnO"
},
"billing": {
"balance_usd": 24.5,
"currency": "usd"
},
"payer": "api_balance"
}
}
}Errors: 401 Missing, invalid or revoked API key · 429 Rate limited: 60 requests/minute per key. All codes
Studio plan credits, next refill, plan limits and the credit price list. These apply to connector (MCP) keys; API keys pay from the API balance (see GET /developer/me).
curl https://qulture-webapi-staging-381114038302.us-central1.run.app/api/v1/studio/me \
-H "Authorization: Bearer $QULTURE_API_KEY"Errors: 401 Missing, invalid or revoked API key · 429 Rate limited: 60 requests/minute per key. All codes
Billing
Prices and your API balance. GET /developer/pricing is public; the other billing endpoints are used by the Console and need the signed-in dashboard session — they can't be called with an API key.
- GET/api/v1/developer/pricing
- GET/api/v1/developer/billing
- GET/api/v1/developer/billing/ledger
- POST/api/v1/developer/billing/checkout
- PUT/api/v1/developer/billing/auto-recharge
- POST/api/v1/developer/billing/portal
API prices
No key neededThe pay-as-you-go price list in USD, top-up limits and the default concurrency limit. Public: no key needed.
curl https://qulture-webapi-staging-381114038302.us-central1.run.app/api/v1/developer/pricing \
-H "Authorization: Bearer $QULTURE_API_KEY"{
"success": true,
"message": "OK",
"data": {
"success": true,
"message": "OK",
"data": {
"currency": "usd",
"prices": {
"video_draft_per_second": 0.1,
"video_standard_per_second": 0.18,
"video_pro_per_second": 0.26,
"audio_per_second": 0.02,
"image_flash": 0.06,
"image_pro": 0.12,
"recap": 0.3,
"story_assembly": 0.05,
"edit_render_per_minute": 0.05,
"enhance_per_minute": 0.05,
"character": 0.1
},
"min_topup_usd": 5,
"max_topup_usd": 5000,
"topup_presets_usd": [
10,
25,
100
],
"default_concurrency": 20
}
}
}Balance and billing settings
Dashboard session only**Dashboard session only; not callable with an API key** (an API key gets 403 developer_scope_denied). API balance, status, running generations vs. the concurrency limit, auto-recharge, lifetime totals, 30 days of spend and the latest 20 ledger entries.
{
"success": true,
"message": "OK",
"data": {
"success": true,
"message": "OK",
"data": {
"balance_usd": 24.5,
"currency": "usd",
"status": "active",
"concurrency_limit": 20,
"running": 1,
"auto_recharge": {
"enabled": true,
"threshold_usd": 10,
"amount_usd": 25,
"has_payment_method": true,
"card": {
"brand": "visa",
"last4": "4242"
},
"last_error": null
},
"low_balance_usd": 5,
"owed_usd": 0,
"frozen_usd": 0,
"lifetime": {
"topups_usd": 25,
"spend_usd": 0.5,
"refunds_usd": 0
},
"spend_30d": [
{
"date": "2026-10-29",
"spend_usd": 0.5,
"topups_usd": 25
}
],
"ledger": [
{
"id": "0b8a3c1e-5d2f-4b61-9a77-3e4c2f1d9a01",
"kind": "charge",
"amount_usd": -0.5,
"balance_after_usd": 24.5,
"reference": "job:3f0c…:charge",
"job_id": "8d67563e-bbaf-4357-9380-04c2fe602203",
"image_id": null,
"key_id": "1a976eb1-46bf-44a6-b49a-6254abb5b4ad",
"key_prefix": "qk_live_ULnO",
"description": "Video · Draft · 5 s",
"created_at": "2026-10-29T00:20:00Z"
}
],
"billing_enabled": true,
"portal_available": true,
"prices": {
"video_draft_per_second": 0.1,
"video_standard_per_second": 0.18,
"video_pro_per_second": 0.26,
"audio_per_second": 0.02,
"image_flash": 0.06,
"image_pro": 0.12,
"recap": 0.3,
"story_assembly": 0.05,
"edit_render_per_minute": 0.05,
"enhance_per_minute": 0.05,
"character": 0.1
}
}
}
}Errors: 401 Missing, invalid or revoked API key · 403 Not allowed: scope, Studio disabled, or account suspended (`developer_account_suspended`, e.g. after a refunded or disputed top-up). All codes
Billing history
Dashboard session only**Dashboard session only; not callable with an API key** (an API key gets 403 developer_scope_denied). Every charge, top-up and adjustment on the API balance, newest first.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| limit | query | integer | |
| offset | query | integer | |
| kind | query | topup | charge | refund | adjustment | promo | auto_recharge | stripe_refund | dispute | dispute_reversal | Only entries of this kind. |
{
"success": true,
"message": "OK",
"data": {
"success": true,
"message": "OK",
"data": {
"items": [
{
"id": "0b8a3c1e-5d2f-4b61-9a77-3e4c2f1d9a01",
"kind": "charge",
"amount_usd": -0.5,
"balance_after_usd": 24.5,
"reference": "job:3f0c…:charge",
"job_id": "8d67563e-bbaf-4357-9380-04c2fe602203",
"image_id": null,
"key_id": "1a976eb1-46bf-44a6-b49a-6254abb5b4ad",
"key_prefix": "qk_live_ULnO",
"description": "Video · Draft · 5 s",
"created_at": "2026-10-29T00:20:00Z"
}
],
"total": 1
}
}
}Errors: 401 Missing, invalid or revoked API key · 403 Not allowed: scope, Studio disabled, or account suspended (`developer_account_suspended`, e.g. after a refunded or disputed top-up). All codes
Add funds (Stripe Checkout)
Dashboard session only**Dashboard session only; not callable with an API key** (an API key gets 403 developer_scope_denied). Starts a Stripe Checkout payment for amount_usd (between min_topup_usd and max_topup_usd). Redirect the user to url; they come back to the Console with ?topup=success or ?topup=cancelled. The card is saved for auto-recharge. Funds are added when Stripe confirms the payment.
Body (JSON)
| Field | Type | Description |
|---|---|---|
| amount_usd * | number | |
| return_url | string |
{
"success": true,
"message": "OK",
"data": {
"success": true,
"message": "OK",
"data": {
"url": "https://checkout.stripe.com/c/pay/cs_…",
"session_id": "cs_…"
}
}
}Errors: 400 Amount out of range · 401 Missing, invalid or revoked API key · 403 Not allowed: scope, Studio disabled, or account suspended (`developer_account_suspended`, e.g. after a refunded or disputed top-up). All codes
Auto-recharge settings
Dashboard session only**Dashboard session only; not callable with an API key** (an API key gets 403 developer_scope_denied). When the balance falls below threshold_usd, charge the saved card amount_usd. Enabling needs a saved card (make one top-up first). Returns the billing object.
Body (JSON)
| Field | Type | Description |
|---|---|---|
| enabled * | boolean | |
| threshold_usd * | number | |
| amount_usd * | number |
{
"success": true,
"message": "OK",
"data": {
"success": true,
"message": "OK",
"data": {
"balance_usd": 24.5,
"currency": "usd",
"status": "active",
"concurrency_limit": 20,
"running": 1,
"auto_recharge": {
"enabled": true,
"threshold_usd": 10,
"amount_usd": 25,
"has_payment_method": true,
"card": {
"brand": "visa",
"last4": "4242"
},
"last_error": null
},
"low_balance_usd": 5,
"owed_usd": 0,
"frozen_usd": 0,
"lifetime": {
"topups_usd": 25,
"spend_usd": 0.5,
"refunds_usd": 0
},
"spend_30d": [
{
"date": "2026-10-29",
"spend_usd": 0.5,
"topups_usd": 25
}
],
"ledger": [
{
"id": "0b8a3c1e-5d2f-4b61-9a77-3e4c2f1d9a01",
"kind": "charge",
"amount_usd": -0.5,
"balance_after_usd": 24.5,
"reference": "job:3f0c…:charge",
"job_id": "8d67563e-bbaf-4357-9380-04c2fe602203",
"image_id": null,
"key_id": "1a976eb1-46bf-44a6-b49a-6254abb5b4ad",
"key_prefix": "qk_live_ULnO",
"description": "Video · Draft · 5 s",
"created_at": "2026-10-29T00:20:00Z"
}
],
"billing_enabled": true,
"portal_available": true,
"prices": {
"video_draft_per_second": 0.1,
"video_standard_per_second": 0.18,
"video_pro_per_second": 0.26,
"audio_per_second": 0.02,
"image_flash": 0.06,
"image_pro": 0.12,
"recap": 0.3,
"story_assembly": 0.05,
"edit_render_per_minute": 0.05,
"enhance_per_minute": 0.05,
"character": 0.1
}
}
}
}Errors: 400 Amount out of range · 401 Missing, invalid or revoked API key · 403 Not allowed: scope, Studio disabled, or account suspended (`developer_account_suspended`, e.g. after a refunded or disputed top-up) · 409 No saved card. All codes
Payment methods and receipts
Dashboard session only**Dashboard session only; not callable with an API key** (an API key gets 403 developer_scope_denied). Opens the Stripe customer portal (saved cards, receipts). Redirect the user to url.
Body (JSON)
| Field | Type | Description |
|---|---|---|
| return_url | string |
{
"success": true,
"message": "OK",
"data": {
"success": true,
"message": "OK",
"data": {
"url": "https://billing.stripe.com/p/session/…"
}
}
}Errors: 401 Missing, invalid or revoked API key · 403 Not allowed: scope, Studio disabled, or account suspended (`developer_account_suspended`, e.g. after a refunded or disputed top-up). All codes
Catalog
Templates, camera-move presets, voices and pricing.
- GET/api/v1/studio/catalog
- GET/api/v1/studio/templates
- GET/api/v1/studio/presets
- GET/api/v1/studio/voices
Public catalog and pricing
No key neededTemplates, presets, Studio plans and the Studio credit price list. Public: no key needed. API prices in USD are at GET /developer/pricing.
curl https://qulture-webapi-staging-381114038302.us-central1.run.app/api/v1/studio/catalog \
-H "Authorization: Bearer $QULTURE_API_KEY"Ready-made video ideas. Each lists the inputs it needs (photo, text…), its defaults and credit cost.
curl https://qulture-webapi-staging-381114038302.us-central1.run.app/api/v1/studio/templates \
-H "Authorization: Bearer $QULTURE_API_KEY"Errors: 401 Missing, invalid or revoked API key · 429 Rate limited: 60 requests/minute per key. All codes
Camera-move presets (dolly in, orbit, whip pan…), effects and styles. Pass a preset id as preset_id when you create a job.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| category | query | string | Filter by category id, e.g. classic, dynamic, effects. |
| mode | query | text_to_video | photo_to_video | template | transition | reference | character | talking_photo | sound_sync | describe | animate | Only presets that work with this mode. |
curl https://qulture-webapi-staging-381114038302.us-central1.run.app/api/v1/studio/presets \
-H "Authorization: Bearer $QULTURE_API_KEY"Errors: 401 Missing, invalid or revoked API key · 429 Rate limited: 60 requests/minute per key. All codes
Voices for talking_photo jobs (voice + speech_text).
curl https://qulture-webapi-staging-381114038302.us-central1.run.app/api/v1/studio/voices \
-H "Authorization: Bearer $QULTURE_API_KEY"Errors: 401 Missing, invalid or revoked API key · 429 Rate limited: 60 requests/minute per key. All codes
Uploads
Upload photos (and short audio/video) to use as inputs.
Multipart upload. Images: JPEG, PNG, WebP or HEIC up to 10 MB (normalised to JPEG). kind=audio (≤ 15 s) and kind=video (≤ 15 s, ≤ 50 MB) are accepted too. Use the returned key in image_keys (or a template's image input). If has_face is true, send consent: true with the job.
Body (multipart/form-data)
| Field | Type | Description |
|---|---|---|
| file * | string | |
| kind | image | audio | video | Default image. |
{
"success": true,
"message": "OK",
"data": {
"success": true,
"message": "OK",
"data": {
"key": "studio/inputs/172a9b77-…/a4095776-….jpg",
"url": "https://media.joinqulture.com/studio/inputs/…",
"width": 1080,
"height": 1350,
"has_face": true,
"kind": "image"
}
}
}Errors: 400 Bad request · 401 Missing, invalid or revoked API key · 413 File too large · 415 Unsupported file · 429 Rate limited: 60 requests/minute per key. All codes
Videos
Create and follow video jobs.
- POST/api/v1/studio/jobs
- GET/api/v1/studio/jobs
- GET/api/v1/studio/jobs/{id}
- DELETE/api/v1/studio/jobs/{id}
- POST/api/v1/studio/jobs/{id}/regenerate
- POST/api/v1/studio/jobs/{id}/extend
- POST/api/v1/studio/jobs/{id}/upgrade
Create a video
Paid from API balanceStarts a video job and charges its price to your API balance (duration × the tier's price per second; cost_usd on the job). The response is the job (usually queued); follow it with GET /jobs/{id} or pass webhook_url to be called when it finishes. You're charged when a generation is submitted and finishes processing, whatever its outcome. Requests rejected before processing (invalid input, insufficient balance, limits) are never charged: not enough balance → 402 insufficient_balance (no job is created).
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| X-Qulture-Request-ID | header | string | Any unique string. Retrying with the same value never creates (or charges) twice. |
Body (JSON)
| Field | Type | Description |
|---|---|---|
| mode * | text_to_video | photo_to_video | template | transition | reference | character | talking_photo | sound_sync | describe | animate | What kind of video to make. |
| prompt | string | What should happen. Required for text_to_video. |
| tier | draft | standard | pro | Quality tier, priced per second. Draft is cheapest. |
| duration | 5 | 10 | Seconds. Billed per second. Default 5. |
| aspect | 9:16 | 1:1 | 4:5 | 16:9 | Default 9:16. |
| preset_id | string | Camera move / effect id from GET /presets. |
| template_id | string | Template id from GET /templates (mode template). |
| inputs | object | Template inputs by key: upload keys for photos, strings for text. |
| image_keys | string[] | Upload keys (photo_to_video, reference, transition = [first, last]). |
| sound | boolean | Generate sound. Default false. |
| consent | boolean | Required when a photo shows a person: you confirm you have their permission. Default false. |
| character_id | string | |
| voice | string | Voice id (talking_photo). |
| speech_text | string | What the photo says (talking_photo). |
| audio_key | string | Uploaded audio (sound_sync). |
| webhook_url | string | https URL Qulture POSTs a signed event to when the job finishes. API keys only. |
curl -X POST https://qulture-webapi-staging-381114038302.us-central1.run.app/api/v1/studio/jobs \
-H "Authorization: Bearer $QULTURE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"mode": "text_to_video",
"prompt": "A neon-lit street market at night, slow camera push in",
"tier": "draft",
"duration": 5,
"aspect": "9:16"
}'More examples: Photo to video with a camera move, Template — open them in the playground.
{
"success": true,
"message": "OK",
"data": {
"success": true,
"message": "OK",
"data": {
"id": "8d67563e-bbaf-4357-9380-04c2fe602203",
"template_id": null,
"template_name": null,
"mode": "text_to_video",
"status": "queued",
"progress": 0,
"stage_label": "In the queue",
"queue_position": 1,
"duration_s": 5,
"quality": "standard",
"sound": false,
"credits_charged": 0,
"billing": "api_balance",
"cost_usd": 0.5,
"charged_usd": 0.5,
"video_url": null,
"download_url": null,
"thumbnail_url": null,
"watermarked": false,
"caption": null,
"hashtags": [],
"fail_reason": null,
"block_category": null,
"posted_media_id": null,
"prompt": "A neon-lit street market at night, slow camera push in",
"inputs": {},
"created_at": "2026-10-29T00:20:00Z",
"finished_at": null,
"expires_at": null,
"kind": "video",
"tier": "draft",
"aspect": "9:16",
"preset_id": null,
"character_id": null,
"parent_job_id": null,
"story_id": null,
"shot_id": null,
"avatar_user_ids": [],
"needs_approval": false,
"post_status": ""
}
}
}Errors: 400 Bad request · 401 Missing, invalid or revoked API key · 402 Not enough API balance (`insufficient_balance`; connector keys: `studio_insufficient_credits`). Nothing is created or charged. · 403 Not allowed: scope, Studio disabled, or account suspended (`developer_account_suspended`, e.g. after a refunded or disputed top-up) · 422 Blocked by safety checks, or consent needed · 429 Rate limited (`rate_limited`: 60 requests/minute, or 200 generations/hour per API key — 20 for connector keys) or too many generations running at once for the account (`concurrency_limit`, 20) · 503 Busy — try again shortly. All codes
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| cursor | query | string | next_cursor from the previous page. |
| limit | query | integer |
curl https://qulture-webapi-staging-381114038302.us-central1.run.app/api/v1/studio/jobs \
-H "Authorization: Bearer $QULTURE_API_KEY"Errors: 401 Missing, invalid or revoked API key · 429 Rate limited: 60 requests/minute per key. All codes
Status, progress and — once ready — signed video_url / download_url (valid for 1 hour; fetch the job again for fresh links). Poll every 5 s.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| id * | path | string | Job id |
curl https://qulture-webapi-staging-381114038302.us-central1.run.app/api/v1/studio/jobs/JOB_ID \
-H "Authorization: Bearer $QULTURE_API_KEY"{
"success": true,
"message": "OK",
"data": {
"success": true,
"message": "OK",
"data": {
"id": "8d67563e-bbaf-4357-9380-04c2fe602203",
"template_id": null,
"template_name": null,
"mode": "text_to_video",
"status": "ready",
"progress": 1,
"stage_label": "Ready",
"queue_position": null,
"duration_s": 5,
"quality": "standard",
"sound": false,
"credits_charged": 0,
"billing": "api_balance",
"cost_usd": 0.5,
"charged_usd": 0.5,
"video_url": "https://media.joinqulture.com/studio/out/…/marked.mp4?X-Amz-Signature=…",
"download_url": "https://media.joinqulture.com/studio/out/…/marked.mp4?…&response-content-disposition=attachment",
"thumbnail_url": "https://media.joinqulture.com/studio/out/…/thumb.jpg?…",
"watermarked": false,
"caption": "Night market glow ✨",
"hashtags": [
"#MadeWithQulture"
],
"fail_reason": null,
"block_category": null,
"posted_media_id": null,
"prompt": "A neon-lit street market at night, slow camera push in",
"inputs": {},
"created_at": "2026-10-29T00:20:00Z",
"finished_at": "2026-10-29T00:21:10Z",
"expires_at": null,
"kind": "video",
"tier": "draft",
"aspect": "9:16",
"preset_id": null,
"character_id": null,
"parent_job_id": null,
"story_id": null,
"shot_id": null,
"avatar_user_ids": [],
"needs_approval": false,
"post_status": ""
}
}
}Errors: 401 Missing, invalid or revoked API key · 404 Not found · 429 Rate limited: 60 requests/minute per key. All codes
Deletes the creation and its files. Jobs still in progress return 409 studio_job_not_ready.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| id * | path | string | Job id |
curl -X DELETE https://qulture-webapi-staging-381114038302.us-central1.run.app/api/v1/studio/jobs/JOB_ID \
-H "Authorization: Bearer $QULTURE_API_KEY"{
"success": true,
"message": "OK",
"data": {
"success": true,
"message": "OK",
"data": null
}
}Errors: 401 Missing, invalid or revoked API key · 404 Not found · 409 Not ready yet · 429 Rate limited: 60 requests/minute per key. All codes
Regenerate
Paid from API balanceSame inputs, new seed. A new job, charged again. Accepts an optional JSON body with webhook_url.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| id * | path | string | Job id |
Body (JSON)
| Field | Type | Description |
|---|---|---|
| webhook_url | string | https URL Qulture POSTs a signed event to when the job finishes. API keys only. |
curl -X POST https://qulture-webapi-staging-381114038302.us-central1.run.app/api/v1/studio/jobs/JOB_ID/regenerate \
-H "Authorization: Bearer $QULTURE_API_KEY"Errors: 401 Missing, invalid or revoked API key · 402 Not enough API balance (`insufficient_balance`; connector keys: `studio_insufficient_credits`). Nothing is created or charged. · 403 Not allowed: scope, Studio disabled, or account suspended (`developer_account_suspended`, e.g. after a refunded or disputed top-up) · 404 Not found · 422 Blocked by safety checks, or consent needed · 429 Rate limited (`rate_limited`: 60 requests/minute, or 200 generations/hour per API key — 20 for connector keys) or too many generations running at once for the account (`concurrency_limit`, 20). All codes
Extend a video
Paid from API balanceContinues a ready video with a new prompt. Returns a new job with parent_job_id set.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| id * | path | string | Job id |
Body (JSON)
| Field | Type | Description |
|---|---|---|
| prompt * | string | |
| duration * | 5 | 10 | |
| tier | draft | standard | pro | Quality tier, priced per second. Draft is cheapest. |
| webhook_url | string | https URL Qulture POSTs a signed event to when the job finishes. API keys only. |
curl -X POST https://qulture-webapi-staging-381114038302.us-central1.run.app/api/v1/studio/jobs/JOB_ID/extend \
-H "Authorization: Bearer $QULTURE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"prompt": "The camera rises above the market",
"duration": 5,
"tier": "draft"
}'Errors: 400 Bad request · 401 Missing, invalid or revoked API key · 402 Not enough API balance (`insufficient_balance`; connector keys: `studio_insufficient_credits`). Nothing is created or charged. · 403 Not allowed: scope, Studio disabled, or account suspended (`developer_account_suspended`, e.g. after a refunded or disputed top-up) · 404 Not found · 409 Not ready yet · 429 Rate limited (`rate_limited`: 60 requests/minute, or 200 generations/hour per API key — 20 for connector keys) or too many generations running at once for the account (`concurrency_limit`, 20). All codes
Upgrade a Draft
Paid from API balanceRe-renders a Draft with the same shot plan and seed at a higher tier. A new job, charged at the new tier's price.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| id * | path | string | Job id |
Body (JSON)
| Field | Type | Description |
|---|---|---|
| tier * | standard | pro | |
| webhook_url | string | https URL Qulture POSTs a signed event to when the job finishes. API keys only. |
curl -X POST https://qulture-webapi-staging-381114038302.us-central1.run.app/api/v1/studio/jobs/JOB_ID/upgrade \
-H "Authorization: Bearer $QULTURE_API_KEY"Errors: 401 Missing, invalid or revoked API key · 402 Not enough API balance (`insufficient_balance`; connector keys: `studio_insufficient_credits`). Nothing is created or charged. · 403 Not allowed: scope, Studio disabled, or account suspended (`developer_account_suspended`, e.g. after a refunded or disputed top-up) · 404 Not found · 409 Not ready yet · 429 Rate limited (`rate_limited`: 60 requests/minute, or 200 generations/hour per API key — 20 for connector keys) or too many generations running at once for the account (`concurrency_limit`, 20). All codes
Images
Create images and turn them into videos.
- POST/api/v1/studio/images
- GET/api/v1/studio/images
- GET/api/v1/studio/images/{id}
- POST/api/v1/studio/images/{id}/animate
Create an image
Paid from API balanceGenerates an image from a prompt (optionally guided by uploaded image_keys). Follow it with GET /images/{id} or webhook_url.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| X-Qulture-Request-ID | header | string | Any unique string. Retrying with the same value never creates (or charges) twice. |
Body (JSON)
| Field | Type | Description |
|---|---|---|
| prompt * | string | |
| quality | flash | pro | Default flash. |
| aspect | 9:16 | 1:1 | 4:5 | 16:9 | Default 9:16. |
| image_keys | string[] | Optional reference photos (upload keys). |
| webhook_url | string | https URL Qulture POSTs a signed event to when the job finishes. API keys only. |
curl -X POST https://qulture-webapi-staging-381114038302.us-central1.run.app/api/v1/studio/images \
-H "Authorization: Bearer $QULTURE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"prompt": "Poster of a rooftop party at golden hour",
"quality": "flash",
"aspect": "9:16"
}'{
"success": true,
"message": "OK",
"data": {
"success": true,
"message": "OK",
"data": {
"id": "4b1f0f1e-9a52-4c43-8d0f-3f7d8f8f2a10",
"prompt": "Poster of a rooftop party at golden hour",
"status": "queued",
"image_url": null,
"width": null,
"height": null,
"billing": "api_balance",
"cost_usd": 0.06,
"charged_usd": 0.06,
"created_at": "2026-10-29T00:20:00Z"
}
}
}Errors: 400 Bad request · 401 Missing, invalid or revoked API key · 402 Not enough API balance (`insufficient_balance`; connector keys: `studio_insufficient_credits`). Nothing is created or charged. · 403 Not allowed: scope, Studio disabled, or account suspended (`developer_account_suspended`, e.g. after a refunded or disputed top-up) · 422 Blocked by safety checks, or consent needed · 429 Rate limited (`rate_limited`: 60 requests/minute, or 200 generations/hour per API key — 20 for connector keys) or too many generations running at once for the account (`concurrency_limit`, 20). All codes
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| cursor | query | string |
curl https://qulture-webapi-staging-381114038302.us-central1.run.app/api/v1/studio/images \
-H "Authorization: Bearer $QULTURE_API_KEY"Errors: 401 Missing, invalid or revoked API key · 429 Rate limited: 60 requests/minute per key. All codes
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| id * | path | string | Image id |
curl https://qulture-webapi-staging-381114038302.us-central1.run.app/api/v1/studio/images/IMAGE_ID \
-H "Authorization: Bearer $QULTURE_API_KEY"{
"success": true,
"message": "OK",
"data": {
"success": true,
"message": "OK",
"data": {
"id": "4b1f0f1e-9a52-4c43-8d0f-3f7d8f8f2a10",
"prompt": "Poster of a rooftop party at golden hour",
"status": "ready",
"image_url": "https://media.joinqulture.com/…/image.jpg?…",
"width": 1080,
"height": 1920,
"billing": "api_balance",
"cost_usd": 0.06,
"charged_usd": 0.06,
"created_at": "2026-10-29T00:20:00Z"
}
}
}Errors: 401 Missing, invalid or revoked API key · 404 Not found · 429 Rate limited: 60 requests/minute per key. All codes
Turn an image into a video
Paid from API balanceCreates a photo_to_video job from a ready image. Same body as POST /jobs without image inputs.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| id * | path | string | Image id |
Body (JSON)
| Field | Type | Description |
|---|---|---|
| mode * | text_to_video | photo_to_video | template | transition | reference | character | talking_photo | sound_sync | describe | animate | What kind of video to make. |
| prompt | string | What should happen. Required for text_to_video. |
| tier | draft | standard | pro | Quality tier, priced per second. Draft is cheapest. |
| duration | 5 | 10 | Seconds. Billed per second. Default 5. |
| aspect | 9:16 | 1:1 | 4:5 | 16:9 | Default 9:16. |
| preset_id | string | Camera move / effect id from GET /presets. |
| template_id | string | Template id from GET /templates (mode template). |
| inputs | object | Template inputs by key: upload keys for photos, strings for text. |
| image_keys | string[] | Upload keys (photo_to_video, reference, transition = [first, last]). |
| sound | boolean | Generate sound. Default false. |
| consent | boolean | Required when a photo shows a person: you confirm you have their permission. Default false. |
| character_id | string | |
| voice | string | Voice id (talking_photo). |
| speech_text | string | What the photo says (talking_photo). |
| audio_key | string | Uploaded audio (sound_sync). |
| webhook_url | string | https URL Qulture POSTs a signed event to when the job finishes. API keys only. |
curl -X POST https://qulture-webapi-staging-381114038302.us-central1.run.app/api/v1/studio/images/IMAGE_ID/animate \
-H "Authorization: Bearer $QULTURE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"mode": "photo_to_video",
"prompt": "Slow orbit around the poster",
"tier": "draft",
"duration": 5
}'Errors: 400 Bad request · 401 Missing, invalid or revoked API key · 402 Not enough API balance (`insufficient_balance`; connector keys: `studio_insufficient_credits`). Nothing is created or charged. · 403 Not allowed: scope, Studio disabled, or account suspended (`developer_account_suspended`, e.g. after a refunded or disputed top-up) · 404 Not found · 409 Not ready yet · 429 Rate limited (`rate_limited`: 60 requests/minute, or 200 generations/hour per API key — 20 for connector keys) or too many generations running at once for the account (`concurrency_limit`, 20). All codes