ЁЯПл The SchoolтА║ЁЯПв APIsтА║ЁЯПв рдзрдбрд╛ 01 тАФ APIs рдХрд╛: рдлреНрд░рдВрдЯ рдСрдлрд┐рд╕
ЁЯЦ╝я╕П See the drawing + lab ЁЯПа Course home ЁЯМ┐ Branch on GitHub тЬПя╕П View source
ЁЯЦ╝я╕П рдЖрдХреГрддреА рдЖрдгрд┐ labThe drawing + lab рдкреВрд░реНрдг рдкрд╛рдирд╛рд╡рд░ рдЙрдШрдбрд╛ тЖЧOpen full page тЖЧ

ЁЯПв рдзрдбрд╛ 01 тАФ APIs рдХрд╛: рдлреНрд░рдВрдЯ рдСрдлрд┐рд╕

ЁЯУН рддреБрдореНрд╣реА рдЗрдереЗ рдЖрд╣рд╛рдд: 12 рдкреИрдХреА рдзрдбрд╛ 01 ┬╖ рдкреБрдвреЗ: lesson-02-http-anatomy


ЁЯУж рдпрд╛ рдмреНрд░рдБрдЪрдордзреНрдпреЗ рдХрд╛рдп рдЖрд╣реЗ

APIs рдХреЛрдгрддреА рд╕рдорд╕реНрдпрд╛ рд╕реЛрдбрд╡рдгреНрдпрд╛рд╕рд╛рдареА рдЕрд╕рддрд╛рдд тАФ рдЖрдгрд┐ рддреА рдПрдХ рдХрд▓реНрдкрдирд╛ (counter рд╡рд░рдЪреЗ contract) рдЬреА рдпрд╛ рдХреЛрд░реНрд╕рдордзрд▓реНрдпрд╛ рдкреБрдврдЪреНрдпрд╛ рдкреНрд░рддреНрдпреЗрдХ design рдирд┐рд░реНрдгрдпрд╛рдЪреЗ рдХрд╛рд░рдг рд╕рд╛рдВрдЧрддреЗ. рдкреВрд░реНрдг рдХреЛрд░реНрд╕рднрд░ рддреБрдореНрд╣реА рд╡рд╛рдкрд░рд╛рд▓ рдЕрд╢рд╛ рдЦрд▒реНрдпрд╛ files:

ЁЯОТ рд╕реБрд░реВ рдХрд░рдгреНрдпрд╛рдЖрдзреА: рддреБрдореНрд╣рд╛рд▓рд╛ рдлрдХреНрдд Python 3 рдЖрдгрд┐ curl рд▓рд╛рдЧрддрд╛рдд, рдмрд╛рдХреА рдХрд╛рд╣реА рдирд╛рд╣реА. рд╣реА рд╢рд╛рд│рд╛ рдПрдХ рдЫреЛрдЯреЗ рдЦрд░реЗ API рдЪрд╛рд▓рд╡реВрди рдХрд▓реНрдкрдирд╛ рд╢рд┐рдХрд╡рддреЗ; frameworks (FastAPI, Express, Spring) рддреБрдореНрд╣реА рдЗрдереЗ рд╡рд╛рдЪрдгрд╛рд░ рдЕрд╕рд▓реЗрд▓реЗ рднрд╛рдЧ automate рдХрд░рддрд╛рдд. рдЪрд╛рдВрдЧрд▓реЗ рд╢реЗрдЬрд╛рд░реА: Database school (рдпрд╛ counter рдорд╛рдЧрдЪреА рдиреЛрдВрджреАрдВрдЪреА рдЦреЛрд▓реА) рдЖрдгрд┐ UI school (рддреНрдпрд╛рд▓рд╛ call рдХрд░рдгрд╛рд░рд╛ рд╕реВрдЪрдирд╛ рдлрд▓рдХ).

ЁЯзТ 5 рд╡рд░реНрд╖рд╛рдВрдЪреНрдпрд╛ рдореБрд▓рд╛рд▓рд╛ рд╕рдордЬрд╛рд╡рд▓реНрдпрд╛рд╕рд╛рд░рдЦреЗ

