Ollama: REST API Fundamentals

The REST API is Ollama's universal interface — any language, any framework, just send an HTTP request and you're connected.

⚠️ Note: The Ollama REST API has no built-in authentication — anyone who can access the service port can freely call Models and view installed Model lists. In production, you must add API Key authentication via a reverse proxy (such as Nginx/Caddy), otherwise your AI service faces risks of abuse, data leakage, and resource exhaustion.

📋 Prerequisites: You need to master the following first

1. What You Will Learn


2. A Real Story from a SaaS Founder

(1) The Pain Point: Manual Replies Are Inefficient

Alice founded the GlobalShop e-commerce platform. Her 50-person customer service team handles 2,000+ tickets daily. Each ticket takes an average of 8 minutes, and customer wait times exceed 30 minutes. She needs to integrate an LLM into the customer service system via API for automatic reply drafts.

(2) The Solution: REST API Generates Replies Instantly

Using curl to call the Ollama API, customer service reply drafts are generated in 3 seconds — agents only need to review and confirm:

BASH
curl http://localhost:11434/api/chat -d '{
  "model": "qwen2.5",
  "messages": [{"role": "user", "content": "Refund for order #12345"}]
}'

⚠️ Warning: The Ollama API has no built-in authentication — anyone who can access the port can call it. In production, you must add API Key authentication via a reverse proxy (Nginx/Caddy). See Lesson 20 for security hardening.

💡 Tip: Streaming API (stream: true) is suited for chat interfaces with real-time typing effects; non-streaming (stream: false) is better for batch processing and API backend integration. Non-streaming is recommended for API integration as it's simpler.

ℹ️ Info: Ollama defaults to http://127.0.0.1:11434, accessible only from the local machine. For LAN access, set the OLLAMA_HOST environment variable, but be mindful of security risks.

3. API Endpoints Complete Guide

(1) Two Core Endpoints Comparison

Dimension /api/generate /api/chat
Purpose Single-shot text generation Multi-turn dialogue
Input model + prompt messages array
Context Single request Supports conversation history
API mapping CLI ollama run CLI ollama chat
Use case Generation, completion, translation Customer service, assistants, multi-turn reasoning
100%
sequenceDiagram
    participant C as Client
    participant O as Ollama Server
    C->>O: POST /api/chat {messages, model, stream}
    O-->>C: NDJSON {message, done: false}
    O-->>C: NDJSON {message, done: false}
    O-->>C: NDJSON {message, done: true, stats}

(2) Common Request Parameters

Parameter Type Default Description
model string Required Model name
stream bool true Whether to stream output
options object Inference parameters (see next section)
format string Output format: json
keep_alive string 5m Model memory retention time

▶ Example 1: Single-shot Generation Request

BASH
# Non-streaming generate request
curl http://localhost:11434/api/generate -d '{
  "model": "llama3.2",
  "prompt": "Write a haiku about coding",
  "stream": false
}'

# Response (abbreviated)
# {
#   "model": "llama3.2",
#   "response": "Lines of logic flow,\nBug hides in the deep syntax—\nSemicolon found.",
#   "done": true,
#   "total_duration": 2500000000,
#   "eval_count": 18
# }

Output:

TEXT
{"status":"ok","data":{}}

▶ Example 2: Multi-turn Dialogue Request

BASH
# Chat with message history
curl http://localhost:11434/api/chat -d '{
  "model": "qwen2.5",
  "messages": [
    {"role": "system", "content": "You are a helpful customer service agent."},
    {"role": "user", "content": "I want to return my order #12345"},
    {"role": "assistant", "content": "I can help with that. May I ask the reason for the return?"},
    {"role": "user", "content": "The product arrived damaged"}
  ],
  "stream": false
}'

Output:

TEXT
{"status":"ok","data":{}}

4. Streaming Response Parsing

💡 Tip: Streaming (stream: true) and non-streaming (stream: false) each have their use cases: streaming is for real-time typing effects in chat interfaces so users see content without waiting for the full response; non-streaming is for batch processing and API backend integration where getting the complete JSON response is easier for program parsing. We recommend starting with non-streaming to validate logic, then switching to streaming to optimize UX.

