Naxis Technologies Docs
Live demo

For developers

The client API

Every deployment exposes one versioned HTTP API under /api/v1: a data plane to push documents into the knowledge base, and a message plane to ask questions and get cited answers. Both are authenticated by a Bearer key you create in the admin console.

Base URL The API lives on your own deployment, e.g. https://assistant.yourcompany.com/api/v1. There is no Naxis-hosted API — your data never leaves your instance.

Two keys, two jobs

The API is surfaced as two catalog cards, each with its own key. Create them under Documents → Add a source → API (the ingest key) and Chat channels → Add a channel → API (the message key). A key is a Bearer secret shown once at creation; it starts with nx_sk_.

Data plane Ingest key
Push documents into the knowledge base.
POST /ingest/documents · /batch · /sync
Message plane Channel key
Ask questions and get cited answers.
POST /messages · /messages/stream · /conversations
CardKey authorisesAnswers as
API sourcethe /ingest/* endpoints
API channelthe /messages* and /conversations* endpoints a guest at the channel's groups, or a specific user for a per-user key

Authenticate every request with the header:

Authorization: Bearer nx_sk_…

Ingesting documents

Push a document by a stable external_id of your choosing — your record id, a file path, anything unique within the source. Re-pushing the same id replaces the document; the sweep re-indexes it in the background (responses are 202 Accepted with a job id).

Create or replace one document

POST /api/v1/ingest/documents
Content-Type: application/json

{
  "external_id": "crm/deal/8842",
  "title": "Acme renewal — terms",
  "text": "# Renewal\nThe Acme contract renews on 2026-09-01 …",
  "acl": ["grp:sales"],
  "metadata": {"source_system": "hubspot"}
}
curl -X POST https://your-assistant/api/v1/ingest/documents \
  -H "Authorization: Bearer $NAXIS_INGEST_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "external_id": "crm/deal/8842",
    "title": "Acme renewal — terms",
    "text": "# Renewal\nThe Acme contract renews on 2026-09-01 …",
    "acl": ["grp:sales"],
    "metadata": {"source_system": "hubspot"}
  }'

Provide exactly one of text (inline markdown/text/HTML) or content_base64 (base64 bytes for PDF, DOCX and other binaries, up to 50 MB). acl is a list of groups (grp:*); omit it and the document inherits the source's own groups. PUT /ingest/documents/{external_id} does the same, taking the id from the path.

Batch

POST /api/v1/ingest/documents/batch
{ "documents": [ { "external_id": "…", "text": "…" }, … ] }
curl -X POST https://your-assistant/api/v1/ingest/documents/batch \
  -H "Authorization: Bearer $NAXIS_INGEST_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "documents": [
      { "external_id": "crm/deal/8842", "title": "Acme renewal",  "text": "…" },
      { "external_id": "crm/deal/8843", "title": "Globex renewal", "text": "…" }
    ]
  }'

Up to 100 documents per call.

Read, delete, sync, status

Method & pathDoes
GET /ingest/documentsList pushed documents with indexing status (limit, offset, prefix).
GET /ingest/documents/{external_id}One document and its status.
DELETE /ingest/documents/{external_id}Tombstone it (the sweep removes it). ?purge=true erases immediately.
POST /ingest/syncRe-index this source's corpus now.
GET /ingest/statusStore and indexing counts for this source.
# List indexed documents (limit / offset / prefix)
curl "https://your-assistant/api/v1/ingest/documents?limit=20&prefix=crm/" \
  -H "Authorization: Bearer $NAXIS_INGEST_KEY"

# One document and its status (slashes in the id are percent-encoded)
curl https://your-assistant/api/v1/ingest/documents/crm%2Fdeal%2F8842 \
  -H "Authorization: Bearer $NAXIS_INGEST_KEY"

# Tombstone it — add ?purge=true to erase immediately
curl -X DELETE https://your-assistant/api/v1/ingest/documents/crm%2Fdeal%2F8842 \
  -H "Authorization: Bearer $NAXIS_INGEST_KEY"

Asking questions

Send a question to the message plane. The same call in three forms:

curl -X POST https://your-assistant/api/v1/messages \
  -H "Authorization: Bearer $NAXIS_MESSAGE_KEY" \
  -H "Content-Type: application/json" \
  -d '{"text":"When does the Acme contract renew?","end_user":"u-3391"}'

The answer is grounded in the documents the caller is allowed to see, and it cites the exact passages — or abstains when the knowledge base doesn't contain the answer, rather than guessing.

{
  "text": "The Acme contract renews on 1 September 2026 [1].",
  "abstained": false,
  "error": false,
  "conversation_id": "6f1c…",
  "citations": [
    { "n": 1, "passage_id": "…", "breadcrumb": "Acme renewal — terms › Renewal" }
  ]
}

end_user scopes conversation memory within the channel, so two of your users don't share a thread. Pass the returned conversation_id back to continue a multi-turn conversation. POST /messages/stream streams the same result over Server-Sent Events (a terminal final event carries the authoritative payload). A per-user key answers as its owner with the owner's own document access; the shared channel key answers as a guest at the channel's groups.

Streaming the answer

The same call over Server-Sent Events: incremental delta events, then one terminal final event carrying the authoritative payload (the same object POST /messages returns).

curl -N -X POST https://your-assistant/api/v1/messages/stream \
  -H "Authorization: Bearer $NAXIS_MESSAGE_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: text/event-stream" \
  -d '{"text":"When does the Acme contract renew?","end_user":"u-3391"}'

The wire format:

event: delta
data: {"text": "The Acme contract renews on "}

event: delta
data: {"text": "1 September 2026 [1]."}

event: final
data: {"text": "The Acme contract renews on 1 September 2026 [1].", "abstained": false, "conversation_id": "6f1c…", "citations": [{"n": 1, "breadcrumb": "Acme renewal — terms › Renewal"}]}

Conversations

Method & pathDoes
GET /conversationsThe caller's conversations.
GET /conversations/{id}One conversation's messages and citations.
DELETE /conversations/{id}Erase a conversation.
CID="6f1c9e2a-…"

# List the caller's conversations
curl https://your-assistant/api/v1/conversations \
  -H "Authorization: Bearer $NAXIS_MESSAGE_KEY"

# One conversation's messages and citations
curl "https://your-assistant/api/v1/conversations/$CID" \
  -H "Authorization: Bearer $NAXIS_MESSAGE_KEY"

# Erase a conversation
curl -X DELETE "https://your-assistant/api/v1/conversations/$CID" \
  -H "Authorization: Bearer $NAXIS_MESSAGE_KEY"

Limits & errors

StatusMeaning
202Ingest accepted; indexing runs in the background (carries a job id).
400Malformed request (missing external_id, both/neither of text and content, empty question).
401Missing or unknown Bearer key.
413Document over 50 MB, or request over 100 MB.
423The assistant is temporarily unavailable — contact your administrator.
429Rate limit: 300 pushes a minute per document key, 60 questions a minute per messaging key and end user, 120 calls a minute per admin key. Slow down and retry.
503The answering service was briefly unavailable; the turn was not saved — retry.
Interactive reference Each deployment serves a machine-readable OpenAPI 3 document for the data plane at /api/v1/openapi.json — point your generator or Postman at it.
Was this page helpful?
Was this page helpful? Sign in with Google Sign in to tell us — or leave a comment.

Last updated 28 Aug 2026