openSERPConsole
Developer documentation

One interface.
Start building.

Normalized search for your application or agent, with the same pricing, health and spending controls.

Make a search request

Send JSON to POST https://openserp.io/api/search. Generate a free API key at openserp.io/keys without signing up, and send it as Authorization: Bearer YOUR_API_KEY. All search requests require a key or a signed-in browser session. The website playground creates and connects an anonymous key automatically on your first Run click; there is no manual setup before searching. Your anonymous keys, projects and usage attach automatically when you sign in in the same browser; the key stays valid and its spending limits are preserved. Choose any engine, including Firehose Lite and auto.search, with provider: auto for the free allowance. Routing is automatic; free requests ignore fast/cheap preferences. Shared caching is always enabled with no maximum age. Client cache settings cannot bypass this policy. Matching cached results cost $0; a cache miss runs a live search within the free allowance. Coordinate searches and page Markdown require credits. The existing network-based daily allowance still applies. Provider selection and fast/cheap routing preferences require a funded account. Free live searches use the daily allowance. Keep keys server-side in your applications. Quotes, status and MCP tool discovery remain public.

curl https://openserp.io/api/search \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Idempotency-Key: my-search-001' \
  -d '{"endpoint":"google.search","query":"Cloudflare Workers","strategy":"cheap","maxCostUsd":"1","cache":{"enabled":true,"ttlHours":24}}'

auto.search selects only Google, Bing or Yahoo, using compatible sources and the same health and routing preferences. Free responses include search metadata and snippets; full-page content and page Markdown are excluded, including content already in shared cache. The homepage playground starts with Google.

Search parameters

ParameterMeaning
endpoint / engineauto.search, firehose.search, google.search, bing.search, yahoo.search, naver.search, yandex.search, baidu.search, duckduckgo.search, google.images, bing.images, mojeek.search, deepseek.search, nimble.search, exa.search
query / qSearch text, up to 2,000 characters
providerauto, provider ID or exact offering ID
strategycheap or fast; eligible healthy sources preferred
country / languageSource-supported locale parameters
page / maxPageBounded pagination, from 1 to 10
maxCostUsdHard customer spending cap; default 1 USD
cacheAPI and MCP examples send enabled: true with ttlHours: 24. Every cacheable request has a five-minute reuse window, including enabled: false and omitted cache. Enable caching to reuse older results up to ttlHours; values below five minutes use five minutes. Dedicated full-page Markdown response caches are private to the account. Use ttlHours: null for no expiration. Free accounts always use shared cache at unlimited age

Use each engine page for source-specific options. Unsupported parameter combinations are rejected before a provider is called. Requests containing coordinates bypass cache reads and writes.

Result URLs and alternatives

Opaque /goto links are retained as successful search results, including responses containing only those links. They do not count as invalid results and use the normal query charge. Readable redirect destinations are still unwrapped; advertising and unsafe URLs remain filtered.

Organic results exclude advertising click URLs, including DuckDuckGo sponsored redirects. Known campaign and click-tracking parameters are removed before merging and delivery. Functional parameters, repeated query values, signed URLs and application hash routes are preserved. Trailing-slash variants are treated as the same destination when merging.

When a source supplies equivalent destinations, results include an alternate_urls array of cleaned alternatives. Equivalences are used across engines, including transitive groups, while unrelated pages remain separate. Cached results and completed replays receive the same cleanup without another source request or change to the recorded charge.

Bing result quality

Bing may return unrelated results across providers despite a successful upstream response. Organic lists of 10 or more valid unique results are rejected when no title, snippet or URL matches a meaningful positive query keyword. Common words, filter syntax and excluded terms do not satisfy the check; case and accents are normalized. These responses count as invalid source failures, are not billed, and can trigger compatible fallback when enabled. Cached Bing results undergo the same check before reuse. See the Bing reliability notice.

Query normalization

REST, MCP, Firehose and realtime Markdown requests share query cleanup before routing, cache lookup and idempotency checks. Leading and trailing whitespace is trimmed, whitespace runs become spaces, control and null characters are removed, HTML entities and percent-encoded UTF-8 are decoded, and typographic quotes become straight quotes. International text, emoji, literal plus signs and percent escapes within visible URLs are preserved.

