Jenn API Documentation
Jenn is an open-source, self-hosted AI message router. It captures messages from multiple sources (Telegram, Desktop CLI, API), processes them through an AI router with multi-provider fallback (Groq → OpenRouter → GigaChat), and routes the results to your knowledge bases (Notion, Obsidian). Your data stays on your machine.
Messages flow through a simple pipeline: Input (Telegram/CLI/API) → Jenn Core (AI Router + Skills) → Output (Notion/Obsidian). The AI router determines intent and category, then executes the appropriate skill to save or process the data.
Quick Start
Get Jenn running in under 5 minutes.
git clone https://github.com/yourusername/jenn.git
cd jenn
npm installcp .env.example .env
# Edit .env with your API keys
# GROQ_KEY, OPENROUTER_KEY, NOTION_API_KEY, JWT_SECRETnpx prisma migrate dev
node index.js
# → http://localhost:3000
# → Console: http://localhost:3000/consoleArchitecture
The data flow from input to output.
Authentication
Public API uses Bearer tokens. Each input source gets its own UUID token.
Authorization: Bearer 550e8400-e29b-41d4-a716-446655440000
Admin API uses JWT tokens (httpOnly cookie or Bearer header). Register via POST /v1/admin/register to get started.
/health
Server Health
No authentication required. Returns server status.
curl http://localhost:3000/health
{
"status": "ok",
"uptime": 123456,
"version": "1.0.0"
}
/v1/ping
Ping
Check that your token is valid and the input source is configured correctly.
curl -H "Authorization: Bearer YOUR_TOKEN" \
http://localhost:3000/v1/ping
{
"status": "ok",
"source": "tg_bot"
}
/v1/message
Send Message
The core endpoint. Sends a message for AI processing and routing.
| Field | Type | Required | Description |
|---|---|---|---|
| source | string | yes | Source name (must match token) |
| text | string | yes | Message text (max 4096 chars) |
| user.id | string | yes | User ID in source system |
| user.name | string | no | Display name |
| meta | object | no | Any additional data |
curl -X POST http://localhost:3000/v1/message \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"source": "tg_bot",
"text": "Meeting notes from today: discussed Q3 roadmap",
"user": { "id": "123456789", "name": "Ivan" },
"meta": { "chat_id": -1001234567890 }
}'
{
"status": "ok",
"message_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"received_at": "2026-07-07T12:00:00Z",
"result": {
"success": true,
"output": "notion",
"destination": "Meeting Notes",
"category": "work"
}
}
Admin Authentication
JWT-based auth via httpOnly cookie or Bearer header.
/v1/admin/register
// Request
{ "username": "admin", "password": "your_password" }
// Response 201
{ "status": "ok", "token": "eyJhbGciOi..." }
/v1/admin/login
// Same body as register
{ "username": "admin", "password": "your_password" }
// Response 200
{ "status": "ok", "token": "eyJhbGciOi..." }
Configuration
/v1/admin/config
Returns the full user configuration (inputs, outputs, skills, routing).
// Response 200
{
"status": "ok",
"config": {
"inputs": ["tg_bot", "desktop"],
"outputs": { "notion": { "api_key": "..." } },
"skills": ["save_entry"]
}
}
/v1/admin/config
// Request — saves full config
{ "config": { ... } }
// Response 200
{ "status": "ok" }
Inputs
Manage input sources (Telegram Bot, Desktop CLI) and review custom marketplace requests from the console.
/v1/admin/inputs— List installed inputs/v1/admin/inputs/library— Browse available inputs/v1/admin/inputs/:name/install— Install input + create token/v1/admin/inputs/:name— Uninstall input/v1/admin/inputs/:name/config— Get input config/v1/admin/inputs/:name/config— Save input config/v1/admin/inputs/:name/test— Test input connection/v1/admin/marketplace-requests— List custom marketplace requests/v1/admin/marketplace-requests— Submit GitHub repo, description, and docs linkOutputs
Manage output targets (Notion, Obsidian) and review custom marketplace requests from the console.
/v1/admin/outputs— List installed outputs/v1/admin/outputs/library— Browse available outputs/v1/admin/outputs/:name/install— Install output/v1/admin/outputs/:name— Uninstall output/v1/admin/outputs/:name/config— Get output config/v1/admin/outputs/:name/test— Test output connection/v1/admin/outputs/:name/destinations— List destinations/v1/admin/outputs/:name/sync-destinations— Sync from external app/v1/admin/outputs/:name/sync-schema— Sync Notion DB schema/v1/admin/outputs/:name/functions— List output functions/v1/admin/marketplace-requests— List custom marketplace requests/v1/admin/marketplace-requests— Submit GitHub repo, description, and docs linkSkills
Manage skills (save_entry, custom skills) and create new ones from the pipeline skill hub.
/v1/admin/skills— List installed skills/v1/admin/skills/library— Browse skill marketplace/v1/admin/skills/:name/install— Install skill/v1/admin/skills/:name— Uninstall skill/v1/admin/skills/create— Create custom skill/v1/admin/skills/:name/publish— Publish to marketplace/v1/admin/skills/:name/config— Get skill config/v1/admin/skills/:name/config— Save skill config/v1/admin/capabilities— Aggregated capabilitiesLogs & Messages
/v1/admin/messages?limit=50— Message history/v1/admin/test-message— Send test message/v1/admin/logs/recent— Recent log entries/v1/admin/logs/stream— SSE real-time streamconst es = new EventSource('/v1/admin/logs/stream?token=YOUR_JWT');
es.onmessage = (e) => {
const log = JSON.parse(e.data);
console.log(log.time, log.level, log.msg);
};
Rate Limits
| Limit | Value |
|---|---|
| Messages per minute | 60 |
| Max text length | 4096 chars |
| Max request body | 64 KB |
Exceeding limits returns 429 Too Many Requests with a Retry-After header.
Error Codes
| Error | HTTP | Description |
|---|---|---|
| invalid_token | 401 | Token not found or expired |
| missing_fields | 400 | Required fields missing |
| source_mismatch | 403 | Token belongs to different source |
| text_too_long | 413 | Text exceeds 4096 characters |
| rate_limited | 429 | Too many requests |
{
"error": "invalid_token",
"message": "Token not found or expired"
}