API DOCUMENTATION

api/search/v2

Search v2 finds Scripture in the Bible v2 data tree. It accepts words, phrases and structured filters through GET or POST, returning both an ordered match list and the matching verses grouped by chapter. If the input resolves as a Scripture reference, it returns that passage in the same outer envelope.

Canonical route: https://search.getbible.net/v2/{translation}/{search}

Live documentation · OpenAPI JSON · Search overview · Support

Quick start#

curl --fail-with-body --compressed --get \
  'https://search.getbible.net/v2/kjv' \
  --data-urlencode 'q=faith hope' \
  --data-urlencode 'limit=25'

The default words=all mode requires both units in the verse. words=any permits either; words=phrase requests their ordered phrase. No token is required for public requests within the anonymous budget.

All request forms#

Method Path Where the query comes from
GET /v2/{translation}/{search} Search text in the path; filters in query parameters
GET /v2/{translation}?q=... Translation in the path, search text and filters in query parameters
GET /v2?q=...&translation=... Search text and translation in query parameters
POST /v2/{translation}/{search} Path text; filters in query parameters and/or JSON
POST /v2/{translation} Search text in query parameters and/or JSON
POST /v2 Translation, search text and filters in query parameters and/or JSON

POST bodies must be JSON objects sent with Content-Type: application/json. They are optional when the URL supplies the search. GET bodies are not read. Neither method modifies Scripture.

Values have this precedence: path, then query string, then JSON body, then configured defaults. If a path contains faith hope, a body q does not replace it. Explicit false and 0 override a lower-priority value. A JSON null value is ignored, leaving the underlying/default value available.

translation defaults to kjv when omitted on a route accepting it as a parameter. An explicitly supplied unknown translation returns 404. Use an abbreviation from the v2 translation catalogue.

Every input and filter#

All filters are optional. These limits follow the published HTTP OpenAPI contract; local Python librarian limits are different in some cases.

Field Values or type Default Notes
q String, 1–500 characters None Required when text is not in the path; words or a Scripture reference
translation String abbreviation kjv Case-insensitive; overridden by a path translation
words all, any, phrase all Relationship among analysed query units
match whole_word, substring whole_word Substring permits a match within an indexed word
case_sensitive Boolean false URL forms accept true/false, 1/0 or yes/no, case-insensitively
scope bible, old_testament, new_testament, deuterocanon bible Restricts the search corpus
book Repeated names or numbers All books Repeat in query strings, or use a scalar/array in JSON
books Comma-separated names/numbers; JSON also accepts arrays All books Combined with book; at most 83 combined selections
diacritics fold, exact fold Compatibility aliases: insensitivefold, sensitiveexact
exclude Repeated words; scalar/array in JSON None At most 32 terms, each 1–100 characters
proximity Integer 0–100 None Maximum intervening units; requires words=all
sort canonical, relevance canonical Use matches as the authoritative result order
limit Integer 1–100 100 Maximum returned verses per full-text page
offset Integer 0–10000 0 Number of full-text matches to skip

book and exclude are repeatable query parameters. Repeating another parameter, such as limit=10&limit=20, returns 400 repeated_parameter. Unknown fields are rejected. Combine book selectors with scope: scope=new_testament&book=John searches only John, not the union of John and the New Testament.

Copy-and-run search recipes#

A phrase in the New Testament#

curl --fail-with-body --compressed --get \
  'https://search.getbible.net/v2/kjv' \
  --data-urlencode 'q=eternal life' \
  --data-urlencode 'words=phrase' \
  --data-urlencode 'scope=new_testament' \
  --data-urlencode 'limit=25'

Several books, an exclusion and relevance order#

curl --fail-with-body --compressed --get \
  'https://search.getbible.net/v2/kjv' \
  --data-urlencode 'q=word life' \
  --data-urlencode 'book=John' \
  --data-urlencode 'book=1 John' \
  --data-urlencode 'exclude=darkness' \
  --data-urlencode 'sort=relevance' \
  --data-urlencode 'limit=20'

Near one another#

curl --fail-with-body --compressed --get \
  'https://search.getbible.net/v2/kjv' \
  --data-urlencode 'q=faith hope' \
  --data-urlencode 'words=all' \
  --data-urlencode 'proximity=5'

Structured JSON request#

curl --fail-with-body --compressed \
  --header 'Content-Type: application/json' \
  --data '{"translation":"kjv","q":"faith hope","words":"all","scope":"new_testament","books":["Romans","1 Corinthians"],"sort":"relevance","limit":20,"offset":0}' \
  'https://search.getbible.net/v2'

Search a continuous script#

