CaveauAI REST API — Complete Reference
3 viewsCaveauAI REST API Documentation
The CaveauAI REST API lets you integrate AI-powered document search and chat into your own applications. Available on Starter plans and above (Trial plans do not have API access).
Base URL: https://ai.bluenotelogic.com/api/v2
Authentication
All API requests require an API key passed in the X-API-Key header.
X-API-Key: bnl_sk_your_api_key_here
Generating an API Key:
- Log in to the AI platform at ai.bluenotelogic.com
- Navigate to the Dashboard or API settings
- Click Generate API Key
- Copy the key immediately — it's only shown once
- Keys are SHA-256 hashed at rest for security
API keys are prefixed with bnl_sk_ for easy identification.
POST /api/v2/chat.php — AI Chat
Send a question and get an AI-generated answer with source citations from your knowledge base.
Request
{
"message": "What are the GDPR requirements for DPIAs?",
"use_corpus": true,
"model": "qwen2.5:72b",
"temperature": 0.3,
"top_p": 0.9,
"max_tokens": 2048,
"stream": false,
"search_packages": ["do-better-legal", "corpus_eu_ai"],
"category": "gdpr",
"language": "en",
"conversation_history": [
{"role": "user", "content": "What is a DPIA?"},
{"role": "assistant", "content": "A Data Protection Impact Assessment..."}
],
"session_id": "optional-session-id"
}
Required fields: message
Optional fields:
| Field | Type | Default | Description |
|---|---|---|---|
use_corpus |
boolean | true | Search document corpus for context |
model |
string | plan default | Specific model to use |
temperature |
float | 0.3 | Creativity (0.0-1.0, lower = more focused) |
top_p |
float | 0.9 | Diversity of token sampling |
max_tokens |
integer | 2048 | Maximum response length (256-4096) |
stream |
boolean | false | Enable SSE streaming response |
search_packages |
array | all | Specific corpus packages to search |
category |
string | null | Filter by document category |
language |
string | null | Preferred response language |
conversation_history |
array | [] | Prior messages for multi-turn chat |
session_id |
string | null | Resume a previous conversation |
Response
{
"success": true,
"query_id": "q_abc123",
"response": "According to Article 35 of the GDPR, a Data Protection Impact Assessment is required when...",
"model": "qwen2.5:72b",
"sources": [
{
"title": "GDPR Article 35 — Data protection impact assessment",
"document_id": 1234,
"relevance": 0.92,
"excerpt": "Where a type of processing... is likely to result in a high risk...",
"package": "corpus_eu_ai"
}
],
"response_time_ms": 2340,
"tokens_used": 1847,
"corpus_chunks_used": 5,
"queries_remaining": 487,
"context_stats": {
"system_tokens": 150,
"rag_tokens": 3200,
"history_tokens": 0,
"response_tokens": 1847,
"max_context": 32768
}
}
Streaming Mode
Set "stream": true to receive responses via Server-Sent Events (SSE). Each event contains a token fragment:
data: {"token": "According"}
data: {"token": " to"}
data: {"token": " Article"}
...
data: {"done": true, "sources": [...], "response_time_ms": 2340}
GET /api/v2/documents.php — List Documents
Retrieve your uploaded documents with metadata.
curl -H "X-API-Key: bnl_sk_..."
"https://ai.bluenotelogic.com/api/v2/documents.php"
Query parameters:
| Parameter | Description |
|---|---|
id |
Get a single document by ID |
category |
Filter by category |
status |
Filter by status (pending, ready, error) |
limit |
Max results (default 50) |
offset |
Pagination offset |
Response:
{
"success": true,
"documents": [
{
"id": 42,
"title": "Employment Contract Template",
"source_type": "pdf",
"category": "contracts",
"language": "no",
"author": "Legal Team",
"tags": "employment, template, 2024",
"word_count": 3200,
"chunk_count": 8,
"file_size_bytes": 245000,
"status": "ready",
"created_at": "2026-03-15T10:30:00Z"
}
],
"total": 156
}
POST /api/v2/documents.php — Upload Document
Upload and ingest a document into your private corpus.
curl -X POST
-H "X-API-Key: bnl_sk_..."
-F "file=@contract.pdf"
-F "title=Service Agreement 2026"
-F "category=contracts"
-F "author=Legal Department"
-F "tags=service,agreement,2026"
-F "source_url=https://example.com/contract"
-F "publication_date=2026-01-15"
https://ai.bluenotelogic.com/api/v2/documents.php
Supported file types: PDF, DOCX, TXT, HTML, MD (max 50 MB)
Response:
{
"success": true,
"document_id": 43,
"chunks_created": 12,
"word_count": 4500,
"status": "ready"
}
DELETE /api/v2/documents.php — Delete Document
curl -X DELETE
-H "X-API-Key: bnl_sk_..."
-H "Content-Type: application/json"
-d '{"id": 43}'
https://ai.bluenotelogic.com/api/v2/documents.php
This permanently removes the document, all its chunks, and vector embeddings from Qdrant.
Rate Limits
| Plan | Monthly Limit |
|---|---|
| Trial | No API access |
| Starter | 500 requests/month |
| Professional | 2,000 requests/month |
| Enterprise | Custom |
Rate limit headers are included in every response:
X-RateLimit-Limit: 2000
X-RateLimit-Remaining: 1487
X-RateLimit-Reset: 2026-05-01T00:00:00Z
What counts: Chat requests and search requests. What doesn't count: Document management (list, upload, delete), failed requests (4xx/5xx).
Error Codes
| HTTP Code | Meaning | Example |
|---|---|---|
| 200 | Success | — |
| 400 | Bad Request | Missing required field |
| 401 | Unauthorized | Invalid or missing API key |
| 403 | Forbidden | Feature not available on plan |
| 429 | Rate Limited | Monthly quota exceeded |
| 500 | Server Error | Internal processing failure |
Error response format:
{
"error": "Rate limit exceeded",
"code": "RATE_LIMIT_EXCEEDED",
"retry_after": 3600
}
Code Examples
Python
import requests
API_KEY = "bnl_sk_your_key"
BASE = "https://ai.bluenotelogic.com/api/v2"
# Ask a question
response = requests.post(
f"{BASE}/chat.php",
headers={"X-API-Key": API_KEY},
json={
"message": "What are the notice periods in Norwegian employment law?",
"use_corpus": True,
"temperature": 0.3
}
)
data = response.json()
print(data["response"])
for source in data["sources"]:
print(f" Source: {source['title']} (relevance: {source['relevance']})")
JavaScript (Node.js)
const response = await fetch("https://ai.bluenotelogic.com/api/v2/chat.php", {
method: "POST",
headers: {
"X-API-Key": "bnl_sk_your_key",
"Content-Type": "application/json"
},
body: JSON.stringify({
message: "Summarize GDPR Article 6 requirements",
use_corpus: true
})
});
const data = await response.json();
console.log(data.response);
PHP
$ch = curl_init("https://ai.bluenotelogic.com/api/v2/chat.php");
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"X-API-Key: bnl_sk_your_key",
"Content-Type: application/json"
],
CURLOPT_POSTFIELDS => json_encode([
"message" => "What is the AI Act risk classification?",
"use_corpus" => true
])
]);
$response = json_decode(curl_exec($ch), true);
echo $response["response"];