API Reference

De Axoverna REST API laat je AI-powered product Q&A integreren in elke applicatie. Alle endpoints accepteren JSON en retourneren JSON.

Base URL: https://axoverna.com/api/v1

Quick Start

Start in drie stappen:

  1. 1Maak een account aan en genereer een API key via API Keys.
  2. 2Voeg content toe via de dashboard of de Ingest API.
  3. 3Stel je eerste vraag via POST /v1/ask.
Quick Start
curl -X POST https://axoverna.com/api/v1/ask \
  -H "Authorization: Bearer nx_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "Which supplement helps with joint pain?"
  }'

Authentication

Alle API requests vereisen een Bearer token in de Authorization header.

Authorization Header
Authorization: Bearer nx_live_YOUR_API_KEY

Er zijn drie typen API keys met verschillende toegangsniveaus:

Key PrefixScopeUse Case
nx_live_QueriesFrontend widget, /ask, /feedback
nx_ing_IngestionContent sync, /ingest/* endpoints
nx_adm_AdminFull access to all endpoints

Workspace Scoping

API keys zijn workspace-scoped of account-wide:

ScopeGedrag
Workspace-scopedKey werkt alleen voor de gekoppelde workspace. Geen extra parameters nodig.
Account-wideKey werkt voor alle workspaces in je account. Vereist workspace (slug) in de request body.
Account-wide keys — Bij gebruik van een account-wide key moet je het workspace veld (workspace slug) meesturen in de request body van elk endpoint. Dit geldt voor /ask, /context, /chat, /feedback en alle /ingest/* endpoints.

POST

/v1/ask

Auth: nx_live_ or nx_adm_

Stel een vraag over je productcatalogus. Retourneert een AI-gegenereerd antwoord met bronvermeldingen en confidence score.

Request Parameters

FieldTypeRequiredDescription
querystringYesThe question to ask (max 2000 chars)
workspacestringNoWorkspace slug. Required for account-wide API keys.
domainsstring[]NoFilter by domain slugs (e.g. ["products", "manuals"]). Auto-routed if omitted.
filtersobjectNoFilter by item metadata (e.g. {"category": "dental"})
top_knumberNoNumber of chunks to retrieve (1-20, default: 5)
session_idstringNoSession ID for conversation context
streambooleanNoEnable SSE streaming (default: false)

Response

200 OK
{
  "answer": "Joint Formula with glucosamine, MSM, and vitamin C...",
  "confidence": 0.94,
  "sources": [
    { "type": "product", "id": "JF-001", "title": "Joint Formula", "score": 0.96 },
    { "type": "manual", "page": 12, "title": "Product Guide", "score": 0.91 }
  ],
  "tokens_used": 342,
  "session_id": "sess_abc123"
}

Streaming (SSE)

Wanneer stream: true, retourneert de API een Server-Sent Events stream:

SSE Stream
data: {"type":"chunk","text":"Joint Formula"}
data: {"type":"chunk","text":" with glucosamine..."}
data: {"type":"sources","sources":[...]}
data: {"type":"done","tokens_used":342}

POST

/v1/context

Auth: nx_live_ or nx_adm_

Haal ruwe context chunks op uit je kennisbank zonder LLM-call. Ideaal voor externe content generatie: gebruik de chunks als context voor je eigen LLM om blogs, productbeschrijvingen of andere content te genereren.

Request Parameters

FieldTypeRequiredDescription
querystringYesSearch query to find relevant chunks (max 2000 chars)
workspacestringNoWorkspace slug. Required for account-wide API keys.
top_knumberNoNumber of chunks to return (1-50, default: 5)
domainsstring[]NoFilter by domain slugs (e.g. ["products", "manuals"]). Auto-routed if omitted.
filtersobjectNoFilter by item metadata (e.g. {"category": "dental"})

Response

200 OK
{
  "chunks": [
    {
      "item_id": "uuid",
      "title": "Joint Formula",
      "text": "Joint Formula with glucosamine, MSM, and vitamin C supports...",
      "section": "Product Description",
      "page_number": null,
      "chunk_index": 0,
      "score": 0.94,
      "metadata": { "category": "supplements" },
      "domain": "products"
    }
  ],
  "total_chunks": 5,
  "query_log_id": "uuid"
}

Example: Content Generation

Use with your own LLM
# 1. Get context from Axoverna
curl -X POST https://axoverna.com/api/v1/context \
  -H "Authorization: Bearer nx_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "joint supplements benefits",
    "top_k": 15
  }'

# 2. Use the chunks as context for your own LLM prompt
#    to generate blogs, product pages, or other content.

POST

/v1/chat

Auth: nx_live_ or nx_adm_

Conversational chat met sessigeheugen. Ondersteunt vervolgvragen — de context van vorige berichten wordt automatisch meegenomen. Retourneert altijd een SSE stream.

Request Parameters

FieldTypeRequiredDescription
messagestringYesThe message to send (max 2000 chars)
workspacestringNoWorkspace slug. Required for account-wide API keys.
session_idstringNoSession ID for conversation context. Auto-generated if omitted.
filtersobjectNoMetadata filters to narrow the knowledge base search

SSE Stream Events

SSE Stream
event: sources
data: [{"item_id":"uuid","title":"Joint Formula","score":0.96}]

event: delta
data: "Joint Formula bevat glucosamine,"

event: delta
data: " MSM en vitamine C..."

event: followups
data: ["Wat is de aanbevolen dosering?","Is het geschikt voor vegetariërs?","Welke alternatieven zijn er?"]

event: done
data: {"confidence":0.94,"tokens_used":312,"query_log_id":"uuid","session_id":"sess_abc123"}
Sessies — Sessies verlopen na 30 minuten inactiviteit. Start een nieuwe sessie door session_id weg te laten. De done event bevat altijd de actieve session_id, gebruik die voor het volgende bericht.

Live Human Chat

Two-sided conversation endpoints for chatting between your end-users and a human support agent, with automatic translation per participant language. Messages are stored in their source language and carry a translations JSONB map keyed by ISO language code. Realtime via Server-Sent Events.

The full stack is shipped: embed widget for customers, agent inbox under /admin/<workspace>/inbox, presence tracking, language-aware auto-routing, image attachments, and opt-in email notifications.

Flow at a glance

  1. Customer opens the widget on your site — conversation is created automatically.
  2. When an agent is online and speaks the customer's language, the conversation is auto-assigned; otherwise it lands in the queue where any agent can claim it.
  3. Agent types in their own language; customer sees it translated. Customer types back; agent sees their translation.
  4. Realtime updates both sides via SSE. Messages stored in both languages so reloads show the same history.

Auth model

All endpoints require a workspace-scoped API key. nx_live_ keys act as the end-user (customer/widget side); nx_adm_ keys act as the support agent. nx_ing_ keys are not allowed. Rate limits: 30 msg/min per live key, configurable per admin key.

Endpoints

POST/v1/chat/conversations

Create a new conversation. Body: end_user_language, handoff_mode (ai_only|human_only|ai_first|human_first), optional subject, end_user_id, end_user_session, source, rag_session_id. Returns 201 + full conversation row.

GET/v1/chat/conversations

List conversations (admin only). Query: status=active,waiting, assignee=<uuid|unassigned>, cursor before=<iso>, limit (max 100). Returns { items, nextBefore }.

GET/v1/chat/conversations/:id

Fetch a single conversation.

PATCH/v1/chat/conversations/:id

Update conversation (admin only). Body: status, assignee_user_id, subject, tags. Invalid status transitions return 409. Allowed: openwaiting|active|closed, waitingactive|closed, activewaiting|resolved|closed, resolvedwaiting|closed.

POST/v1/chat/conversations/:id/messages

Send a message. Body: body (1–10000 chars), source_language. Translations into each participant's language are produced via gpt-4o-mini and stored on the message. Auto-transitions: agent reply in waitingactive; end-user reply in resolvedwaiting. Returns 201 with the full message including translations.

GET/v1/chat/conversations/:id/messages

List messages (cursor paginated). Query: before=<iso>, limit (max 200), include_internal=1 (admin only, includes agent-only notes).

GET/v1/chat/conversations/:id/stream

Server-Sent Events stream. Emits hello once, then message.created, message.updated, message.seen, typing, conversation.updated events. Heartbeat :ping every 20s. Use fetch() + getReader() — not EventSource — so you can send the Authorization header.

POST/v1/chat/conversations/:id/typing

Publish a typing indicator. Body: { isTyping: boolean }. Event-only, no DB write. Returns 204.

POST/v1/chat/conversations/:id/seen

Mark a message seen. Body: { message_id }. Stamps messages.seen_by and emits message.seen. Returns 204.

POST/v1/chat/identify

Upsert an end-user profile. Body: at least one of external_id or email; optional name, language, metadata. Returns the upserted end-user row — use its id when creating a conversation.

POST/v1/chat/conversations/:id/claim

Race-safe claim of an unassigned conversation (admin + inbox key). Returns 409 if already claimed.

POST/v1/chat/agents/presence

Heartbeat for an agent. Body: { status: "online"|"away"|"offline" }. Called every 30s from the inbox; a cron demotes stale entries.

GETPATCH/v1/chat/agents/prefs

Read and update the current agent's notification preferences. Keys: email_new_queue, email_assigned_to_me, email_new_message, sound.

GET/v1/chat/widget/config

Public config the widget fetches on bootstrap: chat_mode, chat_identity_policy, branding, welcome/offline messages, language, workspace id.

GET/v1/chat/inbox/stream

SSE stream of workspace-wide inbox events (new conversations, assignee changes). Admin-only. Powers the realtime inbox list.

Image attachments

POST /v1/chat/conversations/:id/messages accepts multipart/form-data with an attachment field. PNG, JPEG, or WebP up to 5 MB. Images are stored in Vercel Blob and attached to the message with url, mime, and size metadata. Rendered inline in the inbox and widget bubbles.

Plan gating

Human chat is enabled on paid plans. Free workspaces get 402 PLAN_UPGRADE_REQUIRED. Canceled subscriptions get 402 BILLING_CANCELED. Seats per plan: Starter 1, Professional 3, Growth 5, Business 15, Enterprise unlimited. Translation tokens are metered into the workspace's monthly token usage.

Quick example

# 1. Create a conversation in Spanish
curl -X POST https://axoverna.com/api/v1/chat/conversations \
  -H "Authorization: Bearer nx_adm_..." \
  -H "Content-Type: application/json" \
  -d '{"end_user_language":"es","handoff_mode":"human_first","subject":"Support"}'
# → { "id": "...", "status": "open", ... }

# 2. Send an English agent message — gets auto-translated to Spanish
curl -X POST https://axoverna.com/api/v1/chat/conversations/<id>/messages \
  -H "Authorization: Bearer nx_adm_..." \
  -H "Content-Type: application/json" \
  -d '{"body":"Hello! How can I help?","source_language":"en","sender_type":"agent"}'
# → { ..., "translations": { "en": "Hello! How can I help?", "es": "¡Hola! ¿Cómo puedo ayudar?" } }

# 3. Subscribe to realtime events
curl -N https://axoverna.com/api/v1/chat/conversations/<id>/stream \
  -H "Authorization: Bearer nx_adm_..."

Translation

Target languages are derived from the conversation's end_user_language and the assigned agent's users.languages array. Translation is best-effort — failures don't block the send; a background worker retries and publishes a message.updated SSE event when the missing language arrives. Clients read message.translations[lang], falling back to message.body when a language isn't yet present.


POST

/v1/feedback

Auth: nx_live_ or nx_adm_

Stuur feedback over een antwoord. Wordt gebruikt om de kwaliteit te meten en het model te verbeteren.

Request Parameters

FieldTypeRequiredDescription
query_log_idstring (uuid)YesID of the query log entry to rate
rating1 | -1YesPositive (1) or negative (-1) feedback
workspacestringNoWorkspace slug. Required for account-wide API keys.
session_idstringNoSession ID for deduplication
commentstringNoOptional feedback text (max 2000 chars)

Response

200 OK
{ "success": true }

POST

/v1/ingest/items

Auth: nx_ing_ or nx_adm_

Voeg items toe aan je knowledge base. Ondersteunt JSON batch (max 100 items) en multipart/form-data voor PDF uploads.

Feed Import — Automatische import via CSV, JSON of XML feeds is beschikbaar via het Sources dashboard. Feeds worden periodiek gesynchroniseerd zonder API-aanroepen.

JSON Batch - Request Parameters

FieldTypeRequiredDescription
workspacestringNoWorkspace slug. Required for account-wide API keys.
domainstringNoDomain slug for all items in this batch. Overridable per item.
itemsobject[]YesArray of items to ingest (1-100)
items[].external_idstringNoYour unique identifier for the item
items[].typestringYesItem type (e.g. "product", "manual", "faq")
items[].titlestringYesItem title
items[].contentstringNoPlain text content
items[].metadataobjectNoArbitrary key-value metadata
items[].file_urlstring (url)NoURL to a PDF file for processing
items[].domainstringNoDomain slug for this item. Overrides batch-level domain.

JSON Batch - Response

202 Accepted
{
  "items_queued": 3,
  "job_ids": ["job_abc", "job_def", "job_ghi"],
  "status": "queued"
}

PDF Upload (multipart/form-data)

FieldTypeRequiredDescription
fileFileYesPDF file to upload
typestringYesItem type
titlestringYesItem title
external_idstringNoYour unique identifier
metadatastring (JSON)NoMetadata as JSON string
domainstringNoDomain slug for this item
workspacestringNoWorkspace slug. Required for account-wide API keys.
PDF Upload Example
curl -X POST https://axoverna.com/api/v1/ingest/items \
  -H "Authorization: Bearer nx_ing_YOUR_KEY" \
  -F "file=@product-guide.pdf" \
  -F "type=manual" \
  -F "title=Product Guide 2025"

POST

/v1/ingest/sync

Auth: nx_ing_ or nx_adm_

Synchroniseer je volledige catalogus. Items worden vergeleken op external_id. Nieuwe items worden toegevoegd, gewijzigde items geüpdatet, en ontbrekende items verwijderd.

Request Parameters

FieldTypeRequiredDescription
workspacestringNoWorkspace slug. Required for account-wide API keys.
domainstringNoScope sync to a specific domain. Only items in this domain are affected by deletions.
itemsobject[]YesComplete set of items to sync
items[].external_idstringYesRequired for sync - your unique identifier
items[].typestringYesItem type
items[].titlestringYesItem title
items[].contentstringNoPlain text content
items[].metadataobjectNoArbitrary key-value metadata
items[].file_urlstring (url)NoURL to a PDF file

Response

202 Accepted
{
  "to_add": 5,
  "to_update": 2,
  "to_delete": 1,
  "job_ids": ["job_abc", "job_def"],
  "status": "queued"
}

Items die niet in het request voorkomen maar wel in je workspace bestaan worden soft-deleted. Wijzigingen worden gedetecteerd op basis van content, title en metadata.

Domain scoping — Gebruik het domain veld om de sync te beperken tot een specifiek domein. Alleen items binnen dat domein worden vergeleken en eventueel verwijderd. Zonder domain geldt de sync voor alle items in de workspace.

POST

/v1/ingest/urls/analyze

Auth: nx_ing_ or nx_adm_

Analyseer een URL voordat je een web source aanmaakt. Detecteert automatisch sitemaps, paginaaantallen, SPA-status en stelt de optimale crawl-strategie en sync-planning voor.

Request Parameters

FieldTypeRequiredDescription
urlstring (url)YesThe URL to analyze

Response

200 OK
{
  "recommended_mode": "sitemap",
  "sitemap_url": "https://example.com/sitemap.xml",
  "page_count": 47,
  "is_spa": false,
  "suggested_schedule": "daily",
  "suggested_max_pages": 50,
  "internal_links": 12
}

Gebruik de teruggegeven waarden als defaults bij het aanmaken van een web source via het dashboard of API.recommended_mode is een van single, sitemap, of crawl.


Domain Management

Domeinen groeperen je content in logische categorieën (bijv. "products", "manuals", "faq"). Elk domein heeft eigen chunking-instellingen en een zoekgewicht. Gebruik domeinen om queries te filteren en de zoekresultaten te verbeteren.

GET

/v1/domains

Auth: nx_adm_

Lijst alle domeinen voor de huidige workspace.

200 OK
{
  "domains": [
    {
      "slug": "products",
      "label": "Products",
      "description": "Product catalog items",
      "active": true,
      "search_weight": 1.0,
      "split_method": "recursive",
      "chunk_min_tokens": 100,
      "chunk_max_tokens": 600,
      "chunk_overlap": 0.1,
      "created_at": "2026-01-15T10:00:00Z"
    }
  ]
}
POST

/v1/domains

Auth: nx_adm_

Maak een nieuw domein aan.

Request Parameters

FieldTypeRequiredDescription
slugstringYesUnique slug (lowercase, hyphens allowed, max 50 chars)
labelstringYesDisplay name (max 100 chars)
descriptionstringNoDescription (max 500 chars)
split_methodstringNo"recursive" (default), "section", "attribute", or "entity"
chunk_min_tokensnumberNoMinimum chunk size in tokens (100-600)
chunk_max_tokensnumberNoMaximum chunk size in tokens (100-600)
chunk_overlapnumberNoOverlap between chunks (0-0.15)
search_weightnumberNoSearch ranking weight (0.1-10, default: 1.0)
201 Created
{
  "slug": "manuals",
  "label": "Manuals",
  "active": true,
  "search_weight": 1.0,
  "split_method": "recursive",
  "chunk_min_tokens": 100,
  "chunk_max_tokens": 600
}
PUT

/v1/domains/:slug

Auth: nx_adm_

Update een bestaand domein. Alle velden zijn optioneel — alleen meegegeven velden worden gewijzigd.

Request Parameters

FieldTypeRequiredDescription
labelstringNoDisplay name (max 100 chars)
descriptionstring | nullNoDescription (max 500 chars, null to clear)
activebooleanNoEnable or disable the domain
split_methodstringNo"recursive", "section", "attribute", or "entity"
chunk_min_tokensnumberNoMinimum chunk size in tokens (100-600)
chunk_max_tokensnumberNoMaximum chunk size in tokens (100-600)
chunk_overlapnumberNoOverlap between chunks (0-0.15)
search_weightnumberNoSearch ranking weight (0.1-10)
200 OK
{ "status": "updated" }
DELETE

/v1/domains/:slug

Auth: nx_adm_

Verwijder een domein en alle gekoppelde items.

200 OK
{ "status": "deleted" }

GET

/v1/jobs/:id

Auth: nx_live_, nx_ing_ or nx_adm_

Controleer de status van een ingestion job. Poll dit endpoint na het aanmaken van items om te weten wanneer de content geïndexeerd is.

Response

200 OK
{
  "id": "job_abc123",
  "type": "embed_item",
  "status": "done",
  "item_title": "Joint Formula",
  "item_type": "product",
  "attempts": 1,
  "error": null,
  "created_at": "2025-01-15T10:30:00Z",
  "updated_at": "2025-01-15T10:30:05Z"
}

Mogelijke statussen: queued, running, done, failed.


Widget Embed

Voeg de Axoverna chat widget toe aan je website met een enkel script tag. De widget is volledig aanpasbaar via data-attributen.

  • Conversational chat met sessigeheugen — vervolgvragen werken automatisch, context wordt bijgehouden.
  • Slimme vervolgvragen — na elk antwoord toont de widget 2–3 suggesties voor vervolgvragen.
  • Nieuw gesprek (↻) — gebruikers kunnen de context resetten via de herstart-knop.
  • De widget gebruikt automatisch /v1/chat voor conversational mode, met fallback naar /v1/ask.
Embed Snippet
<script
  src="https://axoverna.com/widget.js"
  data-api-key="nx_live_YOUR_KEY"
  data-api-url="https://axoverna.com"
  data-title="Product Assistant"
  data-placeholder="Ask a question..."
  data-position="bottom-right"
  data-accent="#00D4C8"
></script>

Data Attributes

FieldTypeRequiredDescription
data-api-keystringYesYour live API key (nx_live_...)
data-api-urlstringNoAPI base URL (default: https://axoverna.com)
data-titlestringNoChat window title
data-placeholderstringNoInput field placeholder text
data-positionstringNo"bottom-right" (default) or "bottom-left"
data-accentstringNoAccent color in hex (e.g. #00D4C8)

Error Codes

De API retourneert standaard HTTP status codes. Foutresponses bevatten altijd een error veld.

Error Response
{
  "error": "Query limit exceeded for this billing period"
}
StatusCodeDescription
400Bad RequestInvalid JSON or missing required fields
401UnauthorizedMissing or invalid API key
403ForbiddenAPI key lacks permission for this endpoint
404Not FoundResource not found (e.g. job ID)
429Too Many RequestsRate limit or query limit exceeded
500Internal ErrorUnexpected server error

Rate Limiting

De API gebruikt een sliding window rate limiter. Limieten zijn afhankelijk van je plan en gelden per API key.

EndpointWindowLimit
/v1/ask1 minute60 requests
/v1/chat1 minute60 requests
/v1/feedback1 minute120 requests
/v1/ingest/*1 minute30 requests
/v1/jobs/:id1 minute120 requests

Bij overschrijding ontvang je een 429 Too Many Requests response. De Retry-After header geeft aan hoeveel seconden je moet wachten.

Naast rate limiting geldt ook een maandelijks query budget op basis van je plan. Controleer je gebruik via het Usage dashboard.