try { await client.brand.retrieve({ domain: "stripe.com" });} catch (error) { if (error.status === 401) { console.error("Invalid API key"); }}
Possible Causes:
Missing API key in request
Incorrect API key value
API key has been deleted or expired
API key not properly loaded from environment variables
Solutions:
Verify API key is loaded
Copy
// Add debug logging (remove after fixing)console.log("API Key exists:", !!process.env.BRAND_DEV_API_KEY);console.log("API Key length:", process.env.BRAND_DEV_API_KEY?.length);// DO NOT log the actual key value!const client = new BrandDev({ apiKey: process.env.BRAND_DEV_API_KEY,});
Check environment variable naming
Copy
// Make sure the variable name matches exactly// Common mistakes:process.env.BRANDDEV_API_KEY; // ❌ Missing underscoreprocess.env.BRAND_DEV_APIKEY; // ❌ Missing underscoreprocess.env.BRAND_DEV_API_KEY; // ✅ Correct
Verify .env file is loaded
Copy
// Node.js with dotenvimport "dotenv/config"; // Must be at the top of your file// Orimport dotenv from "dotenv";dotenv.config();const client = new BrandDev({ apiKey: process.env.BRAND_DEV_API_KEY,});
Cold hit taking longer than expected (first request for a domain)
Network latency issues
Understanding the timeoutMS Parameter:You can optionally set a custom timeout using the timeoutMS parameter:
Minimum: 1ms
Maximum: 300000ms (5 minutes)
If the request exceeds this timeout, it will be aborted with a 408 status code
Solutions:
Set appropriate timeout values
Copy
// For cold hits, allow more time (up to 5 minutes max)const { brand } = await client.brand.retrieve({ domain: "example.com", timeoutMS: 60000, // 60 seconds});// For time-sensitive operations, use a shorter timeoutconst { brand } = await client.brand.retrieve({ domain: "stripe.com", timeoutMS: 10000, // 10 seconds});
Use prefetching for better latency
Prefetch brand data before you need it (available on paid plans):
Copy
// When user enters email, prefetch immediatelyasync function handleEmailInput(email: string) { if (email.includes("@")) { const domain = email.split("@")[1]; // Fire and forget - doesn't charge credits client.utility.prefetch({ domain }).catch(() => {}); }}// Later, when you need the data, it's cached and fastconst { brand } = await client.brand.retrieve({ domain });
Use fast mode for speed-optimized responses
Copy
// Enable fast mode for quicker responses (less comprehensive data)const { brand } = await client.brand.retrieve({ domain: "example.com", fast: true,});
Implement retry with exponential backoff
Copy
async function fetchWithRetry(domain: string, maxRetries = 3) { for (let i = 0; i < maxRetries; i++) { try { return await client.brand.retrieve({ domain }); } catch (error) { if (error.status === 408 && i < maxRetries - 1) { const delay = Math.pow(2, i) * 1000; // Exponential backoff await new Promise((resolve) => setTimeout(resolve, delay)); continue; } throw error; } }}
Cold hits (first request): ~7 seconds (p50), up to 30 seconds (p99)
Use the fast parameter to optimize for speed at the cost of less
comprehensive data. Use timeoutMS to set a custom timeout (max 300,000ms / 5
minutes).
Solutions:
Use prefetching
Prefetch brand data as early as possible:
Copy
// When user enters email, prefetch immediatelyasync function handleEmailInput(email: string) { if (email.includes("@")) { const domain = email.split("@")[1]; // Fire and forget - doesn't count against credits client.utility.prefetchByEmail({ email }).catch(() => { // Silently fail - the main retrieve will still work }); }}// Later, when you need the data, it's cachedasync function loadUserProfile(email: string) { const domain = email.split("@")[1]; const { brand } = await client.brand.retrieve({ domain }); // Fast! // ... use brand data}
// Allow enough time for cold hitsconst client = new BrandDev({ apiKey: process.env.BRAND_DEV_API_KEY, timeout: 35000, // 35 seconds to account for p99});
Process in background
For non-critical use cases, fetch data asynchronously:
Copy
// Queue for background processingasync function enrichLeadInBackground(leadId: string, domain: string) { try { const { brand } = await client.brand.retrieve({ domain }); // Update lead in database when ready await database.leads.update(leadId, { brand_data: brand, enriched_at: new Date(), }); } catch (error) { console.error(`Failed to enrich lead ${leadId}:`, error); }}// Don't await - process in backgroundenrichLeadInBackground(lead.id, lead.domain);
Explanation:Not all brands have all data fields. Brand.dev returns what’s available from verified sources.Solutions:
Always provide fallbacks
Copy
function getBrandLogo(brand: Brand): string { // Try to get best logo const logo = brand.logos?.[0]?.url; // Fallback to generated avatar if no logo if (!logo) { return generateInitialsAvatar(brand.title || "Company"); } return logo;}function getBrandColor(brand: Brand): string { // Try to get primary color const primaryColor = brand.colors?.[0]?.hex; // Fallback to neutral color return primaryColor || "#6B7280";}
Issue:ModuleNotFoundError: No module named 'brand_dev'Solution:
Copy
# Reinstall the packagepip uninstall brand.devpip install brand.dev# Or use pip3 on some systemspip3 install brand.dev# Verify installationpip list | grep brand
When contacting support, please include: - The domain you’re trying to
retrieve - Full error message and status code - SDK version and language -
Timestamp of the request - Any relevant code snippets