Custom index

Search your own URLs, sitemaps and feeds with the same relevance model, modes and prices as the news index.

A custom index is a list of URLs you choose, like product pages, investor-relations pages, agency bulletins or reviews. We read them, keep them fresh and search them the way we search the news: a calibrated probability on every page, the best candidates read before they are ranked, and typed answers in the same call. You search it with the same POST /v1/search, passing index.

Create an index

curl https://api.typesearch.ai/v1/indexes \
  -H "Authorization: Bearer $TYPESEARCH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Catalog" }'

It answers 201 with the index:

201 Created
{
  "id": "idx_8f3k2m9q",
  "object": "index",
  "name": "Catalog",
  "status": "active",
  "urls": { "total": 0, "ready": 0, "pending": 0, "failed": 0, "blocked": 0 },
  "sources": [],
  "last_read_at": null,
  "created_at": "2026-09-26T14:02:11Z",
  "updated_at": "2026-09-26T14:02:11Z"
}

GET /v1/indexes lists your indexes, with your plan’s limits; GET /v1/indexes/{id} returns one, and DELETE /v1/indexes/{id} deletes it with everything in it ({ "id": "idx_…", "deleted": true }). You can also create and manage indexes from the dashboard, in Indexes.

Add URLs, a sitemap or a feed

POST /v1/indexes/{id}/urls takes any of the three, in the same request:

FieldWhat it adds
urlsUp to 1,000 URLs per request.
sitemapA sitemap or sitemap index: we add its URLs and check it again every hour.
feedAn RSS or Atom feed: we add its URLs and check it again every hour.
curl https://api.typesearch.ai/v1/indexes/idx_8f3k2m9q/urls \
  -H "Authorization: Bearer $TYPESEARCH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "urls": ["https://shop.example/p/ridgeline-trail-4", "https://shop.example/p/canyon-grip-gtx"],
    "sitemap": "https://shop.example/sitemap.xml"
  }'

It answers 202 Accepted: the URLs are queued and read right away.

202 Accepted
{
  "index": "idx_8f3k2m9q",
  "added": 2,
  "existing": 0,
  "invalid": [],
  "over_limit": 0,
  "total": 2,
  "sources": [
    {
      "url": "https://shop.example/sitemap.xml",
      "type": "sitemap",
      "status": "pending",
      "read_at": null,
      "urls": 0,
      "error": null
    }
  ],
  "limits": { "urls": 100, "urls_used": 2, "indexes": 3, "indexes_used": 1 },
  "warnings": []
}
  • added and existing: the URLs that are new, and the ones that were already in the index.
  • invalid: each URL that was rejected, with its reason: not a public http or https address, for example.
  • over_limit: URLs that didn’t fit in your plan’s limit and were not added. See limits and pricing.
  • total: the URLs in the index now. sources: the sitemaps and feeds it follows.
  • warnings: notes that don’t stop the request, each with a code and a message.

To remove URLs, send DELETE /v1/indexes/{id}/urls with the urls to remove, or with sources to remove sitemaps or feeds by their URL. It answers with how many were removed.

Statuses

Every URL has a status:

statusWhat it means
pendingQueued, or being read.
readyRead: it can come up in searches.
failedWe couldn’t read it: it didn’t answer, or answered with an error. error says why, and next_read_at when we try again.
blockedIts robots.txt, an opt-out signal or a publisher exclusion says no. We don’t read it.

GET /v1/indexes/{id}/urls lists them, filtered by status if you want, a page at a time (limit, and cursor with the next_cursor of the previous page; null on the last one):

curl "https://api.typesearch.ai/v1/indexes/idx_8f3k2m9q/urls?status=failed&limit=50" \
  -H "Authorization: Bearer $TYPESEARCH_API_KEY"
urls[0]
{
  "url": "https://shop.example/p/ridgeline-trail-4",
  "status": "ready",
  "title": "Ridgeline Trail 4 · trail running shoe",
  "description": "Grippy, light and made for long days on rough ground.",
  "data": { "price": 109, "currency": "USD", "availability": "InStock", "brand": "Ridgeline", "sku": "RT4-42" },
  "published_at": null,
  "read_at": "2026-09-26T09:14:02Z",
  "changed_at": "2026-09-24T09:10:40Z",
  "next_read_at": "2026-09-27T09:14:02Z",
  "error": null
}

