Every API begins with a question: what problem does this solve? Before writing a single line of code, you need to understand your consumers, your data model, and your constraints.
The API Contract
An API is a contract between your service and its consumers. Like any good contract, it should be:
- Clear — endpoints should be self-documenting
- Consistent — patterns should repeat predictably
- Stable — changes should never break existing consumers
Your First Endpoint
Let’s start with a simple resource. Here’s a basic articles API in Ruby:
class ArticlesController < ApplicationController
def index
articles = Article.published.recent
render json: articles, status: :ok
end
def show
article = Article.find(params[:id])
render json: article, status: :ok
rescue ActiveRecord::RecordNotFound
render json: { error: "Article not found" }, status: :not_found
end
end
Notice the pattern: resource-oriented, HTTP-status-aware, and error-handling built in from the start.
Key Principles
- Resources, not actions — Think
/articles, not/getArticles - HTTP verbs matter — GET reads, POST creates, PUT/PATCH updates, DELETE removes
- Status codes are communication — 200, 201, 404, 422 each tell a different story
The best APIs feel like they were inevitable — as if no other design could have existed.
In the next chapter, we’ll dive into the design principles that make this possible.