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:
- 1Maak een account aan en genereer een API key via API Keys.
- 2Voeg content toe via de dashboard of de Ingest API.
- 3Stel je eerste vraag via
POST /v1/ask.
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: Bearer nx_live_YOUR_API_KEYEr zijn drie typen API keys met verschillende toegangsniveaus:
| Key Prefix | Scope | Use Case |
|---|---|---|
| nx_live_ | Queries | Frontend widget, /ask, /feedback |
| nx_ing_ | Ingestion | Content sync, /ingest/* endpoints |
| nx_adm_ | Admin | Full access to all endpoints |
Workspace Scoping
API keys zijn workspace-scoped of account-wide:
| Scope | Gedrag |
|---|---|
| Workspace-scoped | Key werkt alleen voor de gekoppelde workspace. Geen extra parameters nodig. |
| Account-wide | Key werkt voor alle workspaces in je account. Vereist workspace (slug) in de request body. |
workspace veld (workspace slug) meesturen in de request body van elk endpoint. Dit geldt voor /ask, /context, /chat, /feedback en alle /ingest/* endpoints./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
| Field | Type | Required | Description |
|---|---|---|---|
| query | string | Yes | The question to ask (max 2000 chars) |
| workspace | string | No | Workspace slug. Required for account-wide API keys. |
| domains | string[] | No | Filter by domain slugs (e.g. ["products", "manuals"]). Auto-routed if omitted. |
| filters | object | No | Filter by item metadata (e.g. {"category": "dental"}) |
| top_k | number | No | Number of chunks to retrieve (1-20, default: 5) |
| session_id | string | No | Session ID for conversation context |
| stream | boolean | No | Enable SSE streaming (default: false) |
Response
{
"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:
data: {"type":"chunk","text":"Joint Formula"}
data: {"type":"chunk","text":" with glucosamine..."}
data: {"type":"sources","sources":[...]}
data: {"type":"done","tokens_used":342}/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
| Field | Type | Required | Description |
|---|---|---|---|
| query | string | Yes | Search query to find relevant chunks (max 2000 chars) |
| workspace | string | No | Workspace slug. Required for account-wide API keys. |
| top_k | number | No | Number of chunks to return (1-50, default: 5) |
| domains | string[] | No | Filter by domain slugs (e.g. ["products", "manuals"]). Auto-routed if omitted. |
| filters | object | No | Filter by item metadata (e.g. {"category": "dental"}) |
Response
{
"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
# 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./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
| Field | Type | Required | Description |
|---|---|---|---|
| message | string | Yes | The message to send (max 2000 chars) |
| workspace | string | No | Workspace slug. Required for account-wide API keys. |
| session_id | string | No | Session ID for conversation context. Auto-generated if omitted. |
| filters | object | No | Metadata filters to narrow the knowledge base search |
SSE Stream Events
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"}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.
/admin/<workspace>/inbox, presence tracking, language-aware auto-routing, image attachments, and opt-in email notifications.Flow at a glance
- Customer opens the widget on your site — conversation is created automatically.
- 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.
- Agent types in their own language; customer sees it translated. Customer types back; agent sees their translation.
- 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
/v1/chat/conversationsCreate 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.
/v1/chat/conversationsList conversations (admin only). Query: status=active,waiting, assignee=<uuid|unassigned>, cursor before=<iso>, limit (max 100). Returns { items, nextBefore }.
/v1/chat/conversations/:idFetch a single conversation.
/v1/chat/conversations/:idUpdate conversation (admin only). Body: status, assignee_user_id, subject, tags. Invalid status transitions return 409. Allowed: open→waiting|active|closed, waiting→active|closed, active→waiting|resolved|closed, resolved→waiting|closed.
/v1/chat/conversations/:id/messagesSend 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 waiting → active; end-user reply in resolved → waiting. Returns 201 with the full message including translations.
/v1/chat/conversations/:id/messagesList messages (cursor paginated). Query: before=<iso>, limit (max 200), include_internal=1 (admin only, includes agent-only notes).
/v1/chat/conversations/:id/streamServer-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.
/v1/chat/conversations/:id/typingPublish a typing indicator. Body: { isTyping: boolean }. Event-only, no DB write. Returns 204.
/v1/chat/conversations/:id/seenMark a message seen. Body: { message_id }. Stamps messages.seen_by and emits message.seen. Returns 204.
/v1/chat/identifyUpsert 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.
/v1/chat/conversations/:id/claimRace-safe claim of an unassigned conversation (admin + inbox key). Returns 409 if already claimed.
/v1/chat/agents/presenceHeartbeat for an agent. Body: { status: "online"|"away"|"offline" }. Called every 30s from the inbox; a cron demotes stale entries.
/v1/chat/agents/prefsRead and update the current agent's notification preferences. Keys: email_new_queue, email_assigned_to_me, email_new_message, sound.
/v1/chat/widget/configPublic config the widget fetches on bootstrap: chat_mode, chat_identity_policy, branding, welcome/offline messages, language, workspace id.
/v1/chat/inbox/streamSSE 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.
/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
| Field | Type | Required | Description |
|---|---|---|---|
| query_log_id | string (uuid) | Yes | ID of the query log entry to rate |
| rating | 1 | -1 | Yes | Positive (1) or negative (-1) feedback |
| workspace | string | No | Workspace slug. Required for account-wide API keys. |
| session_id | string | No | Session ID for deduplication |
| comment | string | No | Optional feedback text (max 2000 chars) |
Response
{ "success": true }/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.
JSON Batch - Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| workspace | string | No | Workspace slug. Required for account-wide API keys. |
| domain | string | No | Domain slug for all items in this batch. Overridable per item. |
| items | object[] | Yes | Array of items to ingest (1-100) |
| items[].external_id | string | No | Your unique identifier for the item |
| items[].type | string | Yes | Item type (e.g. "product", "manual", "faq") |
| items[].title | string | Yes | Item title |
| items[].content | string | No | Plain text content |
| items[].metadata | object | No | Arbitrary key-value metadata |
| items[].file_url | string (url) | No | URL to a PDF file for processing |
| items[].domain | string | No | Domain slug for this item. Overrides batch-level domain. |
JSON Batch - Response
{
"items_queued": 3,
"job_ids": ["job_abc", "job_def", "job_ghi"],
"status": "queued"
}PDF Upload (multipart/form-data)
| Field | Type | Required | Description |
|---|---|---|---|
| file | File | Yes | PDF file to upload |
| type | string | Yes | Item type |
| title | string | Yes | Item title |
| external_id | string | No | Your unique identifier |
| metadata | string (JSON) | No | Metadata as JSON string |
| domain | string | No | Domain slug for this item |
| workspace | string | No | Workspace slug. Required for account-wide API keys. |
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"/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
| Field | Type | Required | Description |
|---|---|---|---|
| workspace | string | No | Workspace slug. Required for account-wide API keys. |
| domain | string | No | Scope sync to a specific domain. Only items in this domain are affected by deletions. |
| items | object[] | Yes | Complete set of items to sync |
| items[].external_id | string | Yes | Required for sync - your unique identifier |
| items[].type | string | Yes | Item type |
| items[].title | string | Yes | Item title |
| items[].content | string | No | Plain text content |
| items[].metadata | object | No | Arbitrary key-value metadata |
| items[].file_url | string (url) | No | URL to a PDF file |
Response
{
"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 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./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
| Field | Type | Required | Description |
|---|---|---|---|
| url | string (url) | Yes | The URL to analyze |
Response
{
"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.
/v1/domains
Auth: nx_adm_
Lijst alle domeinen voor de huidige workspace.
{
"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"
}
]
}/v1/domains
Auth: nx_adm_
Maak een nieuw domein aan.
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| slug | string | Yes | Unique slug (lowercase, hyphens allowed, max 50 chars) |
| label | string | Yes | Display name (max 100 chars) |
| description | string | No | Description (max 500 chars) |
| split_method | string | No | "recursive" (default), "section", "attribute", or "entity" |
| chunk_min_tokens | number | No | Minimum chunk size in tokens (100-600) |
| chunk_max_tokens | number | No | Maximum chunk size in tokens (100-600) |
| chunk_overlap | number | No | Overlap between chunks (0-0.15) |
| search_weight | number | No | Search ranking weight (0.1-10, default: 1.0) |
{
"slug": "manuals",
"label": "Manuals",
"active": true,
"search_weight": 1.0,
"split_method": "recursive",
"chunk_min_tokens": 100,
"chunk_max_tokens": 600
}/v1/domains/:slug
Auth: nx_adm_
Update een bestaand domein. Alle velden zijn optioneel — alleen meegegeven velden worden gewijzigd.
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| label | string | No | Display name (max 100 chars) |
| description | string | null | No | Description (max 500 chars, null to clear) |
| active | boolean | No | Enable or disable the domain |
| split_method | string | No | "recursive", "section", "attribute", or "entity" |
| chunk_min_tokens | number | No | Minimum chunk size in tokens (100-600) |
| chunk_max_tokens | number | No | Maximum chunk size in tokens (100-600) |
| chunk_overlap | number | No | Overlap between chunks (0-0.15) |
| search_weight | number | No | Search ranking weight (0.1-10) |
{ "status": "updated" }/v1/domains/:slug
Auth: nx_adm_
Verwijder een domein en alle gekoppelde items.
{ "status": "deleted" }/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
{
"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/chatvoor conversational mode, met fallback naar/v1/ask.
<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
| Field | Type | Required | Description |
|---|---|---|---|
| data-api-key | string | Yes | Your live API key (nx_live_...) |
| data-api-url | string | No | API base URL (default: https://axoverna.com) |
| data-title | string | No | Chat window title |
| data-placeholder | string | No | Input field placeholder text |
| data-position | string | No | "bottom-right" (default) or "bottom-left" |
| data-accent | string | No | Accent color in hex (e.g. #00D4C8) |
Error Codes
De API retourneert standaard HTTP status codes. Foutresponses bevatten altijd een error veld.
{
"error": "Query limit exceeded for this billing period"
}| Status | Code | Description |
|---|---|---|
| 400 | Bad Request | Invalid JSON or missing required fields |
| 401 | Unauthorized | Missing or invalid API key |
| 403 | Forbidden | API key lacks permission for this endpoint |
| 404 | Not Found | Resource not found (e.g. job ID) |
| 429 | Too Many Requests | Rate limit or query limit exceeded |
| 500 | Internal Error | Unexpected server error |
Rate Limiting
De API gebruikt een sliding window rate limiter. Limieten zijn afhankelijk van je plan en gelden per API key.
| Endpoint | Window | Limit |
|---|---|---|
| /v1/ask | 1 minute | 60 requests |
| /v1/chat | 1 minute | 60 requests |
| /v1/feedback | 1 minute | 120 requests |
| /v1/ingest/* | 1 minute | 30 requests |
| /v1/jobs/:id | 1 minute | 120 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.