(1) NDJSON Format Explained

Streaming responses use NDJSON (Newline Delimited JSON), with one JSON object per line:

TEXT
{"model":"llama3.2","message":{"role":"assistant","content":"I"},"done":false}
{"model":"llama3.2","message":{"role":"assistant","content":" can"},"done":false}
{"model":"llama3.2","message":{"role":"assistant","content":" help"},"done":false}
{"model":"llama3.2","message":{"role":"assistant","content":""},"done":true,"total_duration":1500000000}
Field Description
message.content Text fragment for this chunk
done Whether this is the last chunk
total_duration Total Inference time (nanoseconds)
eval_count Generated token count
prompt_eval_count Input token count

(2) Streaming vs Non-streaming Comparison

Dimension Streaming (stream: true) Non-streaming (stream: false)
User experience Real-time character-by-character output Wait for complete response
First-token latency Very low (~200ms) Wait until all generation completes
Implementation complexity Requires NDJSON parsing Read JSON directly
Use case Chat interfaces, real-time display Batch processing, API backends

▶ Example 3: Parsing Streaming Responses

BASH
# Streaming request with real-time output
curl http://localhost:11434/api/chat -d '{
  "model": "llama3.2",
  "messages": [{"role": "user", "content": "Hello!"}],
  "stream": true
}' | while read -r line; do
    # Extract content field from each NDJSON line
    echo "$line" | python3 -c "
import sys, json
data = json.load(sys.stdin)
if data.get('message', {}).get('content'):
    print(data['message']['content'], end='', flush=True)
"
done

Output:

TEXT
{"status":"ok","data":{}}

5. Inference Parameter Tuning

(1) Core Parameter Table

Parameter Type Range Default Effect
temperature float 0-2 0.8 Controls randomness; lower values are more deterministic
top_p float 0-1 0.9 Nucleus sampling, limits candidate token range
top_k int 1-100 40 Sample only from top-K candidates
num_ctx int 128-131072 2048 Context window size
repeat_penalty float 1-2 1.1 Repetition penalty coefficient
seed int Any -1 Random seed (-1 = random)

(2) Parameter Tuning by Scenario

Scenario temperature top_p Notes
Code generation 0.1-0.3 0.9 Requires determinism and accuracy
Customer service replies 0.3-0.5 0.9 Stable but allows moderate variation
Creative writing 0.7-1.0 0.95 Requires diversity and creativity
Data analysis 0.1-0.2 0.9 Must be precise, no Hallucination allowed
⚠️ Warning: num_ctx directly affects memory usage. An 8B Model with num_ctx=8192 needs approximately 6GB VRAM; num_ctx=32768 needs approximately 12GB VRAM. Set it as needed — don't increase it blindly.

▶ Example 4: Parameter Tuning Comparison

BASH
# Low temperature: deterministic output
curl http://localhost:11434/api/generate -d '{
  "model": "llama3.2",
  "prompt": "What is 2+2?",
  "stream": false,
  "options": {"temperature": 0.1}
}'
# Response: "2+2 equals 4."

# High temperature: creative output
curl http://localhost:11434/api/generate -d '{
  "model": "llama3.2",
  "prompt": "What is 2+2?",
  "stream": false,
  "options": {"temperature": 1.5}
}'
# Response: "In the realm of mathematics, 2+2 opens the door to 4..."

Output:

TEXT
{"status":"ok","data":{}}

▶ Example 5: JSON Format Output

BASH
# Force JSON output format
curl http://localhost:11434/api/chat -d '{
  "model": "llama3.2",
  "messages": [
    {"role": "system", "content": "You are a product catalog API. Return JSON only."},
    {"role": "user", "content": "List 3 laptops under $500"}
  ],
  "format": "json",
  "stream": false,
  "options": {"temperature": 0.3}
}'

# Response is valid JSON
# {"products":[{"name":"Acer Aspire 5","price":449,"spec":"8GB RAM, 256GB SSD"},...]}

Output:

TEXT
{"status":"ok","data":{}}

6. Comprehensive Example: SupportBot Customer Service API Prototype

💡 Tip: When calling the API in production, be sure to set the keep_alive parameter (e.g., "keep_alive": "5m") to avoid frequent Model loading/unloading that causes response delays.

