FR | EN
Talk about your project

Designing HTTP APIs in Rails That Your Frontend Team Will Actually Like

Most API complaints are about inconsistency, not missing features. Consistency is the actual deliverable of API design.

Published February 6, 2022 · 4 min read

Most API complaints from frontend teams aren't about missing features, they're about inconsistency: one endpoint returns dates as ISO strings, another as Unix timestamps, and errors come back in three different shapes depending on which controller raised them. Consistency is the actual deliverable of API design.

Pick an error shape once, apply it everywhere

A single, predictable error format lets a frontend write one error handler instead of one per endpoint.

rescue_from ActiveRecord::RecordInvalid do |e|
  render json: {
    error: { code: "validation_failed", message: e.message, fields: e.record.errors.as_json }
  }, status: :unprocessable_entity
end

Serialize explicitly, don't leak the model

Rendering an ActiveRecord object directly exposes every column, including ones added next quarter for an unrelated reason. A dedicated serializer keeps the response shape a deliberate contract instead of an accident of the schema.

Version from day one, even a monolith's internal API

Adding a version prefix to routes costs nothing when there's a single consumer. Retrofitting it after three external integrations already depend on the unversioned path costs a migration plan and a deprecation window. We add the prefix even on APIs we're certain will only ever have one client, because that certainty is usually wrong within a year.

Pagination and filtering are part of the contract, not an afterthought

An endpoint returning all records "for now" becomes a production incident the day that table crosses a few hundred thousand rows. Cursor-based pagination, documented from the first version, avoids both the performance cliff and the breaking change of adding pagination later to a client that assumed a flat array.

None of this is about following a spec for its own sake. It's about making the API something a frontend team can build against without reading the Rails source to guess what happens next.