The early issues are rarely dramatic. A field name stops making sense. One endpoint takes on too many responsibilities. Edge-case states start leaking through because the model underneath was never clearly defined.
Clarity buys flexibility
The best API designs are not the most abstract. They are the most legible. Clear contracts, predictable response shapes, and properly modelled state make change easier later.
type ApiResult<T> =
| { ok: true; data: T }
| { ok: false; error: { code: string; message: string } };