Production-ready patterns for the Juicebox AI-powered people search API. Juicebox provides REST endpoints for searching professional profiles and enriching candidate data. The API authenticates via JUICEBOX_API_KEY and returns structured profile objects with LinkedIn URLs as natural dedup keys. A singleton client centralizes rate-limit handling across search and enrich endpoints.
Singleton Client
const JUICEBOX_BASE = 'https://api.juicebox.work/v1';
let _client: JuiceboxClient | null = null;
export function getClient(): JuiceboxClient {
if (!_client) {
const apiKey = process.env.JUICEBOX_API_KEY;
if (!apiKey) throw new Error('JUICEBOX_API_KEY must be set — get it from juicebox.work/settings');
_client = new JuiceboxClient(apiKey);
}
return _client;
}
class JuiceboxClient {
private headers: Record<string, string>;
constructor(apiKey: string) { this.headers = { 'Authorization': `Bearer ${apiKey}`, 'Content-Type': 'application/json' }; }
async search(query: string, limit = 20): Promise<SearchResponse> {
const res = await fetch(`${JUICEBOX_BASE}/search`, {
method: 'POST', headers: this.headers, body: JSON.stringify({ query, limit }) });
if (!res.ok) throw new JuiceboxError(res.status, await res.text()); return res.json();
}
async enrich(linkedinUrl: string): Promise<Profile> {
const res = await fetch(`${JUICEBOX_BASE}/enrich`, {
method: 'POST', headers: this.headers, body: JSON.stringify({ linkedin_url: linkedinUrl }) });
if (!res.ok) throw new JuiceboxError(res.status, await res.text()); return res.json();
}
}