curl --request GET \
--url https://api.ekly.ai/v1/models/{model_id}/estimate \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.ekly.ai/v1/models/{model_id}/estimate"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.ekly.ai/v1/models/{model_id}/estimate', 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.ekly.ai/v1/models/{model_id}/estimate",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.ekly.ai/v1/models/{model_id}/estimate"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.ekly.ai/v1/models/{model_id}/estimate")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.ekly.ai/v1/models/{model_id}/estimate")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"allowed": true,
"balance": 123,
"can_afford": true,
"credits": 123,
"credits_after_discount": 123,
"model": "<string>",
"billable_duration_seconds": 123,
"discount_percent": 0,
"reason": "<string>"
}{
"error": {
"code": "unauthenticated",
"message": "This API key is not valid. Create a new one in Settings → Team.",
"trace_id": "c3746d5302dc4be6b2e8fa99fa762a8c"
}
}{
"error": {
"code": "forbidden",
"message": "API keys can only call the /v1 API.",
"trace_id": "c3746d5302dc4be6b2e8fa99fa762a8c"
}
}{
"error": {
"code": "not_found",
"message": "No generation with that id for this key.",
"trace_id": "c3746d5302dc4be6b2e8fa99fa762a8c"
}
}{
"error": {
"code": "validation_error",
"details": [
{
"loc": [
"body",
"model"
],
"msg": "Field required",
"type": "missing"
}
],
"message": "Request validation failed.",
"trace_id": "c3746d5302dc4be6b2e8fa99fa762a8c"
}
}{
"error": {
"code": "rate_limited",
"message": "Rate limit exceeded; retry after 12s.",
"trace_id": "c3746d5302dc4be6b2e8fa99fa762a8c"
}
}Estimate cost
The credits a generation would charge for these settings, after your organization’s discounts, and whether your balance and plan allow it. An estimate reserves nothing; the actual charge happens when you generate.
curl --request GET \
--url https://api.ekly.ai/v1/models/{model_id}/estimate \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.ekly.ai/v1/models/{model_id}/estimate"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.ekly.ai/v1/models/{model_id}/estimate', 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.ekly.ai/v1/models/{model_id}/estimate",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.ekly.ai/v1/models/{model_id}/estimate"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.ekly.ai/v1/models/{model_id}/estimate")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.ekly.ai/v1/models/{model_id}/estimate")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"allowed": true,
"balance": 123,
"can_afford": true,
"credits": 123,
"credits_after_discount": 123,
"model": "<string>",
"billable_duration_seconds": 123,
"discount_percent": 0,
"reason": "<string>"
}{
"error": {
"code": "unauthenticated",
"message": "This API key is not valid. Create a new one in Settings → Team.",
"trace_id": "c3746d5302dc4be6b2e8fa99fa762a8c"
}
}{
"error": {
"code": "forbidden",
"message": "API keys can only call the /v1 API.",
"trace_id": "c3746d5302dc4be6b2e8fa99fa762a8c"
}
}{
"error": {
"code": "not_found",
"message": "No generation with that id for this key.",
"trace_id": "c3746d5302dc4be6b2e8fa99fa762a8c"
}
}{
"error": {
"code": "validation_error",
"details": [
{
"loc": [
"body",
"model"
],
"msg": "Field required",
"type": "missing"
}
],
"message": "Request validation failed.",
"trace_id": "c3746d5302dc4be6b2e8fa99fa762a8c"
}
}{
"error": {
"code": "rate_limited",
"message": "Rate limit exceeded; retry after 12s.",
"trace_id": "c3746d5302dc4be6b2e8fa99fa762a8c"
}
}Authorizations
An organization API key created in Settings → Team, sent as Authorization: Bearer <key>.
Path Parameters
A model id from GET /v1/models.
Query Parameters
Video or audio duration in seconds when pricing is per-second. Omit for per-generation models.
x > 0Quality tier when the model prices by quality.
Resolution tier (e.g. 720p, 1080p) when pricing varies by tier.
Model mode (e.g. extend_video) when pricing varies by mode.
Speed/quality variant when the model declares one; omitted, the catalog default is priced.
64JSON object of other priced parameter values, keyed by parameter name (e.g. {"aspect_ratio": "9:16"}). Named arguments win on conflict.
2000Same key the subsequent generate call will send, when you want the quote and the charge to resolve the same supplier.
128Reference image count when the model charges per reference.
x >= 0Opening-image count when an image-to-video model charges for its input image.
0 <= x <= 1Text length in characters for character-priced speech models.
x >= 0Estimated input tokens for token-priced models.
x >= 0Estimated output tokens for token-priced models.
x >= 0Image quality setting when the catalog prices by quality.
Image resolution tier when the catalog prices by resolution.
Aspect ratio or concrete WxH size for matrix-priced image models.
Number of outputs when pricing is per image or batch.
x >= 1Include native video audio in the price; defaults on for Veo.
Response
Successful Response
False when your plan cannot use this model; see reason.
List price in credits before discounts.