For example, Cloudflare%2520%26quot%3BWorkers%26quot%3B becomes Cloudflare "Workers". Active filetype:pdf becomes mime:pdf on Yandex. Supported file-type aliases use filetype: on Google and DuckDuckGo. Full MIME types such as application/pdf are mapped to extensions. Operators inside quoted phrases remain literal text.

The final cleaned query is limited to 2,000 characters; encoded input may contain up to 24,000 characters. Up to four nested encoding layers are cleaned. Empty queries, excessive encoding depth, unsupported file-type operators and oversized cleaned queries return a 400 error before upstream work. Native source limits still apply. Equivalent cleaned queries share cache and idempotency semantics.

Firehose: Lite and Advanced

The playground defaults to results only, with shared caching enabled and a 24-hour maximum cache age for paid searches. Select page Markdown to fetch full result pages; this increases cost and response time. On Firehose, send pageMarkdown: false for results only or pageMarkdown: true for paid page Markdown. Omitted paid API requests retain page Markdown. Free requests always exclude page content and use unlimited-age shared cache.

Set firehoseTier to lite (the default, lower search cost) or advanced (broader coverage at higher search cost). Lite is available to free and paid users. Advanced requires paid access, including cached results. Free requests reuse shared cached results of any age first, then search live on a miss without page Markdown. Each tier has separate cache entries and starting prices.

Your agent’s intelligence shouldn’t be limited by access to information. Send POST /search, or use endpoint: firehose.search with /api/search or the MCP search tool. Firehose Lite is available to free users; Advanced requires paid access, including cached results. Live searches are included in the free allowance; page Markdown requires credits and search permission. Firehose combines parallel searches, deduplicates destinations and ranks by relevance, agreement and domain diversity. Its source composition is managed internally.

Firehose returns organicResults, combined markdown, per-result contentStatus and an explicit partial flag. The default upstream request target is 50, with an input maximum of 100. Every valid unique result received is returned, including extras above this target. The default deadline is 25 seconds, or 15 seconds with fast routing. Set timeoutMs between 5,000 and 30,000. Extra results remain in the response even when the quoted page-fetch allowance is exhausted; their content status is explicit. Use a quote and a sufficient maxCostUsd before starting. Firehose manages routing; provider pinning and pagination are unsupported.

Firehose Lite and Advanced have separate source-status entries, starting query prices, seven-day outcome charts and trailing-hour search-only median/p90 latency. Authenticate to see your account’s final prices. Earlier responses without an explicitly recorded tier are excluded from the tier charts and counted separately.

Search operators

Inline site:, filetype: and mime: operators restrict Firehose routing to sources that support every requested feature. File-type aliases are translated to each eligible source’s syntax; negated and combined filters are preserved. Unsupported MIME types or a lack of compatible sources return an explicit error before paid searches. Operators inside quoted phrases remain literal text.

Console playground

Open Playground beside Sign out in the console. It uses your signed-in account and current balance, with Google selected initially. Build a request with supported advanced controls, compare inclusive prices without a paid search, and run results or realtime Markdown. Copy the current request as cURL, JavaScript, TypeScript, Python, Go, PHP, Ruby, C#, JSON or an MCP tool call. Samples use your own API key through an environment variable; account cookies and key secrets are never embedded. Console searches are limited to $1 per request.

View results, JSON and Markdown, and copy or download responses. Editing request settings generates a fresh idempotency key; repeating an unchanged request replays the completed response without another charge. A new request ID starts new work. Advanced controls, region defaults, Markdown access and source routing follow the chosen engine and your account access.

Account access and fallback

Search pages and both playgrounds recognize your signed-in session and show your account balance. Funded accounts can select a source, routing preference and full-page Markdown; successful live work is charged to that account. Account state refreshes when returning from sign-in or a top-up, restoring a page, changing tabs and before submitting a request. Unfunded accounts retain cache-first search with live results on a miss.

