jackdocs

Query

Two query endpoints — blocking and streaming. Both accept plain-English questions and return sourced answers. Use blocking for simple integrations, streaming for real-time UI.

POST/v1/query

Ask a question. Returns a complete answer with citations in a single response. Set timeout=30 on your HTTP client — complex queries over large document sets can take up to 10 seconds.

Request body

FieldTypeRequiredDefaultDescription
questionstringYesThe question to ask in plain English
filtersobjectNo{}Metadata key-value pairs to scope the search (AND logic)
top_kintegerNo6Number of document chunks retrieved before ranking (1–20)

Request

python
import httpx

response = httpx.post(
    "https://api.usejack.io/v1/query",
    headers={"Authorization": "Bearer jack_xxxxxxxx"},
    json={
        "question": "What is the remote work policy?",
        "filters": {"department": "HR"}
    },
    timeout=30
)

data = response.json()
print(data["answer"])
print(data["citations"])
bash
curl -X POST https://api.usejack.io/v1/query \
  -H "Authorization: Bearer jack_xxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"question": "What is the remote work policy?", "filters": {"department": "HR"}}'
javascript
const res = await fetch("https://api.usejack.io/v1/query", {
  method: "POST",
  headers: {
    "Authorization": "Bearer jack_xxxxxxxx",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    question: "What is the remote work policy?",
    filters: { department: "HR" },
  }),
});

const data = await res.json();
console.log(data.answer);
console.log(data.citations);

Response

json
{
  "answer": "Employees may work remotely up to 3 days per week with manager approval. Remote work requests must be submitted at least 48 hours in advance via the HR portal.",
  "citations": [
    {
      "text": "...employees are permitted to work remotely up to 3 days per week with prior manager approval. Requests must be submitted 48 hours in advance...",
      "source": "remote-work-policy.pdf",
      "score": 0.94
    }
  ],
  "org_id": "your-org-id"
}

Filtering examples

python
# Scope to one department
{"question": "What is the leave policy?", "filters": {"department": "HR"}}

# Scope to one document type
{"question": "Find termination clauses", "filters": {"document_type": "contract"}}

# Scope to one client
{"question": "What are the payment terms?", "filters": {"client_id": "CLIENT-001"}}

# Multiple filters — AND logic
{"question": "...", "filters": {"department": "legal", "year": "2024"}}

# No filter — searches all documents in your org
{"question": "Summarise our refund policy"}

If the answer is not in your documents, jack says so — it never fabricates. The citations array will be empty in that case.

POST/v1/query/stream

Same as /v1/query but streams the answer token by token via Server-Sent Events. Citations arrive as a final SSE event before [DONE]. Use this for a typing effect in your UI.

Request

Same body as /v1/query.

python
import httpx, json

with httpx.stream(
    "POST",
    "https://api.usejack.io/v1/query/stream",
    headers={"Authorization": "Bearer jack_xxxxxxxx"},
    json={
        "question": "What is the remote work policy?",
        "filters": {"department": "HR"}
    },
    timeout=60
) as response:
    citations = []
    for line in response.iter_lines():
        if line.startswith("data: "):
            payload = line[6:]
            if payload == "[DONE]":
                break
            event = json.loads(payload)
            if "token" in event:
                print(event["token"], end="", flush=True)
            elif "citations" in event:
                citations = event["citations"]
            elif "error" in event:
                print("Error:", event["error"])

print()  # newline after streamed answer
print("Sources:", citations)
javascript
const response = await fetch("https://api.usejack.io/v1/query/stream", {
  method: "POST",
  headers: {
    "Authorization": "Bearer jack_xxxxxxxx",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ question: "What is the remote work policy?" }),
});

const reader = response.body.getReader();
const decoder = new TextDecoder();

while (true) {
  const { done, value } = await reader.read();
  if (done) break;

  const lines = decoder.decode(value).split("\n");
  for (const line of lines) {
    if (!line.startsWith("data: ")) continue;
    const payload = line.slice(6);
    if (payload === "[DONE]") break;

    const event = JSON.parse(payload);
    if (event.token) process.stdout.write(event.token);
    if (event.citations) console.log("\nSources:", event.citations);
  }
}

SSE event format

text
data: {"token": "Employees"}
data: {"token": " may"}
data: {"token": " work"}
data: {"token": " remotely"}
data: {"token": " up"}
data: {"token": " to"}
data: {"token": " 3"}
data: {"token": " days"}
data: {"token": " per"}
data: {"token": " week."}
data: {"citations": [{"text": "...", "source": "remote-work-policy.pdf", "score": 0.94}]}
data: [DONE]
← PREVIOUSIngestNEXT →Documents