curl --request POST \
--url https://api.creatorline.io/v1/generations/cost \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"tool": "ugc-video",
"params": {
"duration": "10"
}
}
'import requests
url = "https://api.creatorline.io/v1/generations/cost"
payload = {
"tool": "ugc-video",
"params": { "duration": "10" }
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({tool: 'ugc-video', params: {duration: '10'}})
};
fetch('https://api.creatorline.io/v1/generations/cost', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.creatorline.io/v1/generations/cost",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'tool' => 'ugc-video',
'params' => [
'duration' => '10'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.creatorline.io/v1/generations/cost"
payload := strings.NewReader("{\n \"tool\": \"ugc-video\",\n \"params\": {\n \"duration\": \"10\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.creatorline.io/v1/generations/cost")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"tool\": \"ugc-video\",\n \"params\": {\n \"duration\": \"10\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.creatorline.io/v1/generations/cost")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"tool\": \"ugc-video\",\n \"params\": {\n \"duration\": \"10\"\n }\n}"
response = http.request(request)
puts response.read_body{
"object": "cost_estimate",
"model": "bytedance-seedance-2-0-reference-to-video-fast",
"stage": "video-ref",
"count": 1,
"credits": 48,
"credit_balance": 4433,
"sufficient": true
}{
"error": {
"type": "invalid_request_error",
"code": "invalid_parameter",
"message": "Unknown tool \"video\". Available tools: ugc-video, reshoot, short-clip, scene-video, motion-control, hook-captions, merge-clips, photo-edit, text-to-photo, add-audio, lipsync, change-voice, text-to-speech, dialogue",
"param": "tool"
},
"request_id": "req_8fQ2mRxK1pLd"
}{
"error": {
"type": "authentication_error",
"code": "invalid_api_key",
"message": "Missing or invalid API key."
},
"request_id": "req_8fQ2mRxK1pLd"
}Estimate a generation's cost
Price a run in credits WITHOUT starting it. Takes the same body as the create call and runs it through the same function the debit uses, so an estimate can never disagree with the charge. Free, and available to read keys.
curl --request POST \
--url https://api.creatorline.io/v1/generations/cost \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"tool": "ugc-video",
"params": {
"duration": "10"
}
}
'import requests
url = "https://api.creatorline.io/v1/generations/cost"
payload = {
"tool": "ugc-video",
"params": { "duration": "10" }
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({tool: 'ugc-video', params: {duration: '10'}})
};
fetch('https://api.creatorline.io/v1/generations/cost', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.creatorline.io/v1/generations/cost",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'tool' => 'ugc-video',
'params' => [
'duration' => '10'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.creatorline.io/v1/generations/cost"
payload := strings.NewReader("{\n \"tool\": \"ugc-video\",\n \"params\": {\n \"duration\": \"10\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.creatorline.io/v1/generations/cost")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"tool\": \"ugc-video\",\n \"params\": {\n \"duration\": \"10\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.creatorline.io/v1/generations/cost")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"tool\": \"ugc-video\",\n \"params\": {\n \"duration\": \"10\"\n }\n}"
response = http.request(request)
puts response.read_body{
"object": "cost_estimate",
"model": "bytedance-seedance-2-0-reference-to-video-fast",
"stage": "video-ref",
"count": 1,
"credits": 48,
"credit_balance": 4433,
"sufficient": true
}{
"error": {
"type": "invalid_request_error",
"code": "invalid_parameter",
"message": "Unknown tool \"video\". Available tools: ugc-video, reshoot, short-clip, scene-video, motion-control, hook-captions, merge-clips, photo-edit, text-to-photo, add-audio, lipsync, change-voice, text-to-speech, dialogue",
"param": "tool"
},
"request_id": "req_8fQ2mRxK1pLd"
}{
"error": {
"type": "authentication_error",
"code": "invalid_api_key",
"message": "Missing or invalid API key."
},
"request_id": "req_8fQ2mRxK1pLd"
}Authorizations
Your organization's API key, from Settings → MCP. Authorization: Bearer crl_sk_live_…
Body
Required. Generate as this creator — inherits their look, voice and persona, and the run lands in their API project.
The tool to run. Preferred over stage.
ugc-video, reshoot, short-clip, scene-video, motion-control, hook-captions, merge-clips, photo-edit, text-to-photo, add-audio, lipsync, change-voice, text-to-speech, dialogue Lower-level escape hatch when you want to address a stage directly.
Override the tool's default model. Must belong to the tool's stage.
nano-banana-pro, nano-banana-2-text-to-image, gpt-image-v2-text-to-image, nano-banana-pro-edit, nano-banana-2-edit, bytedance-seedream-v4-5-edit, gpt-image-v2-edit, bytedance-seedance-2-5-image-to-video, bytedance-seedance-2-0-image-to-video, bytedance-seedance-2-0-image-to-video-fast, xai-grok-imagine-video-1-5-preview-image-to-video, minimax-h3-max-image-to-video, minimax-h3-max-turbo-image-to-video, kling-v3-4k-image-to-video, kling-v3-pro-image-to-video, kling-v3-standard-image-to-video, kling-o3-standard-image-to-video, google-gemini-omni-flash-image-to-video, veo-3-1-lite-text-to-video, veo-3-1-lite-first-last-frame-to-video, veo3-1-text-to-video, veo3-1-first-last-frame-to-video, veo3-1-first-last-frame-to-video-fast, veo3-1-reference-to-video, flux-3-text-to-video, flux-3-image-to-video-timestamped, bytedance-seedance-2-0-reference-to-video, bytedance-seedance-2-0-mini-reference-to-video, bytedance-seedance-2-0-reference-to-video-fast, bytedance-seedance-2-5-reference-to-video, xai-grok-imagine-reference-to-video, google-gemini-omni-flash-reference-to-video, kling-v3-standard-motion-control, hook-write, caption-burn, short-clip, bytedance-seedance-2-0-text-to-video, minimax-h3-max-text-to-video, minimax-h3-max-turbo-text-to-video, sync-3-lipsync, sync-lipsync-v2-pro, ffmpeg-api-merge-audio-video, elevenlabs-zrm-text-to-speech, elevenlabs-zrm-text-to-dialogue, change-voice, merge-clips, scene-seedance-2-5, reshoot-seedance-2-0, reshoot-seedance-2-5, scene-seedance-2-0, scene-seedance-2-0-mini, scene-kling-o3-pro-reference, scene-seedance-2-0-fast, scene-kling-o3-standard-reference, scene-kling-o3-pro-edit, scene-kling-o3-standard-edit What to create. Required by most models.
The avatar the run renders with (from GET /v1/avatars): its face goes into the model's character slot and its voice is the default for any voice parameter. Must belong to your workspace (404 otherwise). Omit to use the account's default avatar.
Slot key → asset id(s) or public https URL(s), per the model's inputs. A URL is adopted as an asset automatically.
Show child attributes
Show child attributes
Model parameters. Validated against the model's schema — an unknown key is a 400.
Show child attributes
Show child attributes
Alternatives to produce, up to the model's max_count. Image models only; video is always one take.
1 <= x <= 4For a tool with accepts_source_url (today short-clip): the video LINK to work from, instead of uploading it. Pass this OR the source asset in inputs, never both. The run is priced off the link's real length.
The creator's avatar is added to the model's character slot so they stay recognisable across runs. Set false when the output must NOT contain the creator (a product shot on their account, a scene without them).
Response
The estimate.