рд╢рд╛рд│реЗрдЪреНрдпрд╛ рджрдкреНрддрд░рдЦрд╛рдиреНрдпрд╛рдЪреА (archive) рдХрд▓реНрдкрдирд╛ рдХрд░рд╛ ЁЯЧДя╕П тАФ рдкреНрд░рддреНрдпреЗрдХ рдиреЛрдВрджрд╡рд╣реА, рдкреНрд░рддреНрдпреЗрдХ grade, рдкреНрд░рддреНрдпреЗрдХ рд╡реЗрд│рд╛рдкрддреНрд░рдХ. рдЬреБрдиреНрдпрд╛ рд╡рд╛рдИрдЯ рджрд┐рд╡рд╕рд╛рдВрдд, рдЬреНрдпрд╛рд▓рд╛ рдХрд╛рд╣реА рд╣рд╡реЗ рдЕрд╕реЗрд▓ рддреЛ рдереЗрдЯ archive рдордзреНрдпреЗ рдЬрд╛рдпрдЪрд╛ рдЖрдгрд┐ drawers рдЙрдШрдбрд╛рдпрдЪрд╛: рдЦреЗрд│рд╛рдЪреНрдпрд╛ рд╢рд┐рдХреНрд╖рд┐рдХрд╛, canteen app, рдкрд╛рд▓рдХрд╛рдВрдЪреЗ portal, рдкреНрд░рддреНрдпреЗрдХрд╛рдЪреА рдЧреЛрд╖реНрдЯреА рдХреБрдареЗ рдЖрд╣реЗрдд рдпрд╛рдЪреА рд╕реНрд╡рддрдГрдЪреА рдХрд▓реНрдкрдирд╛. Drawers рдкреБрдиреНрд╣рд╛ рдкреБрдиреНрд╣рд╛ рд╣рд▓рд╡рд▓реЗ рдЬрд╛рдпрдЪреЗ; рдХреЛрдгреА рдХрд╛рдп рдиреЗрд▓реЗ рдпрд╛рдЪреА рдиреЛрдВрдж рдирд╕рд╛рдпрдЪреА; archive рдиреЗ рдПрдХ рдХрдкрд╛рдЯ рд╣рд▓рд╡рд▓реЗ рдХреА рдПрдХрд╛рдЪ рд╕рдХрд╛рд│реА рддреАрди apps рдмрд┐рдШрдбрд╛рдпрдЪреЗ.

рдореНрд╣рдгреВрди рд╢рд╛рд│реЗрдиреЗ counter рдЕрд╕рд▓реЗрд▓реЗ рдлреНрд░рдВрдЯ рдСрдлрд┐рд╕ ЁЯПв рдмрд╛рдВрдзрд▓реЗ. рдЖрддрд╛ рддреБрдореНрд╣реА archive рдордзреНрдпреЗ рдЬрд╛рдд рдирд╛рд╣реА. рддреБрдореНрд╣реА рдкреНрд░рдорд╛рдгрд┐рдд рдЪрд┐рдареНрдареА (slip) рднрд░рддрд╛ ("рд╡рд┐рджреНрдпрд╛рд░реНрдереА 2 рдЪрд╛ grade, рдХреГрдкрдпрд╛"), рдПрдХ рдХрд╛рд░рдХреВрди (clerk) рддреА рддрдкрд╛рд╕рддреЛ, рдЙрддреНрддрд░ рдЖрдгрддреЛ, рдЖрдгрд┐ рддреЗ рд╢рд┐рдХреНрдХрд╛ рдорд╛рд░реВрди рдкрд░рдд рджреЗрддреЛ ("рд╣реЗ рдШреНрдпрд╛ тАФ 200") рдХрд┐рдВрд╡рд╛ рдХрд╛рд░рдгрд╛рд╕рд╣ рдирдХрд╛рд░ рджреЗрддреЛ ("рдЕрд╕рд╛ рд╡рд┐рджреНрдпрд╛рд░реНрдереА рдирд╛рд╣реА тАФ 404"). Slip рдЪрд╛ рдирдореБрдирд╛ рд╕реВрдЪрдирд╛ рджрд┐рд▓реНрдпрд╛рд╢рд┐рд╡рд╛рдп рдХрдзреАрдЪ рдмрджрд▓рдд рдирд╛рд╣реА; рддреБрдореНрд╣реА рд╢рд┐рдХреНрд╖рд┐рдХрд╛ рдЖрд╣рд╛рдд, phone app рдЖрд╣рд╛рдд рдХреА robot, рдпрд╛рдЪреА clerk рд▓рд╛ рдкрд░реНрд╡рд╛ рдирд╕рддреЗ.

