Create async task
curl --request POST \
--url https://api.cloro.dev/v1/async/task \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"taskType": "CHATGPT",
"priority": 5,
"idempotencyKey": "your-custom-identifier-123",
"webhook": {
"url": "https://your-app.com/webhook-handler"
},
"payload": {
"prompt": "What is the weather in New York?",
"country": "US"
}
}
'import requests
url = "https://api.cloro.dev/v1/async/task"
payload = {
"taskType": "CHATGPT",
"priority": 5,
"idempotencyKey": "your-custom-identifier-123",
"webhook": { "url": "https://your-app.com/webhook-handler" },
"payload": {
"prompt": "What is the weather in New York?",
"country": "US"
}
}
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({
taskType: 'CHATGPT',
priority: 5,
idempotencyKey: 'your-custom-identifier-123',
webhook: {url: 'https://your-app.com/webhook-handler'},
payload: {prompt: 'What is the weather in New York?', country: 'US'}
})
};
fetch('https://api.cloro.dev/v1/async/task', 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.cloro.dev/v1/async/task",
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([
'taskType' => 'CHATGPT',
'priority' => 5,
'idempotencyKey' => 'your-custom-identifier-123',
'webhook' => [
'url' => 'https://your-app.com/webhook-handler'
],
'payload' => [
'prompt' => 'What is the weather in New York?',
'country' => 'US'
]
]),
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.cloro.dev/v1/async/task"
payload := strings.NewReader("{\n \"taskType\": \"CHATGPT\",\n \"priority\": 5,\n \"idempotencyKey\": \"your-custom-identifier-123\",\n \"webhook\": {\n \"url\": \"https://your-app.com/webhook-handler\"\n },\n \"payload\": {\n \"prompt\": \"What is the weather in New York?\",\n \"country\": \"US\"\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.cloro.dev/v1/async/task")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"taskType\": \"CHATGPT\",\n \"priority\": 5,\n \"idempotencyKey\": \"your-custom-identifier-123\",\n \"webhook\": {\n \"url\": \"https://your-app.com/webhook-handler\"\n },\n \"payload\": {\n \"prompt\": \"What is the weather in New York?\",\n \"country\": \"US\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.cloro.dev/v1/async/task")
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 \"taskType\": \"CHATGPT\",\n \"priority\": 5,\n \"idempotencyKey\": \"your-custom-identifier-123\",\n \"webhook\": {\n \"url\": \"https://your-app.com/webhook-handler\"\n },\n \"payload\": {\n \"prompt\": \"What is the weather in New York?\",\n \"country\": \"US\"\n }\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"task": {
"id": "b27a21e1-7c39-4aa2-a347-23e828c426f9",
"taskType": "CHATGPT",
"status": "QUEUED",
"priority": 1,
"createdAt": "2026-04-09T15:00:00.000Z",
"latencyMs": null,
"idempotencyKey": "batch-chatgpt-001"
},
"credits": {
"creditsToCharge": 5,
"creditsCharged": null
}
}{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Request validation failed",
"details": [
{
"field": "prompt",
"message": "Prompt cannot be empty"
}
],
"timestamp": "2025-01-15T12:00:00.000Z"
}
}{
"success": false,
"error": {
"code": "MISSING_API_KEY",
"message": "Missing or invalid API key",
"timestamp": "2025-01-15T12:00:00.000Z"
}
}{
"success": false,
"error": {
"code": "INSUFFICIENT_CREDITS",
"message": "Insufficient credits",
"timestamp": "2025-01-15T12:00:00.000Z"
}
}{
"success": false,
"error": {
"code": "RESOURCE_ALREADY_EXISTS",
"message": "Task already exists",
"details": {
"field": "idempotencyKey",
"value": "your-custom-identifier-123",
"taskId": "b27a21e1-7c39-4aa2-a347-23e828c426f9"
},
"timestamp": "2025-01-15T12:00:00.000Z"
}
}{
"success": false,
"error": {
"code": "QUEUE_LIMIT_EXCEEDED",
"message": "Queue limit exceeded. Maximum 100000 queued tasks allowed per organization",
"timestamp": "2026-04-09T15:00:00.000Z",
"details": {
"limit": 100000
}
}
}{
"success": false,
"error": {
"code": "INTERNAL_SERVER_ERROR",
"message": "Maximum retries exceeded",
"timestamp": "2025-01-15T12:00:00.000Z"
}
}Async tasks
Create async task
Submit an asynchronous task for background processing. Returns a task ID that you can use to poll for results or receive via webhook.
POST
/
v1
/
async
/
task
Create async task
curl --request POST \
--url https://api.cloro.dev/v1/async/task \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"taskType": "CHATGPT",
"priority": 5,
"idempotencyKey": "your-custom-identifier-123",
"webhook": {
"url": "https://your-app.com/webhook-handler"
},
"payload": {
"prompt": "What is the weather in New York?",
"country": "US"
}
}
'import requests
url = "https://api.cloro.dev/v1/async/task"
payload = {
"taskType": "CHATGPT",
"priority": 5,
"idempotencyKey": "your-custom-identifier-123",
"webhook": { "url": "https://your-app.com/webhook-handler" },
"payload": {
"prompt": "What is the weather in New York?",
"country": "US"
}
}
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({
taskType: 'CHATGPT',
priority: 5,
idempotencyKey: 'your-custom-identifier-123',
webhook: {url: 'https://your-app.com/webhook-handler'},
payload: {prompt: 'What is the weather in New York?', country: 'US'}
})
};
fetch('https://api.cloro.dev/v1/async/task', 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.cloro.dev/v1/async/task",
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([
'taskType' => 'CHATGPT',
'priority' => 5,
'idempotencyKey' => 'your-custom-identifier-123',
'webhook' => [
'url' => 'https://your-app.com/webhook-handler'
],
'payload' => [
'prompt' => 'What is the weather in New York?',
'country' => 'US'
]
]),
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.cloro.dev/v1/async/task"
payload := strings.NewReader("{\n \"taskType\": \"CHATGPT\",\n \"priority\": 5,\n \"idempotencyKey\": \"your-custom-identifier-123\",\n \"webhook\": {\n \"url\": \"https://your-app.com/webhook-handler\"\n },\n \"payload\": {\n \"prompt\": \"What is the weather in New York?\",\n \"country\": \"US\"\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.cloro.dev/v1/async/task")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"taskType\": \"CHATGPT\",\n \"priority\": 5,\n \"idempotencyKey\": \"your-custom-identifier-123\",\n \"webhook\": {\n \"url\": \"https://your-app.com/webhook-handler\"\n },\n \"payload\": {\n \"prompt\": \"What is the weather in New York?\",\n \"country\": \"US\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.cloro.dev/v1/async/task")
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 \"taskType\": \"CHATGPT\",\n \"priority\": 5,\n \"idempotencyKey\": \"your-custom-identifier-123\",\n \"webhook\": {\n \"url\": \"https://your-app.com/webhook-handler\"\n },\n \"payload\": {\n \"prompt\": \"What is the weather in New York?\",\n \"country\": \"US\"\n }\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"task": {
"id": "b27a21e1-7c39-4aa2-a347-23e828c426f9",
"taskType": "CHATGPT",
"status": "QUEUED",
"priority": 1,
"createdAt": "2026-04-09T15:00:00.000Z",
"latencyMs": null,
"idempotencyKey": "batch-chatgpt-001"
},
"credits": {
"creditsToCharge": 5,
"creditsCharged": null
}
}{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Request validation failed",
"details": [
{
"field": "prompt",
"message": "Prompt cannot be empty"
}
],
"timestamp": "2025-01-15T12:00:00.000Z"
}
}{
"success": false,
"error": {
"code": "MISSING_API_KEY",
"message": "Missing or invalid API key",
"timestamp": "2025-01-15T12:00:00.000Z"
}
}{
"success": false,
"error": {
"code": "INSUFFICIENT_CREDITS",
"message": "Insufficient credits",
"timestamp": "2025-01-15T12:00:00.000Z"
}
}{
"success": false,
"error": {
"code": "RESOURCE_ALREADY_EXISTS",
"message": "Task already exists",
"details": {
"field": "idempotencyKey",
"value": "your-custom-identifier-123",
"taskId": "b27a21e1-7c39-4aa2-a347-23e828c426f9"
},
"timestamp": "2025-01-15T12:00:00.000Z"
}
}{
"success": false,
"error": {
"code": "QUEUE_LIMIT_EXCEEDED",
"message": "Queue limit exceeded. Maximum 100000 queued tasks allowed per organization",
"timestamp": "2026-04-09T15:00:00.000Z",
"details": {
"limit": 100000
}
}
}{
"success": false,
"error": {
"code": "INTERNAL_SERVER_ERROR",
"message": "Maximum retries exceeded",
"timestamp": "2025-01-15T12:00:00.000Z"
}
}Submits a task for asynchronous processing. The response carries a
taskId you can poll via GET /v1/async/task/{taskId}; if you provide a webhook.url, cloro also delivers the results to that URL.
- Priority: optional, 1 (lowest, default) to 10 (highest). The scheduler runs higher priority tasks first, then FIFO within the same level. Check your queue’s priority distribution with the async status endpoint.
- Idempotency: an optional
idempotencyKeyprevents duplicate task creation. Reusing a key returns409 Conflict, anderror.details.taskIdis the ID of the task that already holds the key.
QUEUED. Submitting costs nothing on its own — credits are charged when the task completes. The balance is still checked at submission, so this endpoint returns 403 INSUFFICIENT_CREDITS when your credits do not cover the task’s creditsToCharge, and a queued task can still fail later if the balance runs out before the scheduler reaches it. See what happens when credits run out.
Example usage
curl -X POST "https://api.cloro.dev/v1/async/task" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"taskType": "CHATGPT",
"priority": 5,
"idempotencyKey": "your-custom-identifier-123",
"webhook": {
"url": "https://your-app.com/webhook-handler"
},
"payload": {
"prompt": "What is the weather in New York?",
"country": "US"
}
}'
{
"success": true,
"task": {
"id": "b27a21e1-7c39-4aa2-a347-23e828c426f9",
"taskType": "CHATGPT",
"status": "QUEUED",
"priority": 5,
"createdAt": "2025-11-10T15:00:00.000Z",
"latencyMs": null,
"idempotencyKey": "your-custom-identifier-123"
},
"credits": {
"creditsToCharge": 5,
"creditsCharged": null
}
}
Authorizations
cloro API key as a bearer token. One key grants every endpoint in this spec; per-key scopes are not available, so a client cannot request a narrower permission. Keys are created and revoked in the dashboard.
Body
application/json
The provider's request body, validated against the same schema as its sync endpoint (for example ChatGPTMonitorRequest). That makes country required here too, or gl on the Google endpoints. For GOOGLE_PRODUCT, send only productResultToken.
Example:
{
"prompt": "What do you know about Acme Corp?",
"country": "US"
}
Was this page helpful?