OpenSERP Cloud uses a single unit - credits - for every billable request. Top up your balance from /dashboard/topup; credits never expire.
Live prices are exposed at
GET /v1/pricingand shown inside the Search Playground. The numbers below are the launch defaults and may change; your account is always charged the live price at request time.
Default credit cost
| Operation | Credits per successful response |
|---|---|
Single-engine search (/v1/{engine}/search) |
1 |
Any/Fast web search (/v1/any/search, /v1/fast/search) |
1 |
Any/Fast image search (/v1/any/image, /v1/fast/image) |
1 |
Image search (/v1/{engine}/image) |
1 per 10 returned images |
Megasearch (/v1/mega/search) |
Dynamic, based on successful engines |
Mega image search (/v1/mega/image) |
Dynamic, based on returned image volume per successful engine |
Account / pricing endpoints (/v1/me, /v1/pricing) |
0 (free) |
Worked examples
GET /v1/google/search?text=foo&limit=10-> 1 credit.GET /v1/fast/search?text=foo&engines=google,bing,yandex-> 1 credit on success.GET /v1/any/image?text=cat&engines=google,bing,yandex-> 1 credit on success.GET /v1/google/image?text=cat&limit=25-> up to 3 credits (ceil(returned_images/10)).GET /v1/mega/search?text=foo&engines=google,bing,yandex-> dynamic; checkX-Credits-Used.- A revoked key returning
401-> 0 credits (errors are never billed).
Credit price
The default price is $0.02 per credit (50 credits per $1). The current price for your account is returned by:
curl https://api.openserp.org/v1/pricing \
-H "Authorization: Bearer YOUR_API_KEY"
{
"credit_price_usd": 0.02,
"search": { "credits": 1 },
"mega_search": { "credits": 1 },
"image_search": { "credits": 1 },
"any_search": { "credits": 1 },
"fast_search": { "credits": 1 },
"any_image": { "credits": 1 },
"fast_image": { "credits": 1 }
}
If you display “$X to run this query” inside your own app, fetch /v1/pricing (cache it for about 10 minutes) rather than hardcoding a rate.
What counts as a billable response
You are charged only when the API returns results. Specifically:
| Response | Billed? |
|---|---|
200 OK with results |
Yes |
200 OK with empty results array (engine returned nothing for the query) |
Yes - the upstream call was made |
400 Bad Request (your input was invalid) |
No |
401 Unauthorized (bad / revoked key) |
No |
402 Payment Required (insufficient credits) |
No |
429 Too Many Requests (rate limited) |
No |
5xx from us / upstream engine |
No |
Mega endpoints are billed from the engines and results that actually succeeded. Any/Fast endpoints return 502 without debiting credits if every OpenSERP/proxy attempt and fallback fails.
Reading the cost from response headers
Every billable response includes:
| Header | Meaning |
|---|---|
X-Credits-Used |
Credits charged for this exact request |
X-Credits-Remaining |
Your balance after this request |
X-Engine-Used |
Present on Any/Fast responses; the engine that answered |
const res = await fetch(url, { headers: { Authorization: `Bearer ${key}` } });
console.log("charged:", res.headers.get("X-Credits-Used"));
console.log("balance:", res.headers.get("X-Credits-Remaining"));
console.log("engine:", res.headers.get("X-Engine-Used"));
Track X-Credits-Used per request if you bill your own users. It is the source of truth.
Running out of credits
When your balance hits zero, calls return 402 Payment Required:
{
"error": "insufficient_credits",
"code": 402,
"message": "Insufficient credits. Top up to continue."
}
The response is not charged. Top up at /dashboard/topup; credits are added immediately after payment confirmation, and your next request goes through.
To avoid surprise outages:
- Watch
X-Credits-Remainingin your application and refill before you hit zero. - Use Any/Fast endpoints when you prefer predictable 1-credit fallback routing.
- Keep a buffer if you run scheduled jobs or high-volume image searches.
Next
- Errors & rate limits - what every status code means and how to retry.
- Endpoints reference - the full parameter list for each endpoint.