Programming and IT
What is an API
An API is an agreed way for one program to ask another for something. No screens and no buttons — the request travels as text over the network, and the answer comes back in a machine-readable form. Once you understand the four parts of an HTTP request, you can read the documentation of any service.
In this article
A contract between programs#
An Application Programming Interface is a list of operations one program has agreed to perform at another's request, together with the rules: how to phrase the request, what comes back and what counts as an error.
A service counter works better as a comparison than the usual waiter metaphor. You do not walk into the warehouse or dig through the service's database — you hand a form of a set shape through the window and get an answer of a set shape back. What happens inside is none of your business; what matters is that the form does not change without warning.
That is where the main benefit comes from. A weather site does not measure the temperature itself — it asks a meteorological service. A shop does not calculate shipping costs — it asks the carrier. A banking app does not store a map of the city — it takes one from a mapping service. Everyone does their own job, and they exchange data through a documented interface.
The word "API" is used more broadly than networks: a library inside a programming language also has an API — the set of its functions. But when a job ad or an article says "working with APIs" with no further detail, it almost always means a web interface over HTTP. That is what the rest of this page is about.
What a request is made of#
An HTTP request has four parts.
- Method — what exactly you want to do.
- URL — what to do it to:
https://api.example.com/users/42. - Headers — service notes: data format, access key, language.
- Body — the data itself; read requests do not have one.
The response mirrors it: a status code, headers and a body.
URLs in a well-designed service follow one scheme: a plural noun is a collection,
and an identifier after a slash is a single object. /orders — all orders,
/orders/1207 — one order, /orders/1207/items — what is in it.
Methods#
| Method | Meaning | Changes data |
|---|---|---|
GET |
get an object or a list | no |
POST |
create a new object | yes |
PUT |
replace an object entirely | yes |
PATCH |
change some of the fields | yes |
DELETE |
delete an object | yes |
GET is called a safe method: by the standard it must not change anything on the
server, so browsers and intermediate nodes repeat and cache it freely. PUT and
DELETE are idempotent — ten identical calls have the same result as one. POST,
however, is not idempotent: two clicks on "pay" create two payments, and protecting
against that is the developer's job.
Status codes#
The first digit of a code sets its whole meaning: 2 — it worked, 3 — look elsewhere, 4 — the error is on the side of whoever asked, 5 — something broke on the server.
| Code | Meaning | What to do |
|---|---|---|
| 200 | OK, the answer is in the body | read the data |
| 201 | object created | take the address of the new object |
| 204 | done, no body | nothing to parse |
| 301, 302 | the address has moved | follow the address in the Location header |
| 400 | the request is malformed | look for a typo in the body or parameters |
| 401 | you did not identify yourself | send a key or token |
| 403 | identified, but no permission | check the account's permissions |
| 404 | no such object | check the URL and the identifier |
| 409 | conflict with the current state | re-read the object and retry |
| 422 | the data fails validation | read the error text in the body |
| 429 | too many requests | wait and slow down |
| 500 | the server failed | retry later; if it repeats, contact support |
| 502, 503 | the service is unavailable | retry with increasing pauses |
401 and 403 are the pair people confuse most. 401 means "I do not know who you are" — the key header is missing, expired or wrong. 403 means "I know who you are, and you are not allowed here": swapping in another key is pointless; you need permissions.
JSON#
Data is almost always sent as JSON — a text format that humans and machines read equally well.
There are only a few rules: keys are always in double quotes, so are strings;
numbers and true, false, null go without quotes; a comma after the last
element is forbidden. Nesting is unlimited: a value can be an object or an array.
The most common beginner mistake is single quotes: {'id': 1207} is not JSON, it is
Python syntax. The second is a trailing comma before the closing bracket. The server
answers both with a 400.
The Content-Type: application/json header tells the server that the body really is
JSON. Without it, many services try to read the body as form data and refuse.
API keys#
Few public interfaces work without identification. Usually the service issues a key, and you attach it to every request.
- A token in a header — the common option:
Authorization: Bearer TOKEN. - A key in a separate header — for example
X-Api-Key: TOKEN. - A key as a URL parameter — found in older services; a bad approach: the whole URL ends up in server logs and browser history.
Three rules for handling a key: do not commit it to a repository (environment variables and a file listed in .gitignore exist for that), do not expose it on a page the browser can see, and reissue it at the slightest suspicion. A leaked key means other people's requests in your name, and you paying for them.
Rate limits are a separate matter: a service allows, say, sixty requests a minute and answers 429 beyond that. The right reaction is exponential backoff: wait a second, then two, then four.
Your first request with curl#
curl is available on almost every system and does exactly what the command line
says — which makes it handy for checking documentation before you write any code.
The simplest call is a read. The first line prints the response body, the second adds the status line and headers, and the third follows redirects and saves the result to a file:
Creating an object needs three additions: a method, a header with the data type and a body.
-d on its own switches the method to POST, so you can drop -X POST next to it.
Long JSON is awkward in a terminal — put it in a file and refer to it:
-d @body.json.
The key goes in a header, and the value itself comes from an environment variable so it does not end up in your shell history:
To inspect a response, pipe it through a formatter: curl … | jq . adds colour and
indentation. Other tricks for working with terminal output are in the
Linux commands cheat sheet.
How to read someone else's documentation#
The reading order is always the same. First the section on authentication: where to get a key and which header carries it. Then the base URL that paths are appended to. Then the one specific operation you need: method, path, required parameters, an example response. Only after that everything else.
Good documentation gives a ready-made curl line for each operation — start with
that and put in your key. If there is none, build it yourself from the parameter
table: a call that works in the terminal saves you guessing why your code does not.
It helps to know two related description formats. OpenAPI is a machine-readable description of an interface, from which documentation pages and client libraries in different languages are generated. GraphQL is a different approach: there is one URL, and the client describes in the request body exactly what to return.
Common mistakes#
A forgotten content-type header. The body is JSON, but the server does not know that: the answer is 400 or 415.
A trailing slash in the path. For some services /users and /users/ are
different addresses; one answers, the other redirects or returns 404.
Parsing the response without checking the code. The program reads the body without looking at the status code and crashes trying to parse an error page. Code first, data second.
A key in the source code. Check the repository history before the first publication: removing it from the current version is not enough.
A practice service you can send any request to without worry is easiest to run in a container — how that works is described in what is Docker.
Step-by-step plan
- Read a response by handMake a GET request to a public service with curl -i and name all four parts of the response.
- Pick apart the JSONTake a response and extract three fields from it, including a nested one and an array element.
- A request with a bodySend a POST with a Content-Type header and a JSON body, and compare the status code with the documentation.
- AuthenticationGet a key from any free service, send it in a header and confirm that without the key you get 401.
- Error handlingWrite a program that checks the status code and retries with a pause on 429 and 503.
Start learning this in your own space
The plan goes into your repository: tick off stages, keep notes — the change history shows how far you have come.
Check yourself
1.Which HTTP status code means “object not found”?
2.Which status code does the server return when an object has been created successfully?
3.Which HTTP method must not change data on the server according to the standard?
4.What does status code 401 mean?
Sources
-
HTTP on MDNMethods, status codes and headers, each one explainedfree
-
OpenAPI SpecificationThe standard for describing interfaces that many services' documentation is built onfree
-
curl documentationThe primary source on command-line optionsfree
Was this helpful?