Developer API · v1

API reference

A JSON API over the DeepSearch public-footprint engine. Authenticate with a key, POST a request, and read results as a live stream or a single response.

Introduction

#

Every endpoint lives under https://deepsearch.app/api/v1 and accepts a JSON body over POST. Responses stream as Server-Sent Events by default, or return a typed JSON object when you pass "format": "json".

Base URLhttps://deepsearch.app/api/v1

Quickstart

Create a key in the portal, export it, and call your first endpoint:

12345678curl https://deepsearch.app/api/v1/search \  -H "Authorization: Bearer $DEEPSEARCH_API_KEY" \  -H "Content-Type: application/json" \  -d '{        "query": "Ada Lovelace",        "type": "name",        "format": "json"      }'

Authentication

#

Authenticate every request with a bearer token in the Authorization header. Keys are created in the developer portal and are shown in full only once - store them somewhere safe and never expose them in client-side code.

Authorization header
1234curl https://deepsearch.app/api/v1/search \  -H "Authorization: Bearer $DEEPSEARCH_API_KEY" \  -H "Content-Type: application/json" \  -d '{ "query": "Ada Lovelace" }'

Scopes

Each key carries scopes that gate which endpoints it can call. New keys are granted all three by default, but production keys can be narrowed to only the endpoints they need and can be given an expiry date or per-key minute limit.

searchSearch
dossierDossier
chatChat

A request with a missing or revoked key returns 401; a valid key without the required scope returns 403.

SDKs

#

The repo includes dependency-free starters for TypeScript and Python plus reference apps for Node, Next.js server routes, and MCP clients — and a published command-line interface. Keep API keys server-side and start with sandbox: true while wiring parsers and UI states.

TypeScript SDK
sdks/typescript
Python SDK
sdks/python
Node example
examples/node-cli
Next.js starter
examples/nextjs-starter
MCP agent
examples/mcp-agent
TypeScript SDK
12345678910111213import { DeepSearchClient } from "@deepsearch/client";const deepsearch = new DeepSearchClient({  apiKey: process.env.DEEPSEARCH_API_KEY!,});const result = await deepsearch.search({  query: "Ada Lovelace",  type: "name",  sandbox: true,});console.log(result.hits);

Command-line interface

#

@reloadapp/deepsearch is a single self-contained CLI — no runtime dependencies — that shares the same scopes, wallet metering, and sandbox behavior as the REST API. Run it with npx or install it globally as deepsearch. Requires Node.js ≥ 20.9.

Install
123456# Run without installing anythingnpx @reloadapp/deepsearch search "Ada Lovelace" --sandbox# Or install globally, then call `deepsearch`npm install -g @reloadapp/deepsearchdeepsearch --help

Authentication

The CLI resolves your key in order: --api-key DEEPSEARCH_API_KEY~/.deepsearch/config.json (written by deepsearch login, stored with 0600 permissions). Every command takes --json, --sandbox, and --stream.

Common commands
12345678910# Save a key once (written to ~/.deepsearch/config.json, 0600)deepsearch login# Name search, then a streaming dossierdeepsearch search "Ada Lovelace" --type name --sandboxdeepsearch dossier "Ada Lovelace" --stream# Ask a follow-up, or queue an async job from a payload filedeepsearch chat "Ada Lovelace" "Summarize the public sources" --sandboxdeepsearch jobs create dossier --input @job.json --idempotency-key demo-1

Commands

search <query>
Find people by name, phone, email, or username.
dossier <name>
Build or replay a public-footprint dossier.
chat <name> <message…>
Ask a follow-up question about a person.
jobs <create|list|get|events>
Queue and inspect async background jobs.
status
Show developer API availability (no key required).
login
Save an API key and base URL to the CLI config.
config <get|set|path>
Inspect or edit stored CLI config.

Add --sandbox while integrating: it requires a valid scoped key but returns deterministic Ada Lovelace fixtures and never spends wallet credits.

MCP integration

#

