ScriptureFlow Supported Languages and Translations — Public
Purpose
This document explains how developers should discover and use the languages and translations currently available through the public ScriptureFlow API.
ScriptureFlow is built with multilingual Scripture access in mind. The goal is not only to support major global languages, but also to make room for underrepresented languages, regional languages, African languages, Indigenous languages, diaspora languages, and other communities often overlooked in digital Bible tools.
Source of Truth
The live translation catalog is the source of truth for public language and translation availability:
https://scriptureflow-api-preview.pages.dev/translations.json
Developers should use the catalog instead of hardcoding assumptions about which languages or translations are available.
The public docs may summarize availability, but the live catalog should always be treated as the current source of truth.
Related Public Resources
ScriptureFlow currently exposes these public metadata resources:
https://scriptureflow-api-preview.pages.dev/translations.json
https://scriptureflow-api-preview.pages.dev/public-catalog.json
https://scriptureflow-api-preview.pages.dev/status.json
Use them together:
| Resource | Use |
|---|---|
translations.json | Find available translation/version keys and translation metadata. |
public-catalog.json | Review public catalog-level information. |
status.json | Review public readiness/status summary for the current generated output. |
Key Concept: Version Key vs. Language Code
ScriptureFlow uses version keys to identify the exact translation a request should use.
A version key is not the same thing as a language code.
For example:
en-kjv
This is a version key. It identifies a specific translation in the public API.
A language code identifies the language associated with a translation. A language may have one translation, several translations, or no currently public translation.
Developers should use the exact version key from translations.json when calling /api/verse.
Important Version Identifier Rule
Use the version key exactly as listed in the translation catalog.
For the King James Version, use:
en-kjv
Do not use:
kjv
Do not use:
en-KJV
Correct request:
https://scriptureflow-api-preview.pages.dev/api/verse?version=en-kjv&book=Psalm&chapter=23&verse=1
Incorrect request:
https://scriptureflow-api-preview.pages.dev/api/verse?version=kjv&book=Psalm&chapter=23&verse=1
Incorrect request:
https://scriptureflow-api-preview.pages.dev/api/verse?version=en-KJV&book=Psalm&chapter=23&verse=1
Why the Catalog Matters
Developers may be tempted to guess version keys based on familiar Bible abbreviations.
That is risky.
A public API request should be based on the catalog, not on memory or assumption.
Recommended flow:
- Load
translations.json. - Display available translations to the user.
- Store the selected version key.
- Use that exact version key in
/api/verserequests.
This helps avoid failed lookups caused by incorrect casing, missing language prefixes, or unsupported abbreviations.
Fetch the Translation Catalog
Browser
Open:
https://scriptureflow-api-preview.pages.dev/translations.json
JavaScript
const baseUrl = "https://scriptureflow-api-preview.pages.dev";
const response = await fetch(`${baseUrl}/translations.json`);
const translations = await response.json();
console.log(translations);
Python
import requests
base_url = "https://scriptureflow-api-preview.pages.dev"
response = requests.get(f"{base_url}/translations.json", timeout=20)
translations = response.json()
print(translations)
cURL
curl "https://scriptureflow-api-preview.pages.dev/translations.json"
Reading the Catalog
The catalog is designed to help applications discover public translation availability.
Depending on the current catalog shape, each translation entry may include fields such as:
| Field | Meaning |
|---|---|
version | Exact version key to use in API requests. |
language_code | Language code associated with the translation. |
translation_name | Human-readable translation name, when available. |
name | Human-readable translation or catalog name, when used by the catalog. |
status | Public readiness or availability status, when included. |
Applications should be tolerant of small metadata changes over time. Use the version key as the main API lookup value.
Build a Translation Selector
A simple translation selector usually needs two things:
- A display label for the user.
- The exact version key for API requests.
Example JavaScript pattern:
const baseUrl = "https://scriptureflow-api-preview.pages.dev";
async function loadTranslationOptions() {
const response = await fetch(`${baseUrl}/translations.json`);
if (!response.ok) {
throw new Error(`Could not load translations: HTTP ${response.status}`);
}
const translations = await response.json();
return translations.map((item) => ({
label:
item.translation_name ||
item.name ||
item.version,
version: item.version,
languageCode: item.language_code || "",
}));
}
const options = await loadTranslationOptions();
console.log(options);
A user might see:
King James Version
But your application should store and use the version key:
en-kjv
Group Translations by Language
If your app wants to show translations by language, group catalog entries by language_code.
Example JavaScript:
const baseUrl = "https://scriptureflow-api-preview.pages.dev";
async function groupTranslationsByLanguage() {
const response = await fetch(`${baseUrl}/translations.json`);
const translations = await response.json();
const grouped = {};
for (const item of translations) {
const languageCode = item.language_code || "unknown";
if (!grouped[languageCode]) {
grouped[languageCode] = [];
}
grouped[languageCode].push(item);
}
return grouped;
}
const grouped = await groupTranslationsByLanguage();
console.log(grouped);
Example Python:
import requests
from collections import defaultdict
base_url = "https://scriptureflow-api-preview.pages.dev"
response = requests.get(f"{base_url}/translations.json", timeout=20)
translations = response.json()
grouped = defaultdict(list)
for item in translations:
language_code = item.get("language_code") or "unknown"
grouped[language_code].append(item)
for language_code, items in grouped.items():
print(language_code, len(items))
Count Available Languages
To count how many unique language codes are currently present in the live catalog, count distinct language_code values.
JavaScript:
const baseUrl = "https://scriptureflow-api-preview.pages.dev";
const response = await fetch(`${baseUrl}/translations.json`);
const translations = await response.json();
const languageCodes = new Set(
translations
.map((item) => item.language_code)
.filter(Boolean)
);
console.log(`Translation entries: ${translations.length}`);
console.log(`Language codes: ${languageCodes.size}`);
Python:
import requests
base_url = "https://scriptureflow-api-preview.pages.dev"
response = requests.get(f"{base_url}/translations.json", timeout=20)
translations = response.json()
language_codes = {
item.get("language_code")
for item in translations
if item.get("language_code")
}
print("Translation entries:", len(translations))
print("Language codes:", len(language_codes))
This keeps the public documentation from becoming stale. The live catalog provides the current answer.
Language Codes and Countries
Language codes do not always map neatly to one country.
Some languages are spoken across borders. Some are used by diaspora communities. Some have regional or script variations. Some may be associated with a primary country, but not limited to that country.
For example:
- Hausa is strongly associated with Nigeria and Niger, but Hausa-speaking communities extend beyond one country.
- Swahili is used across parts of East Africa.
- Twi is strongly associated with Ghana, but speakers also exist in diaspora communities.
- English, Spanish, Arabic, French, Portuguese, and other major languages are used across many countries.
- Some Indigenous or regional languages may be tied to a smaller geographic area but still require careful handling.
For that reason, public documentation should treat country or region labels as orientation aids, not as exclusive ownership labels.
A future public docs page may include a language-region reference table, but the live catalog remains the source of truth for availability.
Suggested UI Pattern
A developer-friendly translation selector can show:
[Language Code] Translation Name — Version Key
Example:
eng — King James Version — en-kjv
Your exact display text may vary depending on the metadata fields present in the catalog.
A practical selector should:
- Use the catalog-provided version key.
- Show a readable translation name when available.
- Optionally group by language code.
- Avoid assuming every language has only one translation.
- Avoid assuming every translation is available forever without checking the catalog.
Request a Verse After Selecting a Translation
Once a user selects a version key, use that key in /api/verse.
Example with en-kjv:
https://scriptureflow-api-preview.pages.dev/api/verse?version=en-kjv&book=Psalm&chapter=23&verse=1
JavaScript:
const baseUrl = "https://scriptureflow-api-preview.pages.dev";
async function getVerse(version, book, chapter, verse) {
const params = new URLSearchParams({
version,
book,
chapter: String(chapter),
verse: String(verse),
});
const response = await fetch(`${baseUrl}/api/verse?${params.toString()}`);
if (!response.ok) {
const error = await response.json().catch(() => ({
error: `HTTP ${response.status}`,
}));
throw new Error(error.error || `Request failed with HTTP ${response.status}`);
}
return response.json();
}
const data = await getVerse("en-kjv", "Psalm", 23, 1);
console.log(data);
Translation Availability Can Change
ScriptureFlow separates technical readiness from responsible publication.
A translation may be technically structured and readable by the pipeline while still needing review for publication, copyright, licensing, attribution, or redistribution status.
Because of that, developers should:
- Check the live catalog.
- Avoid assuming unavailable translations can be used publicly.
- Respect copyright, licensing, and attribution requirements.
- Avoid hardcoding old catalog results forever.
- Build applications that can handle translations being added, removed, renamed, or reclassified.
Recommended Developer Practices
When working with languages and translations, developers should:
- Load the catalog from
translations.json. - Use the exact version key from the catalog.
- Treat language codes as identifiers, not full cultural descriptions.
- Give users readable labels, but store exact version keys.
- Handle missing or unavailable translations gracefully.
- Avoid guessing translation IDs.
- Avoid assuming one language equals one country.
- Avoid assuming one language has only one available translation.
- Design multilingual interfaces with humility and room for future expansion.
Common Mistakes
Mistake 1: Guessing a Version Key
Incorrect:
version=kjv
Correct:
version=en-kjv
Mistake 2: Changing Casing
Incorrect:
version=en-KJV
Correct:
version=en-kjv
Mistake 3: Treating Language Code as Version Key
Incorrect assumption:
language_code = version
Correct understanding:
language_code identifies the language.
version identifies the exact translation used in API requests.
Mistake 4: Hardcoding a Static Language List
Static language lists can become stale.
Better pattern:
Load translations.json and build the list from the current catalog.
Public API Boundary
This document explains public translation discovery and language-related API usage.
It does not explain:
- Private corpus structure
- Internal translation ingestion
- Build or indexing logic
- Deployment workflow internals
- Legal review workflow
- Contributor-only translation governance
Developers should use the public catalog and public API documentation when building applications.
Next Steps
After reviewing supported languages and translations, developers should review:
- Developer Quickstart
- Endpoint Specification
- Example Requests
- API Product Overview
- Terms and Attribution