allowFallback is a boolean, checked by default in the playground and true by default in REST and MCP. With it enabled, the selected source is a preference. A route with at least ten attempts and less than 90% success in the trailing hour can be bypassed. After a failure or unavailable source, retries first use another viable source for the same engine, preserving the selected fast or cheap strategy. Automatic routing keeps its initially selected engine while viable sources remain. Compatible alternate engines are considered only after viable same-engine sources are exhausted or unavailable within the spending cap. Known high-failure sources remain deprioritized. At most three attempts share the deadline. Alternative web engines are Google, Bing and Yahoo; image searches stay on image engines. Native searches can fall back to these web engines if they support every requested option. Filters, operators, locale and spending caps are retained.

Turn fallback off for one attempt without changing the requested engine or source. Automatic source selection still chooses an eligible source within that engine; auto.search still selects its initial engine from Google, Bing or Yahoo. Firehose continues its combined search, with the flag controlling additional source retries within each component. Free requests never make live fallback calls.

Quotes mark fallback candidates. Responses identify the requested and actual engine/source with requestedEngine, requestedProvider, fallbackUsed and fallbackReason. Failed work is absorbed; only a successful delivered response is charged, under the request and API-key limits. Cache hits remain free. Default-true requests preserve existing receipt and shared-cache identities.

Engine-dependent advanced inputs

The playground’s Advanced search options reflect the chosen engine and source. Depending on support, choose interface language, result language, country restriction, location, search domain, device, Safe Search, freshness, pagination, result target, site, exact phrase, excluded phrase and file type. Automatic routing excludes sources that cannot honor every selected option; unsupported values are rejected before spending.

Country names, native names and ISO codes normalize to one country code: USA, U.S., United States and United States of America become us. GBR and United Kingdom become gb; Deutschland becomes de. The old fallback that silently replaced unrecognized countries with the US is removed from validated searches.

English and eng become en; French, Français and fra become fr. Regional spellings such as en-US use the base language; Simplified and Traditional Chinese retain zh-cn/zh-tw when supported. Locale inputs use a pinned Unicode CLDR name/code snapshot, with no external lookup per request.

Aliases such as country_code/gl, language_code/hl, safe_search, time_period, siteSearch, exact_terms, exclude_terms and structured mime map to canonical inputs. phone becomes mobile, past week becomes week, and on/true becomes strict Safe Search. Conflicting aliases return 400. Structured file types accept extensions or supported MIME types and use each engine’s query syntax. Native limits still apply, including DeepSeek’s final query length and engines that cannot accept locale or advanced filters.

Compare prices before spending

POST /api/quote accepts the same parameters and returns eligible offerings, inclusive prices, source timeouts, median latency and p90 latency. A quote itself makes no paid search request. Cache hits are free. Live quotes show the final customer price for the authenticated account. Sign in or send your API key to obtain your account’s prices; unauthenticated price listings show standard prices. Completed requests keep their original recorded value and charge.

DataForSEO operator pricing

Standard-account DataForSEO Google searches start at $0.00256 per requested results page at the configured Live rate. Keyword operators such as site:, filetype:, inurl: and intitle: multiply that rate by five, once per task, including queries that combine operators. Structured site/file-type inputs and normalized encodings use the same pricing rule. For a standard account, one page with these operators quotes $0.0128; three pages quote a maximum of $0.0384. Account-specific prices may differ; authenticate when requesting a quote. Plain queries retain the base rate even when the rich-result adapter is selected.

Google Images has its own operator rules and bills in 100-image depth buckets. Its related: operator also incurs the surcharge; unsupported cache: image queries are excluded before dispatch. The Google operator surcharge is not applied to Bing or Yahoo. Quotes and responses expose operatorMultiplier, surchargeOperators and the pricing policy version. Settlement uses DataForSEO’s reported task cost, including lower actual depth costs, with the quote as a hard ceiling. A missing or null reported cost uses the same operator-aware estimate as the quote. No usable result means no customer charge.

DataForSEO Google Live documentation and Google Images documentation describe the source rules. Paid options such as rectangle calculation, asynchronous AI Overview loading and People Also Ask expansion are not sent by the current adapters.