DeepSearch also exposes a hosted MCP server for agents and IDEs that support Streamable HTTP. Use the same API key as a bearer token; scopes, expiry, rate limits, wallet metering, and onboarding errors behave the same as REST.

streamable-httphttps://deepsearch.app/api/mcp
oauthhttps://deepsearch.app/.well-known/oauth-protected-resource
Open setup panel
1234567891011{  "mcpServers": {    "deepsearch": {      "type": "streamable-http",      "url": "https://deepsearch.app/api/mcp",      "headers": {        "Authorization": "Bearer ${DEEPSEARCH_API_KEY}"      }    }  }}
search_people
Search people
build_dossier
Build dossier
ask_about_person
Ask about a person

Put DEEPSEARCH_API_KEYin your MCP client's local secret store or environment. Do not commit a plaintext key inside mcp.json.

Sandbox mode

#

Sandbox mode returns deterministic Ada Lovelace fixtures for search, dossier, and chat. It still requires a valid scoped API key, but it does not spend credits and includes usage.sandbox, metadata.sandbox, and X-DeepSearch-Sandbox.

Sandbox request
12345curl https://deepsearch.app/api/v1/search \  -H "Authorization: Bearer $DEEPSEARCH_API_KEY" \  -H "Content-Type: application/json" \  -H "X-DeepSearch-Sandbox: true" \  -d '{ "query": "anything", "type": "name", "format": "json" }'

Rate limits & billing

#

API usage draws on the same wallet as the app. Every account gets 10 metered requests per 7-day window; after that, each metered request costs 1 coin.

  • The weekly allowance is spent first, then coins - automatically, with no separate configuration.
  • /dossier results are cached and shared. A cache hit returns instantly and does not spend credits; only a fresh build meters.
  • When the weekly allowance is exhausted and no coins remain, metered requests return 402.
  • Default per-key limits are 60/min for search, 30/min for dossier, and 60/min for chat, plus an IP abuse ceiling.
  • Production keys can also carry an optional monthly credit budget. Budgeted keys return 402 api_key_budget_exceeded before spending more credits.

There is no separate API price. If you can run a search in the app, you can run it from the API on the same balance.

Streaming & formats

#

Endpoints stream text/event-stream by default - each chunk is a data: line carrying one JSON event. Pass "format": "json" in the body to receive a typed response once the run completes: search_result includes hits, dossier_result includes dossier, and chat_result includes answer.

status
A human-readable progress label.
hit
A candidate person match (search).
section
A filled dossier section (dossier).
summary
A streamed chunk of the written summary (dossier).
sources
The cited sources backing the result (dossier).
text
A streamed chunk of the chat answer (chat).
related
Suggested follow-up questions (chat).
social_account_found
Additive social-discovery evidence (search).
account_updated
Updated social-account evidence (search).
cluster_updated
Updated candidate-cluster evidence (search).
evidence
A provenance claim backing an account or cluster (search).
avatar_updated
A profile-photo candidate was verified or updated (search).
done
The stream completed; partial: true if cut short.
error
A fatal error occurred mid-stream.

Clients should ignore unknown event types - new ones may be added over time without a version bump.

Idempotency

#

Send Idempotency-Key on retries. For format=json, DeepSearch stores and replays the completed JSON response when the same key and body are used again. If the same key is reused with a different body, the API returns 409 idempotency_conflict.

  • For SSE requests, idempotency protects wallet spend but does not replay a prior event stream.
  • Responses include X-Request-Id, X-DeepSearch-Metered, X-DeepSearch-Credits-Charged, and standard RateLimit-* headers.
  • Request bodies are capped at 64KB; chat requests accept up to 20 messages.

Async jobs

#

Queue long-running API work through POST /api/v1/jobs. Jobs support idempotent creation, background execution, polling, stored SSE replay, sandbox mode, and signed webhook delivery.

Create job
123456789101112curl https://deepsearch.app/api/v1/jobs \  -H "Authorization: Bearer $DEEPSEARCH_API_KEY" \  -H "Content-Type: application/json" \  -H "Idempotency-Key: demo-job-1" \  -d '{    "operation": "dossier",    "input": {      "person": { "name": "Ada Lovelace" },      "format": "json"    },    "sandbox": true  }'
POST /api/v1/jobs

