From apollo-pack
Collects Apollo.io API debug bundle with environment info, connectivity, rate limits, key type, and endpoint tests for support tickets and issue documentation.
How this skill is triggered — by the user, by Claude, or both
Slash command
/apollo-pack:apollo-debug-bundleThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
!`node --version 2>/dev/null || echo 'N/A'`
!node --version 2>/dev/null || echo 'N/A'
!python3 --version 2>/dev/null || echo 'N/A'
!uname -a
Collect comprehensive debug information for Apollo.io API issues. Generates a JSON diagnostic bundle with environment info, connectivity tests, rate limit status, key type verification, and sanitized request/response logs.
APOLLO_API_KEY environment variable set// src/scripts/debug-bundle.ts
import axios from 'axios';
import os from 'os';
const BASE_URL = 'https://api.apollo.io/api/v1';
interface DebugBundle {
timestamp: string;
environment: Record<string, string>;
connectivity: { reachable: boolean; latencyMs: number; statusCode?: number };
keyType: 'master' | 'standard' | 'invalid' | 'unknown';
rateLimits: { limit?: string; remaining?: string; window?: string };
endpointTests: Array<{ endpoint: string; status: number | string; ok: boolean }>;
systemInfo: Record<string, string>;
}
async function collectDebugBundle(): Promise<DebugBundle> {
const headers = {
'Content-Type': 'application/json',
'x-api-key': process.env.APOLLO_API_KEY ?? '',
};
const bundle: DebugBundle = {
timestamp: new Date().toISOString(),
environment: {
nodeVersion: process.version,
platform: os.platform(),
arch: os.arch(),
apiKeySet: process.env.APOLLO_API_KEY ? 'yes (redacted)' : 'NOT SET',
apiKeyLength: String(process.env.APOLLO_API_KEY?.length ?? 0),
apiKeyPrefix: process.env.APOLLO_API_KEY?.slice(0, 4) + '...' ?? 'N/A',
},
connectivity: { reachable: false, latencyMs: 0 },
keyType: 'unknown',
rateLimits: {},
endpointTests: [],
systemInfo: {},
};
return bundle;
}
async function testConnectivity(bundle: DebugBundle) {
const headers = { 'Content-Type': 'application/json', 'x-api-key': process.env.APOLLO_API_KEY! };
// Test basic auth
const start = Date.now();
try {
const resp = await axios.get(`${BASE_URL}/auth/health`, { headers, timeout: 10_000 });
bundle.connectivity = { reachable: true, latencyMs: Date.now() - start, statusCode: resp.status };
bundle.keyType = resp.data.is_logged_in ? 'standard' : 'invalid'; // at minimum standard
} catch (err: any) {
bundle.connectivity = { reachable: false, latencyMs: Date.now() - start, statusCode: err.response?.status };
return;
}
// Test master key access
try {
await axios.post(`${BASE_URL}/contacts/search`, { per_page: 1 }, { headers, timeout: 10_000 });
bundle.keyType = 'master';
} catch (err: any) {
if (err.response?.status === 403) bundle.keyType = 'standard';
}
}
async function testEndpoints(bundle: DebugBundle) {
const headers = { 'Content-Type': 'application/json', 'x-api-key': process.env.APOLLO_API_KEY! };
const tests = [
{ name: 'Auth Health', method: 'GET', url: `${BASE_URL}/auth/health` },
{ name: 'People Search', method: 'POST', url: `${BASE_URL}/mixed_people/api_search`,
body: { per_page: 1, q_organization_domains_list: ['apollo.io'] } },
{ name: 'Org Enrichment', method: 'GET', url: `${BASE_URL}/organizations/enrich?domain=apollo.io` },
{ name: 'Contacts Search', method: 'POST', url: `${BASE_URL}/contacts/search`, body: { per_page: 1 } },
{ name: 'Sequences Search', method: 'POST', url: `${BASE_URL}/emailer_campaigns/search`, body: { per_page: 1 } },
{ name: 'Email Accounts', method: 'GET', url: `${BASE_URL}/email_accounts` },
];
for (const test of tests) {
try {
const resp = await axios({ method: test.method as any, url: test.url, data: test.body, headers, timeout: 10_000 });
bundle.endpointTests.push({ endpoint: test.name, status: resp.status, ok: true });
// Capture rate limit headers from any successful response
if (resp.headers['x-rate-limit-limit']) {
bundle.rateLimits = {
limit: resp.headers['x-rate-limit-limit'],
remaining: resp.headers['x-rate-limit-remaining'],
window: resp.headers['x-rate-limit-window'],
};
}
} catch (err: any) {
bundle.endpointTests.push({
endpoint: test.name,
status: err.response?.status ?? err.code ?? err.message,
ok: false,
});
}
}
}
async function main() {
console.log('Collecting Apollo debug bundle...\n');
const bundle = await collectDebugBundle();
await testConnectivity(bundle);
await testEndpoints(bundle);
// System info
bundle.systemInfo = {
hostname: os.hostname(),
platform: `${os.platform()} ${os.release()}`,
memory: `${Math.round(os.freemem() / 1024 / 1024)}MB free / ${Math.round(os.totalmem() / 1024 / 1024)}MB total`,
};
// Write to file
const fs = await import('fs');
const filename = `apollo-debug-${Date.now()}.json`;
fs.writeFileSync(filename, JSON.stringify(bundle, null, 2));
// Print summary
console.log('=== Apollo Debug Summary ===');
console.log(`API Key: ${bundle.environment.apiKeySet} (${bundle.environment.apiKeyLength} chars)`);
console.log(`Key Type: ${bundle.keyType}`);
console.log(`Reachable: ${bundle.connectivity.reachable} (${bundle.connectivity.latencyMs}ms)`);
console.log(`Rate Limit: ${bundle.rateLimits.remaining ?? '?'}/${bundle.rateLimits.limit ?? '?'} remaining`);
console.log(`Endpoints:`);
for (const t of bundle.endpointTests) {
console.log(` ${t.ok ? 'OK' : 'FAIL'} ${t.endpoint}: ${t.status}`);
}
console.log(`\nBundle saved: ${filename}`);
}
main().catch(console.error);
| Issue | Debug Step |
|---|---|
| Connection timeout | Check network/firewall, verify DNS for api.apollo.io |
| Key type = invalid | Key was revoked — regenerate in Apollo dashboard |
| Key type = standard | Master key needed — check which endpoints fail with 403 |
| All endpoints fail | Check status.apollo.io for outages |
# One-liner: test auth + connectivity
curl -s -w "\nHTTP %{http_code} in %{time_total}s\n" \
-H "x-api-key: $APOLLO_API_KEY" \
"https://api.apollo.io/api/v1/auth/health"
# Test rate limit headers
curl -s -D - -o /dev/null \
-H "Content-Type: application/json" -H "x-api-key: $APOLLO_API_KEY" \
-X POST -d '{"per_page":1,"q_organization_domains_list":["apollo.io"]}' \
"https://api.apollo.io/api/v1/mixed_people/api_search" 2>/dev/null | grep -i "x-rate"
Proceed to apollo-rate-limits for rate limiting implementation.
npx claudepluginhub jeremylongshore/claude-code-plugins-plus-skills --plugin apollo-packDiagnoses Apollo.io API errors like 401 auth, 403 master key issues, 429 rate limits via curl health checks, code examples in JS/TS/Python.
Collects SalesLoft API debug bundle with auth checks, rate limits, endpoint tests, env info, and redacted configs. For preparing support tickets or diagnosing API issues.
Generates Klaviyo debug bundle capturing SDK version, API connectivity/auth tests, rate limits, errors, redacted config, and logs for support tickets.