CrawlBrain Docs
Pricing Support Open dashboardDashboard

Widget and Queries API

The widget runs on the endpoints below, and the same API has calls for managing an agent from your backend.

Base URL: https://api.crawlbrain.com/v1

Search and answers

These four take an agent key, not an API key. They work on every account, Pro or not, because they are what the widget runs on, and they spend credit like any other answer or search.

Send it as an Agent-Key header, or as ?key= on any of them. See Authentication.

Instant search

GET /agent/search

This is the type-ahead layer: hybrid vector plus keyword search with no model call, so it is fast.

Parameter Type Required Notes
key string yes Agent key
q string yes Max 200 characters
limit integer no 1 to 20. Defaults to the widget's results setting
exclude string no Comma-separated URLs to leave out, max 4,000 characters
filters string no Store filters, for example color:red|green;size:38. Up to 6 attributes
session string no Your visitor session id, max 96 characters
curl "https://api.crawlbrain.com/v1/agent/search?key=YOUR-AGENT-KEY&q=shipping&limit=5"
{
  "success": true,
  "results": [
    {
      "title": "Shipping and delivery",
      "url": "https://example.com/shipping",
      "urlPath": "/shipping",
      "snippet": "We ship to Canada in 5 to 8 business days...",
      "badges": ["both"],
      "section": "Help",
      "product": null,
      "meta": { "image": "https://example.com/img/shipping.jpg" }
    }
  ],
  "total": 4
}
Field Meaning
badges Why it matched: both, title, url, semantic or keyword
section Breadcrumb category, when the page has one
product Product card (price, image, stock) on store pages, else null
meta Featured image, date and excerpt, when known
total Results after duplicates and filters are removed
corrected Present when a misspelt or foreign-language query was corrected. Show "Showing results for ..."
facets Store filters (Color, Size, Brand) with counts, stores only
ready false while the website's index is still being built

A query shorter than 2 characters returns no results. Each search is paid from credit. When the balance runs low, search keeps working on keyword matching only, at no cost. Search is rate limited to 600 per minute per agent.

exclude is how a "keep searching" button works: pass the URLs already shown and get the next set.

Ask a question

POST /agent/query

Use this one for the AI answer, with citations.

Field Type Required Notes
question string yes Max 1,000 characters
session string no Your visitor session id, max 96 characters
history array no Earlier turns, [{"question": "...", "answer": "..."}], last 20 kept
exclude_urls array no Up to 50 URLs to leave out of the answer

Add ?locale=fr to the URL to answer in a given language.

curl -X POST https://api.crawlbrain.com/v1/agent/query \
  -H "Agent-Key: YOUR-AGENT-KEY" \
  -H "Content-Type: application/json" \
  -d '{"question":"Do you ship to Canada during winter?"}'
{
  "success": true,
  "response": "Yes. Winter delivery to Canada takes 6 to 10 business days [Source 1].",
  "sources": [
    { "n": 1, "url": "https://example.com/shipping", "title": "Shipping and delivery", "product": null }
  ],
  "cited": [1],
  "products": []
}
Field Meaning
response The answer. [Source N] markers point into sources
sources The pages the answer used, with product cards on store pages
cited The n values the answer actually cites. Show only these
products Store products the answer names by model code

When the site's content does not cover the question, the response carries only success and response (a short explanation) with no sources, and the call costs nothing. Answers are cached for 10 minutes, so a repeat of the same question is fast and free.

Each answer is paid from credit. With too little credit the call returns 402:

{ "success": false, "code": "credit_balance_empty", "response": "AI answers are temporarily unavailable..." }

Questions are rate limited to 20 per minute.

Follow-up questions. Send the earlier turns in history and the answer takes them into account, so "how much for a sofa?" after "do you ship to Europe?" answers about shipping a sofa to Europe. An empty history list means a fresh question with no context. If you leave history out, CrawlBrain uses the turns it remembers for that session.

Streaming. Send Accept: text/event-stream to receive the answer as Server-Sent Events: meta, then chunk events with text, then citations and done. The streamed answer has no product cards and no products list.

Feedback

POST /agent/feedback
Field Type Required Notes
question string yes Max 1,000 characters
feedback string yes like or dislike
session string no The session sent with the question

This records the thumbs up or down. It shows up in Conversations, where filtering by thumbs down is the fastest way to find answers worth fixing.

Settings

GET /agent/settings

The response holds everything needed to render the widget: placement, colors, texts and starter questions.

curl "https://api.crawlbrain.com/v1/agent/settings?key=YOUR-AGENT-KEY"

