{"author":{"@type":"Person","name":"Alexander Bock","url":"https://abxk.ai/en/autor/alexander-bock/"},"categories":["AI Development"],"content":{"markdown":"Chat apps are the easiest way to use a large language model. But maybe you want AI inside your own software: a support form, a report generator or a small internal tool. Then your program has to talk to the model directly, through its **API** (application programming interface). Your code sends a request, and the answer comes back as data that your program can use.\n\nThis is part 1 of Level 1 in our AI Development learning path. You will create an API key, store it safely, send a first request in Python, read the response and handle errors. If tokens and context windows are new to you, start with [APIs, Tokens and Context Windows Explained](/en/ai-development/learn/apis-tokens-and-context-windows/) from Level 0.\n\n## What happens during an API call\n\nAn API call is a short exchange between two programs over the internet. Your program sends a **request** to a fixed web address, the **endpoint**. The provider's server checks your key and your limits, passes your messages to the model and returns a **response**. Request and response are written in **JSON**, a simple text format of names and values that almost every programming language can read.\n\n![Sequence diagram: your code sends a request with key, model and messages; the provider API checks key and limits and passes the messages on; the model writes the answer; the response with text, stop reason and token usage returns to your code](/images/learn/en/your-first-llm-api-call-sequence.webp \"One API call in five steps: request out, checks at the provider, answer back.\")\n\nWith a typical chat API, the model does not remember earlier calls. Each request must contain everything the model needs: the instructions, the question and, in a conversation, the earlier messages that matter. This sounds like extra work, but it also makes your app predictable: the model sees exactly what you send.\n\n## Step 1: Get an API key and keep it out of your code\n\nAn **API key** is a long secret string that identifies you to the provider. Every request with your key is billed to your account, so treat it like a password.\n\n1. Open the developer console of a model provider, create an account and set up billing.\n2. Create a new key with a clear name, such as \"faq-bot-dev\", so you know later where it is used.\n3. Copy the key right away. Many consoles show it only once.\n4. Store it in an **environment variable**: a named value that lives in your system or in your hosting settings — not in your source code.\n\nOn macOS or Linux, you set the variable for the current terminal session like this:\n\n```bash\nexport LLM_API_KEY=\"paste-your-key-here\"\n```\n\nOn Windows, in PowerShell:\n\n```powershell\n$env:LLM_API_KEY = \"paste-your-key-here\"\n```\n\nIn projects, many developers keep keys in a local file called `.env` and load it with a small library. Add `.env` to your `.gitignore` file so the key never ends up in version control.\n\n{{\u003c callout type=\"warning\" title=\"Check before your first commit\" \u003e}}\nRun `git status` before you commit. If `.env` shows up in the list, your `.gitignore` does not work yet, so fix it first. A key that once landed in a commit counts as leaked, even if you delete it later. Level 0 explained what to do then: revoke it and create a new one. Part 5 of this level shows [where the key lives in a deployed app](/en/ai-development/learn/deploy-a-small-ai-web-app/).\n{{\u003c /callout \u003e}}\n\n## Step 2: Build the request\n\nA request has three parts: where it goes, who sends it and what it asks for.\n\n![Annotated request: the endpoint address, the authorization header with the API key from an environment variable, the model name, the messages with system and user role, and the settings temperature and max tokens](/images/learn/en/your-first-llm-api-call-request.webp \"The parts of a typical chat request. Field names vary slightly between providers.\")\n\n- **Endpoint and method.** The web address comes from the provider's documentation. You send data with the HTTP method POST.\n- **Headers.** Extra lines that travel with the request: your API key and the content type `application/json`. Many providers expect the key as `Authorization: Bearer …`; others use a header with a different name.\n- **Body.** The JSON with the model, the messages and the settings.\n\nEach message has a **role**. The system message holds rules for the whole conversation. User messages hold the input. Assistant messages hold earlier answers of the model. Part 2 of this level, [Prompt Design for Developers](/en/ai-development/learn/prompt-design-for-developers/), shows how to write them well.\n\nThe settings control how the model answers. These are the ones you will use most:\n\n| Setting | What it does | A good start |\n|---|---|---|\n| model | Picks the model that answers | A mid-size model of your provider |\n| messages | System rules, user input, earlier answers | One system and one user message |\n| temperature | Randomness: low = focused and repeatable, high = more varied | 0–0.3 for facts and data, higher for ideas |\n| max tokens | Upper limit for the length of the answer | Enough for your longest normal answer |\n| stream | Sends the answer in small pieces while it is written | Off in scripts, on in chat interfaces |\n| stop | Text at which the model stops writing | Only if you need it |\n\nNames and ranges differ between providers, and some models — reasoning models in particular — do not accept every setting. The API reference of your provider lists what each model supports.\n\n## Step 3: Send your first request\n\nHere is the request as plain HTTP. `api.example.com` and `model-name` are placeholders: use the endpoint and the model ID from your provider's documentation.\n\n```http\nPOST https://api.example.com/v1/chat\nAuthorization: Bearer \u003cyour key from LLM_API_KEY\u003e\nContent-Type: application/json\n\n{\n  \"model\": \"model-name\",\n  \"messages\": [\n    {\"role\": \"system\", \"content\": \"Answer in plain English, in at most three sentences.\"},\n    {\"role\": \"user\", \"content\": \"What is an API key?\"}\n  ],\n  \"temperature\": 0.2,\n  \"max_tokens\": 300\n}\n```\n\nThe same call in Python, with the popular `requests` library (install it with `pip install requests`):\n\n```python\nimport os\nimport requests\n\nAPI_KEY = os.environ[\"LLM_API_KEY\"]        # read the key from the environment\nURL = \"https://api.example.com/v1/chat\"    # your provider's endpoint\n\npayload = {\n    \"model\": \"model-name\",\n    \"messages\": [\n        {\"role\": \"system\", \"content\": \"Answer in plain English, in at most three sentences.\"},\n        {\"role\": \"user\", \"content\": \"What is an API key?\"},\n    ],\n    \"temperature\": 0.2,\n    \"max_tokens\": 300,\n}\n\nresponse = requests.post(\n    URL,\n    headers={\"Authorization\": f\"Bearer {API_KEY}\"},\n    json=payload,      # sends the body as JSON and sets the content type\n    timeout=30,        # never wait forever\n)\nresponse.raise_for_status()   # stop with an error message if the call failed\nprint(response.json())\n```\n\nMost providers also offer official libraries, called **SDKs** (software development kits), that wrap these steps into a few lines. They are convenient, but the structure underneath stays the same. Even open-weight models that you run yourself, for example on a GPU cloud such as Runpod, usually offer the same kind of chat endpoint, so your code barely changes.\n\n## Step 4: Read the response\n\nThe response is JSON as well. Its exact layout depends on the provider, but you will find the same four kinds of information.\n\n![Annotated response: ID and model version, the generated text inside a list of output parts, the stop reason, and token usage for input and output](/images/learn/en/your-first-llm-api-call-response.webp \"What comes back: the answer plus the data you need for checks and cost control. Sample values.\")\n\n- **The generated text.** It sits in a field such as `content` or `text`, often inside a list, because a response can have several parts.\n- **The stop reason.** It tells you whether the model finished normally or hit your max tokens limit. If it hit the limit, the answer is cut off. Raise the limit or ask for a shorter answer.\n- **Token usage.** The number of input and output tokens. Providers bill per token, so log these numbers from day one.\n- **ID and model version.** You need them to trace a strange answer later.\n\nThe `model` field decides who answers. Our [LLM database](/en/llm/) lists {{\u003c stat \"models\" \u003e}} models with release dates and test results. Here are a few current models from different providers:\n\n{{\u003c llm-models \"claude-sonnet-5-5 gpt-6-luna gemini-3-8-flash deepseek-v4-1-flash\" \u003e}}\n\nThe names in our database are display names. The exact model ID for your request is in the provider's documentation. Part 4 of this level explains how to [choose a model for your app](/en/ai-development/learn/choose-a-model-for-your-app/).\n\n## Step 5: Handle errors and retry the right way\n\nCalls fail. The network drops, the provider is overloaded or your request contains a mistake. The **status code** of the response tells you which case you have. Codes in the 200s mean success; everything else needs a reaction:\n\n| Status code | Usual meaning | What to do |\n|---|---|---|\n| 400 | Bad request: wrong field, invalid JSON, input too long | Fix the request; do not retry |\n| 401 / 403 | Key missing, wrong or without permission | Check the key and its rights |\n| 404 | Unknown endpoint or model ID | Check the address and the model ID |\n| 429 | Too many requests, or a usage limit reached | Wait, then retry; check your limits |\n| 500 / 503 | Error or overload at the provider | Wait, then retry |\n| Timeout | No answer in time | Retry once or twice, then stop cleanly |\n\nThe rule behind the table: retry what is temporary, fix what is permanent.\n\n![Two groups of errors: temporary ones such as 429, 500 to 503 and timeouts, which you retry; permanent ones such as 400, 401, 403 and 404, which you fix first; below, the rule for exponential backoff](/images/learn/en/your-first-llm-api-call-retry.webp \"Retry temporary errors with growing waits; fix permanent errors in code or settings.\")\n\nWhen you retry, wait a little longer each time — for example about 1, then 2, then 4 seconds, plus a small random extra. This pattern is called **exponential backoff**. The random part stops many clients from retrying at the same moment. If the response has a `Retry-After` header, wait at least that long. After three or four attempts, give up and show the user a clear message.\n\n```python\nimport random\nimport time\n\nimport requests\n\ndef post_with_retry(url, headers, payload, tries=4):\n    for attempt in range(tries):\n        try:\n            r = requests.post(url, headers=headers, json=payload, timeout=30)\n            if r.status_code != 429 and r.status_code \u003c 500:\n                r.raise_for_status()   # 400, 401, 403, 404: fix the request, no retry\n                return r.json()\n        except (requests.exceptions.Timeout, requests.exceptions.ConnectionError):\n            pass                       # network problems are temporary, too\n        if attempt \u003c tries - 1:        # no pause after the last attempt\n            time.sleep(2 ** attempt + random.random())   # about 1, 2, 4 seconds\n    raise RuntimeError(\"The API still fails after several attempts.\")\n```\n\n## Exercise: your first call in 20 minutes\n\n{{\u003c callout type=\"try\" \u003e}}\nUse the Python script from step 3:\n\n1. Set `LLM_API_KEY` in your terminal and run the script. In the output, find the generated text, the stop reason and the token usage.\n2. Send the same question three times with temperature 0 and three times with temperature 1 (if your model supports the setting). How much do the answers change?\n3. Set max tokens to 20. Look at the stop reason and at the cut-off answer.\n4. Change one character of the key and run the script again. You should get an error, usually 401 Unauthorized — now you know what a wrong key looks like.\n5. Write the input and output tokens of each run into a small table. You will need this habit to estimate costs.\n{{\u003c /callout \u003e}}\n\nPrefer not to write code? No-code platforms such as MindStudio build on the same models, and you do not write these calls yourself. Part 3 of this level shows how to [build a simple AI app without code](/en/ai-development/learn/build-a-simple-ai-app-without-code/).","text":"Chat apps are the easiest way to use a large language model. But maybe you want AI inside your own software: a support form, a report generator or a small internal tool. Then your program has to talk to the model directly, through its API (application programming interface). Your code sends a request, and the answer comes back as data that your program can use.\nThis is part 1 of Level 1 in our AI Development learning path. You will create an API key, store it safely, send a first request in Python, read the response and handle errors. If tokens and context windows are new to you, start with APIs, Tokens and Context Windows Explained from Level 0.\nWhat happens during an API call An API call is a short exchange between two programs over the internet. Your program sends a request to a fixed web address, the endpoint. The provider\u0026rsquo;s server checks your key and your limits, passes your messages to the model and returns a response. Request and response are written in JSON, a simple text format of names and values that almost every programming language can read.\nOne API call in five steps: request out, checks at the provider, answer back. With a typical chat API, the model does not remember earlier calls. Each request must contain everything the model needs: the instructions, the question and, in a conversation, the earlier messages that matter. This sounds like extra work, but it also makes your app predictable: the model sees exactly what you send.\nStep 1: Get an API key and keep it out of your code An API key is a long secret string that identifies you to the provider. Every request with your key is billed to your account, so treat it like a password.\nOpen the developer console of a model provider, create an account and set up billing. Create a new key with a clear name, such as \u0026ldquo;faq-bot-dev\u0026rdquo;, so you know later where it is used. Copy the key right away. Many consoles show it only once. Store it in an environment variable: a named value that lives in your system or in your hosting settings — not in your source code. On macOS or Linux, you set the variable for the current terminal session like this:\nexport LLM_API_KEY=\u0026#34;paste-your-key-here\u0026#34; On Windows, in PowerShell:\n$env:LLM_API_KEY = \u0026#34;paste-your-key-here\u0026#34; In projects, many developers keep keys in a local file called .env and load it with a small library. Add .env to your .gitignore file so the key never ends up in version control.\n!Check before your first commit\nRun git status before you commit. If .env shows up in the list, your .gitignore does not work yet, so fix it first. A key that once landed in a commit counts as leaked, even if you delete it later. Level 0 explained what to do then: revoke it and create a new one. Part 5 of this level shows where the key lives in a deployed app.\nStep 2: Build the request A request has three parts: where it goes, who sends it and what it asks for.\nThe parts of a typical chat request. Field names vary slightly between providers. Endpoint and method. The web address comes from the provider\u0026rsquo;s documentation. You send data with the HTTP method POST. Headers. Extra lines that travel with the request: your API key and the content type application/json. Many providers expect the key as Authorization: Bearer …; others use a header with a different name. Body. The JSON with the model, the messages and the settings. Each message has a role. The system message holds rules for the whole conversation. User messages hold the input. Assistant messages hold earlier answers of the model. Part 2 of this level, Prompt Design for Developers, shows how to write them well.\nThe settings control how the model answers. These are the ones you will use most:\nYour First LLM API Call, Step by Step Setting What it does A good start model Picks the model that answers A mid-size model of your provider messages System rules, user input, earlier answers One system and one user message temperature Randomness: low = focused and repeatable, high = more varied 0–0.3 for facts and data, higher for ideas max tokens Upper limit for the length of the answer Enough for your longest normal answer stream Sends the answer in small pieces while it is written Off in scripts, on in chat interfaces stop Text at which the model stops writing Only if you need it Names and ranges differ between providers, and some models — reasoning models in particular — do not accept every setting. The API reference of your provider lists what each model supports.\nStep 3: Send your first request Here is the request as plain HTTP. api.example.com and model-name are placeholders: use the endpoint and the model ID from your provider\u0026rsquo;s documentation.\nPOST https://api.example.com/v1/chat Authorization: Bearer \u0026lt;your key from LLM_API_KEY\u0026gt; Content-Type: application/json { \u0026#34;model\u0026#34;: \u0026#34;model-name\u0026#34;, \u0026#34;messages\u0026#34;: [ {\u0026#34;role\u0026#34;: \u0026#34;system\u0026#34;, \u0026#34;content\u0026#34;: \u0026#34;Answer in plain English, in at most three sentences.\u0026#34;}, {\u0026#34;role\u0026#34;: \u0026#34;user\u0026#34;, \u0026#34;content\u0026#34;: \u0026#34;What is an API key?\u0026#34;} ], \u0026#34;temperature\u0026#34;: 0.2, \u0026#34;max_tokens\u0026#34;: 300 } The same call in Python, with the popular requests library (install it with pip install requests):\nimport os import requests API_KEY = os.environ[\u0026#34;LLM_API_KEY\u0026#34;] # read the key from the environment URL = \u0026#34;https://api.example.com/v1/chat\u0026#34; # your provider\u0026#39;s endpoint payload = { \u0026#34;model\u0026#34;: \u0026#34;model-name\u0026#34;, \u0026#34;messages\u0026#34;: [ {\u0026#34;role\u0026#34;: \u0026#34;system\u0026#34;, \u0026#34;content\u0026#34;: \u0026#34;Answer in plain English, in at most three sentences.\u0026#34;}, {\u0026#34;role\u0026#34;: \u0026#34;user\u0026#34;, \u0026#34;content\u0026#34;: \u0026#34;What is an API key?\u0026#34;}, ], \u0026#34;temperature\u0026#34;: 0.2, \u0026#34;max_tokens\u0026#34;: 300, } response = requests.post( URL, headers={\u0026#34;Authorization\u0026#34;: f\u0026#34;Bearer {API_KEY}\u0026#34;}, json=payload, # sends the body as JSON and sets the content type timeout=30, # never wait forever ) response.raise_for_status() # stop with an error message if the call failed print(response.json()) Most providers also offer official libraries, called SDKs (software development kits), that wrap these steps into a few lines. They are convenient, but the structure underneath stays the same. Even open-weight models that you run yourself, for example on a GPU cloud such as Runpod, usually offer the same kind of chat endpoint, so your code barely changes.\nStep 4: Read the response The response is JSON as well. Its exact layout depends on the provider, but you will find the same four kinds of information.\nWhat comes back: the answer plus the data you need for checks and cost control. Sample values. The generated text. It sits in a field such as content or text, often inside a list, because a response can have several parts. The stop reason. It tells you whether the model finished normally or hit your max tokens limit. If it hit the limit, the answer is cut off. Raise the limit or ask for a shorter answer. Token usage. The number of input and output tokens. Providers bill per token, so log these numbers from day one. ID and model version. You need them to trace a strange answer later. The model field decides who answers. Our LLM database lists 343 models with release dates and test results. Here are a few current models from different providers:\nModels from our LLM database ModelReleasedWeightsECIRank Claude Sonnet 5.5 AnthropicSep 28, 2026closed164.46 GPT-6 Luna OpenAISep 22, 2026closed156.328 Gemini 3.8 Flash Google DeepMindSep 2, 2026closed157.219 DeepSeek V4.1 Flash DeepSeekSep 9, 2026open155.631 ECI = Epoch Capabilities Index, one overall score across many benchmarks; rank among all models with an ECI. Data: Epoch AI, retrieved on October 17, 2026, licensed CC BY 4.0. All models: LLM database.\nThe names in our database are display names. The exact model ID for your request is in the provider\u0026rsquo;s documentation. Part 4 of this level explains how to choose a model for your app.\nStep 5: Handle errors and retry the right way Calls fail. The network drops, the provider is overloaded or your request contains a mistake. The status code of the response tells you which case you have. Codes in the 200s mean success; everything else needs a reaction:\nYour First LLM API Call, Step by Step (2) Status code Usual meaning What to do 400 Bad request: wrong field, invalid JSON, input too long Fix the request; do not retry 401 / 403 Key missing, wrong or without permission Check the key and its rights 404 Unknown endpoint or model ID Check the address and the model ID 429 Too many requests, or a usage limit reached Wait, then retry; check your limits 500 / 503 Error or overload at the provider Wait, then retry Timeout No answer in time Retry once or twice, then stop cleanly The rule behind the table: retry what is temporary, fix what is permanent.\nRetry temporary errors with growing waits; fix permanent errors in code or settings. When you retry, wait a little longer each time — for example about 1, then 2, then 4 seconds, plus a small random extra. This pattern is called exponential backoff. The random part stops many clients from retrying at the same moment. If the response has a Retry-After header, wait at least that long. After three or four attempts, give up and show the user a clear message.\nimport random import time import requests def post_with_retry(url, headers, payload, tries=4): for attempt in range(tries): try: r = requests.post(url, headers=headers, json=payload, timeout=30) if r.status_code != 429 and r.status_code \u0026lt; 500: r.raise_for_status() # 400, 401, 403, 404: fix the request, no retry return r.json() except (requests.exceptions.Timeout, requests.exceptions.ConnectionError): pass # network problems are temporary, too if attempt \u0026lt; tries - 1: # no pause after the last attempt time.sleep(2 ** attempt + random.random()) # about 1, 2, 4 seconds raise RuntimeError(\u0026#34;The API still fails after several attempts.\u0026#34;) Exercise: your first call in 20 minutes ▸Try it\nUse the Python script from step 3:\nSet LLM_API_KEY in your terminal and run the script. In the output, find the generated text, the stop reason and the token usage. Send the same question three times with temperature 0 and three times with temperature 1 (if your model supports the setting). How much do the answers change? Set max tokens to 20. Look at the stop reason and at the cut-off answer. Change one character of the key and run the script again. You should get an error, usually 401 Unauthorized — now you know what a wrong key looks like. Write the input and output tokens of each run into a small table. You will need this habit to estimate costs. Prefer not to write code? No-code platforms such as MindStudio build on the same models, and you do not write these calls yourself. Part 3 of this level shows how to build a simple AI app without code.\n","words":1784},"date":"2026-10-14","description":"Create an API key, keep it safe, send your first request to a language model, read the response and handle errors — step by step, with Python code.","image":"https://abxk.ai/images/cover/your-first-llm-api-call.webp","json":"https://abxk.ai/en/ai-development/learn/your-first-llm-api-call/index.json","kind":"page","language":"en","learning_path":{"category":"ai-development","level":1,"level_name":"Beginner"},"modified":"2026-10-14","related_tools":["MindStudio","Netlify","Runpod"],"section":"ai-development","tags":["llm-api","api-keys","python","beginner"],"title":"Your First LLM API Call, Step by Step","translations":[{"json":"https://abxk.ai/de/ai-development/learn/your-first-llm-api-call/index.json","language":"de","url":"https://abxk.ai/de/ai-development/learn/your-first-llm-api-call/"}],"url":"https://abxk.ai/en/ai-development/learn/your-first-llm-api-call/"}