Follow these patterns to build reliable, performant, and secure integrations with the Yoshi API.
Error handling
Always check the response envelope before accessing data:
const response = await fetch ( "https://api.yoshi.ai/accounts" , {
headers: { Authorization: `Bearer ${ process . env . YOSHI_API_KEY } ` },
});
if ( ! response . ok ) {
const { error , meta } = await response . json ();
console . error ( `[ ${ meta . request_id } ] ${ error . code } : ${ error . message } ` );
throw new Error ( error . display_message || error . message );
}
const { data } = await response . json ();
Include request_id in error logs and support tickets — it lets Yoshi trace exactly what happened.
Retry strategy
Status Retry? Strategy 429Yes Wait retry_after seconds, then retry 500Yes Exponential backoff: 1s, 2s, 4s (max 3 retries) 503Yes Exponential backoff 400No Fix the request — the input is invalid 401No Check your API key 404No The resource doesn’t exist 409No Duplicate idempotency key with different parameters
async function fetchWithRetry ( url , options , maxRetries = 3 ) {
for ( let attempt = 0 ; attempt <= maxRetries ; attempt ++ ) {
const response = await fetch ( url , options );
if ( response . ok ) return response ;
if ( response . status === 429 ) {
const retryAfter = Number ( response . headers . get ( "Retry-After" )) || 60 ;
await sleep ( retryAfter * 1000 );
continue ;
}
if ( response . status >= 500 && attempt < maxRetries ) {
await sleep ( 1000 * Math . pow ( 2 , attempt ));
continue ;
}
return response ; // Don't retry 4xx errors
}
}
The SDKs handle retries automatically with configurable maxRetries (default: 2).
Caching
Resource Safe to cache Duration Account metadata (names, types) Yes 5–15 minutes Balances No Changes every sync Transactions list Briefly 1–5 minutes Scores Yes 1 hour (recalculated daily) Recurring streams Yes 1 hour Card products catalog Yes 24 hours
Never cache balance data — it changes with every sync and users expect current numbers.
Webhook processing
Respond fast, process later:
app . post ( "/webhooks/yoshi" , async ( req , res ) => {
// Verify signature
const event = verifyWebhook ( req );
// Acknowledge immediately
res . sendStatus ( 200 );
// Process asynchronously
await queue . add ( "process-event" , event );
});
Return a 2xx response within 15 seconds. If your handler takes longer, Yoshi marks the delivery as failed and retries.
Idempotent processing: Events can be delivered more than once. Use event.id to deduplicate:
async function processEvent ( event ) {
const already = await db . get ( `processed: ${ event . id } ` );
if ( already ) return ;
await handleEvent ( event );
await db . set ( `processed: ${ event . id } ` , true , { ex: 86400 });
}
Security
Never expose API keys client-side. API keys grant full access to the user’s financial data. Always make API calls from a backend server.
❌ fetch("https://api.yoshi.ai/accounts", {
headers: { Authorization: "Bearer yoshi_3xK9mP..." }
}) // in browser JavaScript
✅ // Browser calls YOUR backend, which calls Yoshi
fetch("/api/accounts")
Use environment variables. Don’t hardcode keys in source code:
export YOSHI_API_KEY = yoshi_3xK9mP ...
Rotate keys periodically. Create a new key, update your services, then revoke the old one. Multiple active keys are supported for zero-downtime rotation.
Verify webhook signatures. Always verify the signature before processing webhook events — otherwise anyone can send fake events to your endpoint.
Rate limit budgeting
Each API key has a limit of 100 requests per minute . If you have multiple services sharing a key:
Track usage across services using the X-RateLimit-Remaining header
Prioritize user-facing requests over background jobs
Use webhooks to reduce polling — each webhook you process replaces multiple poll requests
Consider separate keys for different services so they have independent limits
const remaining = Number ( response . headers . get ( "X-RateLimit-Remaining" ));
if ( remaining < 10 ) {
console . warn ( "Approaching rate limit, throttling background jobs" );
pauseBackgroundJobs ();
}
What’s next
Errors Full error codes reference.
Rate limits Detailed rate limiting documentation.