Documentation menu

Start here

Quickstart

From a fresh token to a knowledge search, a new entry, and a running workflow — in five short steps.

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:

Credentials JSON (from the token page)
{
  "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:

Request
curl https://api.simplynice.ai/api/ai/knowledge/me -H "Authorization: Bearer $DJC_TOKEN"
Response
{
  "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:

List bases
curl https://api.simplynice.ai/api/ai/knowledge/bases -H "Authorization: Bearer $DJC_TOKEN"
Response
[ { "id": "5327d9b2-…", "name": "Product FAQ", "entryCount": 142, "sourceCount": 3,  } ]
Search
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 }'
Response
{ "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.

Same thing from Node.js
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:

Request
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."
  }'
Response
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:

Create
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, … }
Run and poll
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"
Execution
{ "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