Reference
Account & Utilities
Your balance, and what this API serves right now. All free (0 credits); each needs your API key, like every other call.
Endpoints#
- GET
/credits/balance - GET
/credit/balance - GET
/search/capabilities - GET
/search/countries - GET
/search/states
Credit Balance#
GET /credits/balance returns the credits available to your account, and nothing else about it. It works with an API key (x-api-key, or Authorization: Bearer sk_...) and with a dashboard login. It is free, and like any call it counts against your request limits.
{ "success": true, "credits": { "available": 2500, "reserved": 6, "expiresAt": "2027-09-01T10:00:00.000Z", "expiringCredits": 2500 }}| Field | Description |
|---|---|
available | Credits you can spend now. It is the balance GET /user/profile shows (0 while the account is on hold) |
reserved | Present when known: how much of available requests still in flight, or awaiting settlement, already hold |
expiresAt / expiringCredits | Present when some credits expire: when the next ones do, and how many expire then |
The answer is never cached (Cache-Control: no-store).
GET /credit/balance is the fuller view: the same balance with a low-balance flag and the expiry of each grant.
{ "statusCode": 200, "data": { "balance": 2500, "available": 2500, "isLowBalance": false, "lastUpdated": "2026-09-29T08:12:03.000Z", "expiry": { "policyApplies": true, "durationDays": 365, "totalExpiringAmount": 2500, "nonExpiringAmount": 0, "nextExpiryAt": "2027-09-01T10:00:00.000Z", "daysUntilNextExpiry": 336, "nextExpiryAmount": 2500, "breakdown": [ { "sourceType": "purchase", "amount": 2500, "grantedAt": "2026-09-01T10:00:00.000Z", "expiresAt": "2027-09-01T10:00:00.000Z", "daysRemaining": 336, "status": "active" } ] } }, "message": "Credit balance retrieved successfully", "success": true}| Field | Description |
|---|---|
available | Credits you can spend now (balance is the same number) |
isLowBalance | Below the low-balance threshold (100 credits by default) |
expiry.nextExpiryAt / nextExpiryAmount | When credits next expire, and how many expire then |
expiry.breakdown | Each purchase or grant still holding credits, soonest expiry first |
Every metered response also carries X-Credits-Deducted and X-Credits-Remaining, so a client rarely needs to poll this.
Capabilities#
GET /search/capabilities lists every endpoint this deployment serves, what it costs, whether it is switched on, and how it has done over the last two hours. Read it instead of hard-coding which endpoints are available: a switched-off endpoint answers 403 FEATURE_NOT_AVAILABLE (not charged), and this tells you before you pay the round trip.
{ "success": true, "generatedAt": "2026-09-29T17:20:00.000Z", "capabilities": [ { "id": "serp/html", "method": "GET", "path": "/serp/html", "credits": 2, "creditsNote": "per page; 8 with js=true (rendered, AI Overview opened out)", "group": "google", "enabled": true, "state": "live", "health": { "window": "2h", "ok": 412, "fail": 6, "successRate": 0.99 } }, { "id": "backlinks", "method": "GET", "path": "/backlinks", "credits": 0, "group": "backlinks", "enabled": false, "reason": "No backlink provider is bound to this deployment. The endpoints answer 501 rather than returning synthesised link data.", "state": "off", "health": { "window": "2h", "ok": 0, "fail": 0, "successRate": null } } ], "states": { "live": "serving", "degraded": "on, but most recent calls failed", "off": "switched off here" }}state is off when the endpoint is switched off (reason says why), degraded when at least 3 calls in the window and fewer than half of them succeeded, and live otherwise. successRate is a fraction (0–1), null with no calls in the window. The response may be cached for 30 seconds.
Countries and States#
GET /search/countries lists the countries the AI answer endpoints accept as gl. The search endpoints accept any two-letter gl, applied as the results country.
{ "success": true, "engine": "all", "countries": [ { "code": "US", "name": "United States", "states": true, "exit": true }, { "code": "GB", "name": "United Kingdom", "states": false, "exit": true } ]}GET /search/states lists the US states with Google's name and uule token for each. State- and city-level location is not available yet (Location): the response says targeting: false, and a state passed as location or uule returns 400 CITY_LOCATION_UNAVAILABLE. Only country=US is available; any other country returns 400.
{ "success": true, "country": "US", "exitPinning": false, "targeting": false, "message": "State- and city-level location is not available yet: a state passed as location returns 400 CITY_LOCATION_UNAVAILABLE. Country (gl) and language (hl) are applied.", "states": [ { "code": "TX", "name": "Texas", "location": "Texas,United States", "uule": "w+CAIQICIT..." } ]}exitPinning: false: results are not localized to the state.
Examples
curl "https://api.searlo.tech/api/v1/credits/balance" \ -H "x-api-key: sk_your_api_key" curl "https://api.searlo.tech/api/v1/credit/balance" \ -H "x-api-key: sk_your_api_key" curl "https://api.searlo.tech/api/v1/search/capabilities" \ -H "x-api-key: sk_your_api_key"const headers = { "x-api-key": process.env.SEARLO_API_KEY };const res = await fetch("https://api.searlo.tech/api/v1/search/capabilities", { headers });const { capabilities } = await res.json(); // Only call what is on here right nowconst live = new Set(capabilities.filter(c => c.state !== "off").map(c => c.path));console.log(live.has("/serp/html"));import osimport requests HEADERS = {"x-api-key": os.environ["SEARLO_API_KEY"]}balance = requests.get("https://api.searlo.tech/api/v1/credits/balance", headers=HEADERS).json()print(balance["credits"]["available"], balance["credits"].get("expiresAt"))Stuck? Write to [email protected], or check live status.