4.2 KiB
ESV API integration
Disciples Journal sources passage text from the ESV API.
This doc covers how requests are made, how content is stored, and the caching model.
Primary code: src/services/ESVApiService.ts and src/services/BibleContentService.ts.
Authentication
- The user supplies an ESV API token in plugin settings (Settings → Disciples
Journal → ESV API). It is stored in
settings.esvApiToken. - Requests send
Authorization: Token <esvApiToken>. - With no token set,
onloadshows a notice, and any download attempt returns aBibleApiResponseerror of typeApiAuthentication.
When the API is called
Content resolution runs through BibleContentService.getBibleContent(ref), which
only reaches the network as a last resort:
- In-memory
passageCache(keyed byBibleReference). - A local note on disk — its frontmatter is parsed back into a response via
ESVApiService.toBibleApiResponse. - The ESV API — only if
settings.downloadOnDemandis enabled. Otherwise it returns aRequestsForbiddenerror and logs.
The request
downloadFromESVApi(ref) calls Obsidian's requestUrl (not fetch, per the
obsidian-plugin-development guidelines) against:
https://api.esv.org/v3/passage/html/?q=<ref>
&include-passage-references=false
&include-verse-numbers=true
&include-first-verse-numbers=true
&include-footnotes=true
&include-headings=true
The HTML format is requested so the renderer can preserve ESV typesetting (poetry, headings, footnotes, Words of Christ).
Footnotes are always fetched, then hidden at render time
include-footnotes=true is hardcoded, so footnotes are always baked into the
stored HTML — hiding them is a render-time concern, not an API one (and changing
the toggle doesn't require re-downloading). Two independent settings control it:
hideFootnotes— rendered full passages; applied as CSS byBibleStyles.hideFootnotesInPreview— hover preview;BibleReferenceRenderer.showVersePreviewremoves.footnotes/.extra_text/.footnotenodes from the cloned HTML.
Both default to false. To change footnote behavior, look here — not at the request.
Single-chapter-book workaround
The ESV API returns only the first verse when you request a whole single-chapter
book (e.g. Obadiah 1). As a workaround, for chapter references to books with a
single chapter the request is widened to verses 1-999. See downloadFromESVApi
and BookNames.getChapterCount.
Storage: notes as cache
A successful download is persisted by saveESVApiResponseAsMdNote:
- Location —
<bibleContentVaultPath>/<preferredBibleVersion>/<Book>/with filenames fromBibleFiles.pathForPassage(Book N.mdfor chapters,Book NvV[-E].mdfor verse ranges). Missing folders are created. - Body — a
biblecode block containing the canonical reference. - Frontmatter — the raw API response is written field-by-field
(
query,canonical,parsed,passage_meta,passages) viaapp.fileManager.processFrontMatter, plus any user-configured custom frontmatter (FrontmatterUtil).
Because the frontmatter is the cache, reopening a chapter reads the note and
runs toBibleApiResponse on the stored JSON instead of re-hitting the API. The
Update frontmatter on all Bible notes command re-applies custom frontmatter
across existing notes.
Errors
All failures funnel through BibleApiResponse.error(message, ErrorType)
(ApiAuthentication, BadApiResponse, RequestsForbidden, …). User-visible cases
surface an Obsidian Notice; internal ones are logged to the console.
Attribution when reproducing verse text
The verse-selection blockquote format (VerseFormatter.formatBlockquote) reproduces
ESV text into the user's note and appends a — <ref> (ESV) citation. The ESV API
copyright/permissions terms require attribution when ESV text is
quoted; the (ESV) suffix is the minimum, and larger reproductions carry a fuller
copyright-notice obligation. If the quoting story expands (e.g. exporting many passages),
revisit the notice requirement here. The other two formats (inline reference, bible
block) store only a reference, not text, so they don't trigger this.