Bible Index
bibleIndex returns the structure of a translation — every book, its localized name, how
many chapters it has, and how many verses are in each chapter. No verse text.
This is what you build navigation from.
- GraphQL
- cURL
- Ruby
- Node.js
- Response
query {
bibleIndex(translation: "eng-web") {
bookId
name
chapterCount
}
}
curl https://bibleql.org/graphql \
-H "Authorization: Bearer $BIBLEQL_API_KEY" \
-H "Content-Type: application/json" \
--data '{"query":"query { bibleIndex(translation: \"eng-web\") { bookId name chapterCount } }"}'
require "bibleql"
client = BibleQL::Client.new(
api_key: ENV.fetch("BIBLEQL_API_KEY"),
api_url: "https://bibleql.org/graphql"
)
index = client.bible_index(translation: "eng-web")
index.each { |book| puts "#{book.name}: #{book.chapter_count} chapters" }
import { BibleQLClient } from "bibleql-js";
const client = new BibleQLClient({
apiKey: process.env.BIBLEQL_API_KEY!,
apiUrl: "https://bibleql.org/graphql",
});
const index = await client.bibleIndex({
translation: "eng-web",
});
index.forEach((b) => console.log(b.name, b.chapterCount));
{
"data": {
"bibleIndex": [
{
"bookId": "GEN",
"name": "Genesis",
"chapterCount": 50
},
{
"bookId": "EXO",
"name": "Exodus",
"chapterCount": 40
},
{
"bookId": "LEV",
"name": "Leviticus",
"chapterCount": 27
},
// ... 63 more
]
}
}
Full structure in one request
query {
bibleIndex(translation: "eng-web") {
bookId
name
testament
position
chapterCount
chapters {
number
verseCount
}
}
}
That is enough to render a complete book → chapter → verse picker without touching the text at all. Fetch it once, cache it, and drive your whole navigation from it.
verses hereChapter also exposes a verses field. Asking for it across the whole index means requesting
every verse of the entire Bible in one query, which will exceed the complexity budget — and if
it did not, it would be an enormous response.
Use bibleIndex for structure, then chapter to fetch the
text of the one chapter your user opened.
Verse counts differ between translations
Do not hard-code them. Chapter and verse counts vary — some translations merge or split verses, and versification genuinely differs between editions. Always read counts from the index for the translation you are displaying.
This is also why you should not assume a reference valid in one translation resolves in another.
Structure versus canonical books
| Query | Returns | Scope |
|---|---|---|
books | 66 canonical books, English names | Translation-independent |
bibleIndex(translation:) | Books present in that translation, localized names, with chapter structure | One translation |
Use books for a canonical list; use bibleIndex when the answer depends on the translation.
- GraphQL
- cURL
- Ruby
- Node.js
- Response
query {
books {
bookId
name
testament
position
}
}
curl https://bibleql.org/graphql \
-H "Authorization: Bearer $BIBLEQL_API_KEY" \
-H "Content-Type: application/json" \
--data '{"query":"query { books { bookId name testament position } }"}'
require "bibleql"
client = BibleQL::Client.new(
api_key: ENV.fetch("BIBLEQL_API_KEY"),
api_url: "https://bibleql.org/graphql"
)
client.books.each { |b| puts "#{b.book_id} — #{b.name}" }
import { BibleQLClient } from "bibleql-js";
const client = new BibleQLClient({
apiKey: process.env.BIBLEQL_API_KEY!,
apiUrl: "https://bibleql.org/graphql",
});
const books = await client.books();
books.forEach((b) => console.log(b.bookId, b.name));
{
"data": {
"books": [
{
"bookId": "GEN",
"name": "Gen",
"testament": "OT",
"position": 1
},
{
"bookId": "EXO",
"name": "Exod",
"testament": "OT",
"position": 2
},
{
"bookId": "LEV",
"name": "Lev",
"testament": "OT",
"position": 3
},
// ... 63 more
]
}
}