| name | juicebox-upgrade-migration |
| description | Plan Juicebox SDK upgrades.
Trigger: "upgrade juicebox", "juicebox migration".
|
| allowed-tools | Read, Write, Edit, Bash(npm:*) |
| version | 1.16.0 |
| license | MIT |
| author | Jeremy Longshore <jeremy@intentsolutions.io> |
| tags | ["saas","recruiting","juicebox"] |
| compatibility | Designed for Claude Code |
Juicebox Upgrade & Migration
Overview
Juicebox is an AI-powered people search and analysis platform used for recruiting and market research. The API provides endpoints for dataset management, people searches, and AI-generated analyses. Tracking API versions is essential because Juicebox evolves its search query syntax, dataset schema, and analysis output format — upgrading without testing can break saved search filters, corrupt dataset imports, and change the structure of AI-generated candidate profiles that downstream systems consume.
Version Detection
const JUICEBOX_BASE = "https://api.juicebox.work/v1";
async function detectJuiceboxVersion(apiKey: string): Promise<void> {
const res = await fetch(`${JUICEBOX_BASE}/datasets`, {
headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" },
});
const version = res.headers.get("x-juicebox-api-version") ?? "v1";
console.log(`Juicebox API version: ${version}`);
const searchRes = await fetch(`${JUICEBOX_BASE}/search`, {
method: "POST",
headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" },
body: JSON.stringify({ query: "test", limit: 1 }),
});
deprecation = searchRes..();
(deprecation) .();
}
Migration Checklist
Schema Migration
interface OldSearchResult {
id: string;
name: string;
title: string;
company: string;
email?: string;
linkedin_url?: string;
}
interface NewSearchResult {
id: string;
profile: {
full_name: string;
current_title: string;
current_company: { name: string; domain: string };
emails: Array<{ address: string; type: "work" | "personal"; verified: boolean }>;
social: { linkedin?: string; twitter?: string };
};
match_score: number;
enrichment_sources: string[];
}
function migrateSearchResult(old: OldSearchResult): NewSearchResult {
{
: old.,
: {
: old.,
: old.,
: { : old., : },
: old. ? [{ : old., : , : }] : [],
: { : old. },
},
: ,
: [],
};
}
Rollback Strategy
class JuiceboxClient {
private currentVersion: "v1" | "v2";
constructor(private apiKey: string, version: "v1" | "v2" = "v2") {
this.currentVersion = version;
}
async search(query: string, filters?: Record<string, any>): Promise<any> {
try {
const res = await fetch(`https://api.juicebox.work/${this.currentVersion}/search`, {
method: "POST",
headers: { Authorization: `Bearer ${this.apiKey}`, "Content-Type": "application/json" },
body: JSON.stringify({ query, filters }),
});
if (!res.ok) throw new Error(`Juicebox search ${res.status}`);
res.();
} (err) {
(. === ) {
.();
. = ;
.(query, filters);
}
err;
}
}
}
Error Handling
| Migration Issue | Symptom | Fix |
|---|
| Search filter syntax changed | 400 Bad Request with invalid filter operator | Update filter syntax to new query DSL format |
| Dataset schema mismatch | Import succeeds but columns mapped incorrectly | Re-map dataset columns using /datasets/schema endpoint |
| Profile field restructured | Code crashes accessing result.name (now result.profile.full_name) | Update all property access paths to new nested structure |
| Analysis format changed | AI analysis output missing expected sections | Update parser for new structured analysis response |
| Rate limit reduced | 429 Too Many Requests on previously working batch sizes | Reduce batch size and implement request queuing |
Resources
- Juicebox Changelog
- Juicebox API Documentation
Next Steps
For CI pipeline integration, see juicebox-ci-integration.