Shipping and specialties
API design as UX
Resource names, errors, versioning and webhooks are the interface. Prefer additive compatibility.
Resource names, error shapes and pagination are interface design, not style trivia. The Google API Design Guide and Stripe's public API are worth studying as products. Low-level resource design also lives in API design; here the question is how those choices feel to a tired integrator.
Concept
Developer experience is the whole path. API shape is the part they live in after the first call: can they predict the next endpoint, debug a failure, and bet their business on your versioning promise?
Practices that change adoption
- Predictable resources — nouns users already know (
Customer,PaymentIntent), consistent list/get/create patterns. - Actionable errors —
error.code, human message, docs URL, request id. "Card declined" with a next step beats HTTP 400 with a stack trace fragment. - Idempotency keys for money-moving or side-effecting POSTs (idempotency).
- Test mode that mirrors production shapes so code does not fork.
- Versioning policy stated in one page: additive changes are safe; breaking changes require a version bump and a deprecation window.
Trade-off
Strict backwards compatibility (Stripe-style additive evolution) maximizes trust and long-lived integrations, at the cost of carrying legacy fields and slower cleanup. Aggressive versioning keeps the surface clean but taxes every integrator and your own DevRel. Default to compatibility for anything customers run in production; break only with multi-month notice and migration tooling.
Deprecation is a launch in reverse (launching): announce date, migration guide, dual-run period, then cut. Silent breaks are how platforms lose the trust that took years to build.
Walking through a rename
You want to rename amount_cents to amount with a currency field. Breaking change for every client.
Compatible approach: add amount + currency, keep amount_cents populated, document both, set a removal date 12 months out, emit a dashboard warning when old fields are the only ones sent, then remove. Integrators migrate on their roadmap. Your API stays boring — which is a compliment.
Webhooks are another interface
Many API products are incomplete without webhooks (or equivalent event streams). From a DX view, webhooks need signing secrets, retry semantics, delivery logs, and a CLI that can forward events to localhost. If developers cannot debug "why didn't my endpoint get invoice.paid?", they will not trust you with production money. Request logs for outbound deliveries belong next to inbound API logs in the dashboard.
Common mistakes
- HTTP 400 with a stack fragment. Errors need a code, a human message, a docs URL and a request id.
- Silent breaking changes. Deprecate like a launch: date, guide, dual-run, then cut.
- Webhooks with no delivery log. Debugging becomes a support ticket at 2 a.m.
Check yourself
Rename amount_cents to amount. Ship a breaking version next week?
No. Add the new fields, keep the old ones populated, warn in the dashboard, remove in 12 months.
Integrators cannot tell why invoice.paid never arrived. What is missing?
Delivery logs, retries you can see, and a way to forward events to localhost.
Key takeaways
- API shape, errors, versioning and deprecation are UX.
- Prefer additive compatibility for production APIs; deprecation is a launch in reverse.
- Webhooks need the same inspectability as inbound calls.
Further learning
Google Cloud API Design GuideA set of guidelines for designing APIs that are consistent with Google AIPs.Google Cloud DocumentationNext: SDKs and quickstarts.
Related
Developer experience
Developers adopt a path from curiosity to production, measured in time-to-first-call, not endpoint count.
Developer and API products
Treating APIs, SDKs and docs as products: developer experience and adoption.
API design
An API is a contract that outlives the code behind it. Design the styles, methods, pagination, errors and async flows so changes stay additive.