Public Search API
Integrate AI-powered sacred text search into your applications
The SifterSearch Public API provides programmatic access to our hybrid search system with full AI analysis, scoring, and highlighting. Use it to build custom search interfaces, research tools, or integrate sacred text search into your own applications.
An interactive Swagger UI is available at https://api.siftersearch.com/api/v1/docs for exploring and testing all endpoints directly in your browser.
API Endpoints
| Service | Endpoint | Description |
|---|---|---|
| Search — Full-text + semantic search across sacred texts | ||
POST /api/v1/search | Hybrid search with AI analysis and scoring | |
POST /api/v1/search/quick | Fast keyword-only search (no AI, cacheable) | |
GET /api/v1/paragraph/:id | Get a specific paragraph by ID | |
GET /api/v1/collections | List religions and collections with counts | |
| Library — Browse and search the document catalog | ||
GET /api/v1/library/documents | Search documents by title, author, metadata | |
GET /api/v1/library/documents/:id | Get single document metadata + canonical URL | |
GET /api/v1/library/authors | List authors with document counts | |
GET /api/v1/library/religions | Religion/collection tree with counts | |
| Chat — AI research assistant | ||
POST /api/v1/chat | Conversational AI search (SSE streaming) | |
| Tools — For AI agents and chatbots | ||
POST /api/v1/tools/search | Unified search tool (passages/documents/count/read) | |
GET /api/v1/tools/library | Library overview stats | |
| System | ||
GET /api/v1/health | API health check (no auth required) | |
Authentication
All API requests require an API key passed in the X-API-Key header.
curl -X POST https://api.siftersearch.com/api/v1/search \
-H "Content-Type: application/json" \
-H "X-API-Key: your-api-key-here" \
-d '{"query": "what is justice"}' API keys are self-service. Sign up for a SifterSearch account, subscribe to an API plan in Settings → API Keys, then create your first key. Your key is active immediately. See API Billing for pricing details.
Getting Started
Four steps to your first request:
- Sign up — Create a free SifterSearch account at /login.
- Subscribe — In Settings → API Keys, activate the pay-per-search plan.
- Create a key — Click "Create API Key", give it a name, and copy the key shown once.
- Make a request — Pass the key in the
X-API-Keyheader on every call.
Your first request (example with cURL):
curl -X POST https://api.siftersearch.com/api/v1/search \
-H "Content-Type: application/json" \
-H "X-API-Key: sk_live_your-key-here" \
-d '{"query": "what does Islam teach about gratitude"}' Rate Limits
Standard accounts are limited to 1,000 requests per hour with up to 50 results per request. Rate limit headers are included in every response:
X-RateLimit-Limit— Maximum requests per hourX-RateLimit-Remaining— Requests remaining in current windowX-RateLimit-Reset— Unix timestamp when the window resets
Billing
The API uses metered pay-per-search pricing at approximately $0.001 per search.
Hybrid searches (/search) are always billed. Quick/keyword searches (/search/quick)
are free when served from cache — the same keyword query within 15 minutes costs nothing.
Admin accounts have free unlimited access. Invoices are generated monthly via Stripe.
See API Billing documentation for full details.
Search Service
Search results from both /search and /search/quick include
url and documentUrl fields containing canonical
siftersearch.com links to the passage and its parent document respectively.
POST /api/v1/search
Full hybrid search with AI-powered analysis. Returns scored, highlighted results with brief summaries. Best for detailed research queries.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
query | string | Yes | Search query (1-500 characters) |
limit | integer | No | Max results to return (1-50, default: 10) |
filters | object | No | Filter criteria (see below) |
Filter Options
| Field | Type | Description |
|---|---|---|
religion | string | Filter by religion (e.g., "Baha'i", "Buddhism") |
collection | string | Filter by collection (e.g., "Pilgrim Notes") |
yearFrom | integer | Minimum publication year |
yearTo | integer | Maximum publication year |
Faceting Examples
Filter by religion:
{
"query": "the nature of the soul",
"filters": {
"religion": "Buddhism"
}
} Filter by collection:
{
"query": "daily devotional practice",
"filters": {
"collection": "Pilgrim Notes"
}
} Filter by author:
{
"query": "unity of religions",
"filters": {
"author": "Abdu'l-Baha"
}
} Filter by year range:
{
"query": "interfaith dialogue",
"filters": {
"yearFrom": 1900,
"yearTo": 1950
}
} Example Request
POST /api/v1/search
Content-Type: application/json
X-API-Key: sk_live_your-key-here
{
"query": "meaning of prayer and meditation",
"limit": 5,
"filters": {
"religion": "Baha'i"
}
} Example Response
{
"results": [
{
"id": "1907_07_martha_root_reflections_p42",
"documentId": "1907_07_martha_root_reflections",
"paragraphIndex": 42,
"text": "Prayer and supplication are two wings whereby man soars...",
"highlightedText": "<mark>Prayer and supplication</mark> are two wings...",
"title": "Reflections on Prayer and Contemplation",
"author": "Martha Root",
"religion": "Baha'i",
"collection": "Pilgrim Notes",
"score": 92,
"summary": "Prayer enables spiritual ascent",
"url": "https://siftersearch.com/read/1907_07_martha_root_reflections#p42",
"documentUrl": "https://siftersearch.com/read/1907_07_martha_root_reflections"
}
],
"query": "meaning of prayer and meditation",
"totalFound": 47,
"processingTimeMs": 1234
} POST /api/v1/search/quick
Fast keyword-only search without AI analysis. Returns raw Meilisearch results with word-level highlighting. Best for autocomplete, typeahead, or high-volume queries.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
query | string | Yes | Search query (1-200 characters) |
limit | integer | No | Max results (1-50, default: 10) |
filters | object | No | Filter by religion or collection |
Example Response
{
"results": [
{
"id": "hidden_words_p23",
"text": "The light of men is <mark>Justice</mark>...",
"title": "Hidden Words",
"author": "Baha'u'llah",
"religion": "Baha'i",
"collection": "Core Publications",
"score": 0.98,
"url": "https://siftersearch.com/read/hidden_words#p23",
"documentUrl": "https://siftersearch.com/read/hidden_words"
}
],
"query": "justice",
"processingTimeMs": 6
} GET /api/v1/collections
List available religions and collections in the library. Useful for building filter UIs.
Example Response
{
"religions": ["Baha'i", "Buddhism", "Christianity", "Hinduism", "Islam", "Judaism"],
"collections": ["Core Publications", "Pilgrim Notes", "Letters", "Talks"],
"totalDocuments": 12847,
"lastUpdated": "2024-12-14T00:00:00Z"
} GET /api/v1/health
API health check. Does not require authentication.
Example Response
{
"status": "ok",
"version": "1.0.0",
"timestamp": "2024-12-14T22:52:43.717Z"
} Library Service
Browse and query document metadata without consuming search quota. Library endpoints are useful for building browsing interfaces, populating filter dropdowns, or discovering what is available before running searches.
GET /api/v1/library/documents
Search and browse the document library. Returns document metadata and canonical URLs.
Query Parameters
| Parameter | Type | Description |
|---|---|---|
q | string | Search by title, author, or description |
author | string | Filter by author name (partial match) |
religion | string | Filter by religion (exact match) |
collection | string | Filter by collection (exact match) |
language | string | Filter by language code (e.g. en, ar, fa) |
limit | integer | Max results (1-100, default: 20) |
offset | integer | Pagination offset (default: 0) |
Example Response
{
"documents": [
{
"id": "hidden_words",
"title": "The Hidden Words",
"author": "Baha'u'llah",
"religion": "Baha'i",
"collection": "Core Publications",
"language": "en",
"year": 1858,
"description": "A collection of ethical and mystical utterances...",
"paragraphCount": 153,
"url": "https://siftersearch.com/read/hidden_words"
}
],
"total": 1,
"limit": 20,
"offset": 0
} GET /api/v1/library/documents/:id
Get detailed metadata for a single document by its ID.
Example Response
{
"id": "hidden_words",
"title": "The Hidden Words",
"author": "Baha'u'llah",
"religion": "Baha'i",
"collection": "Core Publications",
"language": "en",
"year": 1858,
"description": "A collection of ethical and mystical utterances...",
"paragraphCount": 153,
"url": "https://siftersearch.com/read/hidden_words",
"createdAt": "2024-01-15T00:00:00Z",
"updatedAt": "2024-12-14T00:00:00Z"
} GET /api/v1/library/authors
List all authors with their document counts and associated religions.
Query Parameters
| Parameter | Type | Description |
|---|---|---|
religion | string | Filter authors by religion |
q | string | Search authors by name |
limit | integer | Max results (1-500, default: 100) |
offset | integer | Pagination offset (default: 0) |
Example Response
{
"authors": [
{
"name": "Baha'u'llah",
"documentCount": 42,
"religions": ["Baha'i"]
},
{
"name": "Abdu'l-Baha",
"documentCount": 31,
"religions": ["Baha'i"]
}
],
"total": 2
} GET /api/v1/library/religions
Get the full religion and collection tree, including document counts at each level. Useful for building hierarchical navigation or filter components.
Example Response
{
"religions": [
{
"name": "Baha'i",
"documentCount": 284,
"collections": [
{ "name": "Core Publications", "documentCount": 42 },
{ "name": "Pilgrim Notes", "documentCount": 118 },
{ "name": "Letters", "documentCount": 124 }
]
},
{
"name": "Buddhism",
"documentCount": 196,
"collections": [
{ "name": "Pali Canon", "documentCount": 89 },
{ "name": "Mahayana Sutras", "documentCount": 107 }
]
}
]
} Chat Service
The Chat API provides access to Jafar, the SifterSearch AI research assistant. Jafar synthesizes passages from across the library to answer questions, identify themes, and support sustained research sessions. Responses stream via Server-Sent Events (SSE).
POST /api/v1/chat
Send a message to the AI research assistant. Responses are streamed as Server-Sent Events.
Each event carries a type field indicating what kind of data it contains.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
messages | array | Yes | Conversation history: [{ role: "user"|"assistant", content: string }] |
researchContext | string | No | Prior research context to carry forward across turns |
SSE Event Types
| Type | Description |
|---|---|
status | Progress update (e.g., "Searching library…") |
text | Incremental response text chunk |
citations | Array of source passages used in the response |
done | Stream complete; no further events will follow |
error | Error detail; stream will terminate after this event |
Example Request
POST /api/v1/chat
Content-Type: application/json
X-API-Key: sk_live_your-key-here
{
"messages": [
{ "role": "user", "content": "What do the Baha'i writings say about the oneness of religion?" }
]
} Example SSE Stream
data: {"type":"status","message":"Searching library..."}
data: {"type":"text","content":"The Baha'i writings consistently affirm that "}
data: {"type":"text","content":"all major religions share a common divine origin..."}
data: {"type":"citations","citations":[
{
"id": "gleanings_p1",
"title": "Gleanings from the Writings of Baha'u'llah",
"author": "Baha'u'llah",
"text": "This is the Day in which God's most excellent favors...",
"url": "https://siftersearch.com/read/gleanings#p1"
}
]}
data: {"type":"done"} JavaScript Streaming Example
const response = await fetch('https://api.siftersearch.com/api/v1/chat', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': process.env.SIFTER_API_KEY
},
body: JSON.stringify({
messages: [{ role: 'user', content: 'What is the Baha\'i view on science and religion?' }]
})
});
const reader = response.body.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) break;
const chunk = decoder.decode(value);
for (const line of chunk.split('\n')) {
if (!line.startsWith('data: ')) continue;
const event = JSON.parse(line.slice(6));
if (event.type === 'text') process.stdout.write(event.content);
if (event.type === 'citations') console.log('\nSources:', event.citations);
}
} Error Responses
All errors return a JSON object with error and code fields:
{
"error": "API key required. Set X-API-Key header.",
"code": "unauthorized"
} Error Codes
| HTTP Status | Code | Description |
|---|---|---|
| 400 | bad_request | Invalid request body or parameters |
| 401 | unauthorized | Missing or invalid API key |
| 403 | forbidden | API key lacks required permissions |
| 429 | rate_limit_exceeded | Too many requests, try again later |
| 500 | internal_error | Server error, please report |
SDKs & Libraries
Official SDKs are coming soon. In the meantime, use any HTTP client:
JavaScript / Node.js
const response = await fetch('https://api.siftersearch.com/api/v1/search', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': process.env.SIFTER_API_KEY
},
body: JSON.stringify({
query: 'what is the purpose of life',
limit: 10,
filters: { religion: "Buddhism" }
})
});
const data = await response.json();
data.results.forEach(r => console.log(`{r.score} - {r.title}: {r.summary}`)); Python
import os, requests
response = requests.post(
'https://api.siftersearch.com/api/v1/search',
headers={
'Content-Type': 'application/json',
'X-API-Key': os.environ['SIFTER_API_KEY']
},
json={
'query': 'what is the purpose of life',
'limit': 10,
'filters': {'religion': 'Buddhism'}
}
)
data = response.json()
for result in data['results']:
print(f"{result['score']} - {result['title']}: {result['summary']}") cURL
curl -X POST https://api.siftersearch.com/api/v1/search \
-H "Content-Type: application/json" \
-H "X-API-Key: $SIFTER_API_KEY" \
-d '{"query": "what is the purpose of life", "limit": 10, "filters": {"religion": "Buddhism"}}' Best Practices
- Use semantic queries - Ask questions naturally: "What does Buddhism teach about suffering?" works better than just "Buddhism suffering".
- Filter when possible - If you know the tradition, use the religion filter to improve relevance.
- Cache responses - Results for the same query don't change frequently. Cache for better performance.
- Handle rate limits gracefully - Check the
X-RateLimit-Remainingheader and implement backoff. - Use /search/quick for autocomplete - The quick endpoint is ~10x faster for simple keyword matches.
- Stream chat responses - The chat endpoint uses SSE; consume the stream incrementally rather than waiting for a full response body.
- Persist researchContext - Pass the assistant's prior context back on follow-up chat turns to maintain coherent multi-turn research sessions.