Apollo Multi-Environment Setup
Overview
Configure Apollo.io for development, staging, and production with isolated API keys, environment-specific rate limits, feature gating, and Kubernetes-native secret management. Apollo provides sandbox tokens for testing that return dummy data without consuming credits.
Prerequisites
- Separate Apollo API keys per environment (or sandbox tokens for dev)
- Node.js 18+
Instructions
Step 1: Environment Configuration Schema
import { z } from 'zod';
const EnvironmentSchema = z.enum(['development', 'staging', 'production']);
const ApolloEnvConfig = z.object({
environment: EnvironmentSchema,
apiKey: z.string().min(10),
baseUrl: z.string().url().default('https://api.apollo.io/api/v1'),
isSandbox: z.boolean().default(false),
rateLimit: z.object({
maxPerMinute: z.number().min(1),
concurrency: z.number().min(1).max(20),
}),
features: z.object({
enrichment: z.boolean(),
sequences: z.boolean(),
deals: z.boolean(),
bulkEnrichment: z.boolean(),
}),
credits: z.object({
dailyBudget: z.number(),
alertThreshold: z.number(),
}),
logging: z.object({
level: z.enum(['debug', 'info', 'warn', 'error']),
redactPII: z.boolean(),
}),
});
type ApolloEnvConfig = z.infer<typeof ApolloEnvConfig>;
Step 2: Per-Environment Configs
const configs: Record<string, ApolloEnvConfig> = {
development: {
environment: 'development',
apiKey: process.env.APOLLO_SANDBOX_KEY ?? process.env.APOLLO_API_KEY_DEV!,
baseUrl: 'https://api.apollo.io/api/v1',
isSandbox: true,
rateLimit: { maxPerMinute: 20, concurrency: 2 },
features: { enrichment: true, sequences: false, deals: false, bulkEnrichment: false },
credits: { dailyBudget: 10, alertThreshold: 80 },
logging: { level: 'debug', redactPII: false },
},
staging: {
environment: 'staging',
apiKey: process.env.APOLLO_API_KEY_STAGING!,
baseUrl: 'https://api.apollo.io/api/v1',
isSandbox: false,
rateLimit: { maxPerMinute: , : },
: { : , : , : , : },
: { : , : },
: { : , : },
},
: {
: ,
: process..!,
: ,
: ,
: { : , : },
: { : , : , : , : },
: { : , : },
: { : , : },
},
};
Step 3: Environment-Aware Client Factory
import axios, { AxiosInstance } from 'axios';
export function createEnvClient(config: ApolloEnvConfig): AxiosInstance {
const validated = ApolloEnvConfig.parse(config);
const client = axios.create({
baseURL: validated.baseUrl,
headers: { 'Content-Type': 'application/json', 'x-api-key': validated.apiKey },
timeout: validated.environment === 'development' ? 30_000 : 15_000,
});
client.interceptors.request.use((req) => {
if (req.url?.includes('/people/match') && !validated.features.enrichment)
throw new Error(`Enrichment disabled in ${validated.environment}`);
if (req.url?.includes('/emailer_campaigns') && !validated..)
();
(req.?.() && !validated..)
();
(req.?.() && !validated..)
();
req;
});
(validated.. === ) {
client...( {
.();
req;
});
}
client;
}
(): {
env = process.. ?? ;
(configs[env] ?? configs.);
}
Step 4: Kubernetes Secrets
apiVersion: v1
kind: Secret
metadata:
name: apollo-credentials
namespace: sales-dev
type: Opaque
stringData:
APOLLO_SANDBOX_KEY: "sandbox-token-here"
APOLLO_API_KEY_DEV: "dev-key-here"
---
apiVersion: v1
kind: Secret
metadata:
name: apollo-credentials
namespace: sales-prod
type: Opaque
stringData:
APOLLO_API_KEY_PROD: "master-key-here"
Step 5: Environment Verification Script
async function verifyAllEnvironments() {
for (const [env, config] of Object.entries(configs)) {
try {
const client = createEnvClient(config);
const { data } = await client.get('/auth/health');
const isMaster = await testMasterAccess(client);
console.log(`${env}: ${data.is_logged_in ? 'OK' : 'FAIL'} (${isMaster ? 'master' : 'standard'} key, sandbox: ${config.isSandbox})`);
} catch (err: any) {
console.error(`${env}: FAIL — ${err.message}`);
}
}
}
async function testMasterAccess(client: AxiosInstance): Promise<boolean> {
try { await client.post('/contacts/search', { per_page: }); ; }
{ ; }
}
Output
- Zod-validated environment config schema with feature flags and credit budgets
- Three environment configs (dev with sandbox, staging, production)
- Client factory with feature gating and debug logging
- Kubernetes secrets per namespace
- Environment verification script testing all configs
Error Handling
| Issue | Resolution |
|---|
| Feature disabled | Client throws descriptive error identifying which env blocked it |
| Wrong environment | Check NODE_ENV, client falls back to development |
| Missing API key | Zod throws with clear validation error |
| Sandbox returning dummy data | Expected in development — use staging for real data testing |
Resources
Next Steps
Proceed to apollo-observability for monitoring setup.