Driving Chain Desk from code
Everything the web app does is available over HTTP. The base URL is
https://api.skillsafe.ai/v1/app-api, every request carries
Authorization: Bearer <token>, and every response is the same envelope.
The task field comes first
This app has five lanes behind one endpoint. Every run body must carry a
task field naming the lane - it is what the system prompt routes on. Send
the wrong one and you get a valid package of the wrong kind; omit it and the model picks the
closest lane and tells you which it chose.
One more shape trap: the run body is the input object. Do not wrap it in an
{"input": ...} envelope - that returns 200 while hiding task from the
model, which is the most confusing way this API can fail.
| task | Lane | Fields | Sections returned |
|---|---|---|---|
plan | Write the chain from what you want | brief, known | Summary, The Chain, The Numbers, Reasoning, Next Step |
check | What this chain actually does to the picture | sheet, worry | Summary, Verdict, Findings, Corrected Chain, Next Step |
order | Which swaps change the picture | sheet | Summary, Step By Step, Every Swap, What The Order Buys, Next Step |
pixels | What survives, and what was invented | sheet | Summary, The Source Region, The Bottleneck, What Survives, Next Step |
deliver | Decide what changes: the order, the numbers, or the source | sheet, fixed | Summary, A Reorder Fixes, Only Different Numbers Fix, Nothing Fixes, Next Step |
Only task and the lane's own required fields are mandatory:
sheet on check, order, pixels and deliver; brief on plan.
Every field is a string - there are no number fields on this app.
sheet is the chain itself: the -vf string, a
filter_complex, or a whole ffmpeg command line, with a few optional
KEY: value lines above it.
The header takes JOB, SOURCE, TARGET and
FORMAT. SOURCE: 1920x1080 is the line that matters
most, because every rectangle in the answer is measured from it - and a chain with
iw/2 in it means a different number of pixels at a different source size.
Without it the engine assumes 1920x1080 and says so on every answer.
The filters followed exactly are scale, crop,
pad, transpose, hflip, vflip,
format, fps and setsar. Named arguments
work (crop=w=1080:h=1080:x=420:y=0), a crop or pad with no offsets is
centred the way ffmpeg centres it, and iw, ih,
-1 and -2 are resolved against the frame that step is
handed - which is the entire reason the order matters.
Filters that move the frame and are not modelled are named, not
guessed. rotate, overlay, scale2ref,
zscale and the stack filters are kept in the chain, treated as changing
nothing, and reported - so an answer that involves one is partial and says which step
made it partial. Any other unknown filter is treated as changing no geometry, which is
true of most of them.
A filter_complex is read as a chain. Pad labels such as
[0:v] and [v] are stripped and the filters are followed in
the order they appear. A graph that genuinely branches - two inputs, an overlay, a
split - is not a chain, and the filters that join or move frames are reported as
unfollowed rather than misinterpreted.
A SIZE is reported as WxH, a rectangle as WxH at (x,y) in
source coordinates, a pixel count in Mpx above a million, a share as a percentage to
one place, and a scale factor to three. The engine works in pixels: aspect-ratio
metadata is somebody else's subject.
Add $model to any body to choose the model for that run:
gpt-5.6-luna, gpt-5.6-terra (the default) or
gpt-5.6-sol. Luna caps output at 4,096 tokens and will fail the check,
order and pixels lanes rather than shorten them - a findings table, a corrected chain,
or a row per step and per swap, is several thousand characters before the reasoning
starts.
The response envelope
Success and failure have the same outer shape, so one check covers both.
{
"ok": true,
"data": {
"...": "the result"
}
}
{
"ok": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "seconds should be number, got string",
"details": {}
}
}
| HTTP | error.code | What it means |
|---|---|---|
400 | VALIDATION_ERROR | The body was not a JSON object, or a declared field had the wrong type. A number field sent as a string is the usual cause. |
401 | UNAUTHORIZED | No token, or a token that has expired or been revoked. Mint a new one. |
402 | INSUFFICIENT_CREDITS | The balance is below the run's minimum. Call /estimate first and compare hold_credits against /me. |
404 | NOT_FOUND | Wrong path, or a job id that does not belong to this token. |
409 | CONFLICT | An Idempotency-Key replay whose body differs from the original request. |
429 | RATE_LIMITED | Too many requests. Back off; do not tight-loop. |
503 | UPSTREAM_UNAVAILABLE | The model provider is unavailable. Retry with backoff. |
1. Get a token
Open /tokens.html in a browser and copy the token this app already
holds - no developer console needed. A guest token is minted automatically and
is enough for /me and /estimate; writing a package is metered and needs
a personal token, which comes from signing in on that page.
Keep it in an environment variable rather than in source:
export SKILLSAFE_TOKEN="YOUR_TOKEN"
2. Check the session and the balance
GET /me is free. It returns only three fields: subject_type,
subject_id and credits. Signed-in means
subject_type == "user" - there is no username or email to test.
curl -sS -X GET "https://api.skillsafe.ai/v1/app-api/me" \ -H "Authorization: Bearer $SKILLSAFE_TOKEN"
import json, urllib.request
TOKEN = "YOUR_TOKEN" # from /tokens.html
BASE = "https://api.skillsafe.ai/v1/app-api"
def call(method, path, payload=None, headers=None):
data = json.dumps(payload).encode() if payload is not None else None
req = urllib.request.Request(BASE + path, data=data, method=method)
req.add_header("Authorization", "Bearer " + TOKEN)
req.add_header("Content-Type", "application/json")
req.add_header("Accept", "application/json")
# A plain urllib request with no User-Agent is refused with 403.
req.add_header("User-Agent", "chain-desk-client/1.0")
for k, v in (headers or {}).items():
req.add_header(k, v)
with urllib.request.urlopen(req) as r:
return json.loads(r.read())
out = call("GET", "/me")
print(json.dumps(out["data"], indent=2))
const TOKEN = "YOUR_TOKEN"; // from /tokens.html
const BASE = "https://api.skillsafe.ai/v1/app-api";
async function call(method, path, payload) {
const res = await fetch(BASE + path, {
method,
headers: {
"Authorization": `Bearer ${TOKEN}`,
"Content-Type": "application/json"
},
body: payload === undefined ? undefined : JSON.stringify(payload)
});
const json = await res.json();
if (!res.ok || !json.ok) throw new Error(json.error?.message || res.statusText);
return json.data;
}
const data = await call("GET", "/me");
console.log(data);
package main
import (
"bytes"
"fmt"
"io"
"net/http"
)
const base = "https://api.skillsafe.ai/v1/app-api"
const token = "YOUR_TOKEN" // from /tokens.html
func main() {
req, _ := http.NewRequest("GET", base+"/me", nil)
req.Header.Set("Authorization", "Bearer "+token)
req.Header.Set("Content-Type", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
out, _ := io.ReadAll(res.Body)
fmt.Println(string(out))
}
import java.net.URI;
import java.net.http.*;
public class Main {
static final String BASE = "https://api.skillsafe.ai/v1/app-api";
static final String TOKEN = "YOUR_TOKEN"; // from /tokens.html
public static void main(String[] args) throws Exception {
HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create(BASE + "/me"))
.header("Authorization", "Bearer " + TOKEN)
.header("Content-Type", "application/json")
.method("GET", HttpRequest.BodyPublishers.noBody())
.build();
HttpResponse<String> res = HttpClient.newHttpClient()
.send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(res.body());
}
}
require 'net/http'
require 'json'
require 'uri'
BASE = "https://api.skillsafe.ai/v1/app-api"
TOKEN = "YOUR_TOKEN" # from /tokens.html
uri = URI("#{BASE}/me")
req = Net::HTTP::Get.new(uri)
req["Authorization"] = "Bearer #{TOKEN}"
req["Content-Type"] = "application/json"
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |h| h.request(req) }
puts JSON.pretty_generate(JSON.parse(res.body)["data"])
<?php
$base = "https://api.skillsafe.ai/v1/app-api";
$token = "YOUR_TOKEN"; // from /tokens.html
$opts = ["http" => [
"method" => "GET",
"header" => "Authorization: Bearer $token\r\nContent-Type: application/json\r\n",
]];
$res = file_get_contents($base . "/me", false, stream_context_create($opts));
$json = json_decode($res, true);
print_r($json["data"]);
using System.Net.Http;
using System.Text;
const string Base = "https://api.skillsafe.ai/v1/app-api";
const string Token = "YOUR_TOKEN"; // from /tokens.html
var http = new HttpClient();
http.DefaultRequestHeaders.Add("Authorization", $"Bearer {Token}");
var res = await http.SendAsync(new HttpRequestMessage(new HttpMethod("GET"), Base + "/me")
{
Content = null
});
Console.WriteLine(await res.Content.ReadAsStringAsync());
3. Price the run before making it
POST /estimate costs nothing, creates no job, and returns the worst-case cost.
Compare hold_credits against the balance from step 2 before you submit: a 402 after
the fact is avoidable. hold_credits is a reservation priced at the full
output cap - the actual charge is usually far lower.
It also echoes model, model_alias and markup_bps, which is
the authoritative check that a run is bound to the model you think it is. Estimate each lane
separately: their prompts and caps differ, so their holds do.
curl -sS -X POST "https://api.skillsafe.ai/v1/app-api/estimate" \
-H "Authorization: Bearer $SKILLSAFE_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"task": "check",
"sheet": "<SOURCE: 1920x1080 and a -vf chain; the grammar is in /llms.txt>",
"worry": "it graded fine last time and this one will not come clean",
"rules": "<the working rules for this lane, sent by the app>"
}'
import json, urllib.request
TOKEN = "YOUR_TOKEN" # from /tokens.html
BASE = "https://api.skillsafe.ai/v1/app-api"
def call(method, path, payload=None, headers=None):
data = json.dumps(payload).encode() if payload is not None else None
req = urllib.request.Request(BASE + path, data=data, method=method)
req.add_header("Authorization", "Bearer " + TOKEN)
req.add_header("Content-Type", "application/json")
req.add_header("Accept", "application/json")
# A plain urllib request with no User-Agent is refused with 403.
req.add_header("User-Agent", "chain-desk-client/1.0")
for k, v in (headers or {}).items():
req.add_header(k, v)
with urllib.request.urlopen(req) as r:
return json.loads(r.read())
payload = {
"task": "check",
"sheet": "<SOURCE: 1920x1080 and a -vf chain; the grammar is in /llms.txt>",
"worry": "it graded fine last time and this one will not come clean",
"rules": "<the working rules for this lane, sent by the app>"
}
out = call("POST", "/estimate", payload)
print(out["data"]["hold_credits"], out["data"]["model"])
const TOKEN = "YOUR_TOKEN"; // from /tokens.html
const BASE = "https://api.skillsafe.ai/v1/app-api";
async function call(method, path, payload) {
const res = await fetch(BASE + path, {
method,
headers: {
"Authorization": `Bearer ${TOKEN}`,
"Content-Type": "application/json"
},
body: payload === undefined ? undefined : JSON.stringify(payload)
});
const json = await res.json();
if (!res.ok || !json.ok) throw new Error(json.error?.message || res.statusText);
return json.data;
}
const payload = {
"task": "check",
"sheet": "<SOURCE: 1920x1080 and a -vf chain; the grammar is in /llms.txt>",
"worry": "it graded fine last time and this one will not come clean",
"rules": "<the working rules for this lane, sent by the app>"
};
const data = await call("POST", "/estimate", payload);
console.log(data.hold_credits, data.model, data.model_alias);
package main
import (
"bytes"
"fmt"
"io"
"net/http"
)
const base = "https://api.skillsafe.ai/v1/app-api"
const token = "YOUR_TOKEN" // from /tokens.html
func main() {
payload := []byte(`{
"task": "check",
"sheet": "<SOURCE: 1920x1080 and a -vf chain; the grammar is in /llms.txt>",
"worry": "it graded fine last time and this one will not come clean",
"rules": "<the working rules for this lane, sent by the app>"
}`)
req, _ := http.NewRequest("POST", base+"/estimate", bytes.NewReader(payload))
req.Header.Set("Authorization", "Bearer "+token)
req.Header.Set("Content-Type", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
out, _ := io.ReadAll(res.Body)
fmt.Println(string(out))
}
import java.net.URI;
import java.net.http.*;
public class Main {
static final String BASE = "https://api.skillsafe.ai/v1/app-api";
static final String TOKEN = "YOUR_TOKEN"; // from /tokens.html
public static void main(String[] args) throws Exception {
String payload = """
{
"task": "check",
"sheet": "<SOURCE: 1920x1080 and a -vf chain; the grammar is in /llms.txt>",
"worry": "it graded fine last time and this one will not come clean",
"rules": "<the working rules for this lane, sent by the app>"
}
""";
HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create(BASE + "/estimate"))
.header("Authorization", "Bearer " + TOKEN)
.header("Content-Type", "application/json")
.method("POST", HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse<String> res = HttpClient.newHttpClient()
.send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(res.body());
}
}
require 'net/http'
require 'json'
require 'uri'
BASE = "https://api.skillsafe.ai/v1/app-api"
TOKEN = "YOUR_TOKEN" # from /tokens.html
payload = {
"task": "check",
"sheet": "<SOURCE: 1920x1080 and a -vf chain; the grammar is in /llms.txt>",
"worry": "it graded fine last time and this one will not come clean",
"rules": "<the working rules for this lane, sent by the app>"
}
uri = URI("#{BASE}/estimate")
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer #{TOKEN}"
req["Content-Type"] = "application/json"
req.body = JSON.dump(payload)
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |h| h.request(req) }
puts JSON.pretty_generate(JSON.parse(res.body)["data"])
<?php
$base = "https://api.skillsafe.ai/v1/app-api";
$token = "YOUR_TOKEN"; // from /tokens.html
$payload = json_encode([
"task" => "check",
"sheet" => "<SOURCE: 1920x1080 and a -vf chain; the grammar is in /llms.txt>",
"worry" => "it graded fine last time and this one will not come clean",
"rules" => "<the working rules for this lane, sent by the app>"
]);
$opts = ["http" => [
"method" => "POST",
"header" => "Authorization: Bearer $token\r\nContent-Type: application/json\r\n",
"content" => $payload,
]];
$res = file_get_contents($base . "/estimate", false, stream_context_create($opts));
$json = json_decode($res, true);
print_r($json["data"]);
using System.Net.Http;
using System.Text;
const string Base = "https://api.skillsafe.ai/v1/app-api";
const string Token = "YOUR_TOKEN"; // from /tokens.html
var http = new HttpClient();
http.DefaultRequestHeaders.Add("Authorization", $"Bearer {Token}");
var payload = """
{
"task": "check",
"sheet": "<SOURCE: 1920x1080 and a -vf chain; the grammar is in /llms.txt>",
"worry": "it graded fine last time and this one will not come clean",
"rules": "<the working rules for this lane, sent by the app>"
}
""";
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var res = await http.SendAsync(new HttpRequestMessage(new HttpMethod("POST"), Base + "/estimate")
{
Content = content
});
Console.WriteLine(await res.Content.ReadAsStringAsync());
4. Write a package
POST /run submits the job. Always send an Idempotency-Key: a network
blip that replays the same request must not bill twice. A replay with the same key returns the
stored result and is not charged again; a replay with the same key but a different body
is a 409.
The response carries output.output (the Markdown package), charged_credits
and truncated. If truncated is true the balance sat between
min_credits and hold_credits and the output was cut short - render what
arrived and say so rather than presenting it as complete.
curl -sS -X POST "https://api.skillsafe.ai/v1/app-api/run" \
-H "Authorization: Bearer $SKILLSAFE_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"task": "check",
"sheet": "<SOURCE: 1920x1080 and a -vf chain; the grammar is in /llms.txt>",
"worry": "it graded fine last time and this one will not come clean",
"rules": "<the working rules for this lane, sent by the app>"
}'
import json, urllib.request
TOKEN = "YOUR_TOKEN" # from /tokens.html
BASE = "https://api.skillsafe.ai/v1/app-api"
def call(method, path, payload=None, headers=None):
data = json.dumps(payload).encode() if payload is not None else None
req = urllib.request.Request(BASE + path, data=data, method=method)
req.add_header("Authorization", "Bearer " + TOKEN)
req.add_header("Content-Type", "application/json")
req.add_header("Accept", "application/json")
# A plain urllib request with no User-Agent is refused with 403.
req.add_header("User-Agent", "chain-desk-client/1.0")
for k, v in (headers or {}).items():
req.add_header(k, v)
with urllib.request.urlopen(req) as r:
return json.loads(r.read())
payload = {
"task": "check",
"sheet": "<SOURCE: 1920x1080 and a -vf chain; the grammar is in /llms.txt>",
"worry": "it graded fine last time and this one will not come clean",
"rules": "<the working rules for this lane, sent by the app>"
}
out = call("POST", "/run", payload)
print(out["data"]["output"]["output"])
const TOKEN = "YOUR_TOKEN"; // from /tokens.html
const BASE = "https://api.skillsafe.ai/v1/app-api";
async function call(method, path, payload) {
const res = await fetch(BASE + path, {
method,
headers: {
"Authorization": `Bearer ${TOKEN}`,
"Content-Type": "application/json"
},
body: payload === undefined ? undefined : JSON.stringify(payload)
});
const json = await res.json();
if (!res.ok || !json.ok) throw new Error(json.error?.message || res.statusText);
return json.data;
}
const payload = {
"task": "check",
"sheet": "<SOURCE: 1920x1080 and a -vf chain; the grammar is in /llms.txt>",
"worry": "it graded fine last time and this one will not come clean",
"rules": "<the working rules for this lane, sent by the app>"
};
const data = await call("POST", "/run", payload);
console.log(data.output.output);
package main
import (
"bytes"
"fmt"
"io"
"net/http"
)
const base = "https://api.skillsafe.ai/v1/app-api"
const token = "YOUR_TOKEN" // from /tokens.html
func main() {
payload := []byte(`{
"task": "check",
"sheet": "<SOURCE: 1920x1080 and a -vf chain; the grammar is in /llms.txt>",
"worry": "it graded fine last time and this one will not come clean",
"rules": "<the working rules for this lane, sent by the app>"
}`)
req, _ := http.NewRequest("POST", base+"/run", bytes.NewReader(payload))
req.Header.Set("Authorization", "Bearer "+token)
req.Header.Set("Content-Type", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
out, _ := io.ReadAll(res.Body)
fmt.Println(string(out))
}
import java.net.URI;
import java.net.http.*;
public class Main {
static final String BASE = "https://api.skillsafe.ai/v1/app-api";
static final String TOKEN = "YOUR_TOKEN"; // from /tokens.html
public static void main(String[] args) throws Exception {
String payload = """
{
"task": "check",
"sheet": "<SOURCE: 1920x1080 and a -vf chain; the grammar is in /llms.txt>",
"worry": "it graded fine last time and this one will not come clean",
"rules": "<the working rules for this lane, sent by the app>"
}
""";
HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create(BASE + "/run"))
.header("Authorization", "Bearer " + TOKEN)
.header("Content-Type", "application/json")
.method("POST", HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse<String> res = HttpClient.newHttpClient()
.send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(res.body());
}
}
require 'net/http'
require 'json'
require 'uri'
BASE = "https://api.skillsafe.ai/v1/app-api"
TOKEN = "YOUR_TOKEN" # from /tokens.html
payload = {
"task": "check",
"sheet": "<SOURCE: 1920x1080 and a -vf chain; the grammar is in /llms.txt>",
"worry": "it graded fine last time and this one will not come clean",
"rules": "<the working rules for this lane, sent by the app>"
}
uri = URI("#{BASE}/run")
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer #{TOKEN}"
req["Content-Type"] = "application/json"
req.body = JSON.dump(payload)
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |h| h.request(req) }
puts JSON.pretty_generate(JSON.parse(res.body)["data"])
<?php
$base = "https://api.skillsafe.ai/v1/app-api";
$token = "YOUR_TOKEN"; // from /tokens.html
$payload = json_encode([
"task" => "check",
"sheet" => "<SOURCE: 1920x1080 and a -vf chain; the grammar is in /llms.txt>",
"worry" => "it graded fine last time and this one will not come clean",
"rules" => "<the working rules for this lane, sent by the app>"
]);
$opts = ["http" => [
"method" => "POST",
"header" => "Authorization: Bearer $token\r\nContent-Type: application/json\r\n",
"content" => $payload,
]];
$res = file_get_contents($base . "/run", false, stream_context_create($opts));
$json = json_decode($res, true);
print_r($json["data"]);
using System.Net.Http;
using System.Text;
const string Base = "https://api.skillsafe.ai/v1/app-api";
const string Token = "YOUR_TOKEN"; // from /tokens.html
var http = new HttpClient();
http.DefaultRequestHeaders.Add("Authorization", $"Bearer {Token}");
var payload = """
{
"task": "check",
"sheet": "<SOURCE: 1920x1080 and a -vf chain; the grammar is in /llms.txt>",
"worry": "it graded fine last time and this one will not come clean",
"rules": "<the working rules for this lane, sent by the app>"
}
""";
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var res = await http.SendAsync(new HttpRequestMessage(new HttpMethod("POST"), Base + "/run")
{
Content = content
});
Console.WriteLine(await res.Content.ReadAsStringAsync());
5. Stream a run
POST /run-stream is the same call with a text/event-stream response.
Worth knowing before you build on it: from a server or from cURL you get
event: delta frames carrying the output token by token; from a browser you get
event: tick heartbeats and then one event: done with the whole
output. Handle both, and treat ticks as liveness rather than progress.
Frame types are job (the job id), delta ({"text": "..."}),
tick ({"t": seconds}), done, and error. An
idempotent replay returns plain JSON with no stream at all, so check the content type before you
start reading frames.
curl -sS -N -X POST "https://api.skillsafe.ai/v1/app-api/run-stream" \
-H "Authorization: Bearer $SKILLSAFE_TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: text/event-stream" \
-H "Idempotency-Key: cbd-$(date +%s)" \
-d '{
"task": "check",
"sheet": "<SOURCE: 1920x1080 and a -vf chain; the grammar is in /llms.txt>",
"worry": "it graded fine last time and this one will not come clean",
"rules": "<the working rules for this lane, sent by the app>"
}'
import json, urllib.request
TOKEN = "YOUR_TOKEN"
BASE = "https://api.skillsafe.ai/v1/app-api"
payload = {
"task": "check",
"sheet": "<SOURCE: 1920x1080 and a -vf chain; the grammar is in /llms.txt>",
"worry": "it graded fine last time and this one will not come clean",
"rules": "<the working rules for this lane, sent by the app>"
}
req = urllib.request.Request(BASE + "/run-stream", data=json.dumps(payload).encode(), method="POST")
req.add_header("Authorization", "Bearer " + TOKEN)
req.add_header("Content-Type", "application/json")
req.add_header("Accept", "text/event-stream")
req.add_header("Idempotency-Key", "cbd-demo-1")
req.add_header("User-Agent", "chain-desk-client/1.0")
event, data = "message", ""
with urllib.request.urlopen(req) as r:
for raw in r:
line = raw.decode().rstrip("\n")
if line.startswith("event:"):
event = line[6:].strip()
elif line.startswith("data:"):
data += line[5:].strip()
elif line == "":
if data:
frame = json.loads(data)
if event == "delta":
print(frame.get("text", ""), end="")
elif event == "done":
print("\n--- charged:", frame.get("charged_credits"))
event, data = "message", ""
const TOKEN = "YOUR_TOKEN";
const BASE = "https://api.skillsafe.ai/v1/app-api";
const payload = {
"task": "check",
"sheet": "<SOURCE: 1920x1080 and a -vf chain; the grammar is in /llms.txt>",
"worry": "it graded fine last time and this one will not come clean",
"rules": "<the working rules for this lane, sent by the app>"
};
const res = await fetch(BASE + "/run-stream", {
method: "POST",
headers: {
"Authorization": `Bearer ${TOKEN}`,
"Content-Type": "application/json",
"Idempotency-Key": "cbd-demo-1"
},
body: JSON.stringify(payload)
});
// An idempotent replay comes back as plain JSON with no stream at all.
if (!(res.headers.get("content-type") || "").includes("text/event-stream")) {
const json = await res.json();
console.log(json.data.output.output);
} else {
const reader = res.body.getReader();
const dec = new TextDecoder();
let buf = "";
for (;;) {
const { done, value } = await reader.read();
if (done) break;
buf += dec.decode(value, { stream: true });
let i;
while ((i = buf.indexOf("\n\n")) >= 0) {
const frame = buf.slice(0, i);
buf = buf.slice(i + 2);
let name = "message", data = "";
for (const line of frame.split("\n")) {
if (line.startsWith("event:")) name = line.slice(6).trim();
else if (line.startsWith("data:")) data += line.slice(5).trim();
}
if (!data) continue;
const p = JSON.parse(data);
if (name === "delta") process.stdout.write(p.text || "");
if (name === "tick") console.error("still writing:", p.t + "s");
if (name === "done") console.log("\ncharged:", p.charged_credits);
}
}
}
package main
import (
"bytes"
"fmt"
"io"
"net/http"
)
const base = "https://api.skillsafe.ai/v1/app-api"
const token = "YOUR_TOKEN" // from /tokens.html
func main() {
payload := []byte(`{
"task": "check",
"sheet": "<SOURCE: 1920x1080 and a -vf chain; the grammar is in /llms.txt>",
"worry": "it graded fine last time and this one will not come clean",
"rules": "<the working rules for this lane, sent by the app>"
}`)
req, _ := http.NewRequest("POST", base+"/run-stream", bytes.NewReader(payload))
req.Header.Set("Authorization", "Bearer "+token)
req.Header.Set("Content-Type", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
out, _ := io.ReadAll(res.Body)
fmt.Println(string(out))
}
import java.net.URI;
import java.net.http.*;
public class Main {
static final String BASE = "https://api.skillsafe.ai/v1/app-api";
static final String TOKEN = "YOUR_TOKEN"; // from /tokens.html
public static void main(String[] args) throws Exception {
String payload = """
{
"task": "check",
"sheet": "<SOURCE: 1920x1080 and a -vf chain; the grammar is in /llms.txt>",
"worry": "it graded fine last time and this one will not come clean",
"rules": "<the working rules for this lane, sent by the app>"
}
""";
HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create(BASE + "/run-stream"))
.header("Authorization", "Bearer " + TOKEN)
.header("Content-Type", "application/json")
.method("POST", HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse<String> res = HttpClient.newHttpClient()
.send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(res.body());
}
}
require 'net/http'
require 'json'
require 'uri'
BASE = "https://api.skillsafe.ai/v1/app-api"
TOKEN = "YOUR_TOKEN" # from /tokens.html
payload = {
"task": "check",
"sheet": "<SOURCE: 1920x1080 and a -vf chain; the grammar is in /llms.txt>",
"worry": "it graded fine last time and this one will not come clean",
"rules": "<the working rules for this lane, sent by the app>"
}
uri = URI("#{BASE}/run-stream")
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer #{TOKEN}"
req["Content-Type"] = "application/json"
req.body = JSON.dump(payload)
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |h| h.request(req) }
puts JSON.pretty_generate(JSON.parse(res.body)["data"])
<?php
$base = "https://api.skillsafe.ai/v1/app-api";
$token = "YOUR_TOKEN"; // from /tokens.html
$payload = json_encode([
"task" => "check",
"sheet" => "<SOURCE: 1920x1080 and a -vf chain; the grammar is in /llms.txt>",
"worry" => "it graded fine last time and this one will not come clean",
"rules" => "<the working rules for this lane, sent by the app>"
]);
$opts = ["http" => [
"method" => "POST",
"header" => "Authorization: Bearer $token\r\nContent-Type: application/json\r\n",
"content" => $payload,
]];
$res = file_get_contents($base . "/run-stream", false, stream_context_create($opts));
$json = json_decode($res, true);
print_r($json["data"]);
using System.Net.Http;
using System.Text;
const string Base = "https://api.skillsafe.ai/v1/app-api";
const string Token = "YOUR_TOKEN"; // from /tokens.html
var http = new HttpClient();
http.DefaultRequestHeaders.Add("Authorization", $"Bearer {Token}");
var payload = """
{
"task": "check",
"sheet": "<SOURCE: 1920x1080 and a -vf chain; the grammar is in /llms.txt>",
"worry": "it graded fine last time and this one will not come clean",
"rules": "<the working rules for this lane, sent by the app>"
}
""";
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var res = await http.SendAsync(new HttpRequestMessage(new HttpMethod("POST"), Base + "/run-stream")
{
Content = content
});
Console.WriteLine(await res.Content.ReadAsStringAsync());
6. Read the result
output.output is Markdown in the envelope this app's system prompt guarantees: every
section is a level-two heading spelled exactly as listed in the lane table above, in that order;
tables are GitHub pipe tables with the declared columns; prompts are in fenced blocks opened with
three backticks and the word text; checklists are - [x] lines.
So parsing is a split on /^## / - but do it fence-aware, because a prompt block can
legitimately contain a line starting with ##. Count the sections you got against the
ones the lane declares: a short list means the run was truncated, not that the contract changed.
def sections(md):
out, name, buf, fence = {}, None, [], False
for line in md.split("\n"):
if line.lstrip().startswith("```"):
fence = not fence
if not fence and line.startswith("## "):
if name:
out[name] = "\n".join(buf).strip()
name, buf = line[3:].strip(), []
continue
if name:
buf.append(line)
if name:
out[name] = "\n".join(buf).strip()
return out
The artifact most callers want is the fenced text block inside
## The Sheet or ## Corrected Sheet - that is a complete sheet in the
grammar above, so it can be fed straight back into another lane with nothing carried alongside
it. Every other section is prose and tables meant to be read.
Rate limits and good manners
/estimateand/meare free. Call them as much as you like, within reason.- A 429 means back off with a delay, not retry immediately.
- Send an
Idempotency-Keyon every/run. Derive it from a hash of the body plus an attempt counter, so a retry of the same request reuses the key and a deliberate re-run gets a new one. - The engine in the web app is client-side only and has no endpoint. What it computes is
published in full in llms.txt - every geometry step is an affine
map on coordinates plus a rectangle, so
source_x = bx + mx * out_xper axis; ascalemultipliesmxbyw_in / w_out, acropaddsmx * xtobxand shrinks the rectangle, apadsubtracts and maps its border OUTSIDE the source, and atransposeswaps the two axis maps. The whole chain is therefore one map and its inverse is exact, which is what gives the source rectangle; the bottleneck isminofw*hover the chain and the invented share is1 - bottleneck / output; and whether two adjacent filters commute is decided by RUNNING the chain both ways, because it depends on the numbers and not on the filter names - so you can compute every figure this app produces in your own pipeline without it. It is arithmetic on the chain you paste: it has decoded no frame, run no ffmpeg and looked at no pixel; it follows the geometry filters and names the ones it cannot; it reads the expressions people write and not all of them; the rounding is ffmpeg's convention rather than a measurement; quality is not modelled, only pixel counts; and this is geometry, not colour. The frame after every step with the source rectangle it is made of, the end-to-end result with the clipped source region and both scale factors, the bottleneck with the invented share, every adjacent swap with its own verdict, the chroma and macroblock grids, and every finding are all sent with each run asprescan, and the system prompt requires answering them.