Search API
Real-time search across web and news using Grok AI.
Endpoint
POST https://blockrun.ai/api/v1/search
Request
Headers
| Header | Required | Description |
|---|---|---|
Content-Type | Yes | Must be application/json |
PAYMENT-SIGNATURE | Conditional | Base64-encoded x402 payment payload (required after 402, x402 v2). X-PAYMENT is accepted as an alias. |
Body Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
query | string | Yes | Search query text (1-1000 characters) |
sources | array | No | Sources to search (default: ["web"]) |
max_results | integer | No | Maximum results per source, 1-50 (default: 10) |
from_date | string | No | Start date filter (YYYY-MM-DD) |
to_date | string | No | End date filter (YYYY-MM-DD) |
Source Types
| Source | Description |
|---|---|
web | General web search results |
news | News articles from major outlets |
Response
Success (200)
{
"query": "latest AI funding rounds",
"summary": "Several major AI companies have announced significant funding rounds...",
"citations": [
"https://techcrunch.com/ai-startup-series-b",
"https://www.reuters.com/technology/ai-funding-round"
],
"sources_used": 10,
"model": "xai/grok-3-mini"
}
Response Fields
| Field | Type | Description |
|---|---|---|
query | string | The original search query |
summary | string | AI-generated summary of search results with citations |
citations | string[] | Source URLs cited by the summary, in citation order. Plain URL strings — there are no title/source sub-fields. |
sources_used | integer | Number of sources actually queried (falls back to max_results when upstream does not report it) |
model | string | Model used for search (currently xai/grok-3-mini) |
Successful responses also carry two headers: PAYMENT-RESPONSE (the x402 v2 settlement receipt — base64 JSON with success, transaction, network, payer) and X-Payment-Receipt (the on-chain settlement transaction hash).
Payment Required (402)
When you first make a request without payment, you'll receive:
{
"x402Version": 2,
"accepts": [{
"scheme": "exact",
"network": "eip155:8453",
"amount": "263500",
"asset": "0x8335…",
"payTo": "0x…",
"maxTimeoutSeconds": 300
}],
"error": "Payment Required",
"message": "This endpoint requires x402 payment",
"price": {
"amount": "0.2625",
"currency": "USD",
"perSourceCost": 0.025,
"maxResults": 10
},
"paymentInfo": {
"network": "base",
"asset": "USDC",
"x402Version": 2
}
}
The full x402 v2 payment requirements are in the X-Payment-Required and PAYMENT-REQUIRED headers (base64 JSON, identical content) and in WWW-Authenticate: X402 requirements="...", and are now also mirrored at the top of the JSON body as x402Version/accepts (for clients that only read the body). Sign against accepts[0].amount (header or body, they're identical), not price.amount: price.amount is the per-source cost plus margin before the flat $0.001 transaction fee, while accepts[0].amount is the exact USDC (6-decimal) amount you will be charged — for the default 10 sources that is 263500, i.e. $0.2635. Payment authorizations are valid for maxTimeoutSeconds: 300.
A GET to the same URL returns a 402 quoting the default price (10 sources) — useful for discovery.
Payment verification failed (402)
If a payment header is present but does not verify, the body carries a machine-readable code so a client can branch on it instead of parsing details:
{
"error": "Payment verification failed",
"code": "PAYMENT_UNFUNDED",
"message": "The payment authorization could not be executed on-chain. ...",
"details": "<raw verifier error>"
}
code | Meaning |
|---|---|
PAYMENT_INVALID | Signature, amount, network or recipient did not match the requirements (default when nothing more specific applies; message is omitted) |
PAYMENT_UNFUNDED | The authorization could not execute on-chain — usually insufficient USDC on Base, or an expired validAfter/validBefore window |
PAYMENT_BLOCKHASH_STALE | Solana-gateway only: signed against an expired blockhash — re-sign against a current one |
PAYMENT_REPLAY | The same authorization was already used (error: "Payment authorization already used"). Sign a fresh authorization for every request |
A 402 with error: "Payment settlement failed" means the search ran but settlement did not complete; nothing was charged.
Pricing
Search pricing is per-source with a 5% BlockRun margin, plus the flat $0.001 per-transaction fee charged on every paid call:
- Base cost: $0.025 per source
- Margin: 5%
- Transaction fee: $0.001 per request (flat)
- Formula:
max_results × $0.025 × 1.05 + $0.001
| max_results | Base Cost | With Margin | Charged (incl. fee) |
|---|---|---|---|
| 1 | $0.025 | $0.02625 | $0.02725 |
| 5 | $0.125 | $0.13125 | $0.13225 |
| 10 (default) | $0.250 | $0.26250 | $0.26350 |
| 25 | $0.625 | $0.65625 | $0.65725 |
| 50 | $1.250 | $1.31250 | $1.31350 |
The price depends only on max_results, not on how many sources you list in sources or how many the search actually used.
Examples
Chat Completions Alternative
You can also access Grok's live search through the Chat Completions API by including search_parameters in your request:
{
"model": "xai/grok-4.3",
"messages": [{"role": "user", "content": "What's trending in AI today?"}],
"search_parameters": {
"mode": "on",
"sources": [{"type": "web"}, {"type": "news"}],
"max_search_results": 10,
"return_citations": true
}
}
This gives you the raw chat completion response with search-augmented context. The /v1/search endpoint provides a more structured search-specific response format.
Error Codes
| Code | Description |
|---|---|
| 400 | Invalid request — body is not JSON (code: "INVALID_JSON") or fails validation (error: "Invalid request body" with Zod details) |
| 402 | Payment required, payment verification failed (see code above), replayed authorization (PAYMENT_REPLAY), or settlement failed |
| 500 | Server error (error: "Internal server error", with details) — includes upstream search failures |
Upstream calls are made only after payment verifies; settlement happens after the search returns, so a failed search is never charged.
Error Response
{
"error": "Invalid request body",
"details": [
{
"code": "too_small",
"minimum": 1,
"path": ["query"],
"message": "String must contain at least 1 character(s)"
}
]
}