data is the structured data the page itself declares (price, currency, availability, brand, sku…), or null when it declares none.

The index has its own status: active, or paused when your credit runs out. A paused index keeps its URLs, but they aren’t re-read until there is credit again.

How fresh it stays

  • Every URL is re-read once a day. read_at says when it was last read, changed_at when its content last changed, and next_read_at when it will be read again.
  • Sitemaps and feeds are checked every hour, and new or updated URLs in them are read right away.
  • robots.txt is honored on every read.

Re-reading is included in the price.

Search it

Pass index to POST /v1/search. Everything else works as in any search (modes, typed questions, tone, highlights, max_results, max_tokens), with two differences: a request with index takes one query, and there is no date filter unless you set one (days, published_after or published_before).

curl https://api.typesearch.ai/v1/search \
  -H "Authorization: Bearer $TYPESEARCH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "query": "trail running shoes under $120", "index": "idx_8f3k2m9q", "mode": "fast" }'

The response is a regular search response. It adds custom_index, and every result says found_in: "custom_index" and carries the page’s data:

Response (abridged)
{
  "object": "search",
  "mode": "fast",
  "custom_index": { "id": "idx_8f3k2m9q", "name": "Catalog" },
  "found": true,
  "results": [
    {
      "url": "https://shop.example/p/ridgeline-trail-4",
      "title": "Ridgeline Trail 4 · trail running shoe",
      "score": 0.96,
      "found_in": "custom_index",
      "data": { "price": 109, "currency": "USD", "availability": "InStock", "brand": "Ridgeline", "sku": "RT4-42" }
    }
  ]
}

To put your pages next to the press coverage, send the same query twice: once with index, once without.

Typed questions: price, stock, “did it change?”

data gives you what the page declares. A typed question answers what it doesn’t: is size M available, is it under your budget, did the return policy change, did the company revise its guidance. Use normal or deep when the answer is in the page and not in its title: they read the best candidates before ranking them.

curl https://api.typesearch.ai/v1/search \
  -H "Authorization: Bearer $TYPESEARCH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "Alpine rain jacket in size M",
    "index": "idx_8f3k2m9q",
    "mode": "normal",
    "questions": {
      "in_stock": { "type": "boolean", "instructions": "Is size M in stock?" },
      "on_sale": { "type": "boolean", "instructions": "Is it discounted from its regular price?" }
    }
  }'
results[0].answers
{
  "basis": "article",
  "values": {
    "in_stock": { "type": "boolean", "probability": 0.97 },
    "on_sale": { "type": "boolean", "probability": 0.08 }
  }
}

As in any search, a probability between 0.35 and 0.65 means undecided, and basis says whether the answer came from the page or only from its title.

Limits and pricing

PlanURLsIndexes
Pay as you goUp to 1003
Monthly credit planUp to 10,00050
EnterpriseUnlimitedUnlimited

URLs past your limit come back in over_limit and are not added. limits in GET /v1/indexes and in every POST /v1/indexes/{id}/urls says how many you use; null means unlimited. More URLs come with the monthly credit plan.

An index costs $2.00 per 1,000 URLs a month, billed daily and prorated from the same prepaid credit: a full pay-as-you-go index of 100 URLs costs $0.20 a month, and 10,000 URLs cost $20. Re-reading is included. Searches over it cost the same as any search in that mode: $1.00 per 1,000 in ultra, $1.40 in fast, $2.20 in normal and $5.60 in deep. See Costs and caching.

What we read, and what we don’t

  • Only public URLs. Pages anyone can open over http or https: no logins, cookies or paywalls. Private and internal network addresses are rejected, and come back in invalid.
  • The same compliance gate as the news index. robots.txt, AI opt-out signals and publisher exclusions apply to every URL you add. A page that says no comes back as blocked, and we don’t read it.
  • Yours only. An index and what we read for it belong to your organization: no other customer can search it.
  • Never used for training. Your URLs, the pages we read for them and your queries are never used to train models.

From the MCP server

The MCP server’s search_news takes an optional index: pass your idx_… and it searches your index instead of the news index, with the same key and prices. Your agent can then check your catalog and the news with the same tool:

search_news
{ "query": "Alpine rain jacket in size M", "index": "idx_8f3k2m9q", "mode": "fast" }

On this page