curl --fail-with-body --compressed --get \
  'https://search.getbible.net/v2/cus' \
  --data-urlencode 'q=神爱世人' \
  --data-urlencode 'limit=20'

The normal matching defaults handle the script; the caller does not need to force substring matching. Translation availability comes from the selected version's catalogue.

How matching works#

all requires every distinct analysed unit somewhere in the same verse. any requires at least one. phrase requires ordered units at the spacing represented by the query; punctuation can occur between them. proximity narrows an all search by the number of intervening units.

Alphabetic scripts use word boundaries. Continuous scripts use position-aware character units. Abjad analysis accounts for optional pointing and supported attached-particle stems. Brahmic and continuous scripts preserve combining marks that carry meaningful vowels. Mixed-script text keeps the appropriate rules for each run. The engine derives these choices from Unicode script properties rather than trusting the translation language label alone.

Case-insensitive analysis uses Unicode case folding. diacritics=fold removes applicable accents or optional pointing and folds additional supported characters; exact distinguishes them. Returned Scripture text is preserved as supplied by the source.

For space-delimited scripts, substring fragments normally need at least three characters. That Latin-style floor is not imposed on ordinary short units in Han, Hangul, Thai, Hebrew, Arabic or Devanagari. A mixed query still applies the floor to an applicable alphabetic run. The librarian matching documentation explains these rules and their version history.

The response envelope#

Every successful response contains three members:

Member Type Meaning
query Object Request interpretation, selected translation and counts
results Object Chapter-grouped Scripture keyed by {translation}_{book}_{chapter}
matches Array Ordered match records pointing into those chapters

Query metadata#

Field Available on Meaning
text Both kinds Search/reference input
kind Both search or reference
translation Both Compact translation object; schema also permits an identifier string fallback
engine_version Both Search/response semantics version; use it in downstream cache invalidation
total Both Total matching/selected verses
returned Both Number of verses in this response
criteria Full-text Normalized criteria applied by the engine
sha Full-text Underlying translation content version, or null if unavailable
offset, limit Full-text Effective pagination
has_more Full-text Whether additional matching verses remain
cache.checked_at Full-text Last source-check timestamp, or null
cache.stale Full-text Whether retained data is marked stale
analysis.script Full-text Analysis classification such as alphabetic or continuous
cost.work_units Full-text Measured search work units
cost.deadline_seconds Full-text Configured execution deadline
cost.expensive Full-text Whether expensive-query handling applies

query.translation contains the source's available translation, abbreviation, lang, language, direction and encoding fields. The same compact translation fields appear in each result chapter. Fetch the static translation catalogue separately for descriptions, source terms and history. Empty results still retain query/translation metadata.

Chapter and verse data#

Each entry in results contains the compact translation fields, book_nr, book_name, chapter, name, ref and verses. Its selected verse objects retain their source fields and nested values. The chapter name uses name; the translation display name uses translation.

v2 verse representation#

Version 2 reads the v2 source tree and returns the established verse fields: chapter, verse, name and text. The outer search envelope does not require the application to adopt a new Scripture renderer. For optional source lexical and annotation metadata, use Search v3.

Match records and ordering#

Every match has reference, book_nr, chapter and verse. Full-text matches additionally provide numeric score, integer occurrences and a terms array. Reference-kind matches omit those scoring fields.

matches determines the displayed order, especially under relevance sorting. results is organized for Scripture retrieval and rendering rather than ranking. Find a matched verse in its chapter using its integer verse number; do not assume its position in the selected verses array equals verse - 1.

async function searchScripture(text, offset = 0) {
  const parameters = new URLSearchParams({
    q: text,
    sort: 'relevance',
    limit: '25',
    offset: String(offset)
  });
  const response = await fetch(`https://search.getbible.net/v2/kjv?${parameters}`);
  const body = await response.json();
  if (!response.ok) throw new Error(body.detail ?? `HTTP ${response.status}`);
  return body;
}

const page = await searchScripture('faith hope');
for (const match of page.matches) {
  const key = `kjv_${match.book_nr}_${match.chapter}`;
  const chapter = page.results[key];
  const verse = chapter?.verses.find(item => item.verse === match.verse);
  if (verse) console.log(match.reference, verse.text, match.score);
}
if (page.query.kind === 'search' && page.query.has_more) {
  console.log('Next offset:', page.query.offset + page.query.returned);
}

This complete example works in a modern browser console or an ES module with fetch.

Reference detection is a separate result kind#

curl --fail-with-body --compressed \
  'https://search.getbible.net/v2/kjv/John3:16'

This input resolves as a reference, so query.kind is reference. Full-text criteria, pagination, source SHA, cache, analysis and cost are absent from query; score, occurrences and terms are absent from matches. Full-text filters are not applied to this kind, including a supplied limit or book restriction. Branch on query.kind before building pagination controls or assuming score data exists. Use Query v2 when the input is explicitly a Scripture reference.

