Error Types
ScriptBase errors fall into several categories:- Authentication - Invalid/missing API key
- Validation - Invalid parameters
- Resource - Video/channel not found
- Rate Limiting - Too many requests
- Quota - Monthly limit exceeded
- Server - Internal errors
Basic Error Handling
Copy
async function safeApiCall(url: string, apiKey: string) {
try {
const response = await fetch(url, {
headers: { 'X-API-Key': apiKey }
});
const data = await response.json();
if (!data.success) {
// Handle API error
console.error(`API Error: ${data.error.code} - ${data.error.message}`);
return null;
}
return data.data;
} catch (error) {
// Handle network error
console.error('Network error:', error);
return null;
}
}
Handling Rate Limits
Implement exponential backoff for rate limit errors:Copy
async function fetchWithRetry(
url: string,
apiKey: string,
maxRetries = 3
) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
const response = await fetch(url, {
headers: { 'X-API-Key': apiKey }
});
if (response.status === 429) {
const retryAfter = parseInt(
response.headers.get('Retry-After') || '60'
);
console.log(`Rate limited. Waiting ${retryAfter}s...`);
await new Promise(resolve =>
setTimeout(resolve, retryAfter * 1000)
);
continue;
}
return response.json();
}
throw new Error('Max retries exceeded');
}
Handling Quota Errors
Copy
if (error.code === 'QUOTA_EXCEEDED') {
const resetDate = error.details.resetDate;
console.error(`Quota exceeded. Resets on ${resetDate}`);
// Options:
// 1. Enable auto-recharge
// 2. Upgrade plan
// 3. Wait for reset
// 4. Use cached data
}
Handling Missing Transcripts
Not all videos have transcripts:Copy
async function getTranscriptSafely(videoId: string) {
try {
const response = await fetch(
`https://api.scriptbase.app/api/v1/transcripts/${videoId}`,
{ headers: { 'X-API-Key': apiKey } }
);
const data = await response.json();
if (data.error?.code === 'TRANSCRIPT_UNAVAILABLE') {
console.log('No transcript available for this video');
return null;
}
return data.data;
} catch (error) {
console.error('Failed to fetch transcript:', error);
return null;
}
}
Production-Ready Error Handler
Copy
class YTAPIClient {
constructor(private apiKey: string) {}
async request(endpoint: string, options = {}) {
const maxRetries = 3;
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
const response = await fetch(
`https://api.scriptbase.app${endpoint}`,
{
...options,
headers: {
'X-API-Key': this.apiKey,
...options.headers
}
}
);
const data = await response.json();
// Success
if (data.success) {
return data.data;
}
// Handle specific errors
switch (data.error.code) {
case 'RATE_LIMIT_EXCEEDED':
if (attempt < maxRetries - 1) {
const retryAfter = parseInt(
response.headers.get('Retry-After') || '60'
);
await this.sleep(retryAfter * 1000);
continue;
}
break;
case 'QUOTA_EXCEEDED':
throw new QuotaExceededError(data.error);
case 'TRANSCRIPT_UNAVAILABLE':
return null; // Expected for some videos
case 'INVALID_API_KEY':
throw new AuthError('Invalid API key');
default:
throw new APIError(data.error);
}
} catch (error) {
if (attempt === maxRetries - 1) throw error;
await this.sleep(1000 * Math.pow(2, attempt));
}
}
}
private sleep(ms: number) {
return new Promise(resolve => setTimeout(resolve, ms));
}
}