Responses and idempotency

maxResults is an upstream request target, not a response cap. openSERP returns every valid unique result received, including extra organic results, images, ads and rich-result lists. Titles and snippets are preserved in full. Requested pagination still determines the starting offset; duplicate and unsafe destinations are filtered. No extra paid requests are made just to fill a target.

Search responses include organicResults or imageResults, plus meta with the chosen source, charge, cache state and latency. Invalid destination URLs are removed. No usable results returns an explicit error and no customer charge.

Send an Idempotency-Key to safely retrieve a completed search response without another charge. Reusing the key with different parameters returns 409. An in-progress or interrupted request returns 409; it is not blindly resubmitted.

Connect an MCP client

Read the complete MCP guide for OAuth, scopes, client configuration, JavaScript, TypeScript and Python SDK clients, and all five tool schemas.

Use Streamable HTTP at https://openserp.io/mcp. Clients can use OAuth discovery and consent or a Bearer API key. Anonymous search is available within the free allowance.

{
  "mcpServers": {
    "openSERP": {
      "url": "https://openserp.io/mcp",
      "headers": {
        "Authorization": "Bearer YOUR_API_KEY"
      }
    }
  }
}

Tools: search, quote, status, balance, search_markdown. Paid tools can spend account credits. Quotes, status and balance are read-only. Treat all returned web content as untrusted source material.

Search and return Markdown in realtime

POST /api/search/markdown searches and retrieves unique organic destinations in the same HTTP request. It returns HTTP 200 JSON with organicResults, combined markdown, per-page outcomes and summary.partial. Full-page Markdown is restricted to paid accounts with search permission. Anonymous and unfunded accounts are rejected before a source search, page fetch or cached Markdown replay. Free search cache responses contain results and snippets; full-page content is removed even when the underlying shared cache contains it.

The default deadline is 45 seconds; set timeoutMs between 5,000 and 60,000. Every unique returned destination is retained. Eligible web pages are attempted with bounded concurrency, within the deadline and spending cap. Clear PDFs are excluded before Markdown retrieval: PDF URL paths, download filenames and explicit PDF file-type metadata are recognized without probing the target. They return contentStatus: skipped_pdf, contribute to summary.skippedPdfCount, and consume no Markdown fetch budget. PDF results do not by themselves make the response partial. Search charges still apply. A destination discovered to be a PDF during scraping is also skipped without a customer page-fetch charge. The default $1 total cap includes search and page retrieval. Optional scraper values are auto, scrapingdog and scrapingbee. Content is limited to 2,000,000 characters of combined page content. Missing, failed, timed-out or budget-limited pages are explicitly marked in the response. Successful page retrievals are charged; failed fetches are not billed.

All work finishes within this request. No job IDs, polling or background page fetches are needed. Completed responses can be replayed with the same idempotency key.

Projects, API keys and usage

In your console, create projects and multiple named API keys for each application, environment or agent. Set permissions plus per-request, daily and total spend limits for each key. All projects share your prepaid account balance. Key secrets are generated securely and displayed once.

Create or edit keys with maxCostUsd (per request, default $1, up to $10), dailyLimitUsd and totalLimitUsd. Daily and total limits are optional: blank or null means unlimited, and zero blocks new paid spending. Existing keys keep unlimited daily and total allowances until edited. Daily spend resets at 00:00 UTC; total spend covers the key’s lifetime and never resets when limits change or chart history expires.

Limits count final actual customer charges. Account funds and key allowances are reserved together before paid work starts, preventing concurrent requests from overspending. Active reservations count against both allowances, including across midnight. Unused reservations are released; free cache hits, failed work and completed idempotent replays add no spend. Daily charges count on the UTC day of settlement. A limit edit applies to new approvals; already approved requests can finish. Search and page retrieval share one combined limit for Markdown and Firehose.

