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"
}
}{
"success": false,
"error": "Maximum retries exceeded"
}Get credit balance
Read your organization’s current credit balance and billing cycle. Lets you observe your balance programmatically — including from async-only workloads — without making a sync /v1/monitor/* request just to inspect the X-Credits-Remaining header. The authoritative check is enforced when each task is charged.
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"
}
}{
"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
Bearer authentication header of the form Bearer <token>, where <token> is your auth token.
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?