Documentation
Customer API reference for SSIT AI Kit: base URL /api/v1, scoped keys, plans and scopes, endpoint table, OpenAPI JSON, Swagger explorer, and code samples.
Overview
All customer endpoints are under /api/v1. Send your workspace API key as X-API-Key or Authorization: Bearer <key>. GET /health does not require a key. Catalog defaults below can be adjusted by the operator in admin.
Plans and scopes
Scopes determine which routes your keys can call. Token credits are an abstract monthly budget per plan (not raw LLM tokens).
| Plan | Scopes | Monthly token credits |
|---|---|---|
|
trial_chat Trial Chat API · bounded free tier for evaluation |
chat | 15,000 |
|
paid_chat Starter Higher chat limits for production apps |
chat | 600,000 |
|
chat_agent Builder Chat + create and manage agents |
chat, chat_agent | 1,500,000 |
|
chat_agent_train Pro Agents + fine-tuning and training APIs |
chat, chat_agent, chat_agent_train | 4,000,000 |
|
local_agent_train Local train Your Ollama only — connect, fine-tune, and run models on hardware you control |
chat, chat_agent, chat_agent_train, local_model_access | 10,000,000 |
|
enterprise Enterprise Custom limits and SLA — contact sales |
chat, chat_agent, chat_agent_train | — |
Endpoint reference
Credit = token credits charged on a successful call (0 = free for metering). Paths use :id as a placeholder for resource IDs.
| Method | Path | Description | Required scope | Credit |
|---|---|---|---|---|
| GET | /health | Service health (no API key) | — | 0 |
| GET | /models | List Ollama models available to your key | chat | 0 |
| POST | /chat | Chat completion — set `model` to your base or fine-tuned Ollama name | chat | 1 |
| POST | /chat/stream | Streaming chat | chat | 1 |
| POST | /generate | Text generation | chat | 1 |
| GET | /finetune/datasets | List training datasets | chat_agent_train | 0 |
| POST | /finetune/datasets | Create dataset (JSON body: title, records or jsonl) | chat_agent_train | 5 |
| DELETE | /finetune/datasets/:id | Delete dataset (no jobs referencing it) | chat_agent_train | 0 |
| GET | /finetune/jobs | List fine-tune jobs | chat_agent_train | 0 |
| POST | /finetune/jobs | Create job (datasetId, baseModel, epochs, …) | chat_agent_train | 3 |
| GET | /finetune/jobs/:id | Get job status | chat_agent_train | 0 |
| POST | /finetune/jobs/:id/start | Start training run | chat_agent_train | 25 |
| POST | /finetune/jobs/:id/cancel | Cancel running job | chat_agent_train | 0 |
| GET | /finetune/jobs/:id/log | Training log lines | chat_agent_train | 0 |
| POST | /finetune/jobs/:id/register | Register output in Ollama (JSON: modelName) — then use that name in /chat | chat_agent_train | 12 |
| DELETE | /finetune/jobs/:id | Delete job | chat_agent_train | 0 |
OpenAPI and explorer
Download the machine-readable spec or open the interactive Swagger UI (same host; no admin login).
https://ai.systemsolveit.com — if PUBLIC_BASE_URL is set, use that host in clients and in Postman imports.
Postman
In Postman: Import → Link → paste your deployment’s OpenAPI URL (replace host with yours if needed).
https://ai.systemsolveit.com/documentation/openapi.json
Code samples
Replace YOUR_API_BASE (origin only, no trailing slash) and YOUR_API_KEY. Paths are under /api/v1.
Chat — Node (axios)
const axios = require('axios');
const API_BASE = 'YOUR_API_BASE'; // e.g. https://your-domain.com
const API_KEY = 'YOUR_API_KEY';
async function chat() {
const { data } = await axios.post(
`${API_BASE}/api/v1/chat`,
{
model: 'llama3.2',
messages: [{ role: 'user', content: 'Hello' }],
},
{ headers: { 'Content-Type': 'application/json', 'X-API-Key': API_KEY } }
);
return data;
}
Chat — Node (fetch)
const API_BASE = 'YOUR_API_BASE';
const API_KEY = 'YOUR_API_KEY';
const res = await fetch(`${API_BASE}/api/v1/chat`, {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'X-API-Key': API_KEY },
body: JSON.stringify({
model: 'llama3.2',
messages: [{ role: 'user', content: 'Hello' }],
}),
});
const data = await res.json();
Chat — Python
import requests
API_BASE = 'YOUR_API_BASE'
API_KEY = 'YOUR_API_KEY'
r = requests.post(
f'{API_BASE}/api/v1/chat',
headers={'X-API-Key': API_KEY, 'Content-Type': 'application/json'},
json={'model': 'llama3.2', 'messages': [{'role': 'user', 'content': 'Hello'}]},
timeout=120,
)
r.raise_for_status()
print(r.json())
Chat — PHP (cURL)
<?php $base = 'YOUR_API_BASE'; $key = 'YOUR_API_KEY'; $payload = json_encode([ 'model' => 'llama3.2', 'messages' => [['role' => 'user', 'content' => 'Hello']], ]); $ch = curl_init($base . '/api/v1/chat'); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'X-API-Key: ' . $key], CURLOPT_POSTFIELDS => $payload, CURLOPT_RETURNTRANSFER => true, ]); $out = curl_exec($ch); curl_close($ch);
Streaming chat — fetch (SSE)
const API_BASE = 'YOUR_API_BASE';
const API_KEY = 'YOUR_API_KEY';
const res = await fetch(`${API_BASE}/api/v1/chat/stream`, {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'X-API-Key': API_KEY },
body: JSON.stringify({
model: 'llama3.2',
messages: [{ role: 'user', content: 'Hello' }],
}),
});
const reader = res.body.getReader();
const dec = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) break;
console.log(dec.decode(value, { stream: true }));
}
Generate — fetch
const API_BASE = 'YOUR_API_BASE';
const API_KEY = 'YOUR_API_KEY';
const res = await fetch(`${API_BASE}/api/v1/generate`, {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'X-API-Key': API_KEY },
body: JSON.stringify({ model: 'llama3.2', prompt: 'Summarize: …' }),
});
const data = await res.json();
Health — fetch
const API_BASE = 'YOUR_API_BASE';
const res = await fetch(`${API_BASE}/api/v1/health`);
console.log(await res.text());
Fine-tune flow — fetch (outline)
const API_BASE = 'YOUR_API_BASE';
const API_KEY = 'YOUR_API_KEY';
const hdr = { 'Content-Type': 'application/json', 'X-API-Key': API_KEY };
// 1) Create dataset
let r = await fetch(`${API_BASE}/api/v1/finetune/datasets`, {
method: 'POST', headers: hdr,
body: JSON.stringify({ title: 'My dataset', records: [] }),
});
const ds = await r.json();
const datasetId = ds.id || ds._id;
// 2) Create job
r = await fetch(`${API_BASE}/api/v1/finetune/jobs`, {
method: 'POST', headers: hdr,
body: JSON.stringify({ datasetId, baseModel: 'llama3.2' }),
});
const job = await r.json();
const jobId = job.id || job._id;
// 3) Start training
await fetch(`${API_BASE}/api/v1/finetune/jobs/${jobId}/start`, { method: 'POST', headers: hdr });
// 4) Poll status
let status;
do {
await new Promise((x) => setTimeout(x, 5000));
r = await fetch(`${API_BASE}/api/v1/finetune/jobs/${jobId}`, { headers: { 'X-API-Key': API_KEY } });
status = await r.json();
} while (status.state === 'running' || status.state === 'pending');
// 5) Register model in Ollama, then chat with modelName
await fetch(`${API_BASE}/api/v1/finetune/jobs/${jobId}/register`, {
method: 'POST', headers: hdr,
body: JSON.stringify({ modelName: 'my-tuned-model' }),
});
await fetch(`${API_BASE}/api/v1/chat`, {
method: 'POST', headers: hdr,
body: JSON.stringify({
model: 'my-tuned-model',
messages: [{ role: 'user', content: 'Hello' }],
}),
});