Build the mental model
Every skill from this chapter serves one goal: integrating a third-party API safely. The default architecture is layered: frontend talks to your backend, your backend talks to the third-party API, and your backend validates the response before it ever reaches the frontend.
That layering exists for a reason: a secret API key embedded in frontend code is visible to anyone who opens developer tools — it isn't secret at all. Routing through your backend keeps the credential server-side, where a browser can't read it.
| Direct frontend call | OK, or not? |
|---|---|
| Public API, no secret needed | OK — nothing sensitive is exposed. |
| Client-side key made for browsers, CORS supported | OK — the provider designed it for this. |
| Secret key, privileged operation, sensitive logic | Not OK — route it through your backend. |
Knowing the architecture is half the job; executing it safely is a workflow — from reading docs and storing credentials safely, through testing, validating, and handling errors, to logging and monitoring.
LAYERED INTEGRATION ARCHITECTURE
--------------------------------
FRONTEND --request--> YOUR BACKEND --request--> 3RD-PARTY API
|
FRONTEND <--result---- YOUR BACKEND <--response-------+
(validates before trusting it)
Secrets and privileged logic live only in YOUR BACKEND, never
in code the browser can read.Connect it to a real scenario
Say you're integrating a payments provider. The workflow starts before any code: read the docs, then create API credentials in the provider's dashboard and store them as environment variables — never in frontend code or a Git commit.
1. Read the docs
Use the reading order from this chapter to know exactly what you're calling before writing anything.
2. Create credentials
Generate API keys or tokens in the provider's dashboard.
3. Store them safely
Environment variables on the server, never in frontend code or committed to Git.
4. Test manually first
A Postman request against a sandbox confirms the basics before any code exists.
5. Build the server integration
Your backend, not the browser, makes the real call.
6. Validate the response
Never trust a third-party response blindly — check its shape and values before acting on it.
7. Handle errors
Different failures need different handling — a declined card differs from a timeout.
8. Handle rate limits
Respect documented limits so a traffic spike doesn't get your account throttled.
9. Log failures safely
Enough detail to debug later, but never the raw secret key itself.
10. Add monitoring
So a silent failure surfaces immediately, not days later from a customer complaint.
Try the working example
// Checks a described integration setup against the key
// requirements of the safe integration workflow, and reports what's
// still missing before it's production-ready.
function checkProductionReadiness(setup) {
const requirements = [
{ key: "credentialsReadFromDocs", label: "Read the docs and know what credentials are needed" },
{ key: "hasCredentialsStored", label: "Credentials stored safely (not in frontend code or Git)" },
{ key: "testedManuallyFirst", label: "Tested the API manually (e.g. in Postman) before coding" },
{ key: "hasServerIntegration", label: "Calls go through your backend, not directly from the browser" },
{ key: "hasResponseValidation", label: "Backend validates the third-party response before trusting it" },
{ key: "hasErrorHandling", label: "Errors from the third-party API are caught and handled" },
{ key: "hasRateLimitHandling", label: "Rate limit responses are detected and handled (e.g. retry/backoff)" },
{ key: "hasLogging", label: "Failures are logged safely, without leaking secrets" },
{ key: "hasMonitoring", label: "Monitoring/alerts exist for ongoing integration health" },
];
const missing = requirements.filter((r) => !setup[r.key]).map((r) => r.label);
return {
total: requirements.length,
met: requirements.length - missing.length,
missing,
productionReady: missing.length === 0,
};
}
const solidSetup = {
credentialsReadFromDocs: true,
hasCredentialsStored: true,
testedManuallyFirst: true,
hasServerIntegration: true,
hasResponseValidation: true,
hasErrorHandling: true,
hasRateLimitHandling: true,
hasLogging: true,
hasMonitoring: false,
};
const riskySetup = {
credentialsReadFromDocs: true,
hasCredentialsStored: false,
testedManuallyFirst: true,
hasServerIntegration: false,
hasResponseValidation: false,
hasErrorHandling: true,
hasRateLimitHandling: false,
hasLogging: false,
hasMonitoring: false,
};
console.log("Solid setup:", checkProductionReadiness(solidSetup));
console.log("Risky setup:", checkProductionReadiness(riskySetup));Actual output when run:
Solid setup: {
total: 9,
met: 8,
missing: [ 'Monitoring/alerts exist for ongoing integration health' ],
productionReady: false
}
Risky setup: {
total: 9,
met: 3,
missing: [
'Credentials stored safely (not in frontend code or Git)',
'Calls go through your backend, not directly from the browser',
'Backend validates the third-party response before trusting it',
'Rate limit responses are detected and handled (e.g. retry/backoff)',
'Failures are logged safely, without leaking secrets',
'Monitoring/alerts exist for ongoing integration health'
],
productionReady: false
}
The solid setup is one missing monitor away from production-ready; the risky setup is missing the two most important protections — server-side routing and response validation — the exact gaps this chapter's architecture is built to close.5-minute try-it
Describe a real or planned integration you know (or invent a plausible one). Fill in a setup object like the ones above honestly, run it through checkProductionReadiness, and write one sentence for each missing requirement explaining exactly what you'd need to build or change to close that gap.
One important caution
Putting a secret API key directly in frontend code because "it's just for one feature" — anyone can read it from the browser regardless of intent.
Trusting a third-party response without validating it — a compromised or buggy provider response can otherwise flow straight into your own system unchecked.
OWASP API Security Top 10 (2023) — API Integration & Webhooks