Create a queued background job.

GET /api/v1/jobs

List the caller's recent jobs.

GET /api/v1/jobs/{id}

Fetch status, errors, and final result.

GET /api/v1/jobs/{id}/events

Replay stored Server-Sent Events.

Webhooks

#

Webhooks notify your backend when background work finishes. Endpoints receive signed JSON with a stable event id, type, v1 API version, timestamp, and event data.

job.succeededjob.failed
Webhook headers
123X-DeepSearch-Event: job.succeededX-DeepSearch-Delivery: evt_...X-DeepSearch-Signature: t=1760000000,v1=<hmac_sha256>

Verify X-DeepSearch-Signature by computing HMAC SHA-256 over {timestamp}.{raw_body} with the webhook secret shown once at creation time.

Analytics

#

The developer portal includes usage charts, request tables, key breakdowns, credits, cache hit rate, latency, MCP vs REST transport, errors, and request IDs. The same window can be exported as CSV from the portal or from /api/developer/usage/export?windowDays=30.

Usage

Requests, metered calls, credits, operations, and cache hit rate.

Reliability

Success rate, blocked calls, errors, latency, and slowest requests.

Audit

API key breakdowns, request IDs, idempotency keys, and CSV export.

Safety

#

DeepSearch is for public-footprint research only. Keep API keys server-side, use the narrowest key scopes that work for your integration, and preserve X-Request-Id in your logs for auditability.

  • Do not scrape login-gated, private, or paywalled profiles.
  • Do not collect breached contents, passwords, secrets, or credentials.
  • Do not make credit, housing, employment, insurance, education, or similar eligibility decisions from API output.
  • Surface sources and confidence so a human can verify important claims.

See terms and the checked-in acceptable-use guide for the complete policy.

Dossier

#
POST/api/v1/dossierdossier scope

Pass a candidate from /search (or a minimal person object) and stream a structured dossier - identity, contact, social accounts, locations, work, mentions and a written summary with cited sources. Results are cached: a shared cache hit returns instantly and does not spend wallet credits.

Body parameters

person
object· required

The subject to profile. Only person.name is required; pass the full PersonHit from /search to focus on the exact candidate.

person.name
string· required

The person's full name.

refresh
boolean· optional

Bypass the shared cache and rebuild from scratch (this always meters).

default: false
format
enum· optional

sse to stream sections as they fill, or json for a single collected response.

ssejsondefault: sse
sandbox
boolean· optional

Return deterministic, unmetered fixtures for CI, demos, and parser development.

default: false

Request

1234567891011121314curl https://deepsearch.app/api/v1/dossier \  -H "Authorization: Bearer $DEEPSEARCH_API_KEY" \  -H "Content-Type: application/json" \  -d '{        "person": {          "name": "Ada Lovelace",          "headline": "Mathematician · London",          "confidence": 82,          "tags": [            "Computing pioneer"          ]        },        "format": "json"      }'

Response

200 · application/json
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768{  "object": "dossier_result",  "request_id": "req_01HZY8N9M52JGQ7PC1X3TPEF5R",  "metadata": {    "api_version": "v1",    "operation": "dossier",    "request_id": "req_01HZY8N9M52JGQ7PC1X3TPEF5R",    "generated_at": "2026-06-19T12:00:00.000Z"  },  "usage": {    "metered": true,    "credits": 1,    "allowanceSource": "weekly",    "cached": false  },  "cached": false,  "dossier": {    "summary": "Ada Lovelace was a 19th-century mathematician widely regarded as the first computer programmer.",    "sections": {      "identity": {        "name": "Ada Lovelace",        "age": null      }    },    "sources": [      {        "id": "src-1",        "position": 1,        "url": "https://en.wikipedia.org/wiki/Ada_Lovelace",        "title": "Ada Lovelace",        "domain": "en.wikipedia.org"      }    ]  },  "events": [    {      "type": "section",      "key": "identity",      "data": {        "name": "Ada Lovelace",        "age": null      }    },    {      "type": "summary",      "delta": "Ada Lovelace was a 19th-century mathematician "    },    {      "type": "summary",      "delta": "widely regarded as the first computer programmer."    },    {      "type": "sources",      "sources": [        {          "id": "src-1",          "position": 1,          "url": "https://en.wikipedia.org/wiki/Ada_Lovelace",          "title": "Ada Lovelace",          "domain": "en.wikipedia.org"        }      ]    },    {      "type": "done"    }  ]}

