/ API Docs

SourceTruth API

Semantic search and AI-powered Q&A over 30 pre-indexed canonical corpora — Quran, Bible, Plato, Confucius, and more. No ingestion pipeline. One API key.

Base URL: https://api.sourcetruth.io  ·  Version: 1.0.0

New here? Jump to Quick start to make your first call in under two minutes, or issue a free key now.

Quick start

1. Get a free API key

curl
curl -X POST https://api.sourcetruth.io/v1/keys \
  -H "Content-Type: application/json" \
  -d '{"name": "My App", "email": "you@example.com"}'

# → {"key": "st_a1b2c3...", "tier": "free", "daily_limit": 100}

Store the key — it is shown only once.

2. Search a corpus

Python
import requests

r = requests.post(
    "https://api.sourcetruth.io/v1/search",
    headers={"X-API-Key": "st_..."},
    json={
        "query": "What does the Quran say about patience?",
        "corpus_codes": ["quran", "sahih-bukhari"],
        "top_k": 5,
    },
)
for p in r.json()["passages"]:
    print(p["reference"], p["text"][:100])

3. Get a grounded answer (paid tiers)

Python
r = requests.post(
    "https://api.sourcetruth.io/v1/answer",
    headers={"X-API-Key": "st_..."},
    json={
        "question": "What does the Quran say about patience?",
        "corpus_codes": ["quran", "sahih-bukhari"],
    },
)
print(r.json()["answer"])   # grounded prose with numbered citations
print(r.json()["citations"]) # [{"index":1,"reference":"2:153","corpus":"quran",...}]

Authentication

Pass your API key in the X-API-Key request header. Keys are prefixed st_.

Header
X-API-Key: st_a1b2c3d4e5f6...

/v1/search and /v1/corpora accept anonymous requests (rate-limited). /v1/answer requires a paid key.

POST /v1/search

Hybrid semantic + keyword retrieval over indexed corpora. Returns ranked passages with citation metadata. Available to all tiers including free.

Request body

FieldTypeDescription
query requiredstringNatural language query in any supported language.
corpus_codes optionalstring[]Scope to specific corpora — e.g. ["quran","sahih-bukhari"]. Takes priority over traditions for reranking. See corpus codes.
traditions optionalstring[]Filter by tradition — e.g. ["islam"], ["judaism"].
languages optionalstring[]Filter by ISO language code — e.g. ["en"], ["ara"].
collections optionalstring[]Filter by collection within a corpus — e.g. ["hadith"] to scope within a multi-collection corpus.
top_k optionalintegerPassages to return. Default 8, max 20.
Cross-corpus tip: For balanced results across two corpora (e.g. Quran + Hadith, Tanakh + Mishnah), make two scoped calls and merge. A single unscoped call may be dominated by whichever corpus has stronger semantic overlap.

Response

JSON
{
  "query": "What does the Quran say about patience?",
  "passages": [{
    "chunk_id": 18432,
    "text": "O you who have believed, seek help through...",
    "reference": "2:153",
    "tradition": "islam",
    "language": "en",
    "corpus": "quran",
    "score": 0.912
  }],
  "resolved_entities": [],
  "latency_ms": 84
}

POST /v1/answer

Retrieval-augmented generation. Retrieves relevant passages then generates a grounded answer via Claude with numbered inline citations. Requires Starter or Professional.

Request body

FieldTypeDescription
question requiredstringThe question to answer from the corpus.
corpus_codes optionalstring[]Scope retrieval to specific corpora.
traditions optionalstring[]Filter retrieval by tradition.
languages optionalstring[]Filter retrieval by language.
max_passages optionalintegerPassages to retrieve as context. Default 6, max 10.

Response

JSON
{
  "question": "What does the Quran say about patience?",
  "answer": "The Quran emphasises patience (sabr) repeatedly.
In 2:153 believers are instructed to seek help
through patience and prayer [1]...

Citations:
[1] 2:153 — Surah Al-Baqarah",
  "citations": [{ "index": 1, "reference": "2:153", "corpus": "quran" }],
  "latency_ms": 1840
}
The answer model is instructed never to invent references from memory. If the retrieved passages don't support an answer, it says so explicitly rather than hallucinating citations.

GET /v1/corpora

Returns all indexed corpora with codes, traditions, languages, and licence metadata. No authentication required. Use returned code values as corpus_codes filter values.

curl
curl https://api.sourcetruth.io/v1/corpora

GET /v1/text/{uid}

Returns the full chunked text of a document by its canonical UID. UID format is corpus-specific — pass the value of chunk_id from a search result, or use corpus reference notation (e.g. 2:153 for Quran, gen-1 for Genesis KJV).

ParamInDescription
uid requiredpathCanonical document ID.
lang optionalqueryLanguage code. Default en.

