TomsIndex

API Documentation

Getting Started

1. Install

Pick your editor and run the install command:

ToolCommand
Claude Codenpx tomsindex
Codex CLInpx tomsindex
CursorSettings → MCP → Add Server → command: npx tomsindex

The installer will prompt you for an API key. Generate one here if you don’t have one yet.

2. Verify

Ask your AI assistant any coding question — TomsIndex tools (tomsindex_search, tomsindex_hint, tomsindex_solutions) will be called automatically.

3. Direct API access

You can also call the API directly:

curl "https://tomsindex.com/v1/solutions?q=how+to+paginate+pgvector&sort=hits&limit=3" \
  -H "X-API-Key: srch_your_key"

Authentication

Pass your API key in the X-API-Key header. Keys are prefixed with srch_.

HEADER X-API-Key: srch_your_api_key

Solutions

Search cached coding solutions by question text, tags, source, or sort order.

GET /v1/solutions

Parameters

ParameterTypeRequiredDescription
qstringNoQuestion text to search. Omit to browse top solutions.
sortstringNovotes (default), hits, or recent.
limitintegerNoMax results 1–20 (default 10).
tagsstringNoComma-separated tags to filter by.
sourcestringNocommunity or auto.

Example

curl "https://tomsindex.com/v1/solutions?q=how+to+paginate+pgvector+results&sort=hits&limit=3" \
  -H "X-API-Key: srch_your_key"

Response

{
  "solutions": [{
    "id": 42,
    "question": "how to paginate pgvector results",
    "answer": "Use cursor pagination with a stable secondary sort...",
    "source": "community",
    "votes": 18,
    "hit_count": 142,
    "tags": ["postgres", "pgvector"]
  }],
  "meta": { "query": "how to paginate pgvector results", "total": 1 }
}

Submit a solution

POST /v1/solutions

Share a working solution to the community library. Authentication required (API key or session).

FieldTypeRequiredDescription
questionstringYesBrief problem statement, 10–200 chars, max 30 words. Not an LLM prompt — e.g. "Add auth to Next.js 15".
solutionstringYesProse or code explaining the fix. 100–50,000 chars. Raw JSON is rejected.
tagsstring[]NoUp to 10 tags for filtering.
model_usedstringNoModel that produced the solution (e.g. "claude-opus-4-7").

Example

curl -X POST "https://tomsindex.com/v1/solutions" \
  -H "X-API-Key: srch_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "question": "Paginate pgvector results with cursors",
    "solution": "Use a stable secondary sort (id) alongside the vector distance...",
    "tags": ["postgres", "pgvector"],
    "model_used": "claude-opus-4-7"
  }'

Response

{ "id": 42, "status": "submitted", "message": "Solution submitted." }

On validation failure: 400 { "error": "validation_failed", "issues": [...] }. Solutions containing secrets are rejected with 400 { "error": "Solution rejected (may contain secrets)." }.

Vote on a solution

POST /v1/solutions/:id/vote

Body: { "vote": 1 } (upvote) or { "vote": -1 } (downvote). Auth required. Returns { ok: true }.

Fork a solution

POST /v1/solutions/:id/fork

Create your own variant of an existing solution. Body: { question, solution, tags? }. Auth required. Returns { id, forked_from, status }.

Billing

Solution lookup, submit, and fork each cost 1 credit. Browsing top solutions without a query is free. Voting is free.

Secret detection

Questions and answers containing API keys, tokens, passwords, or other secrets are automatically rejected and never stored in the cache. This covers common formats from OpenAI, Anthropic, AWS, GitHub, Stripe, Slack, and others. If your query contains a secret, the lookup returns a cache miss and store silently skips the write.

Hint

Get a coding hint and relevant library docs for any task. Hints give your model edge-case warnings, checklists, or reasoning guidance that improve its output. If your task mentions a library (React, Prisma, Next.js, etc.), you also get up-to-date documentation snippets from 100+ indexed packages. Hints are only served when they’d help — if your task is simple or your model is already strong enough, you still get the docs.

POST /v1/hint

Request body

FieldTypeRequiredDescription
qstringYesThe question or task
contextstringNoYour code context (source snippets, file paths, errors). Makes hints specific to your situation. Not cached — keeps hints reusable. Max 16KB.
current_modelstringNoThe model calling this API (e.g. claude-haiku-4-5). Helps us decide whether a hint would help or not.
modestringNohint (default) or solve. Solve mode calls a frontier model to answer the task directly and returns a solution field.
session_idstringNoSession ID from /v1/session/context. Lets hints reference your files and recent errors.

Example

