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.

Updated
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.

  1. Method — what exactly you want to do.
  2. URL — what to do it to: https://api.example.com/users/42.
  3. Headers — service notes: data format, access key, language.
  4. 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.

{
  "id": 1207,
  "title": "Headphones",
  "price": 49.90,
  "in_stock": true,
  "tags": ["audio", "wireless"],
  "discount": null
}

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:

curl https://api.github.com/repos/torvalds/linux
curl -i https://api.github.com/repos/torvalds/linux
curl -L -o repo.json https://api.github.com/repos/torvalds/linux

Creating an object needs three additions: a method, a header with the data type and a body.

curl -X POST https://api.example.com/users \
     -H "Content-Type: application/json" \
     -d '{"name": "Anna", "email": "anna@example.com"}'

-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:

curl -H "Authorization: Bearer $API_TOKEN" https://api.example.com/me

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

  1. Read a response by handMake a GET request to a public service with curl -i and name all four parts of the response.
  2. Pick apart the JSONTake a response and extract three fields from it, including a nested one and an array element.
  3. A request with a bodySend a POST with a Content-Type header and a JSON body, and compare the status code with the documentation.
  4. AuthenticationGet a key from any free service, send it in a header and confirm that without the key you get 401.
  5. 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.

Start the plan

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

Was this helpful?

More articles

Programming and IT What is Docker Docker packages a program together with everything it needs to run into a single image — and that image starts the same way on a developer's laptop and on a server. Below — what an image is, how it differs from a container, how to write your first Dockerfile and where the technology is overkill. Programming and IT C++ from scratch C++ is a compiled language used wherever speed and direct access to memory matter — game engines, browsers, databases, firmware. It is harder to get into than Python, but you can build your first working program on the very first evening. Programming and IT How to learn Python from scratch Python is a good first programming language: code reads almost like text, and the standard library covers most everyday tasks. This plan takes you from installing the interpreter to your own scripts covered by tests in about four months, at roughly an hour a day. Programming and IT How to learn SQL from scratch SQL is the query language of relational databases. Developers, analysts, testers and managers who want to pull numbers themselves all need it. Basic queries take a few weeks to learn; working confidently with complex reports takes two or three months of practice. Below is the order of topics and ways to train on a real database. Programming and IT How to learn Linux from scratch Linux runs most servers, containers and countless devices, so developers, testers, analysts and system administrators all need the command line. The easiest way to learn it is not by reading lists of commands but by working in the terminal every day and solving small practical tasks. Below is a sequence of topics for two to three months. Programming and IT How to learn Java from scratch Java is a strictly typed language behind banking systems, the servers of large services and Android apps. The strictness slows you down at first, but the compiler catches many mistakes before the program ever runs. This plan takes about six months at an hour a day and leads from your first program to a small backend application.

More solutions