curl --request GET \
--url https://api.cloro.dev/v1/credits \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.cloro.dev/v1/credits"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.cloro.dev/v1/credits', 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/credits",
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.cloro.dev/v1/credits"
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.cloro.dev/v1/credits")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.cloro.dev/v1/credits")
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{
"remaining": 48210,
"perCycle": 1562500,
"cycleResetsAt": "2026-08-10T17:35:27.000Z"
}{
"error": {
"code": "MISSING_API_KEY",
"message": "Missing or invalid API key",
"timestamp": "2025-01-15T12:00:00.000Z"
}
}{
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "API key rate limit exceeded",
"timestamp": "2025-01-15T12:00:00.000Z"
}
}{
"success": false,
"error": "Maximum retries exceeded"
}Get credit balance
Read your organization’s credit balance and billing cycle programmatically, so async-only workloads can alert or pause before the balance runs out.
curl --request GET \
--url https://api.cloro.dev/v1/credits \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.cloro.dev/v1/credits"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.cloro.dev/v1/credits', 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/credits",
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.cloro.dev/v1/credits"
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.cloro.dev/v1/credits")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.cloro.dev/v1/credits")
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{
"remaining": 48210,
"perCycle": 1562500,
"cycleResetsAt": "2026-08-10T17:35:27.000Z"
}{
"error": {
"code": "MISSING_API_KEY",
"message": "Missing or invalid API key",
"timestamp": "2025-01-15T12:00:00.000Z"
}
}{
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "API key rate limit exceeded",
"timestamp": "2025-01-15T12:00:00.000Z"
}
}{
"success": false,
"error": "Maximum retries exceeded"
}/v1/monitor/* request made only to read the X-Credits-Remaining header. Poll it to alert your team before you run out, and to pause task submission when the balance is too low to cover the next batch.
Response fields
| Field | Type | Description |
|---|---|---|
remaining | integer | Credits currently remaining for your organization |
perCycle | integer | null | Credits granted per billing cycle. null for free-tier organizations with no active subscription |
cycleResetsAt | string | null | ISO 8601 timestamp for when the current billing cycle ends and credits reset. null for free-tier organizations |
Example usage
Read your current balance
curl -X GET "https://api.cloro.dev/v1/credits" \
-H "Authorization: Bearer YOUR_API_KEY"
{
"remaining": 48210,
"perCycle": 1562500,
"cycleResetsAt": "2026-08-10T17:35:27.000Z"
}
Low-balance alerts and a submission breaker
import axios from 'axios';
const API_KEY = process.env.API_KEY;
const CREDITS_URL = 'https://api.cloro.dev/v1/credits';
const COST_PER_BATCH = 5000;
async function getCredits() {
const { data } = await axios.get(CREDITS_URL, {
headers: { Authorization: `Bearer ${API_KEY}` },
});
return data;
}
const { remaining, cycleResetsAt } = await getCredits();
if (remaining < 10_000) {
const resetInfo = cycleResetsAt ? `resets ${cycleResetsAt}` : 'no active billing cycle';
console.warn(`Low credit balance: ${remaining} remaining (${resetInfo})`);
}
if (remaining < COST_PER_BATCH) {
console.log('Insufficient credits — pausing submission until the cycle resets or you top up');
} else {
await submitNextBatch();
}
import os
import requests
API_KEY = os.environ['API_KEY']
CREDITS_URL = 'https://api.cloro.dev/v1/credits'
COST_PER_BATCH = 5000
def get_credits():
response = requests.get(
CREDITS_URL,
headers={'Authorization': f'Bearer {API_KEY}'}
)
response.raise_for_status()
return response.json()
credits = get_credits()
remaining = credits['remaining']
cycle_resets_at = credits['cycleResetsAt']
if remaining < 10_000:
reset_info = f'resets {cycle_resets_at}' if cycle_resets_at else 'no active billing cycle'
print(f'Low credit balance: {remaining} remaining ({reset_info})')
if remaining < COST_PER_BATCH:
print('Insufficient credits — pausing submission until the cycle resets or you top up')
else:
submit_next_batch()
remaining counts completed charges only — it does not net out work you have already queued, so subtract your own outstanding creditsToCharge before sizing the next batch. To attribute exact cost per task, use the creditsCharged field on the task status response instead.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, rotated, and revoked at https://dashboard.cloro.dev/api-keys. Full details, including the versioning and deprecation policy, are at https://cloro.dev/auth.md.
Response
Current credit balance and billing cycle.
Credits currently remaining for your organization.
48210
Credits granted per billing cycle. Null for free-tier organizations with no active subscription.
1562500
When the current billing cycle ends and credits reset. Null for free-tier organizations with no active subscription.
"2026-08-10T17:35:27.000Z"
Was this page helpful?