The HighlightsClient class provides methods for managing user Bible highlights through the YouVersion Platform API. All endpoints require OAuth authentication with appropriate scopes.
All HighlightsClient methods require OAuth authentication. See the Authentication guide for implementing the PKCE flow.
Highlights endpoints require a valid OAuth access token. You can provide the token in two ways:
Pass as parameter - Explicitly pass the lat (long access token) parameter to each method
Global configuration - Set the token in YouVersionPlatformConfiguration.accessToken
import { YouVersionPlatformConfiguration } from '@youversion/platform-core';// Option 1: Set globally (recommended)YouVersionPlatformConfiguration.saveAuthData( accessToken, refreshToken, idToken, expiryDate);// Now all methods use the global tokenconst highlights = await highlightsClient.getHighlights();// Option 2: Pass explicitlyconst highlights = await highlightsClient.getHighlights(undefined, accessToken);
// Get all highlights for the authenticated userconst highlights = await highlightsClient.getHighlights();console.log(`Total highlights: ${highlights.data.length}`);highlights.data.forEach(highlight => { console.log( `${highlight.passage_id} in version ${highlight.version_id}: #${highlight.color}` );});
import { ApiClient, HighlightsClient, BibleClient, YouVersionPlatformConfiguration} from '@youversion/platform-core';// Initialize clientsconst apiClient = new ApiClient({ appKey: process.env.YOUVERSION_APP_KEY!,});const highlightsClient = new HighlightsClient(apiClient);const bibleClient = new BibleClient(apiClient);// Assume user has authenticated via OAuthconst accessToken = 'user-oauth-access-token';YouVersionPlatformConfiguration.saveAuthData( accessToken, 'refresh-token', 'id-token', new Date(Date.now() + 3600000) // 1 hour from now);// Get user's existing highlightsconst highlights = await highlightsClient.getHighlights({ version_id: 111 // NIV});console.log(`User has ${highlights.data.length} highlights in NIV`);// Highlight a new verse in yellowawait highlightsClient.createHighlight({ version_id: 111, passage_id: 'JHN.3.16', color: 'ffff00'});console.log('Highlighted John 3:16 in yellow');// Get the passage content with highlightconst passage = await bibleClient.getPassage(111, 'JHN.3.16');console.log(`\n${passage.reference}`);console.log(passage.content);// Update highlight color to greenawait highlightsClient.createHighlight({ version_id: 111, passage_id: 'JHN.3.16', color: '00ff00' // Green});console.log('Changed highlight color to green');// Highlight a range of versesawait highlightsClient.createHighlight({ version_id: 111, passage_id: 'PSA.23.1-6', // Entire Psalm 23 color: '0000ff' // Blue});console.log('Highlighted Psalm 23 in blue');// Get all highlights againconst updated = await highlightsClient.getHighlights({ version_id: 111});console.log(`\nNow user has ${updated.data.length} highlights`);// Group by colorconst byColor = updated.data.reduce((acc, h) => { if (!acc[h.color]) acc[h.color] = []; acc[h.color].push(h.passage_id); return acc;}, {} as Record<string, string[]>);Object.entries(byColor).forEach(([color, passages]) => { console.log(`\nColor #${color}:`); passages.forEach(p => console.log(` - ${p}`));});// Remove a highlightawait highlightsClient.deleteHighlight('JHN.3.16', { version_id: 111});console.log('\nRemoved highlight from John 3:16');
Set the access token globally instead of passing it to every method:
import { YouVersionPlatformConfiguration } from '@youversion/platform-core';// After successful OAuth authenticationYouVersionPlatformConfiguration.saveAuthData( accessToken, refreshToken, idToken, expiryDate);// Now all methods work without explicit tokenconst highlights = await highlightsClient.getHighlights();await highlightsClient.createHighlight({ ... });
Handle authentication errors
Always handle authentication and authorization errors:
try { const highlights = await highlightsClient.getHighlights();} catch (error) { if (error instanceof Error) { const httpError = error as Error & { status?: number }; if (httpError.status === 401) { console.error('Authentication required'); // Redirect to login } else if (httpError.status === 403) { console.error('Insufficient permissions'); // Request additional scopes } }}
Validate colors before sending
Ensure colors are valid 6-digit hex codes:
function isValidColor(color: string): boolean { return /^[0-9a-f]{6}$/i.test(color);}function normalizeColor(color: string): string { // Remove # if present color = color.replace(/^#/, ''); if (!isValidColor(color)) { throw new Error('Invalid color format'); } return color.toLowerCase();}const userColor = '#FFFF00';const normalized = normalizeColor(userColor); // 'ffff00'await highlightsClient.createHighlight({ version_id: 111, passage_id: 'JHN.3.16', color: normalized});
Batch highlight operations
When creating multiple highlights, batch them efficiently:
const versesToHighlight = [ 'JHN.3.16', 'PSA.23.1', 'ROM.8.28'];const color = 'ffff00'; // Yellow// Create all highlightsawait Promise.all( versesToHighlight.map(passage_id => highlightsClient.createHighlight({ version_id: 111, passage_id, color }) ));console.log('Created all highlights');
Sync highlights with local storage
Keep a local cache of highlights for offline access:
async function syncHighlights(versionId: number) { // Fetch from API const highlights = await highlightsClient.getHighlights({ version_id: versionId }); // Store locally localStorage.setItem( `highlights-${versionId}`, JSON.stringify(highlights.data) ); return highlights.data;}async function getHighlightsCached(versionId: number) { // Try local first const cached = localStorage.getItem(`highlights-${versionId}`); if (cached) { return JSON.parse(cached); } // Fetch and cache return await syncHighlights(versionId);}