Back to Article List

Ollama API guide: Endpoints, examples and OpenAI mode

Ollama API guide: Endpoints, examples and OpenAI mode - Ollama API guide: Endpoints, examples and OpenAI mode

Everything the Ollama CLI does goes through a REST API on port 11434, and that API is the real product once you build anything beyond a terminal chat. This guide covers the native endpoints with working curl examples, the request options you'll reach for, model management over HTTP and the OpenAI-compatible layer that lets existing tools talk to your server unmodified. All endpoints and field names below are verified against the official docs as of the v0.32 line (August 2026).

Base URL and authentication

The server listens on http://localhost:11434 by default, and there's no API key. None. Any process that can reach the port can pull models, delete them and run inference, which is harmless on localhost and reckless on a public interface. If you bind to 0.0.0.0 for remote access, put authentication in front of it; the Ollama VPS hosting guide covers OLLAMA_HOST and a reverse proxy with auth in one pass. A quick liveness check to start:

curl http://localhost:11434

That returns "Ollama is running", and curl http://localhost:11434/api/version gives you the version as JSON.

Generate text with /api/generate

POST /api/generate is the single-turn completion endpoint: one prompt in, one answer out, no conversation state. By default the response streams as newline-delimited JSON chunks, one per token batch:

curl http://localhost:11434/api/generate -d '{
  "model": "llama3.1",
  "prompt": "Why is the sky blue?"
}'

Streaming is right for interactive UIs and wrong for scripts, where you want one parseable object. Turn it off with stream:

curl http://localhost:11434/api/generate -d '{
  "model": "llama3.1",
  "prompt": "Why is the sky blue?",
  "stream": false
}'

The final response object carries useful metadata alongside the text: eval_count (tokens generated), prompt_eval_count (tokens in) and duration fields in nanoseconds, which make tokens-per-second math trivial. Generate also accepts system, format for structured output, images for multimodal models and a raw flag that bypasses the prompt template. In practice generate handles my batch jobs and template experiments while chat handles everything else.

Hold a conversation with /api/chat

POST /api/chat takes a messages array with roles, and this is the endpoint real applications build on. The server is stateless, so you send the full history every time:

curl http://localhost:11434/api/chat -d '{
  "model": "llama3.1",
  "messages": [
    { "role": "system", "content": "You answer in one sentence." },
    { "role": "user", "content": "What is a KV cache?" }
  ],
  "stream": false
}'

The reply arrives as a message object with role: "assistant", which you append to your history for the next turn. Chat also accepts tools for function calling and think for reasoning models. Since the full history travels with every request, long conversations grow until they hit the context window and old turns silently fall off, a failure mode the Ollama context window guide dissects properly.

Reading streamed responses

When stream is on (the default), the connection stays open and the server writes one JSON object per line as tokens arrive. Each chunk carries a fragment of the reply and "done": false, until a final object arrives with "done": true plus the timing and token-count stats. Your client reads lines, parses each as JSON and appends the content fragments; every HTTP library that can iterate a response body handles this without special support, no SSE parsing or websockets involved. The one mistake I keep seeing in code review is buffering the whole stream and then parsing it as a single JSON document, which fails because the body is many documents. Parse per line, or set "stream": false and stop pretending you wanted streaming.

Request options: num_ctx, temperature and keep_alive

Both endpoints take an options object for per-request model parameters, and a top-level keep_alive that controls how long the model stays in memory afterward:

curl http://localhost:11434/api/chat -d '{
  "model": "llama3.1",
  "messages": [{ "role": "user", "content": "Summarize this report..." }],
  "options": {
    "num_ctx": 16384,
    "temperature": 0.2,
    "seed": 42
  },
  "keep_alive": "30m",
  "stream": false
}'

Low temperature plus a fixed seed gives near-deterministic output for tests. keep_alive takes duration strings like "30m", seconds as a number or -1 to pin the model in memory forever, which is the right setting for a production endpoint that must answer without a cold-start penalty. The default is five minutes.

