API keys and the API
The Genie API lets your own applications and scripts ask Genie questions, search knowledge bases and add documents. Each application signs in with an API key that a workspace owner creates in Settings. This page shows how to create a key, what a key can and cannot reach, and one complete example: ask a question, stream the answer and read its citations.
Create an API key
You need the Owner role: only owners see the API page.
- Open Settings → API (in the Publish & integrations group).
- Under API Keys, click Create API Key.
- In Name, say which application uses the key, for example
Intranet portal. - Under Access type, keep Scoped access.
- Under Capabilities, select only what the application needs (see the table below). A new key starts with Retrieve knowledge bases, Chat and Read agents.
- Under Knowledge bases, choose the knowledge bases the key may use, for example Human resources. Leave it empty to allow every knowledge base in the workspace.
- Click Create API Key.
- In the list, click the copy button on the key's row and store the key in your application's secret store. Keys start with
sk-.
website-docs/public/screenshots/en/api-keys.pngTo change a key's name, capabilities or knowledge bases, click the edit button on its row (Edit API key). Changes apply at once and the key value stays the same. To revoke a key, click Delete: every integration that uses it stops working immediately.
Choose capabilities
| Capability | What the key can do |
|---|---|
| Retrieve knowledge bases | Search and read the selected knowledge bases. It cannot chat or change anything. |
| Chat | Create its own conversations, ask questions and list agents. |
| Read agents | List agents and read their details and suggested questions. |
| Write KB content | Upload documents and edit content in the selected knowledge bases. It cannot create or empty a knowledge base. |
| Message history | Search the key's own past conversations (with a user identity, that user's). It never reaches other people's conversations. |
The other capabilities (managing knowledge bases, agents, MCP services, data sources, models, channels, members and workspace settings) and Workspace full access are for administration tools. Give them only to a trusted application that runs on a server. Workspace full access ignores the knowledge base list.
What a key can and cannot reach
- Knowledge bases: only those selected on the key. A request that names another knowledge base is refused; when Genie or an agent picks knowledge bases itself, it keeps to the key's list.
- Documents: unrestricted documents only. A document with document permissions is never searched or cited for an API key, whatever its capabilities, including Workspace full access.
- Databases and Power BI: not available. Genie answers API questions from documents and, when allowed, the web.
- Code: Genie does not run code in a sandbox for an API key.
- Features for signed-in people only: sharing and exporting conversations, analytics, managing API keys.
A key acts as an application, not as an employee. Sending a user ID (see Identify your users) keeps each user's conversations apart, but it does not give the key that person's document permissions. The conversations a key starts belong to it: the workspace's admins cannot read them in Genie.
The base URL
The API Base URL field on the API page shows the address to call, for example https://genie.contoso.test/api/v1. Every request sends the key in the X-API-Key header. Requests and responses are JSON; answers stream as server-sent events.
To try a call without writing code, click Open Playground under API Playground on the same page. It creates a conversation and asks a test question, using an API key from the list.
Example: ask a question and stream the answer
This example asks Genie, the default assistant, a question about Contoso's leave policy with a key that has the Chat capability.
Set the base URL and your key:
bashGENIE_API=https://genie.contoso.test/api/v1 GENIE_API_KEY=sk-... # the key you copiedCreate a conversation:
bashcurl -s -X POST "$GENIE_API/sessions" \ -H "X-API-Key: $GENIE_API_KEY" \ -H "Content-Type: application/json" \ -d '{"title":"Annual leave"}'The response contains the conversation ID in
data.id:json{"success":true,"data":{"id":"8b6f2c1e-4d0a-4c55-9a51-2f3e7d9c0b12","title":"Annual leave"}}The real response has more fields; you only need
data.id.Ask the question in that conversation:
bashSESSION_ID=8b6f2c1e-4d0a-4c55-9a51-2f3e7d9c0b12 curl -N -X POST "$GENIE_API/agent-chat/$SESSION_ID" \ -H "X-API-Key: $GENIE_API_KEY" \ -H "Content-Type: application/json" \ -d '{"query":"How many days of annual leave does a new employee get?","agent_id":"builtin-auto","agent_enabled":true,"channel":"api"}'builtin-autois Genie, the default assistant: it chooses the knowledge bases and tools itself, as in the web app. To ask a specific agent, put its ID instead;GET $GENIE_API/agentslists the agents with their IDs.-Nmakes curl print the answer as it arrives.Read the stream. Each event is an
event:messageline followed by adata:line with a JSON object (shortened here):textevent:message data:{"response_type":"agent_query","content":"","done":false,"session_id":"8b6f2c1e-…","assistant_message_id":"c41d9e07-…"} event:message data:{"response_type":"answer","content":"A new employee gets 12 days of annual leave a year","done":false} event:message data:{"response_type":"answer","content":" <kb doc=\"Employee handbook\" chunk_id=\"5a1c…\" kb_id=\"3d7f…\" />.","done":false} event:message data:{"response_type":"references","content":"","done":false,"knowledge_references":[{"id":"5a1c…","knowledge_title":"Employee handbook","knowledge_id":"9e2b…","knowledge_base_id":"3d7f…","content":"Employees receive 12 days of paid annual leave per year…","score":0.82}]} event:message data:{"response_type":"complete","content":"","done":true}
Read the answer and its citations
Handle the events by their response_type:
response_type | What it carries | What to do with it |
|---|---|---|
agent_query | session_id and assistant_message_id | Keep the message ID if you may need to stop the answer. |
answer | The next piece of the answer in content | Append it to the answer text, in order. |
references | knowledge_references: the passages the answer cites | Show them as sources. |
error | Why the answer failed, in content | Show an error. |
complete | The end of the answer (done is true) | Stop reading. |
thinking, tool_call, tool_result and others | Genie's working steps | Optional: ignore them if you only need the answer. |
Citations sit inside the answer text as tags:
<kb doc="…" chunk_id="…" kb_id="…" />cites a passage of a document.docis the document title;chunk_idmatches theidof an entry inknowledge_references, whosecontentis the cited passage andknowledge_titlethe document.<web url="…" title="…" />cites a web page.
Turn the tags into links or footnotes in your application, or remove them if you only show plain text.
To ask a follow-up question, send another agent-chat request with the same conversation ID. To read the whole conversation later, call GET $GENIE_API/messages/$SESSION_ID/load: each answer has its content and knowledge_references.
Identify your users (optional)
If your application serves many employees with one key, tell Genie who is asking so that each person's conversations stay separate. On the API page, under User identity mode:
- Workspace only (default): all calls share one identity.
- Direct user ID: send the user's ID in the
X-External-User-IDheader. Use it only for calls from your own server, never from a browser. - Signed token: your server signs a short-lived token (an HS256 JWT) for the user with the HMAC secret and sends it in the
X-External-User-Tokenheader. Use this for applications your users run themselves.
The page shows a signing example and a request example for the mode you choose.
Good to know
- Never put an API key in a web page, a mobile app or a public code repository. To put Genie on a web page, use the website widget.
- Common errors:
401means the key is missing, wrong or deleted;403means the key lacks the capability or the knowledge base;409means an answer is still being written in that conversation;429means the workspace's monthly budget is used up. - To stop an answer, call
POST $GENIE_API/sessions/$SESSION_ID/stopwith{"message_id":"<assistant_message_id>"}. - To get matching passages without an answer, for example for your own search page, use
POST $GENIE_API/knowledge-searchwith a key that has Retrieve knowledge bases. - The complete endpoint reference is not on this site. Ask your Genie provider for it.