Every time you check your bank balance from your phone, pay by card in an online shop or sign in to a service with your Google account, there is an API working underneath. APIs are the connective tissue of modern software: the standard way one program asks another program for something without needing to know how it is built inside. This first lesson defines exactly what an API is, what problem it solves, what types exist and why it is called a "contract". It also introduces Aroma Store, the speciality coffee shop that will accompany us throughout the course, and closes with a first real example of a request and a response that we will pick apart in the lessons that follow.
Contents
- The core idea: interfaces that hide complexity
- The problem an API solves
- The API as a contract between provider and consumer
- Everyday examples: payment gateways, maps and social login
- Types of API by scope
- What a web API is and the client-server model
- Who consumes an API
- Public, partner and internal APIs
- The scenario for this course: Aroma Store
- First end-to-end example:
GET /v1/coffees
- The core idea: interfaces that hide complexity
API stands for Application Programming Interface. Let's break the term down:
- Interface: a defined point of contact between two parties. A plug socket is the interface between an appliance and the electricity grid.
- Programming: this interface is not used by a person with a mouse, it is used by another program writing code.
- Application: both parties are pieces of software.
An API is therefore the set of operations that one piece of software offers to another, described in a way that lets them be invoked from code. The essential part is what the API does not show: whoever uses it does not know (and does not need to know) what language it is written in, what database sits behind it or how many servers handle it.
Think of the interface of a car: steering wheel, pedals and gear stick. That is the car's "API". You can drive a petrol car and an electric one with the same interface, even though internally they are radically different. If the manufacturer changes the engine tomorrow, you still know how to drive. That decoupling between what is offered and how it is implemented is the heart of the idea.
- The problem an API solves
Imagine Aroma Store wants to show its coffee catalogue in three places: the desktop website, a mobile app and a touchscreen in its physical shop. Without an API, each of those three programs would have to:
- Connect directly to the database.
- Know the table and column names.
- Repeat the business rules (is a coffee that is out of stock shown or not? how is the price with VAT calculated?).
The consequences are predictable: duplicated rules that drift out of sync, database credentials scattered everywhere and the impossibility of changing the schema without breaking three applications at once.
With an API, that logic lives in a single place and the three clients ask for the same thing: "give me the available coffees". The specific problems it solves are:
| Problem without an API | How the API solves it |
|---|---|
| Business logic duplicated in every client | It is centralised on the server, behind the interface |
| Every client needs database access | Only the server has access; clients speak HTTP |
| Changing the implementation breaks everyone | The interface stays stable even when the internals change |
| Integrating a third party means giving them internal access | They get a bounded interface with permissions |
| Every team reinvents the exchange format | A common format is agreed (usually JSON) |
- The API as a contract between provider and consumer
The most useful metaphor for understanding an API is that of a contract. There are two parties:
- The provider (or producer): whoever publishes and maintains the API. In our case, the Aroma Store backend team.
- The consumer (or client): whoever calls it. The mobile app, the website, an external partner.
The contract specifies, as a minimum:
- What operations exist and how they are invoked (addresses, verbs, parameters).
- What data must be sent, in what format and with what constraints.
- What is returned on success: structure, types, units.
- What happens when something fails: how an error is signalled and what information is given.
- What guarantees exist: availability, usage limits, change policy.
And like any contract, it has an uncomfortable consequence: once published, you cannot break it unilaterally. If Aroma Store renames the priceEuros field to price today, the mobile app used by thousands of people will stop showing prices this very afternoon. This idea — that an API is a long-term promise — explains a large part of the design decisions we will see in module 2, and it is the reason versioning exists (lesson 02-07).
Early tip: design on the assumption that the contract will last for years and that you do not control who consumes it. It is a shift in mindset compared with writing internal code you can refactor whenever you like.
- Everyday examples: payment gateways, maps and social login
APIs are easier to understand through cases you have already used as a user:
- Payment gateway: Aroma Store does not store card numbers or talk to banks. It sends the gateway's API the amount and an order reference, and receives a confirmation. The brutal complexity of the payment system stays behind an operation with a couple of fields. It also avoids enormous regulatory responsibilities.
- Maps: to show where the physical coffee shop is, the website asks a maps API for a map centred on some coordinates. Nobody at Aroma Store draws streets.
- Social login ("Sign in with Google"): the shop does not manage passwords; it delegates authentication to an identity provider and receives confirmation of who the user is. We will see the real mechanism (OAuth 2.0 and OpenID Connect) in lesson 04-03.
- Shipping: when an order is marked as paid, Aroma Store calls the API of its courier company, SwiftShip, to generate the label and obtain a tracking number.
The pattern repeats itself: do not build what you can consume; do not keep inside what you can offer outside.
- Types of API by scope
Not every API travels over the network. It is worth distinguishing three scopes, because the term is used for all three:
| Scope | What it is | How it is invoked | Example |
|---|---|---|---|
| Library or language | Public functions and classes of a library | Function call within the same process | Array.prototype.map() in JavaScript, fetch() |
| Operating system | Services the OS offers to programs | System calls | Opening a file, requesting the camera on Android |
| Web (or remote) | Services of another program across the network | HTTP request to an address | GET https://api.aromastore.example/v1/coffees |
Here is an example of a library API you already know:
// The public API of a JavaScript array includes map(), filter(), etc.
// You know WHAT filter() does and what it returns, but not how it is
// implemented internally in the V8 engine. That is exactly an API.
const coffees = [
{ name: 'Ethiopia Yirgacheffe', stock: 120 },
{ name: 'Colombia Huila', stock: 0 }
];
const available = coffees.filter((coffee) => coffee.stock > 0);
console.log(available.length); // 1All three share the same philosophy, but web APIs have one crucial difference: the call crosses the network. That introduces latency, connection failures, security, access control and versions that coexist. This course deals exclusively with web APIs and, within them, with the REST style.
- What a web API is and the client-server model
A web API is an API accessed through the HTTP protocol at a network address. It works under the client-server model:
- The client takes the initiative: it sends a request.
- The server listens, processes and returns a response.
- The conversation is always started by the client (webhooks, in 01-07, reverse that direction).
sequenceDiagram
participant C as Client<br/>(mobile app)
participant A as Aroma Store API
participant DB as Database
C->>A: GET /v1/coffees (HTTP request)
A->>DB: Query available coffees
DB-->>A: Table rows
A-->>C: 200 OK + JSON (HTTP response)
Note two important details in the diagram:
- The client never talks to the database. It only knows the API's address.
- What the API returns is not "rows from a table" but a representation in JSON designed to be consumed. This distinction between the internal data and its representation is central to REST and we will develop it in lesson 01-04.
- Who consumes an API
Knowing who is on the other side changes the design. The typical consumers of the Aroma Store API are:
- Single-page web application (SPA): the online shop. It runs in the browser and requests data with JavaScript. It is sensitive to the number of requests and to browser security policies (CORS, lesson 04-05).
- Native mobile application: Aroma Mobile, for iOS and Android. A critical quirk: the user decides when to update, so old versions will keep calling your API for months.
- Another backend service: the invoicing service asks the API for the month's orders. This is internal traffic, with different performance requirements.
- Third-party integrations: SwiftShip checks which orders are awaiting collection; an accounting tool exports sales.
- Tools and scripts:
curl, Postman (lesson 05-01), maintenance scripts written by the team itself.
- Public, partner and internal APIs
Depending on who the door is opened to, three categories are distinguished. It is a business decision with enormous technical implications:
| Type | Who has access | Control over the consumer | Implications |
|---|---|---|---|
| Public (open) | Anyone who registers | None | Impeccable documentation, strict versioning, usage limits, you cannot break anything |
| Partner | Companies with a prior agreement | Contractual | Credentials per partner, negotiated terms and pace of change |
| Internal (private) | Teams within the company itself | Total | It can evolve quickly, but it still needs security |
A frequent mistake is treating the internal API as if it needed no discipline. As the company grows, the internal API ends up with ten consumers you do not control day to day, and the lack of a contract is paid for dearly.
- The scenario for this course: Aroma Store
From here on, everything we learn will be applied to a single case, so that the concepts do not stay abstract.
Aroma Store is an online speciality coffee shop. It sells single-origin coffees, its own roasts and monthly subscriptions. Its technical reality is:
- A web shop built as an SPA.
- A mobile app, Aroma Mobile, which customers use to reorder.
- An internal admin panel used by the warehouse and customer service teams.
- An integration with SwiftShip, the courier company that delivers the orders.
Its resources (the "things" the business handles) are five, and they will be the same throughout the course:
| Resource | What it represents | Base address |
|---|---|---|
| Coffees / products | The catalogue on sale | /v1/coffees |
| Customers | Who buys | /v1/customers |
| Orders | A confirmed purchase | /v1/orders |
| Reviews | Customer ratings of a coffee | /v1/reviews |
| Carts | A purchase in progress, not yet confirmed | /v1/carts |
The API lives at https://api.aromastore.example/v1 and is in fact two APIs sharing the same business domain: a public one (catalogue and reviews, so that blogs and price comparison sites can show its coffees) and an internal one (orders, stock, customers) used by the admin panel and by SwiftShip as a partner.
From module 3 onwards we will implement it with Node.js 20 and Express, writing clear, descriptive identifiers (getCoffees, createOrder, priceEuros) so that the code is easy to read.
- First end-to-end example:
GET /v1/coffees
GET /v1/coffeesLet's see the simplest possible API in action: asking for the catalogue. We will use curl, a command-line tool that sends HTTP requests and displays the response. It is available on Linux, macOS and Windows 10 or later.
That line contains three things: the program (curl), and an address that in turn indicates where the API is (api.aromastore.example), that we are talking over an encrypted channel (https) and what we are asking for (/v1/coffees, the list of coffees from version 1 of the API). Since nothing else is specified, curl uses the GET method, which means "give me this without modifying anything".
The response the server returns:
{
"data": [
{
"id": "cof_001",
"name": "Ethiopia Yirgacheffe",
"origin": "Ethiopia",
"roast": "light",
"priceEuros": 14.50,
"stock": 120
},
{
"id": "cof_002",
"name": "Colombia Huila",
"origin": "Colombia",
"roast": "medium",
"priceEuros": 12.90,
"stock": 80
}
],
"total": 2
}Let's analyse the response piece by piece, without going into protocol detail just yet:
- It is in JSON (JavaScript Object Notation), today's dominant exchange format. The
{}delimit objects withkey: valuepairs, and the[]delimit lists. - The
datakey holds the list of coffees. Wrapping the list inside an object (rather than returning the array directly) leaves room to add metadata such astotalwithout breaking the contract. - Each coffee has a stable
id(cof_001). That identifier is what later allows a specific coffee to be requested:GET /v1/coffees/cof_001. priceEurosmakes the unit explicit in the field name. A field called merelypriceforces you to read the documentation to find out whether it is euros or cents: a classic source of bugs.roastuses a value from a closed, known set (light,medium,dark).
If instead of the list we want one specific coffee, we change the address:
{
"id": "cof_001",
"name": "Ethiopia Yirgacheffe",
"origin": "Ethiopia",
"roast": "light",
"priceEuros": 14.50,
"stock": 120,
"tastingNotes": ["jasmine", "bergamot", "peach"]
}Notice one detail that is anything but accidental: the address of the individual resource is the collection's address plus its identifier. That regularity, which now looks like a minor point, is one of the hallmarks of REST and we will formalise it in lesson 01-04.
Everything that happens underneath (headers, status codes, methods) we will see in lesson 01-03, devoted to HTTP. For now, hold on to the whole picture: a client asks an address for something and a server responds with a representation in JSON.
Common Mistakes and Tips
- Confusing the API with the database. The API is not a window onto the tables: it is a business interface. Exposing the internal schema as-is ties you to that schema forever.
- Confusing the API with the web application. The website is one consumer. If you design the API thinking only about the screen you are building today, the mobile app that arrives tomorrow will not fit.
- Believing that "API" always means "web API". In a job advert or a conversation, it is worth being precise about which scope is being discussed (library, operating system or network).
- Forgetting that the contract is a promise. Before publishing a field name, think about whether you will want to keep it two years from now.
- Not naming the units.
priceEuros,weightGramsordurationSecondssave real incidents in production. - Tip: when you start designing, write an example request and JSON response first, like the one in this lesson, before writing a single line of server code. That is the essence of the API-first approach we will see in 01-02 and 05-02.
Exercises
Exercise 1: identify the contract
Aroma Store wants an external coffee blog to display its three best-selling coffees on its website. List at least five elements that the contract for that API should specify so that the blog can integrate without having to ask anything by email.
Exercise 2: classify consumers and API type
For each situation, state who the consumer is and whether the API involved should be public, partner or internal, justifying it briefly:
- The admin panel marks an order as shipped.
- A price comparison site displays the Aroma Store catalogue.
- SwiftShip checks every 10 minutes which orders are awaiting collection.
- Aroma Mobile shows the order history of the signed-in user.
Exercise 3: design a first response
Design the JSON that GET /v1/coffees/cof_002/reviews (the reviews of a coffee) would return. It must include at least two reviews, with an identifier, author, rating from 1 to 5, comment and date. Apply what you have learned about field names, units and wrapping the list.
Solutions
Solution 1
A minimally usable contract should specify:
- The exact address of the operation, for example
GET https://api.aromastore.example/v1/coffees?sort=bestSelling&limit=3. - How the blog authenticates: whether it needs an API key and how it is sent.
- The structure of the response: which fields come back, of what type and which may be absent (
nametext,priceEurosdecimal number,stockinteger). - The behaviour on errors: what is returned if the key is invalid or the service is unavailable, and how to tell that apart from a correct but empty response.
- The usage limits: how many requests per minute are allowed and what happens when they are exceeded.
Equally valid additional elements: the versioning policy and notice of changes, terms of use for the data and images, and a support contact.
Solution 2
- Admin panel → internal API. It modifies the state of the business and is used only by company staff.
- Price comparison site → public API. It only reads the catalogue, which is not sensitive information; commercially it is in the shop's interest for it to spread.
- SwiftShip → partner API. It is a specific external company with a prior agreement, with its own credentials and limited access to the orders that concern it.
- Aroma Mobile → internal API (even though it is reachable from the internet). It is an in-house client accessing personal data; it requires user authentication and must return only that user's orders.
Note the nuance in case 4: "internal" refers to who controls it and who it is designed for, not to whether it can be reached over the network.
Solution 3
{
"data": [
{
"id": "rev_101",
"coffeeId": "cof_002",
"author": "Marta G.",
"rating": 5,
"comment": "Balanced and sweet, perfect for filter in the morning.",
"date": "2026-07-14"
},
{
"id": "rev_102",
"coffeeId": "cof_002",
"author": "Luis P.",
"rating": 4,
"comment": "Very decent, though I expected more acidity.",
"date": "2026-07-28"
}
],
"total": 2
}Decisions worth highlighting: the list is wrapped in data so that metadata can be added; each review carries coffeeId so that it is self-explanatory even when copied out of context; rating is an integer rather than text; and the date uses the ISO format YYYY-MM-DD, which is unambiguous internationally (unlike 14/07/2026, which an American consumer might misread).
Conclusion
An API is an interface that lets one program use another's services without knowing its internals, and its value lies as much in what it exposes as in what it hides. We have seen that it works as a contract between provider and consumer, that there are library, operating system and web APIs, and that the latter follow the client-server model over HTTP. We have also classified APIs as public, partner and internal, and we have met Aroma Store, whose five resources — coffees, customers, orders, reviews and carts — will serve as our laboratory until the end of the course. That first GET /v1/coffees has already shown us the fundamental pattern: a request to an address, a response in JSON.
Before getting into how these interfaces are designed, it is worth understanding where they come from. In the next lesson, History and Evolution of APIs, we will trace the path from remote procedure calls to today's API economy, in order to understand why REST prevailed and what practical lessons that history leaves for anyone designing an API today.
REST API Course: Principles of Designing and Developing RESTful APIs
Module 1: Introduction to RESTful APIs
- What Is an API?
- History and Evolution of APIs
- HTTP Fundamentals for APIs
- Basic Principles of REST
- The Richardson Maturity Model and HATEOAS
- REST vs. SOAP
- REST Compared with GraphQL, gRPC and Webhooks
Module 2: Designing RESTful APIs
- RESTful API Design Principles
- Resources and URIs
- HTTP Methods
- HTTP Status Codes
- Representations, Headers and Content Negotiation
- Filtering, Sorting, Pagination and Search
- API Versioning
- API Documentation
Module 3: Building RESTful APIs
- Setting Up the Development Environment
- Building a Basic Server
- Handling Requests and Responses
- Input Data Validation
- Persistence and the Data Access Layer
- Authentication and Authorisation
- Error Handling
- Testing and Validation
Module 4: Best Practices and Security
- API Design Best Practices
- Security in RESTful APIs
- OAuth 2.0 and OpenID Connect in Practice
- Rate Limiting and Throttling
- CORS and Security Policies
- HTTP Caching and Performance
- Observability: Logs, Metrics and Traces
Module 5: Tools and Frameworks
- Postman for API Testing
- Swagger and OpenAPI for Documentation
- Popular Frameworks for RESTful APIs
- Contracts, Mocks and Automated API Testing
- Continuous Integration and Deployment
- API Gateways and Developer Portals