Manage models over the API

Everything ollama pull and friends do has an HTTP equivalent, so remote servers never need an SSH session for model housekeeping. List what's installed and what's loaded:

curl http://localhost:11434/api/tags
curl http://localhost:11434/api/ps

/api/tags is disk, /api/ps is memory, including each loaded model's VRAM footprint. Pull a new model (this streams progress objects until done):

curl http://localhost:11434/api/pull -d '{
  "model": "deepseek-r1:14b"
}'

The pull stream reports status plus total and completed byte counts per layer, which is enough to render a progress bar in a deploy script or just pipe through jq -r .status to watch it move. Delete a model with the DELETE method:

curl -X DELETE http://localhost:11434/api/delete -d '{
  "model": "deepseek-r1:14b"
}'

There's also POST /api/show for model metadata (context length, quantization, template) and POST /api/copy with source and destination fields. Which tags deserve the disk space is a separate question, and the best Ollama models guide has current opinions.

The OpenAI-compatible API under /v1

Ollama also serves OpenAI-compatible endpoints on the same port: /v1/chat/completions, /v1/completions, /v1/models, /v1/embeddings and /v1/responses. The point is drop-in compatibility, since thousands of tools speak the OpenAI wire format, and this layer means they all work against your own server. Point the tool's base URL at Ollama, use the Ollama tag as the model name and pass any string as the API key, because the field is required by most clients but ignored locally:

curl http://localhost:11434/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "llama3.1",
    "messages": [{ "role": "user", "content": "Say this is a test" }]
  }'

The response comes back in OpenAI's shape (choices, usage and so on) rather than Ollama's. Compatibility covers streaming, JSON mode, vision and tools; the OpenAI compatibility docs track the exact feature matrix, worth checking before you assume an edge case works. My rule: new code uses the native API for the richer options and metadata, existing OpenAI code gets pointed at /v1 and left alone.

Python and JavaScript clients

The official ollama-python library wraps the native API. Install with pip install ollama:

from ollama import chat

response = chat(
    model='llama3.1',
    messages=[{'role': 'user', 'content': 'Why is the sky blue?'}],
)
print(response.message.content)

Same shape in JavaScript with ollama-js, installed via npm install ollama:

import ollama from 'ollama'

const response = await ollama.chat({
  model: 'llama3.1',
  messages: [{ role: 'user', content: 'Why is the sky blue?' }],
})
console.log(response.message.content)

And if your codebase already uses the OpenAI SDK, redirect it instead of rewriting it:

from openai import OpenAI

client = OpenAI(
    base_url='http://localhost:11434/v1/',
    api_key='ollama',  # required by the SDK, ignored by the server
)

completion = client.chat.completions.create(
    model='llama3.1',
    messages=[{'role': 'user', 'content': 'Say this is a test'}],
)
print(completion.choices[0].message.content)

Both official libraries expose the management endpoints too (pull, list, delete), so a deployment script can stay in one language end to end.

Embeddings with /api/embed

For semantic search and RAG pipelines, POST /api/embed turns text into vectors. It takes a single string or a list in the input field:

curl http://localhost:11434/api/embed -d '{
  "model": "all-minilm",
  "input": ["Why is the sky blue?", "Why is the grass green?"]
}'

Batching a list in one request is much faster than looping single calls. You'll still find /api/embeddings (plural) in older code and it still answers, but it's the legacy endpoint, so write new code against /api/embed. Use an actual embedding model here; chat models produce vectors of dubious quality and waste memory doing it.

Common API errors

Two failures cover most support threads. A 404 with "model not found" means the exact tag isn't installed on the server answering the request, so curl http://localhost:11434/api/tags to see what's there and pull the missing tag, remembering that llama3.1 and llama3.1:8b are the same thing while llama3.1:70b is very much not. Connection refused means nothing is listening at the address you called: the service is down, or it's bound to 127.0.0.1 while you're calling a remote IP. Beyond those two, 503 responses appear when the request queue is full (512 by default) and the Ollama troubleshooting guide covers the rest, from CORS rejections to GPU fallbacks. The full payload reference lives in the official API docs, which are short enough to read whole.

