Note: the task's "Authoritative research for api" field was delivered empty (
{}). Rather than invent details, every API fact below is sourced directly from the Socheli monorepo —packages/api/src/server.ts,packages/api/src/match.ts,packages/api/package.json,packages/sdk/src/index.ts, anddocs/api.md. No endpoints, fields, env vars, or auth semantics have been invented.
The REST control-plane backbone for Socheli — a Hono API at api.socheli.com that dispatches render jobs across a fleet over MQTT.
@socheli/api is the HTTP control plane for the Socheli content engine. Every first-party client — the SDK, the CLI, the MCP server — and any third-party integration talks to this service.
It is a small, fast Hono server (@hono/node-server) that does two things:
- Reads come straight from the file store (
items,jobs,fleet,schedule). - Writes either dispatch a job to a render device over MQTT or spawn the engine directly.
Generation requests are routed by a capability-aware central scheduler: each job's requirements are derived, then the best-fit online device in the live fleet is selected (preferring an idle device, with more RAM as a tie-breaker).
Auth is a single static API key, passed as a Bearer token.
npm install @socheli/api
# or
pnpm add @socheli/apiThe package exposes a socheli-api binary and a start script.
Run it:
SOCHELI_API_KEY=sk_your_key npm start
# [socheli-api 0.1.0] listening on :8787If
SOCHELI_API_KEYis unset, the server still boots but logs a warning and answers503 API not configured (no SOCHELI_API_KEY)on every authenticated route.
The managed instance lives at https://api.socheli.com (version prefix /v1). You don't need to self-host to use it — point a client at the base URL with your key.
A single Socheli API key, sent as a Bearer token. Every endpoint except GET /v1/health requires it.
Authorization: Bearer <SOCHELI_API_KEY>
| Failure | Status | Body |
|---|---|---|
| Wrong / missing key | 401 |
{ "error": "unauthorized" } |
| Server has no key configured | 503 |
{ "error": "API not configured (no SOCHELI_API_KEY)" } |
Clients (SDK/CLI/MCP) read the key from the SOCHELI_API_KEY environment variable. On a self-hosted deployment, set it in the server's environment (e.g. an .env file or your process manager). For the managed service, provision a key from your Socheli dashboard.
# Health (no auth required)
curl -s https://api.socheli.com/v1/health
# Inspect the fleet
curl -s https://api.socheli.com/v1/fleet \
-H "Authorization: Bearer $SOCHELI_API_KEY"
# Generate + publish a vertical post end to end
curl -s -X POST https://api.socheli.com/v1/generate \
-H "Authorization: Bearer $SOCHELI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"seed":"why we procrastinate","channel":"concept_lab","type":"auto"}'Prefer typed calls? Use the @socheli/sdk:
import { createSocheli } from "@socheli/sdk";
const socheli = createSocheli({ apiKey: process.env.SOCHELI_API_KEY });
const { devices, online } = await socheli.fleet();
const { job } = await socheli.generate({ seed: "the science of habit", channel: "concept_lab" });Base URL: https://api.socheli.com · Version prefix: /v1
All responses are JSON. Errors are { "error": "message" } with conventional status codes:
400 bad input · 401 unauthorized · 404 not found · 502 broker down · 503 unconfigured.
Open (no auth). Liveness + build info.
→ { ok: true, version: string, uptime: number } — uptime in seconds.
List recent items.
Query: limit (number), channel (string).
→ ItemSummary[] — each { id, channel, status, title, createdAt, updatedAt, qa?, costUsd?, publish? }.
Full item.
→ Item (extends ItemSummary, adds idea, script, storyboard, pkg, videoUrl). 404 if missing.
The 30 most recent fleet jobs.
→ JobRow[] — each { id, type, status, device?, itemId?, progress[], … }.
Devices + recent jobs + online count.
→ FleetState — { devices: Device[], jobs: JobRow[], online: number }.
Read the current autopilot schedule (cadence + slots).
→ Schedule.
Dispatch a render job to the fleet. The central scheduler derives the job's capability requirements and routes it to the best-fit device over MQTT.
Body:
{
"seed": "the science of habit",
"channel": "concept_lab",
"type": "new",
"mood": "explainer",
"voice": false
}| Field | Type | Notes |
|---|---|---|
seed |
string | Required. 400 seed required if absent. |
channel |
string | Defaults to concept_lab. |
type |
"new" | "auto" |
"new" = build only; "auto" = build + publish. Anything else coerces to "new". |
mood |
string | Optional render mood (e.g. explainer, cinematic). |
voice |
boolean | true prefers a premium-voice-capable device. |
→ { dispatched: true, job, device, routing }.
503with{ error, requirements }if no online device satisfies the job's hard requirement (render).502 broker unreachable: <message>if the MQTT broker can't be reached.
Scheduler behavior (from match.ts): every generation job hard-requires the render capability. Music (music:musicgen), b-roll (broll:sdturbo, broll:pexels), and — when voice: true — premium voice (voice:eleven) are preferences; a minimal device still renders, degrading gracefully. Among capable online devices, an idle device is strongly preferred (+100), each matched preference adds +10, and more RAM breaks ties.
Publish an existing item to all configured platforms (server-side). Spawns the engine's publish command detached.
Body:
{ "public": true, "aigc": true }| Field | Type | Effect |
|---|---|---|
public |
boolean | true adds --public. |
aigc |
boolean | false adds --no-aigc (AIGC disclosure on by default). |
→ { dispatched: true }.
Replace the autopilot schedule (cadence + slots). Persists to schedule.json and stamps updatedAt.
Body: a Schedule object. 400 bad schedule if the body isn't an object.
→ the saved Schedule.
The @socheli/sdk SocheliClient mirrors this API one-to-one. Zero runtime dependencies — just fetch (Node 18+, Bun, Deno, edge).
| SDK call | HTTP |
|---|---|
socheli.health() |
GET /v1/health |
socheli.items.list({ limit?, channel? }) |
GET /v1/items |
socheli.items.get(id) |
GET /v1/items/:id |
socheli.items.publish(id, input?) |
POST /v1/items/:id/publish |
socheli.generate(input) |
POST /v1/generate |
socheli.jobs() |
GET /v1/jobs |
socheli.fleet() |
GET /v1/fleet |
socheli.schedule.get() |
GET /v1/schedule |
socheli.schedule.set(schedule) |
PUT /v1/schedule |
import { createSocheli, SocheliError } from "@socheli/sdk";
// apiKey ← opts.apiKey ?? process.env.SOCHELI_API_KEY
// baseUrl ← opts.baseUrl ?? process.env.SOCHELI_API_URL ?? https://api.socheli.com
const socheli = createSocheli();
try {
const items = await socheli.items.list({ channel: "concept_lab", limit: 10 });
} catch (e) {
if (e instanceof SocheliError) console.error(e.status, e.message, e.body);
}The server reads everything from environment variables.
| Variable | Default | Purpose |
|---|---|---|
SOCHELI_API_KEY |
(none) | Bearer key required by all /v1/* routes except /v1/health. |
SOCHELI_API_PORT |
8787 |
Listen port. |
SOCHELI_BROKER_URL |
mqtt://127.0.0.1:1883 |
MQTT broker for fleet dispatch. |
SOCHELI_MQTT_USER |
(none) | MQTT username. |
SOCHELI_MQTT_PASS |
(none) | MQTT password. |
SOCHELI_DATA_DIR |
<root>/data |
File store root (items, jobs, fleet, schedule). |
SOCHELI_RENDERS_DIR |
<DATA_DIR>/renders |
Rendered output directory. |
Client-side, @socheli/sdk honors SOCHELI_API_KEY and SOCHELI_API_URL.
POST /v1/generate connects to the broker (SOCHELI_BROKER_URL, with optional user/pass and an 8s connect timeout) and publishes the job to:
socheli/device/<device>/jobs (QoS 1)
where <device> is the device chosen by the central scheduler.
All errors return JSON { "error": "message" }:
| Status | When |
|---|---|
400 |
Bad input (seed required, bad schedule). |
401 |
Wrong or missing API key. |
404 |
Item or route not found. |
502 |
Broker unreachable during dispatch. |
503 |
API not configured, or no online device satisfies the job. |
@socheli/api is one of four packages — pick the surface that fits your stack. All speak to the same control plane.
| Package | What it is | Repo |
|---|---|---|
@socheli/api |
REST control plane (Hono) at api.socheli.com, with MQTT fleet dispatch. |
Socheli/api |
@socheli/sdk |
Official zero-dependency TypeScript client. | Socheli/sdk |
@socheli/cli |
The socheli command-line interface. |
Socheli/cli |
@socheli/mcp |
Model Context Protocol server — Socheli as agent tools. | Socheli/mcp |
Docs: socheli.com/docs
@socheli/api is developed and released from the Socheli monorepo, alongside the engine, SDK, CLI, MCP server, and dashboard. This repo mirrors the packages/api workspace.
MIT