рддреЛ counter рдореНрд╣рдгрдЬреЗ API (application programming interface). Slips рдореНрд╣рдгрдЬреЗ requests, рд╢рд┐рдХреНрдХрд╛ рдорд╛рд░рд▓реЗрд▓реА рдЙрддреНрддрд░реЗ рдореНрд╣рдгрдЬреЗ responses, рдЖрдгрд┐ рдХреЛрдгрддреНрдпрд╛ slips рдЖрд╣реЗрдд рд╡ рддреНрдпрд╛ рдХрд╛рдп рдкрд░рдд рджреЗрддрд╛рдд рдпрд╛рдЪреЗ рдЫрд╛рдкрд▓реЗрд▓реЗ рдирд┐рдпрдо рдореНрд╣рдгрдЬреЗ contract. рдЗрдереВрди рдкреБрдврдЪрд╛ рдкреНрд░рддреНрдпреЗрдХ рдзрдбрд╛ рдПрдХ рдЪрд╛рдВрдЧрд▓рд╛ counter design рдХрд░рдгреНрдпрд╛рдмрджреНрджрд▓ рдЖрд╣реЗ.

ЁЯЧ║я╕П рдЖрдХреГрддреА

flowchart LR
    subgraph before["ЁЯЪк before: everyone in the archive"]
        a1["sports app opens drawer 3"]
        a2["canteen app opens drawer 3 differently"]
        a3["portal opensтАж the drawer moved ЁЯТе"]
    end
    subgraph after["ЁЯПв after: the front office"]
        slip["ЁЯУи 1 a standard slip (request)"]
        clerk["ЁЯзСтАНЁЯТ╝ 2 the clerk checks + fetches"]
        stamp["ЁЯУо 3 a stamped answer (response)"]
        slip --> clerk --> stamp
    end
    before -->|"put a counter in front"| after

тЭУ рдХрд╛рдп

ЁЯдФ рдХрд╛

рдХрд╛рд░рдг "app рд▓рд╛ рдереЗрдЯ database рд╡рд╛рдЪреВ рджреНрдпрд╛" рд╣рд╛ software рдордзрд▓рд╛ рд╕рд░реНрд╡рд╛рдд рдорд╣рд╛рдЧрдбрд╛ shortcut рдЖрд╣реЗ: рдкреНрд░рддреНрдпреЗрдХ рд╡рд╛рдкрд░рдХрд░реНрддрд╛ storage рдЪреНрдпрд╛ рд░рдЪрдиреЗрд╢реА рдмрд╛рдВрдзрд▓рд╛ рдЬрд╛рддреЛ, рдкреНрд░рддреНрдпреЗрдХ schema рдмрджрд▓ рдореНрд╣рдгрдЬреЗ рд╕рд░реНрд╡рд╛рдВрдирд╛ рдПрдХрддреНрд░ рдмрдВрдж рдареЗрд╡рд╛рд╡реЗ рд▓рд╛рдЧрдгрд╛рд░реЗ outage, рдЖрдгрд┐ permission рддрдкрд╛рд╕рдгреА, rate limits, validation рдХрд┐рдВрд╡рд╛ logs рдареЗрд╡рд╛рдпрд▓рд╛ рдЬрд╛рдЧрд╛рдЪ рдЙрд░рдд рдирд╛рд╣реА. рдпрд╛ рд╕рдЧрд│реНрдпрд╛ рдЧреЛрд╖реНрдЯреА counter рд╡рд░рдЪ рд░рд╛рд╣рддрд╛рдд. Counter рд╢рд┐рдХрд╛ рдЖрдгрд┐ рддреБрдореНрд╣реА рдЬрдЧрд╛рддрд▓реЗ рдХреЛрдгрддреЗрд╣реА API рд╡рд╛рдЪреВ рд╢рдХрд╛рд▓ тАФ рд╕рдЧрд│реА рдлрдХреНрдд slips рдЖрдгрд┐ рд╢рд┐рдХреНрдХреЗ рдЖрд╣реЗрдд.