Use it when you are building your own front end instead of embedding ours, so your UI stays in sync with the dashboard.

Add ?locale= with the visitor's language to get starter questions and labels in that language. Settings are cached for 5 minutes, so a change in the dashboard can take that long to show. The response also carries siteType (store, docs, blog or business), which decides the result layout, and topResults, the pages to show before the visitor types.

Products

GET /agent/products
Parameter Type Required Notes
list string no popular (default) or new
limit integer no 1 to 24, default 10
{
  "success": true,
  "list": "popular",
  "products": [
    {
      "url": "https://example.com/product/linen-shirt",
      "title": "Linen Shirt",
      "image": "https://example.com/img/linen-shirt.jpg",
      "price": 70.4,
      "regularPrice": 88,
      "currency": "USD",
      "inStock": true,
      "rating": 4.5,
      "reviewCount": 12
    }
  ]
}

These are the products shown before the visitor types. The list comes back empty unless the website type is store.

POST /agent/products/click
Field Type Required
url string yes

A click on a product card is recorded here and feeds the popular list. You get success: false back when the URL is not a known product.

Latest articles

GET /agent/pages
Parameter Type Required Notes
list string no latest
limit integer no 1 to 24, default 10

The response holds pages, each with url, title and, when known, image, date, excerpt and section. It is empty unless the website type is blog.

Managing an agent

These calls take an API key and need Pro.

Get the agent

GET /agent/get
Field Type Required
id string yes

This call returns the agent for a website, including its public agent key, and it is the one to make when generating an embed snippet for a customer.

{
  "success": true,
  "agent": {
    "key": "3f6b2a1c-...",
    "name": "Ask AI",
    "placement": "search-replace",
    "search_selector": null,
    "floating_position": "bottom-right",
    "brand_color": "#0F172A"
  }
}

The agent also carries its texts, colors, sizes and icon settings, the same fields /agent/update accepts. A website with no widget returns 404 with agent_not_found.

Update appearance and placement

POST /agent/update
Field Values
id Website id, required
placement floating, search-replace, search-adjacent
search_selector CSS selector of the search box. Leave empty to detect it automatically
floating_position bottom-right, bottom-left. Required for floating
search_placeholder Max 60 characters
brand_color #RRGGBB
button_color #RRGGBB
button_text_color #RRGGBB
button_radius 0 to 80
button_icon none, search, sparkle, chat, lightning, robot, question, custom
font_size small, medium, large
font_family system, sans-serif, serif, monospace, rounded, inherit
search_results_shown 3 to 10

Send only what you want to change. Sending a field as null clears it.

{ "success": true, "changed": ["brand_color"], "agent": { "key": "3f6b2a1c-...", "brand_color": "#1D4ED8" } }

A request with none of these fields returns 422 with no_fields. Changes reach visitors within 5 minutes.

This is deliberately narrower than the Setup page: it covers appearance and placement, while the model tier, tone and translations are account decisions that stay in the dashboard.

Starter questions

All three calls take an API key.

POST   /agent/question/add       { id, question }
GET    /agent/question/list      { id }
DELETE /agent/question/delete    { id, question }

Use them to manage starter questions from your own code, for example for seasonal rotation: swap in shipping-deadline questions in December and swap them back in January.

Reading the question log

GET /agent/question/log
Field Type Required Notes
id string yes
days integer yes
type string no ERROR for unanswered questions only, INFO for answered ones
{
  "success": true,
  "log": [
    { "type": "ERROR", "question": "Do you ship to Iceland?", "response": "I could not find shipping details for Iceland..." }
  ]
}

The log holds every visitor question for that period with the answer it got. This call takes an API key.

The obvious use is pulling unanswered questions into whatever you already run, so content gaps land in your backlog rather than waiting to be noticed.

curl "https://api.crawlbrain.com/v1/agent/question/log?id=WEBSITE_ID&days=7" \
  -H "Api-Key: cb_your_key_here"

Building your own front end

The widget is optional. If you want your own interface, the pattern is:

  1. GET /agent/settings once, to pick up texts and starter questions.
  2. GET /agent/search on each keystroke, debounced by 150 to 250 milliseconds.
  3. POST /agent/query on submit, with a session id you generate and keep for the visit, and the earlier turns in history for follow-ups.
  4. POST /agent/feedback when someone rates an answer.

Render the sources from the query response. Do not skip them: they are how a visitor verifies the answer, and they are the reason to trust it at all.

An agent key is safe in front-end code, but an API key is not.