Best Practices
Tips for building great applications with ApiBiblia.
Caching
Cache Bible Content
Bible text doesn't change. Cache aggressively:
javascript
// Simple in-memory cache
const verseCache = new Map();
async function getVerse(ref, version = 'rvr60') {
const key = `${version}:${ref}`;
if (verseCache.has(key)) {
return verseCache.get(key);
}
const data = await fetchFromApi(ref, version);
verseCache.set(key, data);
return data;
}Use HTTP Caching
Our responses include cache headers. Configure your HTTP client to respect them:
javascript
// Using fetch with cache
const response = await fetch(url, {
headers: { 'X-API-Key': apiKey },
cache: 'default' // Respects Cache-Control headers
});Cache Duration Recommendations
| Content Type | Suggested TTL |
|---|---|
| Verses & Passages | 24 hours+ |
| Book lists | 24 hours |
| Version lists | 1 hour |
| Search results | 5 minutes |
Efficient API Usage
Batch Requests
Fetch ranges instead of individual verses:
javascript
// Instead of 3 requests
const v1 = await getPassage('Romans 8:28');
const v2 = await getPassage('Romans 8:29');
const v3 = await getPassage('Romans 8:30');
// Make 1 request
const verses = await getPassage('Romans 8:28-30');Fetch Chapters, Not Verses
When displaying full chapters, use the chapters endpoint:
javascript
// Good: 1 request
const chapter = await fetch('/v1/chapters/psa_23');
// Bad: 6 requests
for (let i = 1; i <= 6; i++) {
await fetch(`/v1/passage?ref=Psalm 23:${i}`);
}Prefetch Content
Anticipate user actions and prefetch:
javascript
// User is viewing John 3, prefetch John 4
if (currentChapter === 'joh_3') {
prefetch('/v1/chapters/joh_4');
}Error Handling
Always Handle Errors
javascript
async function safeGetVerse(ref) {
try {
const response = await fetch(`/v1/passage?ref=${ref}`);
const data = await response.json();
if (!data.success) {
console.error('API error:', data.error);
return null;
}
return data.data;
} catch (error) {
console.error('Network error:', error);
return null;
}
}Implement Retry Logic
javascript
async function fetchWithRetry(url, retries = 3) {
for (let i = 0; i < retries; i++) {
try {
const response = await fetch(url);
if (response.status === 429) {
const wait = Math.pow(2, i) * 1000;
await new Promise(r => setTimeout(r, wait));
continue;
}
return response;
} catch (error) {
if (i === retries - 1) throw error;
}
}
}Security
Keep API Keys Secret
Never expose API keys in client-side code:
javascript
// Bad: Key exposed in browser
fetch('/v1/verses/joh_3_16', {
headers: { 'X-API-Key': 'ab_live_xxx' } // Visible to users!
});
// Good: Proxy through your backend
fetch('/api/verse/joh_3_16'); // Your server adds the API keyUse Environment Variables
bash
# .env (never commit this)
APIBIBLIA_API_KEY=ab_live_xxxxxjavascript
// server.js
const apiKey = process.env.APIBIBLIA_API_KEY;User Experience
Show Loading States
javascript
function VerseDisplay({ reference }) {
const [verse, setVerse] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
setLoading(true);
getVerse(reference)
.then(setVerse)
.finally(() => setLoading(false));
}, [reference]);
if (loading) return <Skeleton />;
return <VerseText verse={verse} />;
}Handle Offline Gracefully
javascript
async function getVerseWithFallback(ref) {
try {
// Try network first
const data = await fetchFromApi(ref);
localStorage.setItem(`verse:${ref}`, JSON.stringify(data));
return data;
} catch (error) {
// Fall back to cached version
const cached = localStorage.getItem(`verse:${ref}`);
if (cached) return JSON.parse(cached);
throw error;
}
}Support Multiple Languages
Both Spanish and English book names work:
javascript
// These are equivalent
getPassage('John 3:16');
getPassage('Juan 3:16');Monitoring
Track API Usage
javascript
let apiCalls = 0;
async function trackedFetch(url) {
apiCalls++;
console.log(`API call #${apiCalls}: ${url}`);
return fetch(url);
}Monitor Rate Limits
javascript
async function fetchAndMonitor(url) {
const response = await fetch(url);
const remaining = response.headers.get('X-RateLimit-Remaining');
if (remaining < 10) {
console.warn(`Low rate limit: ${remaining} requests remaining`);
}
return response;
}