ЁЯФз рдХрд╕реЗ (рдпрд╛ repo рдордзреНрдпреЗ)

Counter рдореНрд╣рдгрдЬреЗ api/school_api.py. рддреЗ рдкрд╛рдЪ рд╡рд┐рджреНрдпрд╛рд░реНрдереА memory рдордзреНрдпреЗ рдареЗрд╡рддреЗ (рд╕рдзреНрдпрд╛ рддреЗрдЪ archive) рдЖрдгрд┐ рддреНрдпрд╛рдВрдЪреНрдпрд╛рдмрджреНрджрд▓рдЪреНрдпрд╛ slips рдирд╛ рдЙрддреНрддрд░ рджреЗрддреЗ. рддреБрдореНрд╣реА рддреЗ рдкреВрд░реНрдг рдзрдбрд╛ 05 рдордзреНрдпреЗ рд╡рд╛рдЪрд╛рд▓; рдЖрдЬ рдлрдХреНрдд рдЪрд╛рд▓рд╡рд╛рдпрдЪреЗ.

ЁЯзк рдХрд░реВрди рдкрд╛рд╣рд╛ (60 рд╕реЗрдХрдВрдж тАФ рд╕рдВрдкреВрд░реНрдг рдХреЛрд░реНрд╕, live)

python3 api/school_api.py          # terminal 1: the office opens on :8080
bash api/smoke_test.sh             # terminal 2: every slip and stamp in the course

рддреБрдореНрд╣рд╛рд▓рд╛ рдЕрд╕реЗ рджрд┐рд╕рд╛рдпрд▓рд╛ рд╣рд╡реЗ (рдЫрд╛рдЯрд▓реЗрд▓реЗ):

тФАтФА L02 ┬╖ GET a student (200 + ETag)
HTTP/1.0 200 OK
{"id": 2, "name": "Katrina", "class": "3A", "grade": "A+"}
тФАтФА L02 ┬╖ unknown id (404, one error shape)
{"error": {"code": "not_found", "message": "No student with id 99."}}
тФАтФА L06 ┬╖ write without a hall pass (401)
{"error": {"code": "unauthenticated", "message": "Writes need an X-API-Key header.", тАж}}
тФАтФА L07 ┬╖ create with an Idempotency-Key (201) тАж same key again тЖТ Idempotent-Replay: true
тФАтФА L08 ┬╖ page 1 then page 2 (cursor) тАж
тФАтФА L10 ┬╖ 40 quick requests тЖТ the queue says 429
200 200 тАж 429 429 429

тЬЕ рддрдкрд╛рд╕рд╛ тАФ рддреБрдореНрд╣рд╛рд▓рд╛ рдХрд╛рдп рджрд┐рд╕рд╛рдпрд▓рд╛ рд╣рд╡реЗ

Terminal 1 рдкреНрд░рддреНрдпреЗрдХ slip рд╕рд╛рдареА рдПрдХ log рдУрд│ рдЫрд╛рдкрддреЛ (GET /v1/students/2 тЖТ 200 ┬╖ 1 ms ┬╖ <id>); terminal 2 рдЪреНрдпрд╛ рд╢реЗрд╡рдЯреА 200 рдЪреА рд░рд╛рдВрдЧ 429 рдордзреНрдпреЗ рдмрджрд▓рддрд╛рдирд╛ рджрд┐рд╕рддреЗ. рдХреЛрдгрддреЗрд╣реА stack traces рдирд╛рд╣реАрдд. Port 8080 рд╡реНрдпрд╕реНрдд рдЕрд╕реЗрд▓ рддрд░ python3 api/school_api.py 8081 рдиреЗ рд╕реБрд░реВ рдХрд░рд╛ рдЖрдгрд┐ smoke test рдордзрд▓рд╛ B= рдмрджрд▓рд╛.

ЁЯПБ рддреБрдореНрд╣реА рдЖрддреНрддрд╛рдЪ рдХрд╛рдп рд╕рд┐рджреНрдз рдХреЗрд▓реЗ

