API documentation is the manual for a service
API documentation is the manual for a service somebody else built. It lists what you can ask for, what to send and what comes back.
Reading it quickly is a core developer skill. It turns a description on a page into a call that works.
By the end of this lesson
Note
I can turn an API's documentation into a working call.
Key words
| Word | What it means | Example |
|---|---|---|
| Endpoint | a URL path that does one job | /v1/chat/completions |
| Parameter | a named input to a call | |
| Required | a parameter you must send | |
| Default | the value used when you send nothing | |
| Error table | the list of statuses and what each one means |
The cells students fill in are left blank in this preview.
A documentation page has four parts
Most pages hold the same four things. The endpoint says where to send the call. The parameter list says what you may send. An example shows one working call. The error table says what each failure means.
Read them in that order. The next table is a sample page, written for this lesson.
Worked example: a sample parameter list
| Parameter | Type | Required | Default |
|---|---|---|---|
| messages | list | Yes | None |
| max_tokens | whole number, 1 to 4096 | No | 256 |
| temperature | number, 0 to 2 | No | 1 |
| stream | true or false | No | false |
The cells students fill in are left blank in this preview.
Make the call the page describes
docker exec -w /home/node/project agent node -e "const u=(process.env.AI_URL||'http://ai:4000')+'/v1/chat/completions';(async()=>{const body={model:'lab',messages:[{role:'user',content:'Name one use of an API in five words.'}],max_tokens:30,temperature:0};console.log('Sent: max_tokens='+body.max_tokens+', temperature='+body.temperature);try{const r=await fetch(u,{method:'POST',headers:{'content-type':'application/json',authorization:'Bearer lab'},body:JSON.stringify(body)});const j=await r.json();if(r.ok===false)throw new Error(r.status+' '+j.error.message);console.log('Model: '+j.choices[0].message.content)}catch(e){console.log('No answer from the model ('+e.message+'). Recorded sample:');console.log('Model: Fetching weather data for an app.')}})()"Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
The example shows the shape
Copy the example first and make it run. That proves your setup works. Then change one parameter at a time, and check each change against the parameter list.
The list tells you the type, the range and the default. A value outside the range gives an error, so check it before you send.
Check parameters against the page
docker exec -w /home/node/project agent node -e "const spec={max_tokens:{min:1,max:4096},temperature:{min:0,max:2}};const check=(p)=>{const out=[];for(const k in p){if(spec[k]===undefined){out.push('unknown '+k);continue}if(k==='max_tokens'&&Number.isInteger(p[k])===false)out.push(k+' must be a whole number');else if(p[k]<spec[k].min||p[k]>spec[k].max)out.push(k+' must be from '+spec[k].min+' to '+spec[k].max)}return out};for(const p of [{max_tokens:50},{max_tokens:5000},{max_tokens:2.5,temperature:3},{top:1}])console.log(JSON.stringify(p)+' -> '+(check(p).join('; ')||'ok'))"Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
The error table says what to do
A good error table does not just name a status. It tells you whether to fix your call, wait, or try later.
A 4xx status usually means you change something. A 5xx status means the service has a problem, so you try again later.
Worked example: a sample error table
| Status | What it means | What to do |
|---|---|---|
| 400 | The body is wrong | Fix the body |
| 401 | The key is missing or wrong | Check the key |
| 403 | Not allowed here | Read the message |
| 429 | Too many requests | Wait, then retry |
| 503 | The service is not ready | Try again later |
The cells students fill in are left blank in this preview.
Read a status with the error table
docker exec -w /home/node/project agent node -e "const u=(process.env.AI_URL||'http://ai:4000')+'/v1/chat/completions';const advice={200:'it worked, read the body',400:'fix the body',401:'check the key',403:'read the message',429:'wait, then retry',503:'try again later'};(async()=>{try{const r=await fetch(u,{method:'POST',headers:{'content-type':'application/json',authorization:'Bearer lab'},body:JSON.stringify({model:'lab',messages:[{role:'user',content:'Say hi.'}],max_tokens:10})});console.log('Status '+r.status+': '+(advice[r.status]||'not in the table'));if(r.status>299)console.log('Recorded sample of a good call: Status 200: '+advice[200])}catch(e){console.log('No answer from the service ('+e.message+'). Recorded sample:');console.log('Status 429: '+advice[429])}})()"Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
A common mistake
Warning
Many people think the example in the docs is the whole API. An example shows one call. The parameter list says what else you may send, and the error table says what to do when a call fails. Read all three.