GET /v1/entity/{entity_id}

Returns entity metadata and name variants (Sanskrit, Chinese, Tibetan, English). Entity IDs appear in the resolved_entities array of search results when named entities are detected in the query.

POST /v1/keys

Self-issue a free-tier API key. No authentication required. Rate-limited to 5 per hour per IP.

FieldTypeDescription
name requiredstringYour name or application name.
email requiredstringValid email address.
JSON response
{ "key": "st_a1b2c3...", "tier": "free", "daily_limit": 100,
  "message": "Store this key safely — it will not be shown again." }

DELETE /v1/keys

Immediately revoke your API key. Pass the key in X-API-Key. Irreversible.

GET /health

Health check. No authentication required.

JSON
{ "status": "ok", "version": "1.0.0" }

Corpus codes

Pass these values in corpus_codes to scope any request. Live list always available at GET /v1/corpora.

CodeNameTraditionLangLicence
quranTanzil Quran CorpusIslamaraCC BY 3.0 ‡
sahih-bukhariSahih al-BukhariIslamenUnlicense
sahih-muslimSahih MuslimIslamenUnlicense
sunan-abu-dawoodSunan Abu DawoodIslamenUnlicense
rumi-masnaviMasnavi (Nicholson)IslamenPublic Domain
cbetaCBETA Chinese CanonMahayanalzhCC BY-NC †
8400084000 TranslationsVajrayanaenCC BY-NC †
tibetan-buddhistEvans-Wentz TibetanVajrayanaenPublic Domain
bdrcBuddhist Digital Resource CenterVajrayanaboOpen (varies)
kjvKing James BibleChristianityenPublic Domain
bible-webWorld English BibleChristianityenCC0
bible-asvAmerican Standard VersionChristianityenPublic Domain
bible-yltYoung's Literal TranslationChristianityenPublic Domain
christian-theologyPatristics (Augustine, Apostolic Fathers)ChristianityenPublic Domain
tanakh-jps1917Tanakh (JPS 1917)JudaismenPublic Domain
mishnah-silversteinMishnah (Silverstein)JudaismenCC BY ‡
bhagavad-gitaBhagavad Gita (Arnold)HinduismenPublic Domain
upanishadsPrincipal Upanishads (Müller)HinduismenPublic Domain
yoga-sutrasYoga Sutras (Johnston)HinduismenPublic Domain
mahabharataMahabharata (Ganguli)HinduismenPublic Domain
rigvedaRigveda (Griffith)HinduismenPublic Domain
sanskrit-classicalRamayana + KalidasaHinduismenPublic Domain
sggsSri Guru Granth Sahib JiSikhismpaPublic Domain
classical-chineseAnalects, Tao Te Ching, Art of WarEast AsianenPublic Domain
greek-philosophyPlato, Aristotle, StoicsHellenismenPublic Domain
classical-latinCaesar, Virgil, Cicero, SenecaClassicismenPublic Domain
political-philosophyHobbes, Locke, Rousseau, MillWestern Phil.enPublic Domain
western-philosophyDescartes to NietzscheWestern Phil.enPublic Domain
avestaZend-Avesta (Darmesteter/Mills)ZoroastrianismenPublic Domain
gretilGRETIL Sanskrit *SanskritsanOpen (varies)

‡ Attribution required. † Non-commercial only. * Always pass corpus_codes: ["gretil"] — excluded from unscoped searches.

Rate limits & tiers

Tier/search /day/answer /dayPrice
Free100—$0
Starter1,000100$29/mo
Professional10,000300$149/mo

Hard per-minute limits: 60 req/min on /v1/search, 20 req/min on /v1/answer. Exceeded limits return HTTP 429. Upgrade at sourcetruth.io/pricing.

Error codes

StatusMeaning
400Invalid request — check required fields.
401Missing or invalid API key.
403Endpoint requires a paid plan.
404Resource not found.
429Daily quota or per-minute rate limit exceeded.
503Billing not configured.

All errors: {"detail": "..."}

Python

Python
import requests
API_KEY = "st_..."

r = requests.post("https://api.sourcetruth.io/v1/search",
    headers={"X-API-Key": API_KEY},
    json={"query": "nature of suffering", "top_k": 5})
for p in r.json()["passages"]:
    print(p["reference"], p["text"][:120])

JavaScript

JavaScript
const res = await fetch("https://api.sourcetruth.io/v1/search", {
  method: "POST",
  headers: { "X-API-Key": "st_...", "Content-Type": "application/json" },
  body: JSON.stringify({ query: "nature of suffering", top_k: 5 }),
});
const { passages } = await res.json();
passages.forEach(p => console.log(p.reference, p.text.slice(0, 120)));