рдЦрд░реЗ API рдореНрд╣рдгрдЬреЗ рдЬрд╛рджреВ рдирд╛рд╣реА: рдХреЛрдгрддреАрд╣реА library рдирд╕рд▓реЗрд▓реНрдпрд╛ рдПрдХрд╛ Python file рдиреЗ рд╣рд╛ рдХреЛрд░реНрд╕ рд╢рд┐рдХрд╡рдгрд╛рд░ рдЕрд╕рд▓реЗрд▓реНрдпрд╛ рдкреНрд░рддреНрдпреЗрдХ рдкреНрд░рдХрд╛рд░рдЪреНрдпрд╛ slip рд▓рд╛ рдЙрддреНрддрд░ рджрд┐рд▓реЗ тАФ рдЖрдгрд┐ рддреБрдореНрд╣реА рддреНрдпрд╛рдЪреА рдЙрддреНрддрд░реЗ рдбреЛрд│реНрдпрд╛рдВрдиреА рд╡рд╛рдЪрд▓реАрдд.

тЪая╕П рдиреЗрд╣рдореАрдЪреНрдпрд╛ рдЪреБрдХрд╛

ЁЯПн рдкреНрд░рддреНрдпрдХреНрд╖ рд╡рд╛рдкрд░рд╛рдд рд╣реЗ рдХрд╛ рдорд╣рддреНрддреНрд╡рд╛рдЪреЗ: рддреБрдореНрд╣рд╛рд▓рд╛ рднреЗрдЯрдгрд╛рд░реА рдкреНрд░рддреНрдпреЗрдХ system тАФ payments, maps, рддреБрдордЪреНрдпрд╛ рдХрдВрдкрдиреАрдЪреНрдпрд╛ рд╕реНрд╡рддрдГрдЪреНрдпрд╛ services тАФ рдореНрд╣рдгрдЬреЗ counters рдЪрд╛ рд╕рдВрдЪ рдЖрд╣реЗ. рдЬреА teams counter рд▓рд╛ product рдореНрд╣рдгреВрди рд╡рд╛рдЧрд╡рддрд╛рдд (documented, versioned, рд╕реБрд░рдХреНрд╖рд┐рдд, рдирд┐рд░реАрдХреНрд╖рдгрд╛рдЦрд╛рд▓реА) рддреНрдпрд╛, рдПрдХрдореЗрдХрд╛рдВрдЪреНрдпрд╛ drawers рдордзреНрдпреЗ рдЙрдЪрдХрд╛рдкрд╛рдЪрдХ рдХрд░рдгрд╛рд▒реНрдпрд╛ apps рдЕрд╕рд▓реЗрд▓реНрдпрд╛ teams рдкреЗрдХреНрд╖рд╛ рдЬрд▓рдж ship рдХрд░рддрд╛рдд.

тПня╕П рдкреБрдвреЗ

Slip рдЖрдгрд┐ рд╢рд┐рдХреНрдХреНрдпрд╛рд╡рд░ рдиреЗрдордХреЗ рдХрд╛рдп рд▓рд┐рд╣рд┐рд▓реЗрд▓реЗ рдЕрд╕рддреЗ? HTTP рдЪреА рд░рдЪрдирд╛ тАФ method, path, headers, body, status.

git checkout lesson-02-http-anatomy

ЁЯПв Lesson 01 тАФ Why APIs: the front office

ЁЯУН You are here: Lesson 01 of 12 ┬╖ Next: lesson-02-http-anatomy


ЁЯУж What's in this branch

The problem APIs exist to solve тАФ and the one idea (a contract at a counter) that explains every design choice in the rest of the course. Real files you will use all the way through:

ЁЯОТ Before you start: you need Python 3 and curl, nothing else. This school teaches the ideas by running a tiny real API; frameworks (FastAPI, Express, Spring) automate the parts you will read here. Good neighbours: the Database school (the record room behind this counter) and the UI school (the notice board that calls it).

ЁЯзТ Explain like I'm 5