Cached dossiers are free. A fresh build uses one allowance, then one coin.

Chat

#
POST/api/v1/chatchat scope

Continue a conversation about a subject. Send the running message history and DeepSearch streams a grounded answer plus suggested follow-up questions, drawing on the person's public footprint.

Body parameters

person
object· required

The subject of the conversation. person.name is required.

messages
Message[]· required

The conversation so far. Each message has a role (user or assistant) and content string. At least one message is required.

context
string· optional

Optional extra grounding context (e.g. a prior dossier summary) to steer the answer.

format
enum· optional

sse to stream the answer token-by-token, or json for the collected response.

ssejsondefault: sse
sandbox
boolean· optional

Return deterministic, unmetered fixtures for CI, demos, and parser development.

default: false

Request

123456789101112131415curl https://deepsearch.app/api/v1/chat \  -H "Authorization: Bearer $DEEPSEARCH_API_KEY" \  -H "Content-Type: application/json" \  -d '{        "person": {          "name": "Ada Lovelace"        },        "messages": [          {            "role": "user",            "content": "Summarize her public footprint."          }        ],        "format": "json"      }'

Response

200 · application/json
12345678910111213141516171819202122232425262728293031323334353637383940{  "object": "chat_result",  "request_id": "req_01HZY8P8V1TXZ6YXMJ56ATJZ1J",  "metadata": {    "api_version": "v1",    "operation": "chat",    "request_id": "req_01HZY8P8V1TXZ6YXMJ56ATJZ1J",    "generated_at": "2026-06-19T12:00:00.000Z"  },  "usage": {    "metered": true,    "credits": 1,    "allowanceSource": "weekly"  },  "answer": "Ada Lovelace is best known for her notes on Babbage's Analytical Engine.",  "related_questions": [    "What did she publish?",    "Who did she collaborate with?"  ],  "events": [    {      "type": "text",      "delta": "Ada Lovelace is best known for "    },    {      "type": "text",      "delta": "her notes on Babbage's Analytical Engine."    },    {      "type": "related",      "questions": [        "What did she publish?",        "Who did she collaborate with?"      ]    },    {      "type": "done"    }  ]}

Each answered question uses one weekly allowance, then one coin.

Errors

#

Errors return the matching HTTP status and a JSON body of the shape { "error": { "code", "message" } }. The code is stable and safe to branch on.

400
invalid_json
The request body was not valid JSON.
400
invalid_request
The body failed validation (a field is missing or malformed).
401
missing_api_key
No Authorization: Bearer <key> header was sent. Body carries an onboarding url.
401
invalid_api_key
The API key is unknown, malformed, or revoked.
401
expired_api_key
The key is valid but past its configured expiry date.
402
not_subscribed
The account has no active subscription. Body carries a url to subscribe.
402
no_coins
The weekly allowance is spent and no coins remain. Body carries a url to add coins.
403
missing_scope
The key is valid but lacks the scope this endpoint needs.
409
idempotency_conflict
The Idempotency-Key was reused with a different request body.
413
request_too_large
The JSON body is larger than the API accepts.
404
developer_api_disabled
The Developer API is not enabled for this deployment.
429
rate_limited
Too many requests from this API key or IP. Retry after the reset time.
503
spend_cap_reached
A temporary service-wide spend cap was hit. Retry later.

Ready to build?

Create a key and try every endpoint live in the playground.

Open the playground