Securing API keys with a backend proxy
Why you must never ship an API key in your app, and how to stand up a tiny proxy that keeps the secret safe.
Never embed a secret API key in an iOS app. Anyone can extract strings from a downloaded app binary in minutes. A leaked key can be used to run up thousands of dollars of charges on your account. This is the single most important security lesson in the course.
The solution is a proxy: a tiny server you control that holds the secret key. Your app calls your server; your server adds the key and calls the model. The key never leaves your infrastructure. That's why InsightsService in the last lesson called apiBase/reflect instead of Anthropic directly.
The architecture
- iPhone app → HTTPS POST to your proxy with just the entry text. No secrets.
- Your proxy (a serverless function) → adds
ANTHROPIC_API_KEYfrom a secure environment variable, calls the model, returns JSON. - The model provider → only ever talks to your server, which you can rate-limit and monitor.
Standing up the proxy
The fastest path is a serverless platform with a free tier (e.g. Vercel or Cloudflare Workers). You deploy the reflect function from the last lesson, set the API key as a secret environment variable in the dashboard (never in code), and you get an HTTPS URL like https://dayone-proxy.vercel.app/api. The walkthrough below uses Vercel. Alongside api/reflect.js, your proxy needs exactly one more file — a minimal package.json that declares the Anthropic SDK dependency:
{
"name": "dayone-proxy",
"private": true,
"dependencies": {
"@anthropic-ai/sdk": "latest"
}
}- 1Install Node.js from nodejs.org — download the LTS installer and run it like any Mac installer. This gives you the
npmcommand the next steps use. - 2Create a folder called
dayone-proxyanywhere you like. Inside it, create a subfolderapicontainingreflect.js(the code from the last lesson), and save thepackage.jsonabove at the folder's root. - 3Create a free account at vercel.com.
- 4In Terminal, run
npm i -g vercel, thencdintodayone-proxyand runvercel. Follow the login prompts — it deploys the folder and prints your URL. - 5Add your API key in the Vercel dashboard: your project ▸ Settings ▸ Environment Variables, name
ANTHROPIC_API_KEY, value the key you created last lesson. It stays server-side. - 6Run
vercel --prodto redeploy with the key in place. - 7Test it — open Terminal and paste (curl comes with macOS):
curl -X POST https://your-proxy/api/reflect -d '{"entry":"Rough day"}' -H 'Content-Type: application/json'. - 8Put the resulting base URL in your app's config (below) — this value is not secret.
enum AppConfig {
// The proxy base URL is safe to ship — it contains no secret.
static let apiBase = URL(string: "https://dayone-proxy.vercel.app/api")!
}Because the proxy is yours, put limits there: cap request body length, and reject bursts from a single client. Ask your assistant to "add a simple in-memory rate limiter and a 16KB body cap to this serverless function." (Keep the proxy cap comfortably above the app's own entry-length limit — the ~4,000-character cap from the Module 5 lab is well under 16KB even after JSON-escaping and emoji.) It protects your wallet regardless of app bugs.