Imagine the school archive ЁЯЧДя╕П тАФ every register, every grade, every timetable. In the bad old days, anyone who needed something walked into the archive and opened drawers: the sports teacher, the canteen app, the parents' portal, each with its own idea of where things were. Drawers got rearranged; nobody logged who took what; when the archive moved a shelf, three apps broke on the same morning.

So the school built a front office ЁЯПв with a counter. You do not enter the archive any more. You fill in a standard slip ("student 2's grade, please"), a clerk checks it, fetches the answer, and hands it back stamped ("here you are тАФ 200") or refused with a reason ("no such student тАФ 404"). The slip format never changes without notice; the clerk does not care whether you are a teacher, a phone app or a robot.

That counter is an API (application programming interface). The slips are requests, the stamped answers are responses, and the printed rules of what slips exist and what they return are the contract. Every lesson from here is about designing a good counter.

ЁЯЧ║я╕П Diagram

flowchart LR
    subgraph before["ЁЯЪк before: everyone in the archive"]
        a1["sports app opens drawer 3"]
        a2["canteen app opens drawer 3 differently"]
        a3["portal opensтАж the drawer moved ЁЯТе"]
    end
    subgraph after["ЁЯПв after: the front office"]
        slip["ЁЯУи 1 a standard slip (request)"]
        clerk["ЁЯзСтАНЁЯТ╝ 2 the clerk checks + fetches"]
        stamp["ЁЯУо 3 a stamped answer (response)"]
        slip --> clerk --> stamp
    end
    before -->|"put a counter in front"| after

тЭУ What

ЁЯдФ Why

Because "just let the app read the database" is the most expensive shortcut in software: every consumer couples to the storage layout, every schema change is a coordinated outage, and there is no place to put permission checks, rate limits, validation or logs. The counter is where all of those live. Learn the counter and you can read any API in the world тАФ they are all slips and stamps.

ЁЯФз How (in this repo)

The counter is api/school_api.py. It keeps five students in memory (the archive, for now) and answers slips about them. You will read all of it in lesson 05; today you only run it.

ЁЯзк Try it (60 seconds тАФ the whole course, live)

python3 api/school_api.py          # terminal 1: the office opens on :8080
bash api/smoke_test.sh             # terminal 2: every slip and stamp in the course

You should see, trimmed:

тФАтФА L02 ┬╖ GET a student (200 + ETag)
HTTP/1.0 200 OK
{"id": 2, "name": "Katrina", "class": "3A", "grade": "A+"}
тФАтФА L02 ┬╖ unknown id (404, one error shape)
{"error": {"code": "not_found", "message": "No student with id 99."}}
тФАтФА L06 ┬╖ write without a hall pass (401)
{"error": {"code": "unauthenticated", "message": "Writes need an X-API-Key header.", тАж}}
тФАтФА L07 ┬╖ create with an Idempotency-Key (201) тАж same key again тЖТ Idempotent-Replay: true
тФАтФА L08 ┬╖ page 1 then page 2 (cursor) тАж
тФАтФА L10 ┬╖ 40 quick requests тЖТ the queue says 429
200 200 тАж 429 429 429

тЬЕ Verify тАФ what you should see

Terminal 1 prints one log line per slip (GET /v1/students/2 тЖТ 200 ┬╖ 1 ms ┬╖ <id>); terminal 2 ends with a row of 200s turning into 429s. No stack traces. If port 8080 is busy, start with python3 api/school_api.py 8081 and edit B= in the smoke test.

ЁЯПБ What you just proved

A real API is not magic: one Python file with no libraries answered every kind of slip this course will teach тАФ and you read its answers by eye.

тЪая╕П Common mistakes

ЁЯПн Why this matters in production: every system you will meet тАФ payments, maps, your company's own services тАФ is a set of counters. Teams that treat the counter as a product (documented, versioned, guarded, observed) ship faster than teams whose apps rummage in each other's drawers.

тПня╕П Next

What exactly is written on a slip and a stamp? HTTP anatomy тАФ method, path, headers, body, status.

git checkout lesson-02-http-anatomy
тЖР Course homeall lessonsNext тЖТhttp anatomy

This page is the lesson's README from the lesson-01-why-apis branch, shown here so the whole School stays on one site. Code files open on GitHub at the same branch.