ITS INCOM AI ITS INCOM AI docs

Cookbook

RAG quickstart

Sign in, create a knowledge base, upload a document, wait for the indexing and ask a question — with curl, then the same in Python.

Last updated: 2026-10-03

From a file on your disk to an answer with its sources, through the app API. You need:

  • an account on ITS INCOM AI with a verified email;
  • curl and jq;
  • a document: PDF, DOCX, TXT or Markdown, up to 50 MB.

1. Sign in

bash
export BASE="https://my.ai.itsincom.org/api/v1"
export TOKEN=$(curl -s $BASE/auth/login \
  -H "Content-Type: application/json" \
  -d '{"email": "you@example.com", "password": "…"}' | jq -r .access_token)
echo "$TOKEN"

If it prints null, the email or the password is wrong. The token lasts 24 hours by default: Signing in explains how to renew it.

2. Create a knowledge base

bash
SLUG=$(curl -s $BASE/rag/kb \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "Quickstart"}' | jq -r .slug)
echo "$SLUG"

The slug is the name plus six random characters, for example quickstart-3f9a1c. Every other call uses it.

3. Upload a document

bash
DOC=$(curl -s $BASE/rag/kb/$SLUG/docs \
  -H "Authorization: Bearer $TOKEN" \
  -F file=@./your-document.pdf | jq -r .id)
echo "$DOC"

The answer is 202: the file is accepted, and the indexing waits its turn in a queue.

4. Wait until it is ready

bash
while true; do
  STATUS=$(curl -s $BASE/rag/kb/$SLUG/docs/$DOC \
    -H "Authorization: Bearer $TOKEN" | jq -r .status)
  echo "$(date +%T) $STATUS"
  [ "$STATUS" = "ready" ] && break
  if [ "$STATUS" = "failed" ]; then
    curl -s $BASE/rag/kb/$SLUG/docs/$DOC -H "Authorization: Bearer $TOKEN" | jq -r .error
    break
  fi
  sleep 3
done

The status goes pending → parsing → chunking → embedding → ready. How long it takes depends on the document and on the queue. For scale: on 22 September 2026 a five-article contract, two passages long, was indexed in 0.20 s (Three examples); a long PDF takes much longer.

5. Ask

bash
curl -s $BASE/rag/kb/$SLUG/chat \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"question": "What is this document about?", "model": "gemma-4-26b"}' \
  | jq '{answer, sources: [.sources[] | {document_filename, chunk_idx, score}]}'

answer cites the passages as [file name: parte N]; sources lists them, the best first, with the score of the reranker. Without model, the answer is written by apertus-70b-instruct. Every field is in Knowledge bases API.

The same in Python

With the account's credentials in EMAIL and PASSWORD:

python
import os
import time

import requests

BASE = "https://my.ai.itsincom.org/api/v1"

# 1. Sign in
login = requests.post(
    f"{BASE}/auth/login",
    json={"email": os.environ["EMAIL"], "password": os.environ["PASSWORD"]},
    timeout=30,
)
login.raise_for_status()
H = {"Authorization": f"Bearer {login.json()['access_token']}"}

# 2. Create a knowledge base
kb = requests.post(f"{BASE}/rag/kb", json={"name": "Quickstart"}, headers=H, timeout=30)
kb.raise_for_status()
slug = kb.json()["slug"]

# 3. Upload a document
with open("your-document.pdf", "rb") as f:
    up = requests.post(f"{BASE}/rag/kb/{slug}/docs", files={"file": f}, headers=H, timeout=300)
up.raise_for_status()
doc_id = up.json()["id"]

# 4. Wait for the indexing
while True:
    doc = requests.get(f"{BASE}/rag/kb/{slug}/docs/{doc_id}", headers=H, timeout=30).json()
    print("status:", doc["status"])
    if doc["status"] == "ready":
        break
    if doc["status"] == "failed":
        raise RuntimeError(doc["error"])
    time.sleep(3)

# 5. Ask
resp = requests.post(
    f"{BASE}/rag/kb/{slug}/chat",
    json={"question": "What is this document about?", "model": "gemma-4-26b"},
    headers=H,
    timeout=120,
)
resp.raise_for_status()
result = resp.json()

print(result["answer"])
for s in result["sources"]:
    print(f"  {s['document_filename']}, passage {s['chunk_idx']} (score {s['score']:.3f})")

If something goes wrong

What you see What it means
403 with email_unverified The account's email is not confirmed yet: confirm it, then retry.
422 on the upload The file is larger than 50 MB, or its content is not PDF, DOCX, TXT or Markdown.
failed with Documento vuoto dopo parsing No text came out of the file. Usually a scanned PDF that went through the pdftotext fallback, which does not read images: run OCR on it first — for example with ocrmypdf — and upload it again.
A document stuck in pending The queue has not reached it yet. If it does not move, write to segreteria@itsincom.it.
An answer saying the information is not in the documents, with sources empty The search found nothing — or the vector database did not answer: Service status shows which.
500 on a question The answer could not be generated. Check that model is in the catalogue.
429 Too many requests in a minute: wait for Retry-After. The limits are in Knowledge bases API.

Clean up

bash
curl -s -X DELETE $BASE/rag/kb/$SLUG/docs/$DOC -H "Authorization: Bearer $TOKEN"

This removes the document, its passages, its vectors and the file. The knowledge base itself can be deleted only from the dashboard.

Next