External API responses use schema allowlists, not blocklist sanitization
Declare a response schema per integration and parse at the client boundary — never strip unknown fields with a deny list.
integrations-third-party-response-schema-required
Why it matters
| Stake | If ignored |
|---|---|
| Data leak |
|
| Unclear failure |
|
| API drift |
|
How to fix
Each client exports a ResponseSchema (Zod or JSON Schema) per operation. Parse at the boundary: ResponseSchema.parse(raw). Persist and return only validated objects. No INTERNAL_KEYS, no destructuring { vendorMeta, ...safe }. Code blocks below are illustrative, not prescriptive.
Examples
ts
const INTERNAL_KEYS = ['_links', '_meta', 'providerTraceId'];
export function sanitizeVendorPayload(raw: unknown) {
return stripKeys(raw, INTERNAL_KEYS);
}
await repo.save({ payload: vendorResponse });ts
export const ChargeSchema = z.object({
id: z.string(),
amount: z.number(),
currency: z.string().length(3),
});
async getCharge(id: string): Promise<Charge> {
const raw = await this.http.get(`/charges/${id}`);
return ChargeSchema.parse(raw);
}