The key list shows daily/lifetime usage and reserved spending. An API key with balance permission can inspect its own limits, spend, remaining allowance and next UTC reset through GET /api/account or MCP balance in keyLimits. Insufficient daily or total allowance returns 402 with key_daily_spend_limit or key_total_spend_limit before any paid source call. Lower the request cap or adjust the key’s allowance before retrying.

Compare searches, actual charges and unsuccessful results across keys over 24 hours, seven days or 30 days. Filter by project or one key. Cache hits count once and cost zero; upstream retries and idempotent replays do not add queries. Search and Markdown requests keep their originating key attribution. Revoked keys remain in usage history. Per-key tracking starts when this feature was enabled; older requests are not retroactively attributed.

REST and MCP both use the project associated with the supplied API key. Project names do not need to be added to search requests. Key and project management and account-wide analytics require a signed-in console session.

Anonymous account retention

Anonymous browser accounts and their keys expire 30 days after the first key. Sign in in the original browser before expiry to claim the keys and usage history. Creating extra keys does not reset the deadline. Anonymous account/key responses expose expiresAt in milliseconds since epoch. Unclaimed expired keys return 401; the playground can automatically create a new browser key within the existing network issuance and search quotas. Scheduled cleanup removes the old account, keys and private receipts while retaining anonymous aggregate statistics under Historic anonymous usage. Claimed and signed-in account keys keep their existing lifetimes.

Authentication and credits

Sign in with Google or GitHub. Generate API keys in your console; raw keys appear once. Keys use search and balance scopes with per-request, daily and lifetime spending controls. Revoke keys and OAuth connections from your account.

Credit purchases start at $5. A successful, verified Stripe webhook updates your balance; the browser’s success redirect never does. Refunds and disputes reconcile the credited amount. Negative balances pause paid usage. Auto-recharge is optional and requires explicit consent.

Native Mojeek and DeepSeek searches

Use mojeek.search or deepseek.search with the normal REST or MCP search interface. DeepSeek returns up to 50 results for one source request, with a 128-character final query limit and no pagination or country-code filter. Its summaries are AI-generated and may contain errors. Mojeek Business returns up to 40 results; country and language parameters boost results. USD prices use a dated currency reference, refreshed daily. Request a quote for your account’s final price. Unsupported native parameters are rejected before a paid call.

Mojeek accounts without verified storage rights bypass result caches and retain only financial metadata. Idempotent replays return 409 without another query or charge; replayable Markdown responses require verified storage rights. Source status shows any pricing still awaiting account verification.

Payment and daily spend exports

In your account dashboard, use Export your history to download payment history or daily spend as CSV. All history is included by default; turn off All history to choose inclusive UTC dates.

GET /api/account/exports/payments.csv includes top-ups, auto-recharges, recorded payment status, credit reversals and net credited amounts. GET /api/account/exports/daily-spend.csv totals actual wallet charges by UTC day across every project and key, including zero-spend dates. Wallet history remains available beyond the 35-day operational analytics window. Credits, reservations and upstream expenses are excluded from daily spend; today is partial through the export timestamp.

Both endpoints accept optional from=YYYY-MM-DD and to=YYYY-MM-DD. They require a signed-in account or an API key with balance permission and always export that account only. CSV downloads stream in the current request and use private, no-store responses.

Timeouts & latency

Source status and pricing charts publish the current work budgets alongside measured median and p90 search latency. Page Markdown fetching is excluded from these measurements. REST quotes and MCP status/quote responses expose the same values in milliseconds.

OperationWork budgetHow it applies
Standalone source attemptUp to 20 secondsAutomatic fallback attempts share the remaining search budget and can receive a shorter limit.
Web search25 secondsShared by source attempts and pagination; selecting a provider does not reset the budget.
Image search50 secondsShared by source attempts and image pagination; each standalone attempt still has a 20-second cap.
Firehose search + Markdown25 seconds default; 15 seconds for fast routingSet timeoutMs from 5,000 to 30,000. Search and page retrieval share one deadline. A content phase is reserved from this budget; partial coverage is explicit.
Realtime Markdown45 seconds defaultSet timeoutMs from 5,000 to 60,000. Search gets up to 25 seconds and each page fetch up to 15 seconds, always within the remaining deadline.

