Search and answers — search returns the passages that match a question, with pages and a link to the original; ask returns a short answer.
API reference
Every public endpoint, in one place
The endpoints the Hippocampus web app uses for import, search, answers and reading, with their fields, streaming, jobs and errors.
Beta: fields can still change before general availability.
Resources for AI
Coding agent
Your coding agent (Claude, Cursor, Codex or another) reads our skill file and sets up Hippocampus in your project by itself.
API clients
Your API client (Postman, Insomnia or Bruno) imports every request with example responses; run Sign in first and the token is set for you.
OpenAPI 3.1
Client generators, Swagger UI and other API tools read every endpoint from this file, in the standard format.
Chat assistants
Your chat assistant (ChatGPT, Claude or Gemini) answers questions about the API from our docs, all in one file.
Authentication
A signed-in user's token
Every request carries an Authorization: Bearer <token> header. The token is the ID token of a signed-in Hippocampus user and lasts about an hour, so a script refreshes it the way any sign-in does. A call reaches only what that user may read.
There are no API keys yet: a script signs in as its own user, with the folders it needs shared to it.
The surface
What the API covers
Documents — import a source and track how it has been broken into sections.
Browse and read — list folders, read a document's text or download the original.
Jobs — check the status of an import.
Errors — the shape of a failure from each service.
Illustrative
The shape of a request
A document imported, and a question answered from what has been imported. Endpoints and fields are not final.
curl -X POST /ingest \
-H "Authorization: Bearer $THALIUS_API_KEY" \
-F "[email protected]" client.documents.create(
file="q3-renewals.pdf",
) await client.documents.create({
file: "q3-renewals.pdf",
}); Illustrative only — not a live contract yet.
Reference
Endpoints
The API has two services, and both take the same token. The core imports, searches and answers; the vault holds folders and documents. Your tenant's addresses are in the Hippocampus app under Manage tenant → API and MCP. The default addresses, used in the examples below, are https://hippocampuscore.thalius.ai for the core and https://hippocampusvault.thalius.ai for the vault.
Every endpoint below has a request in cURL, Python and JavaScript and a trimmed response.
Ids in the examples are shortened.
Import
Import documents
Upload files to the core. Each file is read, split into sections and summarised, then filed in the folder you name. A job tracks the work.
Core
POST /ingest
Upload one or more files for import into a folder.
Query
stream—truestreams progress as server-sent events;false(default) returns a job at once.
Form fields (multipart)
files— one or more files:.pdf,.docx,.md,.markdown,.txt,.text. Required.file_metadata— JSON array with one object per file, in the same order:folder_name(folder path) andtags.
Returns a job: job_id, status (processing, complete or error), total_files, done. A file that was already imported comes back with duplicate: true.
curl -sS -X POST "https://hippocampuscore.thalius.ai/ingest" \
-H "Authorization: Bearer $HIPPOCAMPUS_TOKEN" \
-F "[email protected]" \
-F 'file_metadata=[{"folder_name":"contracts/master-agreements","tags":["msa"]}]' {
"job_id": "c0a9f6d2-…",
"status": "processing",
"message": "Queued 1 file",
"total_files": 1,
"done": false
}
import json, os, requests
with open("MSA-2025.pdf", "rb") as f:
r = requests.post(
"https://hippocampuscore.thalius.ai/ingest",
headers={"Authorization": f"Bearer {os.environ['HIPPOCAMPUS_TOKEN']}"},
files={"files": f},
data={"file_metadata": json.dumps([{"folder_name": "contracts/master-agreements", "tags": ["msa"]}])},
)
print(r.json()) {
"job_id": "c0a9f6d2-…",
"status": "processing",
"message": "Queued 1 file",
"total_files": 1,
"done": false
}
import { readFile } from "node:fs/promises";
const form = new FormData();
form.append("files", new Blob([await readFile("MSA-2025.pdf")]), "MSA-2025.pdf");
form.append("file_metadata", JSON.stringify([{"folder_name": "contracts/master-agreements", "tags": ["msa"]}]));
const res = await fetch("https://hippocampuscore.thalius.ai/ingest", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.HIPPOCAMPUS_TOKEN}` },
body: form,
});
console.log(await res.json()); {
"job_id": "c0a9f6d2-…",
"status": "processing",
"message": "Queued 1 file",
"total_files": 1,
"done": false
}
curl -sS -N -X POST "https://hippocampuscore.thalius.ai/ingest?stream=true" \
-H "Authorization: Bearer $HIPPOCAMPUS_TOKEN" \
-F "[email protected]" \
-F 'file_metadata=[{"folder_name":"contracts/master-agreements","tags":["msa"]}]' data: {"event_type":"processing","current_file":"MSA-2025.pdf","current_step":"ocr","message":"Reading the document"}
data: {"event_type":"processing","current_file":"MSA-2025.pdf","document_id":"8c1f0e4a-…","duplicate":false}
data: {"event_type":"complete","successful_files":1}
Core
GET /jobs/{job_id}
Check an import started without streaming. Poll until done is true.
Path
job_id— from thePOST /ingestresponse.
Returns status, successful, failed and one entry in results per file, with its document_id.
curl -sS "https://hippocampuscore.thalius.ai/jobs/c0a9f6d2-…" \
-H "Authorization: Bearer $HIPPOCAMPUS_TOKEN" {
"job_id": "c0a9f6d2-…",
"status": "complete",
"successful": 1,
"failed": 0,
"results": [
{
"filename": "MSA-2025.pdf",
"success": true,
"document_id": "8c1f0e4a-…",
"folder_name": "contracts/master-agreements",
"duplicate": false
}
],
"done": true
}
import os, requests
r = requests.get(
"https://hippocampuscore.thalius.ai/jobs/c0a9f6d2-…",
headers={"Authorization": f"Bearer {os.environ['HIPPOCAMPUS_TOKEN']}"},
)
print(r.json()) {
"job_id": "c0a9f6d2-…",
"status": "complete",
"successful": 1,
"failed": 0,
"results": [
{
"filename": "MSA-2025.pdf",
"success": true,
"document_id": "8c1f0e4a-…",
"folder_name": "contracts/master-agreements",
"duplicate": false
}
],
"done": true
}
const res = await fetch("https://hippocampuscore.thalius.ai/jobs/c0a9f6d2-…", {
headers: { Authorization: `Bearer ${process.env.HIPPOCAMPUS_TOKEN}` },
});
console.log(await res.json()); {
"job_id": "c0a9f6d2-…",
"status": "complete",
"successful": 1,
"failed": 0,
"results": [
{
"filename": "MSA-2025.pdf",
"success": true,
"document_id": "8c1f0e4a-…",
"folder_name": "contracts/master-agreements",
"duplicate": false
}
],
"done": true
}
Search and answers
Search and ask
Search returns the passages that match a question, each with its pages and a link to the original. Ask returns a short answer written by the model.
Core
POST /search
Find the passages that answer a question, ranked.
Body (JSON)
query— the question. Required.folder_name— limit the search to one folder path.tags— limit it to documents with these tags.
Returns sources: for each passage doc_id, document_title, leaf_title (the section), start_page, end_page, text, score and deep_link to the original at that page.
curl -sS -X POST "https://hippocampuscore.thalius.ai/search" \
-H "Authorization: Bearer $HIPPOCAMPUS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"query":"What is the notice period for termination?","folder_name":"contracts/master-agreements"}' {
"sources": [
{
"doc_id": "8c1f0e4a-…",
"document_title": "Master Services Agreement 2025",
"leaf_title": "12. Term and Termination",
"start_page": 14,
"end_page": 15,
"score": 0.91,
"text": "Either party may terminate this Agreement on ninety (90) days' written notice…",
"deep_link": "/documents/5b7d2c90-….pdf#page=14"
}
]
}
import os, requests
r = requests.post(
"https://hippocampuscore.thalius.ai/search",
headers={"Authorization": f"Bearer {os.environ['HIPPOCAMPUS_TOKEN']}"},
json={
"query": "What is the notice period for termination?",
"folder_name": "contracts/master-agreements"
},
)
print(r.json()) {
"sources": [
{
"doc_id": "8c1f0e4a-…",
"document_title": "Master Services Agreement 2025",
"leaf_title": "12. Term and Termination",
"start_page": 14,
"end_page": 15,
"score": 0.91,
"text": "Either party may terminate this Agreement on ninety (90) days' written notice…",
"deep_link": "/documents/5b7d2c90-….pdf#page=14"
}
]
}
const res = await fetch("https://hippocampuscore.thalius.ai/search", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.HIPPOCAMPUS_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"query": "What is the notice period for termination?",
"folder_name": "contracts/master-agreements"
}),
});
console.log(await res.json()); {
"sources": [
{
"doc_id": "8c1f0e4a-…",
"document_title": "Master Services Agreement 2025",
"leaf_title": "12. Term and Termination",
"start_page": 14,
"end_page": 15,
"score": 0.91,
"text": "Either party may terminate this Agreement on ninety (90) days' written notice…",
"deep_link": "/documents/5b7d2c90-….pdf#page=14"
}
]
}
Core
POST /ask
Get a short answer to a question, written from the matching passages.
Body (JSON)
query— the question. Required.folder_name,tags— as in search.
Returns answer, reasoning and confidence. The passages are not returned; call search for them.
curl -sS -X POST "https://hippocampuscore.thalius.ai/ask" \
-H "Authorization: Bearer $HIPPOCAMPUS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"query":"What is the notice period for termination?","folder_name":"contracts/master-agreements"}' {
"answer": "Either party may terminate on 90 days' written notice (section 12.2).",
"reasoning": "Section 12.2 of the Master Services Agreement states…",
"confidence": 0.86
}
import os, requests
r = requests.post(
"https://hippocampuscore.thalius.ai/ask",
headers={"Authorization": f"Bearer {os.environ['HIPPOCAMPUS_TOKEN']}"},
json={
"query": "What is the notice period for termination?",
"folder_name": "contracts/master-agreements"
},
)
print(r.json()) {
"answer": "Either party may terminate on 90 days' written notice (section 12.2).",
"reasoning": "Section 12.2 of the Master Services Agreement states…",
"confidence": 0.86
}
const res = await fetch("https://hippocampuscore.thalius.ai/ask", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.HIPPOCAMPUS_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"query": "What is the notice period for termination?",
"folder_name": "contracts/master-agreements"
}),
});
console.log(await res.json()); {
"answer": "Either party may terminate on 90 days' written notice (section 12.2).",
"reasoning": "Section 12.2 of the Master Services Agreement states…",
"confidence": 0.86
}
Browse
Folders and what they hold
Folder summaries come from the core; folders and document lists come from the vault.
Core
GET /folders/summary
Read what a folder holds, as written at import, without running a search.
Query
folder_name— the folder path. Required.
Returns status (ok, none or unavailable) and folder_summary with title, description and content.
curl -sS "https://hippocampuscore.thalius.ai/folders/summary?folder_name=contracts/master-agreements" \
-H "Authorization: Bearer $HIPPOCAMPUS_TOKEN" {
"status": "ok",
"folder_summary": {
"folder": "contracts/master-agreements",
"title": "Master agreements",
"description": "Signed MSAs with customers and suppliers, 2019–2025.",
"content": "- Master Services Agreement 2025: term, termination, liability caps…",
"truncated": false
}
}
import os, requests
r = requests.get(
"https://hippocampuscore.thalius.ai/folders/summary?folder_name=contracts/master-agreements",
headers={"Authorization": f"Bearer {os.environ['HIPPOCAMPUS_TOKEN']}"},
)
print(r.json()) {
"status": "ok",
"folder_summary": {
"folder": "contracts/master-agreements",
"title": "Master agreements",
"description": "Signed MSAs with customers and suppliers, 2019–2025.",
"content": "- Master Services Agreement 2025: term, termination, liability caps…",
"truncated": false
}
}
const res = await fetch("https://hippocampuscore.thalius.ai/folders/summary?folder_name=contracts/master-agreements", {
headers: { Authorization: `Bearer ${process.env.HIPPOCAMPUS_TOKEN}` },
});
console.log(await res.json()); {
"status": "ok",
"folder_summary": {
"folder": "contracts/master-agreements",
"title": "Master agreements",
"description": "Signed MSAs with customers and suppliers, 2019–2025.",
"content": "- Master Services Agreement 2025: term, termination, liability caps…",
"truncated": false
}
}
Vault
GET /folders
List the top-level folders, or the folders inside one folder.
Query
parentFolderId— the folder to list. Leave it out for the top level.
Returns an array of folders: id, name, parentFolderId, createdAt, updatedAt.
curl -sS "https://hippocampusvault.thalius.ai/folders?parentFolderId=0c25a285-…" \
-H "Authorization: Bearer $HIPPOCAMPUS_TOKEN" [
{
"id": "0144f7ed-…",
"name": "Onboarding notes",
"parentFolderId": "0c25a285-…",
"createdAt": "2026-09-08T09:15:16.000Z",
"updatedAt": "2026-09-08T09:15:16.000Z"
}
]
import os, requests
r = requests.get(
"https://hippocampusvault.thalius.ai/folders?parentFolderId=0c25a285-…",
headers={"Authorization": f"Bearer {os.environ['HIPPOCAMPUS_TOKEN']}"},
)
print(r.json()) [
{
"id": "0144f7ed-…",
"name": "Onboarding notes",
"parentFolderId": "0c25a285-…",
"createdAt": "2026-09-08T09:15:16.000Z",
"updatedAt": "2026-09-08T09:15:16.000Z"
}
]
const res = await fetch("https://hippocampusvault.thalius.ai/folders?parentFolderId=0c25a285-…", {
headers: { Authorization: `Bearer ${process.env.HIPPOCAMPUS_TOKEN}` },
});
console.log(await res.json()); [
{
"id": "0144f7ed-…",
"name": "Onboarding notes",
"parentFolderId": "0c25a285-…",
"createdAt": "2026-09-08T09:15:16.000Z",
"updatedAt": "2026-09-08T09:15:16.000Z"
}
]
Vault
GET /folders/{id}
One folder. With include=true the same call also returns the folders above it, its documents and its subfolders.
Path
id— the folder id.
Query
include—trueto addancestors,documentsandsubfolders.
curl -sS "https://hippocampusvault.thalius.ai/folders/0144f7ed-…?include=true" \
-H "Authorization: Bearer $HIPPOCAMPUS_TOKEN" {
"id": "0144f7ed-…",
"name": "Onboarding notes",
"parentFolderId": "0c25a285-…",
"ancestors": [
{
"id": "0c25a285-…",
"name": "HR"
}
],
"documents": [
{
"id": "3c76ff09-…",
"name": "comments.md",
"contentType": "text/markdown",
"folderId": "0144f7ed-…",
"version": 1
}
],
"subfolders": [
{
"id": "9e2a…",
"name": "_hippocampus"
}
]
}
import os, requests
r = requests.get(
"https://hippocampusvault.thalius.ai/folders/0144f7ed-…?include=true",
headers={"Authorization": f"Bearer {os.environ['HIPPOCAMPUS_TOKEN']}"},
)
print(r.json()) {
"id": "0144f7ed-…",
"name": "Onboarding notes",
"parentFolderId": "0c25a285-…",
"ancestors": [
{
"id": "0c25a285-…",
"name": "HR"
}
],
"documents": [
{
"id": "3c76ff09-…",
"name": "comments.md",
"contentType": "text/markdown",
"folderId": "0144f7ed-…",
"version": 1
}
],
"subfolders": [
{
"id": "9e2a…",
"name": "_hippocampus"
}
]
}
const res = await fetch("https://hippocampusvault.thalius.ai/folders/0144f7ed-…?include=true", {
headers: { Authorization: `Bearer ${process.env.HIPPOCAMPUS_TOKEN}` },
});
console.log(await res.json()); {
"id": "0144f7ed-…",
"name": "Onboarding notes",
"parentFolderId": "0c25a285-…",
"ancestors": [
{
"id": "0c25a285-…",
"name": "HR"
}
],
"documents": [
{
"id": "3c76ff09-…",
"name": "comments.md",
"contentType": "text/markdown",
"folderId": "0144f7ed-…",
"version": 1
}
],
"subfolders": [
{
"id": "9e2a…",
"name": "_hippocampus"
}
]
}
Vault
GET /documents
List the documents in a folder, without their content.
Query
folderId— the folder. Leave it out for the top level.tag— only documents with this tag.
Returns an array: id, name, contentType, folderId, version, createdAt, updatedAt.
curl -sS "https://hippocampusvault.thalius.ai/documents?folderId=0144f7ed-…" \
-H "Authorization: Bearer $HIPPOCAMPUS_TOKEN" [
{
"id": "0001b85f-…",
"name": "Onboarding notes.md",
"contentType": "text/markdown",
"folderId": "0144f7ed-…",
"version": 1,
"createdAt": "2026-09-08T09:15:17.000Z"
}
]
import os, requests
r = requests.get(
"https://hippocampusvault.thalius.ai/documents?folderId=0144f7ed-…",
headers={"Authorization": f"Bearer {os.environ['HIPPOCAMPUS_TOKEN']}"},
)
print(r.json()) [
{
"id": "0001b85f-…",
"name": "Onboarding notes.md",
"contentType": "text/markdown",
"folderId": "0144f7ed-…",
"version": 1,
"createdAt": "2026-09-08T09:15:17.000Z"
}
]
const res = await fetch("https://hippocampusvault.thalius.ai/documents?folderId=0144f7ed-…", {
headers: { Authorization: `Bearer ${process.env.HIPPOCAMPUS_TOKEN}` },
});
console.log(await res.json()); [
{
"id": "0001b85f-…",
"name": "Onboarding notes.md",
"contentType": "text/markdown",
"folderId": "0144f7ed-…",
"version": 1,
"createdAt": "2026-09-08T09:15:17.000Z"
}
]
Read
Read documents
The vault returns a document's text, its tags and the original file.
Vault
GET /documents/{id}
One document's details. A text document also carries its content as Markdown.
Path
id— the document id.
Returns id, name, contentType, size, version, folderId, createdAt and, for text, content.
curl -sS "https://hippocampusvault.thalius.ai/documents/0001b85f-…" \
-H "Authorization: Bearer $HIPPOCAMPUS_TOKEN" {
"id": "0001b85f-…",
"name": "Onboarding notes.md",
"contentType": "text/markdown",
"size": 510,
"version": 1,
"folderId": "d3f3ed56-…",
"createdAt": "2026-09-08T09:15:17.000Z",
"content": "---
type: document
title: Onboarding notes
---
…"
}
import os, requests
r = requests.get(
"https://hippocampusvault.thalius.ai/documents/0001b85f-…",
headers={"Authorization": f"Bearer {os.environ['HIPPOCAMPUS_TOKEN']}"},
)
print(r.json()) {
"id": "0001b85f-…",
"name": "Onboarding notes.md",
"contentType": "text/markdown",
"size": 510,
"version": 1,
"folderId": "d3f3ed56-…",
"createdAt": "2026-09-08T09:15:17.000Z",
"content": "---
type: document
title: Onboarding notes
---
…"
}
const res = await fetch("https://hippocampusvault.thalius.ai/documents/0001b85f-…", {
headers: { Authorization: `Bearer ${process.env.HIPPOCAMPUS_TOKEN}` },
});
console.log(await res.json()); {
"id": "0001b85f-…",
"name": "Onboarding notes.md",
"contentType": "text/markdown",
"size": 510,
"version": 1,
"folderId": "d3f3ed56-…",
"createdAt": "2026-09-08T09:15:17.000Z",
"content": "---
type: document
title: Onboarding notes
---
…"
}
Vault
POST /documents/batch
Up to 100 documents, with content, in one call.
Body (JSON)
ids— up to 100 document ids. Required.
Returns an array of documents. Ids that do not exist or that you may not read are left out.
curl -sS -X POST "https://hippocampusvault.thalius.ai/documents/batch" \
-H "Authorization: Bearer $HIPPOCAMPUS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"ids":["0001b85f-…","3c76ff09-…"]}' [
{
"id": "0001b85f-…",
"name": "Onboarding notes.md",
"contentType": "text/markdown",
"content": "---
type: document
…"
},
{
"id": "3c76ff09-…",
"name": "comments.md",
"contentType": "text/markdown",
"content": "…"
}
]
import os, requests
r = requests.post(
"https://hippocampusvault.thalius.ai/documents/batch",
headers={"Authorization": f"Bearer {os.environ['HIPPOCAMPUS_TOKEN']}"},
json={
"ids": [
"0001b85f-…",
"3c76ff09-…"
]
},
)
print(r.json()) [
{
"id": "0001b85f-…",
"name": "Onboarding notes.md",
"contentType": "text/markdown",
"content": "---
type: document
…"
},
{
"id": "3c76ff09-…",
"name": "comments.md",
"contentType": "text/markdown",
"content": "…"
}
]
const res = await fetch("https://hippocampusvault.thalius.ai/documents/batch", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.HIPPOCAMPUS_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"ids": [
"0001b85f-…",
"3c76ff09-…"
]
}),
});
console.log(await res.json()); [
{
"id": "0001b85f-…",
"name": "Onboarding notes.md",
"contentType": "text/markdown",
"content": "---
type: document
…"
},
{
"id": "3c76ff09-…",
"name": "comments.md",
"contentType": "text/markdown",
"content": "…"
}
]
Vault
GET /documents/{id}/content
The stored file itself: the original PDF, an image or Markdown, with its own content type.
Path
id— the document id, for example the one in a search result'sdeep_link.
curl -sS -o original.pdf "https://hippocampusvault.thalius.ai/documents/5b7d2c90-…/content" \
-H "Authorization: Bearer $HIPPOCAMPUS_TOKEN" import os, requests
r = requests.get(
"https://hippocampusvault.thalius.ai/documents/5b7d2c90-…/content",
headers={"Authorization": f"Bearer {os.environ['HIPPOCAMPUS_TOKEN']}"},
)
open("original.pdf", "wb").write(r.content) import { writeFile } from "node:fs/promises";
const res = await fetch("https://hippocampusvault.thalius.ai/documents/5b7d2c90-…/content", {
headers: { Authorization: `Bearer ${process.env.HIPPOCAMPUS_TOKEN}` },
});
await writeFile("original.pdf", Buffer.from(await res.arrayBuffer())); Vault
GET /documents/{id}/tags
A document's tags.
Path
id— the document id.
Returns tags.
curl -sS "https://hippocampusvault.thalius.ai/documents/0001b85f-…/tags" \
-H "Authorization: Bearer $HIPPOCAMPUS_TOKEN" {
"tags": [
"onboarding",
"hr"
]
}
import os, requests
r = requests.get(
"https://hippocampusvault.thalius.ai/documents/0001b85f-…/tags",
headers={"Authorization": f"Bearer {os.environ['HIPPOCAMPUS_TOKEN']}"},
)
print(r.json()) {
"tags": [
"onboarding",
"hr"
]
}
const res = await fetch("https://hippocampusvault.thalius.ai/documents/0001b85f-…/tags", {
headers: { Authorization: `Bearer ${process.env.HIPPOCAMPUS_TOKEN}` },
});
console.log(await res.json()); {
"tags": [
"onboarding",
"hr"
]
}
Errors
When a call fails
The core answers with detail. The vault answers with message, or with error when the token is missing or not valid.
401— the token is missing, expired or not valid. Sign in again.403— the user may not read or change that folder.404— not found, or not readable by this user.409— the document changed since you read it.422— a field is missing or has the wrong type.
{
"detail": "Not authenticated"
} {
"detail": [
{
"loc": [
"body",
"query"
],
"msg": "Field required",
"type": "missing"
}
]
} {
"error": "unauthenticated"
} {
"statusCode": 404,
"message": "not_found"
} Clients
For now
curl and our MCP server both work today. Official Python and TypeScript SDKs are planned before general availability.
Want early access to the API?
We are onboarding design partners now.