How-to · Joshua API

Talk to Joshua
from your own programs

Joshua has a built-in API: your scripts, a robot, a home-automation box or any app that works with “OpenAI-compatible” servers can send it a question and get an answer back. Every request runs the full Joshua, with web research, tools and memory, on your computer.

Get started

  1. Open Joshua. The API starts with it, at http://127.0.0.1:7861/v1.
  2. In the right column, open 🔌 API. It shows the address, your key and a ready-made command to try.
  3. Copy the key. Every request must carry it, like a password. Only your computer knows it; Make a new key replaces it if it ever leaks.

Joshua must be running for the API to answer. The key is stored in ~/AskJoshua/joshua/api.json.

Your first request

In Terminal, list the models you can use, then ask a question. Replace YOUR-KEY with the key from the panel.

terminal
curl http://127.0.0.1:7861/v1/models \
  -H "Authorization: Bearer YOUR-KEY"
terminal
curl http://127.0.0.1:7861/v1/chat/completions \
  -H "Authorization: Bearer YOUR-KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "joshua",
    "messages": [{"role": "user", "content": "What is the weather in Turin today?"}]
  }'

The answer comes back in the standard format; the text is in choices[0].message.content:

answer
{
  "id": "chatcmpl-5f2c9a01",
  "object": "chat.completion",
  "model": "qwen3-vl:8b-instruct",
  "choices": [{
    "index": 0,
    "message": {"role": "assistant", "content": "Oggi è domenica, 8 novembre 2026."},
    "finish_reason": "stop"
  }]
}

Joshua may search the web, read pages or run code before answering, so a reply can take from a few seconds to a few minutes, depending on the question and your computer.

Python

The easiest way is the official openai library: point it at Joshua instead of OpenAI.

python · openai
# pip install openai
from openai import OpenAI

joshua = OpenAI(base_url="http://127.0.0.1:7861/v1", api_key="YOUR-KEY")

reply = joshua.chat.completions.create(
    model="joshua",
    messages=[{"role": "user", "content": "Summarise today's main news in Italy in three lines."}],
)
print(reply.choices[0].message.content)

Or with plain requests, for example on a Raspberry Pi robot that keeps the conversation going by sending the history back each time:

python · requests
# pip install requests
import requests

URL = "http://192.168.1.20:7861/v1/chat/completions"   # your computer's address on the home network
KEY = "YOUR-KEY"

def ask_joshua(text, history=()):
    messages = [*history, {"role": "user", "content": text}]
    r = requests.post(URL, headers={"Authorization": f"Bearer {KEY}"},
                      json={"model": "joshua", "messages": messages}, timeout=600)
    r.raise_for_status()
    return r.json()["choices"][0]["message"]["content"]

print(ask_joshua("Which washing programme for a shirt marked 40 °C, gentle?"))

JavaScript

javascript
const reply = await fetch("http://127.0.0.1:7861/v1/chat/completions", {
  method: "POST",
  headers: { "Authorization": "Bearer YOUR-KEY", "Content-Type": "application/json" },
  body: JSON.stringify({
    model: "joshua",
    messages: [{ role: "user", content: "Write a haiku about Turin in the fog." }],
  }),
}).then(r => r.json());

console.log(reply.choices[0].message.content);

A web page on another site can't call Joshua directly; run this in Node or in your own app.

Sending pictures

Send a photo as a data: URL inside the message. With a model that sees images (qwen3-vl does), Joshua looks at it directly; otherwise it uses its local image tool.

python
import base64
from openai import OpenAI

joshua = OpenAI(base_url="http://127.0.0.1:7861/v1", api_key="YOUR-KEY")
photo = base64.b64encode(open("label.jpg", "rb").read()).decode()

reply = joshua.chat.completions.create(model="joshua", messages=[{
    "role": "user",
    "content": [
        {"type": "text", "text": "What does this care label say?"},
        {"type": "image_url", "image_url": {"url": f"data:image/jpeg;base64,{photo}"}},
    ],
}])
print(reply.choices[0].message.content)

Options

You can give Joshua extra instructions with a system message: they are added after Joshua's own. And you can ask it not to save the exchange as a chat:

python
reply = joshua.chat.completions.create(
    model="joshua",
    messages=[
        {"role": "system", "content": "You are the voice of a small robot. Answer in one short sentence, in Italian."},
        {"role": "user", "content": "Che ore sono?"},
    ],
    extra_body={"joshua_save": False},   # don't keep this exchange as a chat
)
FieldWhat it does
modeljoshua = your default local model. Or any name from /v1/models, such as qwen3-vl:8b-instruct. Cloud models (ending in cloud) are used only if you name one.
messagesThe conversation: system, user and assistant messages, oldest first. Joshua keeps no state between requests, so send the history you want it to remember.
streamtrue works with clients that expect streaming, but the whole answer arrives in one piece at the end.
joshua_savefalse = don't save this exchange as a 🔌 chat. Default true.

From other devices

By default only programs on the same computer can connect. To use Joshua from a robot, a phone or another computer at home:

  1. In 🔌 API, tick Allow other devices on my network.
  2. Restart Joshua (run ~/AskJoshua/stop.sh, then open Joshua again).
  3. The panel now shows your computer's network address, such as http://192.168.1.20:7861/v1. Use that address on the other device, with the same key.

Keep it to your home network. Don't open port 7861 on your router: the key protects Joshua, but the connection is not encrypted.

Reference

RequestWhat it does
GET /v1/modelsLists joshua and every installed model that can use tools. owned_by says this computer or cloud.
POST /v1/chat/completionsRuns Joshua on the messages and returns its answer, in the OpenAI chat format.
ErrorMeaning
401The key is missing or wrong. Send Authorization: Bearer YOUR-KEY.
400Something in the request is wrong, such as an unknown model name. The message explains what.
connection refusedJoshua isn't running, or (from another device) “Allow other devices” is off or Joshua hasn't been restarted.

Need only the bare model, without Joshua's tools and memory? Ollama has its own API at http://127.0.0.1:11434, also OpenAI-compatible at /v1, with no key.

Privacy

  • With a local model, requests are answered entirely on your computer.
  • Every request is saved as a 🔌 chat in Joshua, so you can always see what programs asked, unless the program sends joshua_save: false.
  • API requests don't add to Joshua's memory about you, but local models can use your memory notes to answer.
  • A cloud model is used only if a program asks for one by name; then the conversation goes to Ollama's servers, as described in where your data lives.