Problem: Backend returns an error when calling Doshi API.Possible Causes:
Invalid API key
API key not provided in Authorization header
Invalid request parameters
Network connectivity issues
Solutions:
Verify API key:
Copy
# Test your API key curl -X POST https://api.doshi.app/client/auth/token \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Access-Type: client" \ -H "Content-Type: application/json" \ -d '{"email": "test@example.com"}'
Check environment variables:
Copy
// Verify API key is loaded console.log('API Key exists:', !!process.env.DOSHI_API_KEY); console.log('API Key length:', process.env.DOSHI_API_KEY?.length); // Don't log the actual key!
Validate request parameters:
Copy
// Ensure you're sending email OR partnerUserId const requestBody = { email: user.email || undefined, partnerUserId: user.id || undefined }; if (!requestBody.email && !requestBody.partnerUserId) { throw new Error('Must provide email or partnerUserId'); }
Check API response:
Copy
const response = await fetch(doshiApiUrl, options); if (!response.ok) { const errorText = await response.text(); console.error('API Error:', response.status, errorText); throw new Error(`API returned ${response.status}: ${errorText}`); }
Token expired or invalid
Problem: Token is rejected by the iframe.Possible Causes:
Token was generated too long ago
Token was already used
Token format is incorrect
Solutions:
Generate token immediately before use:
Copy
// โ Generate token right before passing to iframe const token = await fetchToken(); passToIframe(token); // โ Don't store tokens for long periods const token = await fetchToken(); localStorage.setItem('token', token); // Don't do this
Donโt reuse tokens:
Copy
// Each iframe load should get a fresh token useEffect(() => { const fetchAndSetToken = async () => { const newToken = await fetchToken(); setToken(newToken); }; fetchAndSetToken(); }, []); // Fresh token on mount
const iframe = document.querySelector('iframe'); iframe.addEventListener('load', () => { console.log('Iframe loaded, waiting for PING...'); }); // Set a timeout to detect if PING never arrives setTimeout(() => { console.warn('No PING received after 5 seconds'); }, 5000);
Check for errors in iframe:
Copy
iframe.addEventListener('error', (e) => { console.error('Iframe failed to load:', e); });
const params = new URLSearchParams(); // Only add defined values if (authToken) params.append('token', authToken); if (userEmail) params.append('email', userEmail); console.log('Params:', Object.fromEntries(params));
const url = buildWebviewUrl(baseUrl, params); if (url.length > 2000) { console.error('URL too long:', url.length, 'characters'); // Switch to postMessage method }
Reduce parameter size:
Copy
// Only include essential parameters const minimalParams = { token: authToken, email: userEmail // Fetch other data from API after auth };
Switch to postMessage:
Copy
// If URL is too long, use postMessage instead if (estimatedUrlLength > 2000) { return <WebviewWithPostMessage {...props} />; } return <WebviewWithQueryParams {...props} />;
Special characters breaking URL
Problem: Special characters not encoding properly.Solutions:
// Check for support if (typeof window.postMessage === 'undefined') { console.error('postMessage not supported'); // Fallback to query parameters return <WebviewWithQueryParams {...props} />; }
URLSearchParams not available
Problem: URLSearchParams not supported in older browsers.Solution:
Copy
// Check for support and provide fallback function buildQueryString(params) { if (typeof URLSearchParams !== 'undefined') { return new URLSearchParams(params).toString(); } // Fallback: manual encoding return Object.entries(params) .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}` ) .join('&'); }
Iframe not loading on iOS Safari
Problem: Iframe doesnโt load on iOS Safari.Solutions:
Problem: External links clicked in Doshi Frontend donโt open.Cause: Popups are blocked for security reasons.Solution: Implement postMessage callback to handle link clicks.
Copy
window.addEventListener('message', (event) => { if (event.origin !== 'https://embed.v2.doshi.app') return; const data = JSON.parse(event.data); if (data.type === 'EXTERNAL_LINK') { // Handle the link in your environment window.open(data.url, '_blank', 'noopener,noreferrer'); } });
Problem: API works in staging but not production (or vice versa).Cause: Different servers have different IPs.Solution:Get the IP from each server and have all of them whitelisted: