Get task status
curl --request GET \
--url https://api.poyo.ai/api/generate/status/{task_id} \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.poyo.ai/api/generate/status/{task_id}"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.poyo.ai/api/generate/status/{task_id}', 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.poyo.ai/api/generate/status/{task_id}",
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.poyo.ai/api/generate/status/{task_id}"
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.poyo.ai/api/generate/status/{task_id}")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.poyo.ai/api/generate/status/{task_id}")
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{
"code": 200,
"data": {
"task_id": "task-unified-1757165031-uyujaw3d",
"status": "finished",
"credits_amount": 2,
"files": [
{
"file_url": "https://storage.poyo.ai/generated/image-abc123.jpg",
"file_type": "image"
}
],
"created_time": "2025-11-12T10:30:00",
"progress": 100,
"error_message": null
}
}{
"code": 200,
"error": {
"message": "<string>",
"type": "<string>"
}
}All Tasks
Get Task Status
Query task execution status and retrieve generation results
GET
/
api
/
generate
/
status
/
{task_id}
Get task status
curl --request GET \
--url https://api.poyo.ai/api/generate/status/{task_id} \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.poyo.ai/api/generate/status/{task_id}"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.poyo.ai/api/generate/status/{task_id}', 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.poyo.ai/api/generate/status/{task_id}",
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.poyo.ai/api/generate/status/{task_id}"
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.poyo.ai/api/generate/status/{task_id}")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.poyo.ai/api/generate/status/{task_id}")
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{
"code": 200,
"data": {
"task_id": "task-unified-1757165031-uyujaw3d",
"status": "finished",
"credits_amount": 2,
"files": [
{
"file_url": "https://storage.poyo.ai/generated/image-abc123.jpg",
"file_type": "image"
}
],
"created_time": "2025-11-12T10:30:00",
"progress": 100,
"error_message": null
}
}{
"code": 200,
"error": {
"message": "<string>",
"type": "<string>"
}
}Get Task Status
Query the execution status of image, video, audio, 3D, and content moderation tasks and retrieve results when complete.Endpoint
GET https://api.poyo.ai/api/generate/status/{task_id}
Authentication
All requests require Bearer token authentication:Authorization: Bearer YOUR_API_KEY
Get API Key
Generate your API key from the console
Parameters
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
task_id | string | Yes | Unique task identifier returned from the submit endpoint |
Response
Success Response (200)
{
"code": 200,
"data": {
"task_id": "task-unified-1757165031-uyujaw3d",
"status": "finished",
"credits_amount": 2,
"files": [
{
"file_url": "https://storage.poyo.ai/generated/image-abc123.jpg",
"file_type": "image"
}
],
"created_time": "2025-11-12T10:30:00",
"progress": 100,
"error_message": null
}
}
Response Fields
| Field | Type | Description |
|---|---|---|
code | integer | HTTP status code (200 for success) |
data.task_id | string | Unique task identifier |
data.status | string | Task status: not_started, running, finished, failed |
data.credits_amount | number | Credits charged for the task |
data.output | object | Optional structured model output. Omni Moderation returns the complete OpenAI moderation response here, with files: [] and credits_amount: 0 |
data.files | array | Generated media files (when status is finished) |
data.files[].file_url | string | Direct URL to generated file |
data.files[].file_type | string | Type of generated file: image, video, audio, 3d, or other |
data.files[].label | string | Optional file label. Common for 3D outputs, such as model_glb or thumbnail |
data.files[].format | string | Optional file format, such as glb, fbx, obj, png, or mp4 |
data.files[].content_type | string | Optional MIME type of the generated file |
data.files[].file_name | string | Optional file name |
data.files[].file_size | integer | Optional file size in bytes |
data.files[] structured fields | object | Some audio workflows return fields such as voice_id, voice_status, is_available, or origin_data instead of a single media URL |
data.created_time | string | ISO 8601 timestamp of task creation |
data.progress | integer | Completion percentage (0-100) |
data.error_message | string | Error description (when status is failed) |
data.output.results[].flagged after the status becomes finished. A flagged: true result means the review completed and detected content; it does not make the task failed. Omni Moderation runs asynchronously, and supports callbacks through callback_url. Streaming is not supported. Its callback body is the same task data object returned here, including output when available and credits_amount: 0.
Status Values
| Status | Description |
|---|---|
not_started | Task is queued, waiting to be processed |
running | Task is currently being generated |
finished | Task completed successfully, results available in files or output |
failed | Task failed, error details in error_message |
Response Examples by Status
Not Started
{
"code": 200,
"data": {
"task_id": "task-unified-1757165031-uyujaw3d",
"status": "not_started",
"credits_amount": 2,
"files": [],
"created_time": "2025-11-12T10:30:00",
"progress": 0,
"error_message": null
}
}
Running
{
"code": 200,
"data": {
"task_id": "task-unified-1757165031-uyujaw3d",
"status": "running",
"credits_amount": 2,
"files": [],
"created_time": "2025-11-12T10:30:00",
"progress": 45,
"error_message": null
}
}
Finished (Image)
{
"code": 200,
"data": {
"task_id": "task-unified-1757165031-uyujaw3d",
"status": "finished",
"credits_amount": 2,
"files": [
{
"file_url": "https://storage.poyo.ai/generated/image-abc123.jpg",
"file_type": "image"
}
],
"created_time": "2025-11-12T10:30:00",
"progress": 100,
"error_message": null
}
}
Finished (Video)
{
"code": 200,
"data": {
"task_id": "task-unified-1757165211-xyz789",
"status": "finished",
"credits_amount": 20,
"files": [
{
"file_url": "https://storage.poyo.ai/generated/video-xyz789.mp4",
"file_type": "video"
}
],
"created_time": "2025-11-12T10:30:00",
"progress": 100,
"error_message": null
}
}
Finished (TTS)
{
"code": 200,
"data": {
"task_id": "KAI9LGP3UIXLG51W",
"status": "finished",
"credits_amount": 1,
"files": [
{
"file_url": "https://cdn.doculator.org/audios/KAI9LGP3UIXLG51W/KAI9LGP3UIXLG51W.mp3",
"file_type": "audio"
},
{
"file_url": "https://cdn.doculator.org/audios/KAI9LGP3UIXLG51W/timestamps.json",
"file_type": "other"
}
],
"created_time": "2026-05-13T10:39:39",
"progress": 100,
"error_message": null
}
}
Finished (3D)
{
"code": 200,
"data": {
"task_id": "9OTM0HH9LBS63LF0",
"status": "finished",
"credits_amount": 30,
"files": [
{
"file_url": "https://cdn.doculator.org/3d/9OTM0HH9LBS63LF0/9OTM0HH9LBS63LF0_1.glb",
"file_type": "3d"
},
{
"file_url": "https://cdn.doculator.org/3d/9OTM0HH9LBS63LF0/9OTM0HH9LBS63LF0_2.png",
"file_type": "image"
},
{
"file_url": "https://cdn.doculator.org/3d/9OTM0HH9LBS63LF0/9OTM0HH9LBS63LF0_3.glb",
"file_type": "3d"
}
],
"created_time": "2026-05-12T02:36:12",
"progress": 100
}
}
Failed
{
"code": 200,
"data": {
"task_id": "task-unified-1757165031-uyujaw3d",
"status": "failed",
"credits_amount": 0,
"files": [],
"created_time": "2025-11-12T10:30:00",
"progress": 0,
"error_message": "The prompt violates our content policy"
}
}
Code Examples
cURL
curl -X GET https://api.poyo.ai/api/generate/status/task-unified-1757165031-uyujaw3d \
-H "Authorization: Bearer YOUR_API_KEY"
Python
import requests
import json
API_KEY = "your-api-key-here"
task_id = "task-unified-1757165031-uyujaw3d"
response = requests.get(
f"https://api.poyo.ai/api/generate/status/{task_id}",
headers={"Authorization": f"Bearer {API_KEY}"}
)
result = response.json()
data = result["data"]
print(f"Status: {data['status']}")
print(f"Progress: {data['progress']}%")
print(f"Credits: {data['credits_amount']}")
if data["status"] == "finished":
for item in data["files"]:
if "file_url" in item:
print(f"Generated file: {item['file_url']}")
else:
print(f"Structured result: {json.dumps(item)}")
elif data["status"] == "failed":
print(f"Error: {data['error_message']}")
JavaScript / Node.js
const API_KEY = 'your-api-key-here';
const taskId = 'task-unified-1757165031-uyujaw3d';
const response = await fetch(
`https://api.poyo.ai/api/generate/status/${taskId}`,
{
headers: {
'Authorization': `Bearer ${API_KEY}`
}
}
);
const result = await response.json();
const data = result.data;
console.log(`Status: ${data.status}`);
console.log(`Progress: ${data.progress}%`);
console.log(`Credits: ${data.credits_amount}`);
if (data.status === 'finished') {
data.files.forEach(item => {
if (item.file_url) {
console.log(`Generated file: ${item.file_url}`);
} else {
console.log(`Structured result: ${JSON.stringify(item)}`);
}
});
} else if (data.status === 'failed') {
console.log(`Error: ${data.error_message}`);
}
Go
package main
import (
"encoding/json"
"fmt"
"io"
"net/http"
)
const (
APIKey = "your-api-key-here"
BaseURL = "https://api.poyo.ai"
)
type APIResponse struct {
Code int `json:"code"`
Data TaskData `json:"data"`
}
type TaskData struct {
TaskID string `json:"task_id"`
Status string `json:"status"`
Files []map[string]any `json:"files"`
CreatedTime string `json:"created_time"`
Progress int `json:"progress"`
CreditsAmount float64 `json:"credits_amount"`
ErrorMessage *string `json:"error_message"`
}
func main() {
taskID := "task-unified-1757165031-uyujaw3d"
req, _ := http.NewRequest(
"GET",
fmt.Sprintf("%s/api/generate/status/%s", BaseURL, taskID),
nil,
)
req.Header.Set("Authorization", "Bearer "+APIKey)
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
var apiResp APIResponse
json.Unmarshal(body, &apiResp)
data := apiResp.Data
fmt.Printf("Status: %s\n", data.Status)
fmt.Printf("Progress: %d%%\n", data.Progress)
fmt.Printf("Credits: %.2f\n", data.CreditsAmount)
if data.Status == "finished" {
for _, item := range data.Files {
if fileURL, ok := item["file_url"].(string); ok {
fmt.Printf("Generated file: %s\n", fileURL)
} else {
encoded, _ := json.Marshal(item)
fmt.Printf("Structured result: %s\n", encoded)
}
}
} else if data.Status == "failed" {
fmt.Printf("Error: %s\n", *data.ErrorMessage)
}
}
Java
import java.net.http.*;
import java.net.URI;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.JsonNode;
public class PoYoAPI {
private static final String API_KEY = "your-api-key-here";
private static final String BASE_URL = "https://api.poyo.ai";
public static void main(String[] args) throws Exception {
String taskId = "task-unified-1757165031-uyujaw3d";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(BASE_URL + "/api/generate/status/" + taskId))
.header("Authorization", "Bearer " + API_KEY)
.GET()
.build();
HttpResponse<String> response = client.send(
request,
HttpResponse.BodyHandlers.ofString()
);
ObjectMapper mapper = new ObjectMapper();
JsonNode root = mapper.readTree(response.body());
JsonNode data = root.get("data");
String status = data.get("status").asText();
int progress = data.get("progress").asInt();
double creditsAmount = data.get("credits_amount").asDouble();
System.out.println("Status: " + status);
System.out.println("Progress: " + progress + "%");
System.out.println("Credits: " + creditsAmount);
if ("finished".equals(status)) {
JsonNode files = data.get("files");
files.forEach(item -> {
if (item.hasNonNull("file_url")) {
System.out.println("Generated file: " + item.get("file_url").asText());
} else {
System.out.println("Structured result: " + item.toString());
}
});
} else if ("failed".equals(status)) {
System.out.println("Error: " + data.get("error_message").asText());
}
}
}
PHP
<?php
$apiKey = 'your-api-key-here';
$taskId = 'task-unified-1757165031-uyujaw3d';
$baseUrl = 'https://api.poyo.ai';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "$baseUrl/api/generate/status/$taskId");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer $apiKey"
]);
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response, true);
$data = $result['data'];
echo "Status: {$data['status']}\n";
echo "Progress: {$data['progress']}%\n";
echo "Credits: {$data['credits_amount']}\n";
if ($data['status'] === 'finished') {
foreach ($data['files'] as $item) {
if (isset($item['file_url'])) {
echo "Generated file: {$item['file_url']}\n";
} else {
echo "Structured result: " . json_encode($item) . "\n";
}
}
} elseif ($data['status'] === 'failed') {
echo "Error: {$data['error_message']}\n";
}
Ruby
require 'net/http'
require 'json'
require 'uri'
api_key = 'your-api-key-here'
task_id = 'task-unified-1757165031-uyujaw3d'
base_url = 'https://api.poyo.ai'
uri = URI("#{base_url}/api/generate/status/#{task_id}")
request = Net::HTTP::Get.new(uri)
request['Authorization'] = "Bearer #{api_key}"
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(request)
end
result = JSON.parse(response.body)
data = result['data']
puts "Status: #{data['status']}"
puts "Progress: #{data['progress']}%"
puts "Credits: #{data['credits_amount']}"
if data['status'] == 'finished'
data['files'].each do |item|
if item['file_url']
puts "Generated file: #{item['file_url']}"
else
puts "Structured result: #{JSON.generate(item)}"
end
end
elsif data['status'] == 'failed'
puts "Error: #{data['error_message']}"
end
Polling Best Practices
When polling for task completion, follow these recommendations:Poll Interval: Check status every 2-5 seconds. Avoid polling more frequently to prevent rate limiting.
Timeout: Implement timeouts to avoid infinite loops. Typical generation times:
- Images: 15-60 seconds
- Videos: 90-300 seconds
Exponential Backoff: On rate limit (429) or server errors (5xx), implement exponential backoff (wait 1s, 2s, 4s, 8s…).
Complete Polling Example
import requests
import time
import json
API_KEY = "your-api-key-here"
BASE_URL = "https://api.poyo.ai"
def wait_for_completion(task_id, timeout=600, poll_interval=2):
"""
Wait for task completion with timeout
Args:
task_id: Task identifier
timeout: Maximum wait time in seconds
poll_interval: Seconds between checks
Returns:
Task data when complete
Raises:
TimeoutError: If timeout exceeded
RuntimeError: If task failed
"""
start_time = time.time()
headers = {"Authorization": f"Bearer {API_KEY}"}
while True:
# Check timeout
if time.time() - start_time > timeout:
raise TimeoutError(f"Task did not complete within {timeout}s")
# Get status
response = requests.get(
f"{BASE_URL}/api/generate/status/{task_id}",
headers=headers
)
if response.status_code == 429:
# Rate limited - wait longer
time.sleep(poll_interval * 2)
continue
response.raise_for_status()
result = response.json()
data = result["data"]
# Log progress
elapsed = int(time.time() - start_time)
print(f"[{elapsed}s] Status: {data['status']}, Progress: {data['progress']}%")
# Check completion
if data["status"] == "finished":
print(f"✓ Task completed successfully")
return data
elif data["status"] == "failed":
raise RuntimeError(f"Task failed: {data['error_message']}")
time.sleep(poll_interval)
# Usage
try:
task_id = "task-unified-1757165031-uyujaw3d"
result = wait_for_completion(task_id)
for item in result["files"]:
if "file_url" in item:
print(f"Download: {item['file_url']}")
else:
print(f"Structured result: {json.dumps(item)}")
except TimeoutError as e:
print(f"Timeout: {e}")
except RuntimeError as e:
print(f"Error: {e}")
Error Responses
HTTP Error Codes
| Code | Description | Action |
|---|---|---|
| 401 | Unauthorized | Check your API key |
| 403 | Forbidden | Task belongs to another user |
| 404 | Not Found | Task ID does not exist |
| 429 | Too Many Requests | Reduce polling frequency, implement backoff |
| 500 | Server Error | Retry with exponential backoff |
| 502 | Bad Gateway | Service temporarily unavailable, retry |
Error Response Format
{
"detail": "Task not found"
}
Important Notes
Content Validity: Generated images and videos are accessible for 3 days after creation. Download and save your content promptly.
Webhooks: For models that support callbacks, you can provide a
callback_url when submitting tasks to receive automatic notifications. Omni Moderation callbacks include the same output object as status queries. See Webhook Callbacks.Next Steps
Submit Task
Learn how to submit generation tasks
Image Models
Browse all image models
Video Models
Browse all video models
Quick Start
Complete integration guide
Authorizations
All API endpoints require Bearer Token authentication.
Create an API key: sign in to PoYo, open Dashboard → API Key at poyo.ai/dashboard/api-key, and click to create a key.
Add it to the request header:
Authorization: Bearer YOUR_API_KEY
Path Parameters
Unique task identifier
Response
Task status retrieved successfully
Business status code. 200 means success; any other value means the request failed. Always check this field: some validation errors return HTTP 200 with code: 400 in the body.
200: Success400: Invalid request parameters401: Missing or invalid API key402: Insufficient credits403: Permission denied404: Resource not found408: Request timeout429: Rate limit exceeded500: Internal server error502: Upstream service error503: Service unavailable
See Error Codes for details.
Available options:
200, 400, 401, 402, 403, 404, 408, 429, 500, 502, 503 Example:
200
Show child attributes
Show child attributes