Axiom REST API

Developer6 min read

nyxCore Axiom RAG API — Integration Guide for External Systems


1. Overview

nyxCore Axiom is a project-scoped document knowledge system with hybrid search (vector similarity + full-text). External systems access it via a REST API authenticated with nyx_ax_ bearer tokens.

Base URL: https://nyxcore.cloud

Authentication: Bearer token with nyx_ax_ prefix


2. Authentication

All requests require a Bearer token in the Authorization header:

Authorization: Bearer nyx_ax_<token>

Token format: nyx_ax_ prefix + 32 bytes base64url (total ~55 chars)

Token scopes (assigned at creation):

Scope Permission
search Search documents (also implies read)
read List documents
upload Ingest/upload new documents

Project-scoped tokens: If the token was created for a specific project, all requests are automatically scoped to that project's documents. You don't need to pass projectId in requests — the token enforces it.

Rate limits:

  • 100 requests/minute per tenant
  • Fail-open (requests allowed if Redis is unavailable)

3. Endpoints

3.1 Search Documents

The primary endpoint for RAG retrieval. Uses hybrid search: 70% vector similarity (pgvector cosine distance) + 30% full-text (PostgreSQL tsvector), with authority-level score boosting.

POST /api/v1/rag/search
Authorization: Bearer nyx_ax_<token>
Content-Type: application/json

Request body:

{
  "query": "Wie funktioniert das Onboarding für neue Mitarbeiter?",
  "limit": 10,
  "authority": ["mandatory", "guideline"]
}
Field Type Required Description
query string yes Search query (1-500 chars)
limit number no Max results (1-50, default: 10)
projectId string (UUID) no Filter to specific project. Ignored if token is project-scoped.
authority string[] no Filter by authority level: "mandatory", "guideline", "informational"

Response (200):

{
  "ok": true,
  "results": [
    {
      "content": "## Onboarding Prozess\n\nNeue Mitarbeiter erhalten am ersten Tag...",
      "heading": "Onboarding Prozess",
      "filename": "hr-handbuch.md",
      "authority": "guideline",
      "score": 0.847,
      "chunkId": "abc-123",
      "documentId": "def-456"
    }
  ],
  "requestId": "req-789"
}

Score composition:

score = (vector_similarity * 0.7) + (text_rank * 0.3) + authority_boost

authority_boost:
  mandatory:     +0.3   (GDPR, ISO, legal  always highest priority)
  guideline:     +0.15  (conventions, standards)
  informational: +0.0   (general context)

Fallback behavior: If embedding generation fails (e.g., no OpenAI key configured for tenant), the search automatically falls back to text-only search.


3.2 List Documents

List all documents available in the knowledge base.

GET /api/v1/rag/documents
Authorization: Bearer nyx_ax_<token>

Query parameters:

Param Type Required Description
projectId string (UUID) no Filter to specific project. Ignored if token is project-scoped.

Response (200):

{
  "ok": true,
  "documents": [
    {
      "id": "def-456",
      "filename": "hr-handbuch.md",
      "mimeType": "text/markdown",
      "fileSize": 24576,
      "sourceUrl": null,
      "status": "ready",
      "chunkCount": 12,
      "authority": "guideline",
      "category": "workflow",
      "createdAt": "2026-03-10T14:30:00.000Z"
    }
  ],
  "requestId": "req-101"
}

Document status values:

Status Meaning
pending Uploaded, not yet processed
processing Chunking + embedding in progress
ready Searchable
failed Processing failed (check errorMessage)

3.3 Upload Documents

Ingest a new document into the knowledge base. Processing (chunking, embedding) happens asynchronously.

POST /api/v1/rag/ingest
Authorization: Bearer nyx_ax_<token>
Content-Type: multipart/form-data

Form fields:

Field Type Required Description
file File yes The document file
projectId string (UUID) conditional Required if token is tenant-wide; ignored if token is project-scoped
filename string no Override filename (defaults to file.name)
authority string no "informational" (default), "guideline", or "mandatory"
category string no "general" (default), "workflow", "coding", "compliance", "style"

Supported file types: .md, .txt, .pdf, .ts, .js, .py, .json, .yaml, .toml, .html, .css

Response (202 Accepted):

{
  "ok": true,
  "documentId": "new-doc-123",
  "status": "processing",
  "requestId": "req-202"
}