BASH
#!/bin/bash
# ============================================
# Comprehensive: SupportBot API prototype
# Multi-turn customer service via REST API
# ============================================

API="http://localhost:11434/api/chat"
MODEL="qwen2.5"

# Function: Send a chat message and extract response
chat() {
    local system_prompt="$1"
    local user_msg="$2"
    local temp="${3:-0.4}"

    curl -s "$API" -d "$(cat <<EOF
{
  "model": "$MODEL",
  "messages": [
    {"role": "system", "content": "$system_prompt"},
    {"role": "user", "content": "$user_msg"}
  ],
  "stream": false,
  "options": {"temperature": $temp, "num_ctx": 4096}
}
EOF
)" | python3 -c "import sys,json; print(json.load(sys.stdin)['message']['content'])"
}

# Customer service system prompt
SYSTEM="You are SupportBot, a customer service agent for an e-commerce store. Be polite, concise, and helpful. If you cannot answer, say 'Let me connect you with a human agent.'"

# Simulate customer interactions
echo "=== Query 1: Order Status ==="
chat "$SYSTEM" "Where is my order #88765? It has been 5 days."

echo ""
echo "=== Query 2: Return Request ==="
chat "$SYSTEM" "I received a damaged item. Order #12345. I want a refund."

echo ""
echo "=== Query 3: Product Question ==="
chat "$SYSTEM" "Does the wireless headphone support Bluetooth 5.3?"

echo ""
echo "=== Benchmark ==="
time chat "$SYSTEM" "Hello" > /dev/null
💻 Output:

TEXT
=== Query 1: Order Status ===
I'd be happy to check on your order #88765. Based on our tracking system, your order is currently in transit and expected to arrive within 2-3 business days. You can track it at track.example.com/88765.

=== Query 2: Return Request ===
I'm sorry to hear about the damaged item. For order #12345, I've initiated a return request. You'll receive a prepaid shipping label via email within 24 hours. Once we receive the item, a full refund will be processed within 3-5 business days.

=== Query 3: Product Question ===
Yes, our wireless headphones support Bluetooth 5.3 with a range of up to 15 meters. They also feature active noise cancellation and 30-hour battery life.

❓ FAQ

Q Why does my curl request return connection refused?
A The Ollama service isn't running. Run ollama serve or verify the systemd service is started: sudo systemctl status ollama.
Q Should I choose stream: true or stream: false?
A Use stream: true for front-end chat interfaces to get real-time typing effects. Use stream: false for backend batch processing to get complete responses directly. Non-streaming is recommended for API integration as it's simpler.
Q How do I limit output length?
A Set the num_predict parameter, e.g., "num_predict": 200 to limit generation to 200 tokens. Note this is token count, not character count.
Q Does format: json guarantee valid JSON output?
A It works in most cases, but isn't 100% guaranteed. We recommend adding JSON validation at the application layer, with retry or fallback to text processing on parse failure.
Q How does multi-turn dialogue maintain context?
A The client must maintain the messages array itself, sending the complete conversation history with each request. The Ollama server does not store session state.
Q Are there concurrency limits on API calls?
A By default, only one request is processed at a time. Set the OLLAMA_NUM_PARALLEL environment variable to increase concurrency, but this requires more VRAM. See Lesson 19 for performance tuning.

📖 Summary


📝 Exercises

  1. Basic (Difficulty ⭐): Use curl to call /api/generate to generate a product description, and try both stream: true and stream: false to observe the difference.
  2. Intermediate (Difficulty ⭐⭐): Use /api/chat to implement a 3-turn dialogue, manually maintaining the messages array, outputting the complete reply each turn.
  3. Advanced (Difficulty ⭐⭐⭐): Write a Shell script that simulates a SupportBot customer service flow — receives questions, calls the API, returns classification results (intent + reply) in JSON format, supporting real-time streaming output.
Web-Tutorial.com

Web-Tutorial Tech Team

A team of developers maintaining programming tutorials. Each tutorial is written and reviewed by developers with expertise in that field. We work to keep our content accurate and reliable — if you spot an issue, please let us know.

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