Pagination and empty results#

A full-text search with no matches is a successful response with query.total = 0, empty results and empty matches. A page beyond the final result is also empty. It is not a missing-translation error.

Advance a full-text search by offset + returned while has_more is true. Keep all criteria unchanged, stay within the 10000 offset bound and avoid combining pages if the returned source sha changes. Namespace persisted search results by API version, translation, query, normalized criteria, source SHA and engine_version. The live inspected responses use engine version 5; treat the returned value as authoritative instead of hardcoding it.

Redirects, encoding and caching#

Short forms such as /v2/faith%20hope redirect to the default translation. Unversioned aliases follow the domain's configured default endpoint. GET aliases use 301; POST aliases use 308 to preserve method and body. Prefer an explicit canonical route when integrating.

Use curl --get --data-urlencode or your language's URL builder for search text and filters. A literal & separates URL fields; percent-encode characters belonging to the search value. Plain spaces in a path should be encoded as %20.

Public GET/HEAD data responses advertise cache lifetimes and ETags. Cache the entire URL including every filter. Conditional If-None-Match requests may return 304 with no body. Read actual Cache-Control rather than assuming a fixed lifetime. POST responses and runtime error responses are not cached. Token-only data uses private, no-store; tokens on an otherwise public service do not make the underlying Scripture private.

Access and request limits#

Public access is metered by client address. Application and partner bearer tokens remove those public rate budgets but do not disable filter validation, pagination bounds, cost limits or concurrency controls. Request a token for search.getbible.net through support or email.

Set your issued value as GETBIBLE_SEARCH_TOKEN and use:

curl --fail-with-body --compressed --get \
  --header "Authorization: Bearer ${GETBIBLE_SEARCH_TOKEN:?Set GETBIBLE_SEARCH_TOKEN to your issued token}" \
  'https://search.getbible.net/v2/kjv' \
  --data-urlencode 'q=faith hope' \
  --data-urlencode 'limit=25'

The standard execution deadline is 5 seconds and the service also enforces a work budget. Corpus loading and index preparation can happen outside that execution deadline, so a cold request can take longer. 503 busy signals capacity pressure. Respect Retry-After, avoid immediate retry loops and narrow repeated expensive searches.

Error handling#

Errors are application/problem+json documents with type, title, status, code, detail and instance. Optional retry_after accompanies temporary failures where supplied. Branch on HTTP status/code and use the human-readable detail in diagnostics.

HTTP Code Meaning
400 missing_search No search text in path, q parameter or body
400 invalid_search Invalid text, criteria or values outside the contract
400 invalid_body JSON body is not a valid object of parameters
400 unknown_parameter Parameter is not supported
400 repeated_parameter A non-repeatable query parameter was repeated
400 request_limit Request exceeds a structural/work limit
401 unauthorized Credentials required by token-only access are missing or invalid
404 translation_not_found Translation unavailable
404 unknown_version API version unavailable on this endpoint
405 method_not_allowed Unsupported HTTP method
415 unsupported_media_type Non-JSON POST body
429 rate_limited Public client-address budget exceeded
503 busy, search_timeout, repository_unavailable, readiness_failed Temporary capacity, execution or source-read problem

The contract also describes intermediary/deployment statuses such as 413, 500, 502 and 504. Do not retry invalid 400-class requests unchanged. Retry temporary errors using the supplied Retry-After interval and a bounded retry policy.

Health and API client import#

curl --fail-with-body 'https://search.getbible.net/healthz'
curl --fail-with-body 'https://search.getbible.net/readyz'
curl --fail-with-body --compressed \
  'https://search.getbible.net/v2/openapi.json' \
  --output getbible-search-v2-openapi.json

healthz checks liveness; readyz verifies that the default Scripture is readable. Documentation and these health routes are public without a token. The server's private deployment /probez is not a public API endpoint.

Import the OpenAPI URL or downloaded contract through Postman's Import dialog. It contains the server host, versioned routes, shared query parameters, JSON body schema and response schemas. Prefer GET for reproducible shareable tests and POST to exercise structured body values.

This guide follows the live v2 OpenAPI, live service guide, runtime implementation contract, librarian search semantics, and compact metadata contract. Ask for help at GetBible support, including the URL, status and X-Request-ID response header without any access token.

Complete contract reference#

Open the complete endpoint and schema reference for every operation, parameter, response and component model in the published OpenAPI contract.

Search the documentation

Type to search APIs, projects and guides.

Press Escape to close · Ctrl / ⌘ K to search