After upload, poll GET /api/v1/rag/documents to check when status becomes "ready".


4. Error Responses

All errors follow a consistent format:

{
  "ok": false,
  "error": {
    "code": "UNAUTHORIZED",
    "message": "Missing or invalid Axiom API token"
  },
  "requestId": "req-err-1"
}
HTTP Status Code Meaning
400 VALIDATION_ERROR Invalid JSON, missing fields, unsupported file type
401 UNAUTHORIZED Missing/invalid/expired bearer token
403 FORBIDDEN Token lacks required scope
429 RATE_LIMITED Rate limit exceeded (100 req/min)

5. Integration Examples

5.1 Python (OnboardingTutor / miniRAG)

import requests

AXIOM_BASE = "https://nyxcore.cloud"
AXIOM_TOKEN = "nyx_ax_..."  # from nyxCore dashboard

def search_axiom(query: str, limit: int = 5, authority: list[str] | None = None) -> list[dict]:
    """Search nyxCore Axiom knowledge base."""
    resp = requests.post(
        f"{AXIOM_BASE}/api/v1/rag/search",
        headers={
            "Authorization": f"Bearer {AXIOM_TOKEN}",
            "Content-Type": "application/json",
        },
        json={
            "query": query,
            "limit": limit,
            **({"authority": authority} if authority else {}),
        },
    )
    resp.raise_for_status()
    data = resp.json()
    return data["results"]


def build_context(user_question: str) -> str:
    """Build RAG context from Axiom for injection into LLM prompt."""
    # 1. Always load mandatory rules first
    mandatory = search_axiom(user_question, limit=5, authority=["mandatory"])

    # 2. Then search guidelines + informational
    general = search_axiom(user_question, limit=10)

    # 3. Assemble context with authority headers
    context_parts = []
    for chunk in mandatory:
        context_parts.append(
            f"[MANDATORY — {chunk['filename']}]\n{chunk['content']}"
        )
    for chunk in general:
        if chunk["chunkId"] not in {c["chunkId"] for c in mandatory}:
            context_parts.append(
                f"[{chunk['authority'].upper()}{chunk['filename']}]\n"
                f"{chunk['content']}"
            )

    return "\n\n---\n\n".join(context_parts)

5.2 TypeScript / Node.js

const AXIOM_BASE = "https://nyxcore.cloud";
const AXIOM_TOKEN = process.env.AXIOM_TOKEN!; // nyx_ax_...

interface AxiomChunk {
  content: string;
  heading: string | null;
  filename: string;
  authority: "mandatory" | "guideline" | "informational";
  score: number;
  chunkId: string;
  documentId: string;
}

async function searchAxiom(
  query: string,
  options?: { limit?: number; authority?: string[] }
): Promise<AxiomChunk[]> {
  const res = await fetch(`${AXIOM_BASE}/api/v1/rag/search`, {
    method: "POST",
    headers: {
      Authorization: `Bearer ${AXIOM_TOKEN}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      query,
      limit: options?.limit ?? 10,
      ...(options?.authority && { authority: options.authority }),
    }),
  });

  if (!res.ok) {
    const err = await res.json().catch(() => null);
    throw new Error(
      `Axiom search failed: ${res.status} ${err?.error?.message ?? ""}`
    );
  }

  const data = await res.json();
  return data.results;
}

// Format results for LLM context injection
async function buildAxiomContext(userQuery: string): Promise<string> {
  const chunks = await searchAxiom(userQuery, {
    limit: 8,
    authority: ["mandatory", "guideline"],
  });

  return chunks
    .map(
      (c) =>
        `### ${c.heading ?? c.filename} [${c.authority}]\n${c.content}`
    )
    .join("\n\n");
}

5.3 curl (Quick Testing)

# Search
curl -X POST https://nyxcore.cloud/api/v1/rag/search \
  -H "Authorization: Bearer nyx_ax_YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"query": "GDPR data retention", "limit": 5}'

# List documents
curl https://nyxcore.cloud/api/v1/rag/documents \
  -H "Authorization: Bearer nyx_ax_YOUR_TOKEN"

# Upload a document
curl -X POST https://nyxcore.cloud/api/v1/rag/ingest \
  -H "Authorization: Bearer nyx_ax_YOUR_TOKEN" \
  -F "file=@./my-doc.md" \
  -F "authority=guideline"