F A Q

How do I call the API from a web page without CORS errors?

Browsers block cross-origin calls to the API unless the server allows your origin. Set OLLAMA_ORIGINS in the systemd override, for example Environment="OLLAMA_ORIGINS=https://app.example.com", then restart the service. Wildcards work too, including patterns like chrome-extension://* for browser extensions.

Race towards the future

Unrivaled speed meets competitive pricing

Ready in seconds 7-day money-back guaranteeA risk-free way to try LumaDock. Covers the GPU VPS plan on your first order. Cancel anytime
Billing Cycle

GPU.T4

£116.64 Save  19 %
£94.63 Monthly
  • Dedicated GPU
  • Tesla T4

  • 16 GB GDDR6vRAM
  • 2560CUDA CORES
  • Virtual Server
  • 8 vCPUAMD EPYC
  • 32 GBECC MEMORY
  • 250 GB NVMeSTORAGE
  • Unmetered bandwidth
  • IPv4 & IPv6IPv6 is currently unavailable in France, Finland or the Netherlands. included

GPU.ADA4000SFF

£219.30 Save  17 %
£182.63 Monthly
  • Dedicated GPU
  • RTX 4000 SFF Ada

  • 20 GB GDDR6 ECCvRAM
  • 6144CUDA CORES
  • Virtual Server
  • 16 vCPUAMD EPYC
  • 64 GBECC MEMORY
  • 350 GB NVMeSTORAGE
  • Unmetered bandwidth
  • IPv4 & IPv6IPv6 is currently unavailable in France, Finland or the Netherlands. included

GPU.PRO4000SFF

£263.31 Save  17 %
£219.30 Monthly
  • Dedicated GPU
  • RTX PRO 4000 Blackwell

  • 24 GB GDDR7 ECCvRAM
  • 8960CUDA CORES
  • Virtual Server
  • 16 vCPUAMD EPYC
  • 64 GBECC MEMORY
  • 400 GB NVMeSTORAGE
  • Unmetered bandwidth
  • IPv4 & IPv6IPv6 is currently unavailable in France, Finland or the Netherlands. included

GPU.PRO4500

£373.33 Save  20 %
£299.98 Monthly
  • Dedicated GPU
  • RTX PRO 4500 Blackwell

  • 32 GB GDDR7 ECCvRAM
  • 10496CUDA CORES
  • Virtual Server
  • 16 vCPUAMD EPYC
  • 64 GBECC MEMORY
  • 450 GB NVMeSTORAGE
  • Unmetered bandwidth
  • IPv4 & IPv6IPv6 is currently unavailable in France, Finland or the Netherlands. included

GPU.PRO5000

£512.68 Save  20 %
£410.00 Monthly
  • Dedicated GPU
  • RTX PRO 5000 Blackwell

  • 48 GB GDDR7 ECCvRAM
  • 14080CUDA CORES
  • Virtual Server
  • 32 vCPUAMD EPYC
  • 96 GBECC MEMORY
  • 500 GB NVMeSTORAGE
  • Unmetered bandwidth
  • IPv4 & IPv6IPv6 is currently unavailable in France, Finland or the Netherlands. included

GPU.PRO6000

£879.41 Save  19 %
£710.71 Monthly
  • Dedicated GPU
  • RTX PRO 6000 Blackwell

  • 96 GB GDDR7 ECCvRAM
  • 24064CUDA CORES
  • Virtual Server
  • 32 vCPUAMD EPYC
  • 128 GBECC MEMORY
  • 650 GB NVMeSTORAGE
  • Unmetered bandwidth
  • IPv4 & IPv6IPv6 is currently unavailable in France, Finland or the Netherlands. included

*VAT excluded.

INCLUDED WITH EVERY PLAN

No setup fees 1 Gbps network
Free server monitoring Firewall management 24/7 support KVM virtualization