API errors & retries
Set up interfaces and contracts
Types and env contracts make **resilient TypeScript fetch wrapper around POST /v1/chat** fail closed before any provider or cluster call.
1Learn the idea
Read
Define trusted borders
Implement types or schemas around POST /v1/chat so illegal states are unrepresentable at the boundary. For resilient TypeScript fetch wrapper around POST /v1/chat, trusted inputs come from sessions, signatures, pinned digests, or workload identity — not from free-form model text. mobile client waiting on a grounded answer should be able to read the contract and know which fields are optional, which are enumerated, and which abort the request. Constructors and boot paths must not perform provider side effects; injection points keep tests honest.
Read
Environment and secrets contract
Document required env vars in .env.example with placeholders only. Rotation story belongs later, but the contract already forbids printing secrets and forbids defaulting to fail-open when a dependency is missing. Invariant to encode in types/tests: attempts ≤ 3, wall budget ≤ 8s, non-idempotent POSTs never replay without Idempotency-Key. If a config number lacks units, fix the name (timeout_ms, rpm_hard) before writing logic.
Read
Implementation artifact
export type ApiOk<T> = { ok: true; data: T; attempts: number; latencyMs: number };
export type ApiFail = {
ok: false; code: "timeout" | "http" | "auth" | "invalid_json" | "budget";
status?: number; attempts: number; retryAfterMs?: number;
};
export type FetchResult<T> = ApiOk<T> | ApiFail;
Read
Fixture kit
Create fixtures for the golden path and for INC-429-2026-07-11. Name files after the behavior (429-retry-after.json, cross-tenant.json, empty-citation.json) rather than test1. Each fixture carries expected status/code. This kit is the shared language for validation and failure pages.
Read
Stage depth
Compatibility promise: additive fields may appear only if readers ignore unknowns safely; breaking changes bump a version visible on the wire. For AI payloads, size limits arrive before JSON parse when hostile blobs are a risk. Document how clock skew, idempotency keys, and tracing headers travel through resilient TypeScript fetch wrapper around POST /v1/chat. If you use feature flags later, the contract already states that flags are not authorization. Link each config knob to a unit and a failure mode (“0 means disabled” vs “0 means divide-by-zero”). A peer reviewing the PR should find INC-429-2026-07-11 named in a comment on the adversarial fixture.
Read
Field notes for `api-error-handling` / `setup-and-contract`
Generate OpenAPI or a typed client only after the hand schema is stable for one fixture round-trip. Record how errors look on the wire — problem+json, envelope, or bare status — and stick to one. Clock sources must be injectable for skew tests. If webhooks appear later, document signature header names now even as TODOs. Keep sample payloads UTF-8 and free of real emails. Add a makefile or npm script that validates schemas without network. In this chapter the product is resilient TypeScript fetch wrapper around POST /v1/chat, the human stakeholder is mobile client waiting on a grounded answer, and the incident id you design against is INC-429-2026-07-11. Re-state the oracle in your notes — 429 + Retry-After:2 → sleep once → 200 with attempts=2 — and keep the invariant visible: attempts ≤ 3, wall budget ≤ 8s, non-idempotent POSTs never replay without Idempotency-Key. Track retry_attempts_total{outcome} and p95 wall_ms ≤ 8000 as the scoreboard. Surface under change control: POST /v1/chat. If you only have forty minutes, finish the fixture for 429 storm with missing Retry-After that would amplify to 40 calls before polishing UI. Promotion language stays ternary: promote, hold, or roll back based on evidence, not hope.
Go deeper
Before you start
Why this matters
For API errors & retries, sketch the request and response shapes that cross POST /v1/chat without naming a framework. Mark which fields are trusted (session, signatures, digests) versus untrusted (user text, model JSON, webhook bodies). If a field can change authorization, it does not belong in model output. Predict one 422/401 you will assert before coding adapters for resilient TypeScript fetch wrapper around POST /v1/chat.
In the wild
See how this idea shows up as a product and a company — then come back to the lesson. Skills transfer across vendors.
Related lessons
Check your understanding
Page assessment
Answer from memory. Completion is saved from this evidence, not from opening the next page.
All responses are required.