1. Create a token
Sign in to the DJC AI app, open the avatar menu (top right) and choose API. Click Create token, give it a name, pick Read only or Read & write, tick the resources it may use, and optionally set an expiry.
The token is shown once on creation and can be revealed again from the same page. Copy JSON gives you everything a script or an agent needs in one blob:
{
"apiToken": "djc_…",
"orgId": "d3fe674f-…",
"userId": "Qrpc3k06…",
"resources": {
"knowledge": { "access": "write", "baseUrl": "https://api.simplynice.ai/api/ai/knowledge", "firstCall": "GET /me" },
"workflows": { "access": "write", "baseUrl": "https://api.simplynice.ai/api/ai/simple-flow", "firstCall": "GET /me then GET /node-types" }
}
}Export the token for the examples below:
export DJC_TOKEN="djc_…"Keep it server-side
A write token can add, change and delete content in your workspace and spend your credits. Never ship it to a browser or a mobile app.
2. Check it with /me
Every resource has a /me. It confirms the token is valid and tells you what it may do there:
curl https://api.simplynice.ai/api/ai/knowledge/me -H "Authorization: Bearer $DJC_TOKEN"{
"userId": "Qrpc3k06…", "orgId": "d3fe674f-…",
"tokenKind": "token", "access": "write",
"scopes": ["knowledge:write", "workflows:write"],
"knowledgeBaseId": null, "base": "/bases"
}access is the level this token holds on that resource. If it says read, every write call will answer 403 INSUFFICIENT_SCOPE.
3. Your first read
List your knowledge bases, then search one. Search is free (no model call) and never changes anything:
curl https://api.simplynice.ai/api/ai/knowledge/bases -H "Authorization: Bearer $DJC_TOKEN"[ { "id": "5327d9b2-…", "name": "Product FAQ", "entryCount": 142, "sourceCount": 3, … } ]curl -X POST https://api.simplynice.ai/api/ai/knowledge/bases/$KB_ID/search \
-H "Authorization: Bearer $DJC_TOKEN" -H "Content-Type: application/json" \
-d '{ "query": "warranty on the X200", "topK": 3 }'{ "hits": [ { "id": "…", "subject": "Warranty", "question": "What is the warranty on the X200?",
"answer": "Two years from the date of purchase, parts and labour.", "vectorScore": 0.81, "score": 0.0328 } ],
"embeddingTokens": 12 }Want an answer rather than hits? POST …/ask with the same body returns a grounded answer plus the entries it used — this one uses credits.
const res = await fetch("https://api.simplynice.ai/api/ai/knowledge/bases/" + KB_ID + "/ask", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.DJC_TOKEN}`, "Content-Type": "application/json" },
body: JSON.stringify({ query: "How long is the X200 warranty?" }),
});
const { answer, hits } = await res.json();4. Your first write
Add a Q&A entry. It is indexed immediately and becomes searchable within a second:
curl -X POST https://api.simplynice.ai/api/ai/knowledge/bases/$KB_ID/entries \
-H "Authorization: Bearer $DJC_TOKEN" -H "Content-Type: application/json" \
-d '{
"subject": "Shipping",
"question": "Do you ship to Singapore?",
"altQuestions": ["International shipping"],
"answer": "Not yet — we ship within Malaysia only."
}'201 { "id": "6f2c…", "subject": "Shipping", "question": "Do you ship to Singapore?", "status": "active", "conflicts": 0, … }Search before you add
If a near-identical question already exists, edit that entry (PATCH) instead of adding a competing one — two answers to one question make retrieval worse, not better. The API flags anything ≥ 92 % similar as a draft conflict for you to resolve.
5. Create and run a flow
Create a three-node flow in one call, then run it and read the log:
curl -X POST https://api.simplynice.ai/api/ai/simple-flow/flows \
-H "Authorization: Bearer $DJC_TOKEN" -H "Content-Type: application/json" \
-d '{
"name": "Translate to Chinese",
"nodes": [
{ "id": "node1", "type": "trigger", "config": { "sampleData": { "text": "Good morning" } } },
{ "id": "node2", "type": "llmChain", "label": "Translate", "config": { "prompt": "Translate to Chinese: {{text}}" } },
{ "id": "node3", "type": "output" }
],
"edges": [ { "source": "node1", "target": "node2" }, { "source": "node2", "target": "node3" } ]
}'
# → 201 { "id": "14e452ac-…", "name": "Translate to Chinese", "nodeCount": 3, "edgeCount": 2, … }curl -X POST https://api.simplynice.ai/api/ai/simple-flow/flows/$FLOW_ID/execute -H "Authorization: Bearer $DJC_TOKEN"
# → 202 { "executionId": "3f9c…", "poll": "/api/ai/simple-flow/flows/…/executions/3f9c…" }
# poll every 1–3 s until status is "success" or "error"
curl https://api.simplynice.ai/api/ai/simple-flow/flows/$FLOW_ID/executions/$EXECUTION_ID -H "Authorization: Bearer $DJC_TOKEN"{ "status": "success",
"log": [
{ "nodeId": "node1", "status": "success", "output": [ { "json": { "text": "Good morning" } } ] },
{ "nodeId": "node2", "status": "success", "output": [ { "json": { "text": "早上好", "_llm": { "model": "qwen3.7-flash", "credits": 0.0002 } } } ] },
{ "nodeId": "node3", "status": "success", "output": [ { "json": { "text": "早上好" } } ] }
] }Open Simple Flow in the app — the new flow is on the canvas, and every edit you make through the API appears there within a few seconds.
Next steps
- Authentication & scopes — exactly which calls count as read.
- Knowledge guide — entries, extraction, imports, resolving conflicts, closing the gaps.
- Workflows guide — nodes, items, merge fields, branching, testing.
- API reference — every endpoint with samples.