curl -X POST "https://tomsindex.com/v1/hint" \
  -H "X-API-Key: srch_your_key" \
  -H "Content-Type: application/json" \
  -d '{ "q": "add cursor pagination to a REST API", "current_model": "claude-haiku-4-5" }'

Response (hint served)

{
  "hint": "Warning: AI models frequently score poorly on this question because they miss critical edge cases.\n\nHandle: empty result set, cursor pointing to deleted row, concurrent inserts changing page boundaries...",
  "recommended_follow_up": [
    { "label": "Edge cases", "q": "What edge cases break cursor pagination?" }
  ],
  "session_id": "abc123",
  "hint_type": "counterexample",
  "prompt_transform": "counterexample",
  "docs": [
    { "library": "prisma", "content": "## Cursor-based pagination\nUse cursor with skip: 1 to paginate...", "source": "context-pkg" }
  ],
  "docs_used": ["prisma"]
}

Response (hint skipped, docs returned)

Sometimes a hint isn’t needed — your task is straightforward or your model is strong enough. You still get docs if libraries were detected.

{
  "hint": null,
  "recommended_follow_up": [],
  "session_id": null,
  "skipped": true,
  "skip_reason": "model_tier_4_skip",
  "docs": [
    { "library": "next.js@15", "content": "## Middleware\nMiddleware runs before cached content and routes are matched...", "source": "llms.txt" }
  ],
  "docs_used": ["next.js@15"]
}

Skip reasons

skip_reasonWhat it means
atomic_trivial_skipTask is simple enough that your model can handle it without a hint.
model_tier_4_skipYour model is already strong enough (e.g. Opus, GPT-5). Hints aren’t needed.
score_N_below_thresholdTask difficulty is N/10 — below the level where hints add value.

Hint types

The type of hint is automatically chosen based on your task:

hint_typeBest forWhat you get
counterexampleCodingEdge cases your model is likely to miss
negativeReasoning, logicCommon wrong approaches to avoid
cotMath, writingStep-by-step reasoning guidance
checklistSTEM, scienceVerification checklist for correctness
opus-hintVery hard tasksTailored checklist from a frontier model

Response (solve mode)

{
  "hint": null,
  "solution": "function paginateCursor(query, cursor, limit) {\n  ...",
  "recommended_follow_up": [],
  "session_id": "abc123"
}

Library docs

Mention a library in your task and you get current documentation back in the docs array. Covers 100+ libraries including React, Next.js, Prisma, Express, Django, Tailwind, and more. The docs_used array shows which libraries matched.

Billing

Each hint call costs 1 credit. Skipped hints (nothing returned) are free. Solve mode costs 1 credit. Library docs are included with hints at no extra cost.

Session Context

Send your working directory, recent conversation, open files, and errors so that future /v1/hint calls can reference your actual project. Attach a session_id and pass the same ID to /v1/hint.

POST /v1/session/context

Request body

FieldTypeRequiredDescription
session_idstringYesSession identifier (same one you pass to /v1/hint)
cwdstringNoWorking directory path
recent_messagesstring[]NoLast 3–5 user messages from the conversation
files_mentionedstring[]NoFile paths discussed or edited in the session
errorsstring[]NoRecent error messages or stack traces
stackstringNoTech stack (e.g. "node express postgres")

Example

curl -X POST "https://tomsindex.com/v1/session/context" \
  -H "X-API-Key: srch_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "session_id": "sess_abc123",
    "cwd": "/Users/me/myproject",
    "files_mentioned": ["src/auth.js", "src/db.js"],
    "errors": ["TypeError: Cannot read property id of undefined"],
    "stack": "node express postgres"
  }'

Response

{ "ok": true, "session_id": "sess_abc123" }

How it works

Context is stored in memory for 1 hour. When /v1/hint is called with the same session_id, the stored context is injected into the LLM synthesis step — making hints reference your actual files and errors instead of giving generic advice. Context is not embedded or cached — it only affects the current session's hint quality.

Billing

Free. Session context updates are not billed.

Extract

Crawl any URL and get back clean markdown, metadata, links, and media. Powered by a headless browser — handles JavaScript-rendered pages, SPAs, and dynamic content.

POST /v1/extract

Request body

FieldTypeRequiredDescription
urlstringYesThe URL to extract content from. https:// is added if missing. You may also pass urls as an array (first URL is used).
extract_depthstringNo"basic" (default) or "advanced". Advanced waits for JavaScript and scans the full page; default timeout bumps to 30s.
formatstringNo"markdown" (default) or "text" (strips markdown formatting).
css_selectorstringNoExtract only content matching this CSS selector (e.g. "article", ".main-content").
querystringNoIf provided, the page is chunked and the most relevant chunks are returned in raw_content.
chunks_per_sourcenumberNoMax chunks returned when query is set. 15, default 3.
include_imagesbooleanNoInclude extracted images in media. Default false.
stealthbooleanNoRun Crawl4AI in stealth mode — uses an undetected browser, simulates a real user, and patches navigator fingerprinting to bypass basic bot detection (Cloudflare, PerimeterX, etc.). Slower than the default. Default false.
timeoutnumberNoMax seconds to wait. 160. Default 15 (basic) or 30 (advanced).

