Pepe Node Journey III: API Design for Humans and Machines

API design cover

APIs are conversations. The best ones are polite, predictable, and clear even when something goes wrong. Designing for both humans and machines means naming with intention, shaping responses that minimize guesswork, and managing change with care.

Favor nouns and relationships. Endpoints like /customers/{id}/invoices describe the world. Verbs still matter: POST creates, GET reads, PATCH updates, DELETE removes. Consistency is a feature: if GET returns a resource, PATCH should accept a subset of the same shape.

Return envelopes that help. A top-level data field for the resource, an errors array when things go wrong, and a meta object for paging and totals provide a stable backbone. Include a requestId and timestamp so operators can trace a single call through logs.

Errors are opportunities to teach. Use machine-friendly codes and human-friendly messages. Include a doc link for complex cases and tell the client what to try next. Most important: never reveal secrets or internal stack traces in production; keep those for logs with redaction.

Versioning is about safety. Prefer additive changes within a major version, and when you must break, communicate early, ship an overlap period, and provide upgrade guides. Keep two adjacent versions live during migration and mirror traffic to validate behavior before flipping defaults.

Pagination and filtering deserve a plan. Cursor-based pagination avoids missing items during rapid updates. Filters should be explicit and validated. When in doubt, sort by a stable key and document the guarantees clearly.

Finally, make your API feel alive. Provide a /status that lists dependent systems and a semver for your contract. Publish changelogs that read like a story, not a diff. Good APIs save time twice: once for consumers and again for the teams that operate them.