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:
{
"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:
| Field | What it adds |
|---|---|
urls | Up to 1,000 URLs per request. |
sitemap | A sitemap or sitemap index: we add its URLs and check it again every hour. |
feed | An 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.
{
"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": []
}addedandexisting: the URLs that are new, and the ones that were already in the index.invalid: each URL that was rejected, with itsreason: not a publichttporhttpsaddress, 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 acodeand amessage.
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:
status | What it means |
|---|---|
pending | Queued, or being read. |
ready | Read: it can come up in searches. |
failed | We couldn’t read it: it didn’t answer, or answered with an error. error says why, and next_read_at when we try again. |
blocked | Its 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"{
"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_atsays when it was last read,changed_atwhen its content last changed, andnext_read_atwhen 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:
{
"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?" }
}
}'{
"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
| Plan | URLs | Indexes |
|---|---|---|
| Pay as you go | Up to 100 | 3 |
| Monthly credit plan | Up to 10,000 | 50 |
| Enterprise | Unlimited | Unlimited |
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
httporhttps: no logins, cookies or paywalls. Private and internal network addresses are rejected, and come back ininvalid. - 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:
{ "query": "Alpine rain jacket in size M", "index": "idx_8f3k2m9q", "mode": "fast" }