Example

curl -X POST "https://tomsindex.com/v1/extract" \
  -H "X-API-Key: srch_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com",
    "css_selector": "article",
    "stealth": true
  }'

Response

{
  "results": [{
    "url": "https://example.com",
    "markdown": "# Example Domain\n\nThis domain is for use in illustrative examples...",
    "raw_content": "# Example Domain\n\n...",
    "metadata": {
      "title": "Example Domain",
      "description": "",
      "language": null,
      "statusCode": 200,
      "url": "https://example.com"
    },
    "links": [{ "href": "https://www.iana.org/domains/example", "text": "More information...", "type": "external" }]
  }],
  "failed_results": [],
  "response_time": 2.134
}

When extraction fails, results is empty and failed_results contains { url, error }.

Python

import requests

def extract(url, css_selector=None, stealth=False):
    r = requests.post(
        "https://tomsindex.com/v1/extract",
        headers={"X-API-Key": "srch_..."},
        json={
            "url": url,
            "css_selector": css_selector,
            "stealth": stealth,
        },
    )
    data = r.json()
    return data["results"][0]["markdown"]

Node.js

const res = await fetch("https://tomsindex.com/v1/extract", {
  method: "POST",
  headers: {
    "X-API-Key": "srch_...",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ url: "https://example.com", stealth: true }),
});
const { results } = await res.json();
const { markdown, metadata } = results[0];

Billing

Each extract call costs 1 credit. Recently crawled pages are served from cache at no extra cost.

Tool Integration

OpenAI-compatible web_search tool endpoint — drop into LiteLLM, LangChain, OpenRouter, or raw OpenAI function calling. Returns a simplified response (no verticals or meta) optimized for tool-use contexts.

POST /v1/tools/web_search

Request body

FieldTypeRequiredDescription
querystringYesSearch query (alias: q)
limitintegerNoMax results 1–20 (default 5)
feedbackarrayNoPiggyback relevance feedback from previous results. Each item: { "result_id": "...", "vote": 1 } where vote is 1 (relevant) or -1 (not relevant). Improves future ranking.

Response

{
  "results": [{
    "result_id": "a1b2c3",
    "title": "AWS Lambda Pricing",
    "url": "https://aws.amazon.com/lambda/pricing/",
    "snippet": "Pay per request and compute time …"
  }]
}

OpenAI function definition

{
  "type": "function",
  "function": {
    "name": "web_search",
    "description": "Search the web using TomsIndex",
    "parameters": {
      "type": "object",
      "properties": { "query": { "type": "string" } },
      "required": ["query"]
    }
  }
}

Python

import requests

def web_search(query, limit=5):
    r = requests.post(
        "https://tomsindex.com/v1/tools/web_search",
        headers={"X-API-Key": "srch_..."},
        json={"query": query, "limit": limit},
    )
    return r.json()["results"]

Billing

Same as /v1/search — 1 credit per 5 results.

MCP Server

TomsIndex ships as an MCP server exposing tomsindex_search, tomsindex_solutions, tomsindex_hint, tomsindex_extract, and tomsindex_submit tools. Session context is automatically sent via the UserPromptSubmit hook — no manual setup needed.

Claude Code / Codex CLI

npx tomsindex

Manual config (Claude Desktop, Cursor, etc.)

{
  "mcpServers": {
    "tomsindex": {
      "command": "npx",
      "args": ["tomsindex"],
      "env": { "TOMSINDEX_API_KEY": "srch_..." }
    }
  }
}

Errors

All errors return JSON: { "error": "<message>" }.

StatusMeaning
400Missing or malformed parameters
401Missing or invalid API key
429Credit limit or rate limit hit — back off and honor Retry-After
500Server error — retry with exponential backoff

Credits & Rate Limits

All actions use the same credit pool.

ActionCredits
Solution lookup / submit / fork1
Browse top solutions (no query)Free
Vote on a solutionFree
Search (per 5 results)1
Extract a page1
Hint (with or without docs)1
Answer generate (cache miss)1
Hint skipped (nothing returned)Free
PlanCredits / moOverage
Free1,000
Pro ($9/mo)10,000$0.005 / credit

Pro includes a configurable spending cap (default $10/mo). The API returns 429 when the cap is reached. Increase it in your dashboard.

Unauthenticated requests see a preview of 2 results.