Budgets cover upstream work. Input validation, account checks, storage, settlement and response delivery can add overhead to total HTTP duration. Cached requests make no source call. Failed or timed-out attempts do not produce a customer charge unless other successful work is delivered; costs stay within the quoted cap.

After the response deadline or a client disconnect, already-started paid source calls may continue for up to 25 additional seconds. Valid late search results populate the shared cache; late page Markdown is cached privately per account. No new search or page calls are started after disconnect, and late work adds no customer charge or usage value. Invalid, empty and failed results are not cached. Coordinate queries and source storage restrictions remain excluded. Retries use a new idempotency key to read newly cached results; the original response and receipt remain unchanged. This uses bounded background completion, with no search jobs or polling. Status retains the foreground timeout outcome and latency while recording the actual source expense once.

Search latency uses completed search attempts in the trailing hour, including good, error, empty and invalid responses. Cache hits and client validation errors are excluded. Median is the middle value, or the mean of the middle pair for an even sample count. P90 uses the nearest rank, ceil(0.9 × sample count); 90% of samples are at or below it. No samples are shown as an em dash in charts and null in JSON. Firehose search timing stops after parallel searches finish and results are merged, before page retrieval. Older combined timings are excluded from percentiles while their outcome history is retained. The latencySamples count can therefore differ from the outcome count. Response meta.latencyMs and meta.searchLatencyMs report search only; meta.pageFetchLatencyMs and meta.totalLatencyMs describe page retrieval and the overall operation separately. Cached Firehose results have no live search latency. Older combined receipts expose null search timing with latencyUnavailableReason: legacy_combined_timing. The seven-day bars remain hourly outcome counts.

Realtime Markdown retains every result and URL even when page retrieval is incomplete. The old 20,000-character per-page cutoff is removed. Individual scraper responses are bounded to 2 MB and combined Markdown page content to 2,000,000 characters. contentTruncated, contentStatus: response_size_limit, summary.contentLimited and summary.partial identify a size limit explicitly. These content safeguards never shorten the result list.

Source health

GET /api/status?engine=google.search returns 168 hourly buckets, trailing-hour medianMs and p90Ms, sample counts and published timeout policies. p95Ms remains available for existing clients. Good, error, empty and invalid outcomes refer to completed upstream attempts. Healthy requires at least ten samples and at least 90% good results. Fast mode ranks sources by search-only p95 latency, using configured baseline latency when no timing sample is available; cheap mode ranks by the final user price. Explicit provider selection remains pinned when allowFallback: false. Automatic retries use separate provider accounts and share the request deadline. Healthy sources are attempted first; if preferred sources fail, a degraded fallback can return results with an explicit routing warning.

Payment-exempt accounts and usage value

Payment-exempt accounts have full search access without credit purchases or automatic payments. Successful live work records its service value at its account price in meta.usageValueUsd, the amount charged in meta.chargedUsd, and the waived amount in meta.waivedUsd. Their wallet charge is $0. Cached results have zero new usage value; idempotent replays preserve the original value without adding it again. Failed work is absorbed. Usage value follows the account price in effect when the request was approved. Key spend limits and balances continue to measure actual charges. The console and admin account list show service value beside actual charges; daily CSV exports append usage_value_usd, waived_value_usd and unvalued_requests. Older values without enough original pricing evidence are marked incomplete rather than estimated.

Realtime playground progress

The playground automatically connects a browser key on the first search click and displays key generation, searching and page Markdown fetching when applicable. Search requests may opt into Accept: application/x-ndjson for progress frames and one final type: result frame containing the ordinary response in data. A terminal type: error frame includes status, error and message; an error after streaming starts cannot change the HTTP status. Key authentication and browser origin checks still happen before streaming. JSON remains the default. There are no queued search jobs or progress-polling requests.

Errors

400: invalid input; 401: sign-in or valid key required; 402: insufficient balance or spending cap; 403: missing permission; 409: idempotency conflict; 429: quota or burst limit; 503: no eligible source or incomplete setup. Financial and private responses use no-store caching.