Skip to content

Overview

Search engine results as JSON.

SerpResult returns the organic results of a web search as JSON. Two search endpoints, both synchronous: GET /v1/query runs one search and POST /v1/bulk runs up to 50 in one request. Everything else on this surface is the dashboard’s reporting and credential management.

Authentication

Public API calls send a secret key in the Authorization header:

Authorization: Bearer sk_live_…

Keys are minted in the dashboard (or through POST /v1/api-keys with a session cookie). sk_live_ keys are for production traffic, sk_test_ keys carry a lower rate limit. The dashboard’s session cookie is accepted on the same endpoints. Routes marked session only (usage, history, key management) refuse a bearer key: a key that could mint another key would make revoking the first one meaningless.

Two more principals exist and are described as security schemes below: the marketing site’s keyless demo (X-Demo-Origin) and RapidAPI’s proxy (X-RapidAPI-Proxy-Secret + X-RapidAPI-User). Neither is something an integrator sends by hand.

Targets and what each supports

target page num safe
google_search 1–5 1–20 off, moderate, strict
bing_search 1 only 1–20 off, moderate, strict
duckduckgo_search 1 only 1–10 not supported
yahoo_search 1 only 1–10 off, moderate, strict
brave_search 1–5 1–20 off, moderate, strict
yandex_search 1–5 1–10 not supported

Anything outside a target’s row answers 400 unsupported_parameter: bing_search refuses page above 1; duckduckgo_search refuses page above 1, num above 10 and any safe but off; yahoo_search refuses page above 1 and num above 10; brave_search refuses page above 5; yandex_search refuses num above 10 and any safe but off. A geo outside the supported list answers 400 unsupported_geo with the list in details.

Credits

Every search costs one credit: one for GET /v1/query, one per row of POST /v1/bulk. A cache hit costs the same as a fresh search. An upstream failure (502 / 504) is still charged: the search was run and only the answer is missing. A request refused with 400 or 402, and a failure on our side (500), cost nothing.

Plans and quotas

Every account starts on the trial: 100 requests, granted once per email address, that never reset. The trial has no period at all — nothing rolls over, so there is no reset to wait for.

A paid plan’s quota is measured over its subscription’s billing cycle, which renews monthly on the day the subscription started rather than on the 1st. X-Quota-Reset and period.end carry the exact moment it rolls over; read the reset off those rather than deriving it from a calendar. An account on a paid plan with no subscription cycle behind it — a RapidAPI subscriber, a plan set by hand — is measured over the calendar month in UTC instead, resetting at 00:00:00Z on the 1st.

plan $ / month requests extra requests concurrency
Trial 0 100, once, for life — 1 concurrent request
Starter 9 5,000 / month credit packs at $1.50 per 1,000 2 concurrent requests
Growth 49 75,000 / month credit packs at $0.80 per 1,000 5 concurrent requests
Business 99 200,000 / month credit packs at $0.60 per 1,000 10 concurrent requests
Custom contact us quoted quoted 20 concurrent requests

A plan costs the same bought direct as it does through RapidAPI. Plans bought direct are sold through Polar, our Merchant of Record: Polar takes the payment, handles tax and issues the invoice, and the subscription, payment methods and invoice history are managed in its customer portal.

Credit packs

Every plan is hard-limited — nothing is ever served on credit. An account that needs more requests inside the period buys a credit pack up front: 10,000, 50,000 or 100,000 credits, priced at its own plan’s rate, through a Polar one-time checkout. The credits land on the account when Polar reports the order paid.

Pack credits never expire and are not tied to the subscription: they survive a cancellation and are still spendable on an account that has gone back to the trial. They are spent only after the period’s quota is gone, so the quota is always used first.

Buying a pack needs an active subscription, because that is what prices it. Spending one never does.

/v1/query and /v1/bulk answer with X-Quota-Limit, X-Quota-Used, X-Quota-Remaining and X-Credits-Balance on every response, plus X-Quota-Reset on a plan whose quota rolls over. The trial’s never does, so that header is absent on it. With both the quota and the balance spent, a request answers 402 quota_exceeded, is not logged and is not charged; a bulk request carrying more rows than remain between the two is refused whole, before any row runs.

RapidAPI subscribers are metered and billed by the marketplace against the tier they subscribed to, so the quota headers and 402 do not apply on that path.

Rate limits

A plan’s concurrency is enforced as a request rate over a rolling 60-second window — one concurrent request is 60 requests a minute, so the trial gets 60/min, Starter 120/min, Growth 300/min, Business 600/min and a custom plan 1200/min. Counted per credential, one hit per HTTP request however many searches a bulk request carries. An API key (live or test) and an MCP access token are held to the account plan’s rate; the dashboard session gets that rate or 120/min, whichever is higher; the marketplace proxy 1200/min and the keyless demo 5/min per client IP. /v1/query, /v1/bulk and /v1/me answer with X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset, and a refused request is 429 rate_limited with Retry-After.

Errors

Every error is a JSON envelope with the same three keys, plus issues (field-level validation messages) or details (the supported geo codes) where noted:

{ "error": "unsupported_geo", "message": "…", "request_id": "…", "details": ["us", "in", "…"] }

request_id is also sent as the X-Request-Id header on every response, success or failure. Send a UUID as X-Request-Id on the request to have it echoed; anything else is replaced. Any path not listed here answers 404 not_found in the same envelope.

A secret key from the dashboard: Authorization: Bearer sk_live_… or Bearer sk_test_…. Both are held to the account plan’s rate — 60 a minute on the trial, up to 1200 on a custom plan — and both spend the same quota. Accepted on /v1/query, /v1/bulk, /v1/me and the MCP endpoint POST /mcp only; a session-only route answers 401 to a key.

Security scheme type: http

The dashboard’s session cookie (__Secure-better-auth.session_token when served over HTTPS). Accepted everywhere a key is, and the only credential the session-only routes take. On the search routes it gets the plan’s per-minute limit or 120, whichever is higher.

Security scheme type: apiKey

Cookie parameter name: better-auth.session_token

The marketing site’s keyless hero search. The header must equal the deployment’s configured demo origin, and the request must carry no Authorization header and no session cookie — a credential sent beside it is refused rather than re-metered. The principal is the client IP, limited to 5 requests a minute, with no account behind it. Accepted on /v1/query and /v1/bulk.

Security scheme type: apiKey

Header parameter name: X-Demo-Origin

Requests relayed by the RapidAPI marketplace. The proxy injects X-RapidAPI-Proxy-Secret (compared in constant time against the deployment’s secret) and X-RapidAPI-User (the marketplace account the call is attributed to). Integrators never send these themselves. When the marketplace secret is not configured, or the marketplace account mapping has not landed, every request on this path answers 401 unauthorized — this branch currently answers 401.

Security scheme type: apiKey

Header parameter name: X-RapidAPI-Proxy-Secret