AI Book Tutorial menu

Calling AI APIs from Python and Node.js

To build with AI, your program sends a request to a model over the internet and reads the reply. This is called calling an AI API.

The Chat Completions Shape

Many providers offer an OpenAI-compatible chat completions API. The request and reply have the same shape everywhere, so the same code works with different providers. You only change three settings:

SettingExampleWhere it comes from
AI_BASE_URLhttps://api.example-provider.com/v1Provider's docs
AI_API_KEYa long secret stringProvider's dashboard
AI_MODELa model nameProvider's docs

You send a list of messages. Each message has a role:

  • system: your instructions for how the model should behave
  • user: what the person typed
  • assistant: earlier replies from the model (for chat history)

If you have not set up your .env file yet, see How to Use This Book.

Calling from Python

Install the official openai package, which works with any OpenAI-compatible provider, and python-dotenv to load the .env file:

Example

text
pip install openai python-dotenv

Example

python
# ask.py
import os
from dotenv import load_dotenv
from openai import OpenAI

load_dotenv()  # reads AI_API_KEY, AI_BASE_URL and AI_MODEL from .env

client = OpenAI(
    base_url=os.environ["AI_BASE_URL"],
    api_key=os.environ["AI_API_KEY"],
)

response = client.chat.completions.create(
    model=os.environ["AI_MODEL"],
    messages=[
        {"role": "system", "content": "You are a patient computer teacher. Answer in 3 short sentences."},
        {"role": "user", "content": "What is RAM? Explain it for a Class 9 student."},
    ],
    temperature=0.3,
    max_tokens=200,
)

print(response.choices[0].message.content)
print("Tokens used:", response.usage.total_tokens)

Run it with python ask.py. It prints the model's answer and the number of tokens the request used. The answer text will be different every time, and different for each model.

Some providers and newer models use max_completion_tokens instead of max_tokens. If you get an error about this setting, check your provider's documentation.

Calling from Node.js

Node.js 20 and newer have fetch built in and can load a .env file with a flag, so you need no packages:

Example

javascript
// ask.mjs  -  run with: node --env-file=.env ask.mjs
const response = await fetch(`${process.env.AI_BASE_URL}/chat/completions`, {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    Authorization: `Bearer ${process.env.AI_API_KEY}`,
  },
  body: JSON.stringify({
    model: process.env.AI_MODEL,
    messages: [
      { role: "system", content: "You are a patient computer teacher. Answer in 3 short sentences." },
      { role: "user", content: "What is RAM? Explain it for a Class 9 student." },
    ],
    temperature: 0.3,
    max_tokens: 200,
  }),
  signal: AbortSignal.timeout(30_000), // give up after 30 seconds
});

if (!response.ok) {
  throw new Error(`AI API error ${response.status}: ${await response.text()}`);
}
const data = await response.json();
console.log(data.choices[0].message.content);
console.log("Tokens used:", data.usage.total_tokens);

The file ends in .mjs so we can use await at the top level. To turn this into a web endpoint for a website chatbot, follow Call an AI API from a Server in the Chatbots Tutorial. To show the answer word by word as it is written, see Streaming Replies.

The Settings You Will Use Most

SettingWhat it doesTypical value
modelWhich model answersFrom your provider
messagesThe conversationSystem + user messages
temperatureRandomness: low = focused, high = creative0.2 for facts, 0.8 for ideas
max_tokensMaximum length of the answer100 to 1000
streamSend the answer in small partstrue for chat apps

Handling Errors and Retries

Real APIs sometimes fail. A 429 error means "too many requests" or "out of credit". A 5xx error means a problem on the provider's side. For these, wait and try again, waiting a bit longer each time. Here is the idea with a fake API call, so it runs offline:

Example

python
import time

def with_retries(call, attempts=3, wait=1.0):
    for n in range(1, attempts + 1):
        try:
            return call()
        except Exception as e:
            print(f"Attempt {n} failed: {e}")
            if n == attempts:
                raise
            time.sleep(wait)
            wait *= 2            # wait longer each time (1s, 2s, 4s...)

# A fake API call that fails twice with "429 Too Many Requests", then works
tries = {"count": 0}
def fake_call():
    tries["count"] += 1
    if tries["count"] < 3:
        raise RuntimeError("429 Too Many Requests")
    return "RAM is the computer's short-term memory."

print(with_retries(fake_call, wait=0.1))
Output
Attempt 1 failed: 429 Too Many Requests
Attempt 2 failed: 429 Too Many Requests
RAM is the computer's short-term memory.

Do not retry a 401 (wrong key) or 400 (bad request) error. Fix the cause instead. The official SDKs already retry some errors for you; the OpenAI client has a max_retries option.

Safety Rules for API Keys

  • Call the API from your server or script, never from browser JavaScript
  • Keep the key in environment variables, and .env in .gitignore
  • Set a monthly spending limit in your provider's dashboard
  • Use a separate key for each project, so you can cancel one without breaking the others

Exercise

Exercise

In a chat completions request, which role holds your instructions for how the model should behave?

Learn AI Book with a teacher

Join the AI & Prompt Engineering course at Workownix, online or in Orangi Town, Karachi, and get a certificate.

See the course Ask on WhatsApp