Best practices
Conceptual guidance for building a robust integration. For per-endpoint parameters see the API Reference; for pagination see Pagination.
1. Cache access tokens
Section titled “1. Cache access tokens”Cache access tokens and reuse them for their lifetime (expires_in) instead of
requesting a new token per call:
let cachedToken = null;let tokenExpiry = null;
async function getToken() { if (cachedToken && Date.now() < tokenExpiry) { return cachedToken; } const response = await requestToken(); cachedToken = response.access_token; tokenExpiry = Date.now() + (response.expires_in * 1000); return cachedToken;}2. Handle errors gracefully
Section titled “2. Handle errors gracefully”Always check the response and surface the API’s error message:
try { const response = await fetch(url, { headers: { Authorization: `Bearer ${token}` } }); if (!response.ok) { const error = await response.json(); throw new Error(`API Error: ${error.message}`); } return await response.json();} catch (error) { console.error('API request failed:', error); // Implement retry logic for 5xx errors}3. Paginate correctly
Section titled “3. Paginate correctly”See Pagination for cursor-based (DynamoDB) and offset/syncToken (OpenSearch) strategies and when to use each.
4. Retry with exponential backoff
Section titled “4. Retry with exponential backoff”For 429 or 5xx responses, back off exponentially:
async function fetchWithRetry(url, options, maxRetries = 3) { for (let attempt = 0; attempt < maxRetries; attempt++) { try { const response = await fetch(url, options); if (response.status === 429 || response.status >= 500) { if (attempt === maxRetries - 1) throw new Error('Max retries exceeded'); await sleep(Math.pow(2, attempt) * 1000); // 1s, 2s, 4s continue; } return response; } catch (error) { if (attempt === maxRetries - 1) throw error; await sleep(Math.pow(2, attempt) * 1000); } }}