← Lore Loop
API
Tokens

Drive Lore Loop from your own code

Both metered steps - the scout and the vetting - are available over HTTP. A natural use is a small-town tourism page or a travel newsletter: your code sends a town and the stories people ask about, shows the scouted stops on your own map, and prints an honest rating next to each legend.

The split first: the page does the arithmetic; the model tells the stories and judges them; the page checks the reply. Positions, distances, drive-time estimates, sunrise and sunset, the loop order and the schedule come from lorekit.js, which runs in node as well as in the browser. Its reconcile function then checks every reply against those facts.

Base URL and the envelope

Every endpoint lives under https://api.skillsafe.ai/v1/app-api, and every response uses one envelope:

{ "ok": true,  "data":  { ... } }
{ "ok": false, "error": { "code": "...", "message": "...", "status": 402, "details": { ... } } }

The token is minted for this app (the guest call takes {"slug":"lore-loop"}), so no slug header is needed afterwards. Send it as Authorization: Bearer …. The run body is the input object, sent bare: never wrap it as {"input": {…}}.

StatusCodeMeaning
400validation_errorThe body is not a JSON object, or a required field is missing.
401unauthorizedNo token, or a stale one. Mint a guest token or sign in again.
402insufficient_creditsThe balance is under min_credits. Price with /estimate first.
403forbiddenA guest token tried to run: both tasks are metered and need a personal token.
404not_foundUnknown job id.
429rate_limitedBack off and retry.
5xxserver_errorTransient. Retry with the same Idempotency-Key so a retry never double-bills.

The task field comes first

Every run sends task, which routes the one system prompt to one of two contracts:

taskWhat it returnsVerdict field
scoutA title, summary and story arc; 4–8 stops {id, name, kind, story, era, lat, lon, pos, minutes, best_time, ask, claims[], respect}; dropped [{name, why}]; tips; check_before (hours, closures, dates to confirm).mood: eerie, quirky, historic, mixed
vetA title and summary; one ratings entry per claim {id, rating, confidence, why, check, retell} with rating one of documented, likely, contested, folklore, doubtful, unknown; patterns (red flags); sources (kinds of source, never URLs).verdict: mostly-documented, mixed, mostly-folklore

Stop ids: U1… are the traveller's own stops (kept with their own positions, pos: "user"); L1… are stops the scout added, at approximate positions. kind is one of legend, history, oddity, haunt, festival, food, nature; best_time one of morning, midday, afternoon, dusk, night, any.

The declared input schema carries scalars only, so object- and array-valued fields travel JSON-encoded as strings (LoreKit.toWire does this). task, trip_title and area are required.

Input fields

FieldTypeNotes
taskstringscout or vet.
trip_titlestringA name for the trip.
areastringThe town or region, e.g. "Point Pleasant, West Virginia".
basestring (JSON)scout: {name, lat, lon} - where the traveller stays.
datesstring (JSON)scout: {start, days, time_zone, daylight: [{date, sunrise, sunset}]}, daylight from LoreKit.daylight.
prefsstring (JSON)scout: {interests[], after_dark, roads, start_time}.
heardstringWhat the traveller has heard. Over 3,000 characters keeps the head and tail around a marker.
stopsstring (JSON)scout: [{id: "U1", name, lat, lon, minutes, note}], up to 12; lat/lon may be null.
notesstringscout, optional: anything else (kids, mobility, dislikes).
claimsstring (JSON)vet: [{id, stop, stop_name, text}] from LoreKit.claimsFor(scout, pasted) - C1… from the scout's stops, P1… from a pasted post; up to 24.
pastedstringvet, optional: the post or caption the P-claims came from.
retry_notestringOnly on a reformat retry.

The reply

The job's output.output is a string holding one JSON object. Parse it with LoreKit.parseReply, then normalize, then check it with reconcile(reply, scan, {claims}). For a scout it flags your stops that were neither kept nor dropped, pins the reply moved, stops without a position or placed far from the base, opening times or prices stated in a story, web addresses, and a schedule that does not fit the daylight. For a vet it flags unrated claims, ratings for ids that were not sent, "documented" at low confidence, web addresses, and a verdict that disagrees with the ratings. Drive times are estimates; positions the model supplies are approximate; ratings are a model's judgement, not verification.

Worked examples

Replies produced against the app's prompt for the two built-in examples (long lists shortened here; the full replies ship in example-result.js). The page replays each of them free from its example buttons.

task: scout - a two-day Mothman-country weekend (mixed)

Input:

{
 "task": "scout",
 "trip_title": "Mothman country weekend",
 "area": "Point Pleasant, West Virginia (Mason County, on the Ohio River)",
 "base": "{\"name\":\"Riverfront rental\",\"lat\":38.851,\"lon\":-82.129}",
 "dates": "{\"start\":\"2026-10-24\",\"days\":2,\"time_zone\":\"America/New_York\",\"daylight\":[{\"date\":\"2026-10-24\",\"sunrise\":\"07:47\",\"sunset\":\"18:38\"},{\"date\":\"2026-10-25\",\"sunrise\":\"07:48\",\"sunset\":\"18:37\"}]}",
 "prefs": "{\"interests\":[\"legends\",\"history\",\"oddities\"],\"after_dark\":true,\"roads\":\"rural\",\"start_time\":\"09:00\"}",
 "heard": "Everyone online says the Mothman was first seen in November 1966 near the old TNT plant north of town, and that the sightings stopped after the Silver ...",
 "stops": "[{\"id\":\"U1\",\"name\":\"Mothman statue\",\"lat\":38.8446,\"lon\":-82.1372,\"minutes\":20,\"note\":\"photo stop\"},{\"id\":\"U2\",\"name\":\"TNT area (McClintic Wildlife Management Area)\",\"lat\":38.927,\"lon\":-82.086,\"minutes\":60,\"note\":\"\"},\"...\"]",
 "notes": "We like a little spooky, nothing too scary. One of us does not love long drives."
}

Reply:

{
 "task": "scout",
 "title": "Mothman Country Weekend",
 "summary": "Point Pleasant's most famous legend started in the old TNT plant woods north of town, and the town still tells it two ways: the fun, pop-culture version downtown at the statue and museum, and the older, more solemn history at the river confluence and the Silver Bridge memorial. This loop moves out from downtown to the actual 1966 sighting site in daylight, then winds back through real local history and a gently haunted hotel porch so the trip ends calm rather than tense.",
 "arc": "The loop opens light at the downtown statue and museum, builds to the real 1966 sighting site at the old TNT plant as its daytime climax, then eases down through the river confluence, the Silver Bridge memorial, and a quiet evening on the Lowe Hotel porch.",
 "mood": "mixed",
 "stops": [
  {
   "id": "U1",
   "name": "Mothman statue",
   "kind": "oddity",
   "story": "This stainless-steel sculpture, cast by a local artist in the early 2000s, has become the unofficial face of Point Pleasant's strangest chapter. It isn't a likeness of anything actually seen - it's an artist's take on the shape locals described - but it draws visitors from well outside the area to stand in those wings for a photo. It sits in a small downtown park an easy walk from the museum and Main Street, making it a natural first or last stop.",
   "era": "early 2000s",
   "lat": 38.8446,
   "lon": -82.1372,
   "pos": "user",
   "minutes": 20,
   "best_time": "any",
   "ask": "Which part of the Mothman story do people here actually think happened, and which parts grew later?",
   "claims": [
    "A local sculptor cast the stainless-steel Mothman statue, installed in downtown Point Pleasant in the early 2000s."
   ],
   "respect": "A popular photo spot - give other visitors their turn at the wings."
  },
  {
   "id": "U2",
   "name": "TNT area (McClintic Wildlife Management Area)",
   "kind": "legend",
   "story": "This stretch of fenced woods and crumbling concrete igloos was a wartime TNT and RDX plant before it became the McClintic Wildlife Management Area. On November 15, 1966, two young couples driving through at night said a huge grey, winged shape with glowing red eyes rose up near the old bunkers - the sighting that started the Mothman story. Locals still tell their own version of that night and of the dozens of reports that followed over the next year.",
   "era": "1966-1967",
   "lat": 38.927,
   "lon": -82.086,
   "pos": "user",
   "minutes": 60,
   "best_time": "morning",
   "ask": "Which of these old bunkers are considered safe to walk near, and which trails or access roads actually stay open to the public?",
   "claims": [
    "Two young couples reported a large grey winged creature with glowing eyes near the former TNT plant on November 15, 1966.",
    "The area was built in the early 1940s as the West Virginia Ordnance Works, a wartime TNT and RDX plant, and its concrete storage igloos still stand inside what is now McClintic Wildlife Management Area."
   ],
   "respect": "McClintic is a public wildlife area, but the old ordnance bunkers are deteriorating concrete structures - stay outside them and visit only in daylight. Treat any claim that the bunkers are open for night exploring as unreliable and unsafe, whatever a forum post says."
  },
  "..."
 ],
 "dropped": [
  {
   "name": "Night entry into the TNT bunkers",
   "why": "A forum post claimed the old ordnance bunkers at the TNT site are open to explore at night, but they are deteriorating structures in a wildlife management area with no evening supervision - entering them, especially after dark, is not safe and is not something to build a stop around. The loop keeps this site as a daytime stop instead."
  }
 ],
 "tips": [
  "Wear real shoes for McClintic - the old access roads are gravel and uneven, and there's no cell signal once you're past the gate.",
  "Take in the statue and the Mothman Museum before the TNT site, not after - the story means more once you're standing in the actual woods.",
  "..."
 ],
 "check_before": [
  "Current open hours and admission for the Mothman Museum and the Point Pleasant River Museum.",
  "Whether McClintic Wildlife Management Area has any seasonal access restrictions, since it is an active wildlife area sometimes used for managed hunts.",
  "..."
 ]
}

task: vet - a two-day Mothman-country weekend (mostly-documented)

Input:

{
 "task": "vet",
 "trip_title": "Mothman country weekend",
 "area": "Point Pleasant, West Virginia (Mason County, on the Ohio River)",
 "claims": "[{\"id\":\"C1\",\"stop\":\"U1\",\"stop_name\":\"Mothman statue\",\"text\":\"A local sculptor cast the stainless-steel Mothman statue, installed in downtown Point Pleasant in the early 2000s.\"},{\"id\":\"C2\",\"stop\":\"U2\",\"stop_name\":\"TNT area (McClintic Wildlife Management Area)\",\"text\":\"Two young couples reported a large grey winged creature with glowing eyes near the former TNT plant on November 15, 1966.\"},\"...\"]",
 "heard": "Everyone online says the Mothman was first seen in November 1966 near the old TNT plant north of town, and that the sightings stopped after the Silver ..."
}

Reply:

{
 "task": "vet",
 "title": "Point Pleasant claims, vetted",
 "summary": "Most of this weekend's claims are solid, settled regional history: the 1774 battle, Cornstalk's death at Fort Randolph, the wartime ordnance plant, and the Silver Bridge collapse and its eyebar cause are all the kind of thing records confirm. The softer spots are what a specific small museum currently has on display, the hotel's exact build year, and the tidy idea that sightings stopped right when the bridge fell - plausible, but not pinned down the way the history claims are. None of these twelve claims touch the supernatural part of the story, which is why the set reads as mostly documented.",
 "verdict": "mostly-documented",
 "ratings": [
  {
   "id": "C1",
   "rating": "documented",
   "confidence": "medium",
   "why": "A public statue going up downtown is the kind of thing local news and town records cover at the time; the statue and its local maker are well established, though pinning the installation to an exact year rather than 'early 2000s' would need the record itself.",
   "check": "the town's own records or the local newspaper's archive for the installation",
   "retell": "A local artist cast the stainless-steel Mothman statue that's stood downtown since the early 2000s."
  },
  {
   "id": "C2",
   "rating": "documented",
   "confidence": "medium",
   "why": "The November 15, 1966 report by two young couples is the founding event of the whole story and was covered by the local paper at the time; exact details like color and eye glow shift a little between retellings, so treat those as the witnesses' description, not a verified description of anything.",
   "check": "the local newspaper's archive for mid-November 1966",
   "retell": "Two young couples reported a large winged creature with glowing eyes near the old TNT plant on November 15, 1966 - a real, contemporaneously reported account, not a confirmed sighting of anything in particular."
  },
  "..."
 ],
 "patterns": [
  "A tidy ending - sightings stopping right when the Silver Bridge fell - is a satisfying shape for a story, but no record actually counted reports closely enough to prove that clean a cutoff (C8).",
  "Claims about what a specific small museum currently has on display (C4, C5) are current-state claims, not historical fact; exhibits change and are better confirmed with the museum directly than treated as settled.",
  "..."
 ],
 "sources": [
  "the county historical society",
  "the local newspaper's archive for 1966-67",
  "..."
 ]
}

task: scout - a one-day showfolk-town trip with a pasted viral post (quirky)

Input:

{
 "task": "scout",
 "trip_title": "Showfolk town day trip",
 "area": "Gibsonton and Riverview, Florida (Hillsborough County)",
 "base": "{\"name\":\"Apollo Beach rental\",\"lat\":27.773,\"lon\":-82.407}",
 "dates": "{\"start\":\"2026-11-07\",\"days\":1,\"time_zone\":\"America/New_York\",\"daylight\":[{\"date\":\"2026-11-07\",\"sunrise\":\"06:45\",\"sunset\":\"17:42\"}]}",
 "prefs": "{\"interests\":[\"history\",\"oddities\",\"food lore\"],\"after_dark\":false,\"roads\":\"town\",\"start_time\":\"10:00\"}",
 "heard": "Gibsonton is supposed to be where carnival and sideshow performers spent the winters. I read that the post office had a low counter for little people  ...",
 "stops": "[{\"id\":\"U1\",\"name\":\"International Independent Showmen's Museum\",\"lat\":27.858,\"lon\":-82.332,\"minutes\":90,\"note\":\"\"}]",
 "notes": "Day trip only, back before dark."
}

Reply:

{
 "task": "scout",
 "title": "Gibtown: A Showfolk Lore Day Trip",
 "summary": "Gibsonton grew a nickname, 'Gibtown,' because carnival and circus performers wintered along its waterfront for decades, and the town absorbed their way of life into its ordinary streets - a post office counter, a relaxed attitude about what you could park in your yard, a restaurant run by a famous couple from the sideshow. The loop follows that history from the water that first drew showfolk here to the museum built to keep their own story straight.",
 "arc": "It opens on the quiet Alafia River waterfront that explains why showfolk settled here at all, works through the town's everyday oddities - the post office counter, the old live-and-let-live zoning, the site of a couple's famous fish camp - and climaxes at the Showmen's Museum, where that whole community's history is kept and told by people who lived it.",
 "mood": "quirky",
 "stops": [
  {
   "id": "L1",
   "name": "Alafia River waterfront, Gibsonton",
   "kind": "history",
   "story": "Gibsonton's showfolk history starts on the water. In the 1930s and 40s, carnival and circus workers began wintering along the Alafia River and the edge of Tampa Bay here, drawn by a mild climate, cheap land, and room to dock boats, park trailers and keep show equipment between seasons. The town's showfolk nickname, 'Gibtown,' grew out of that seasonal community rather than out of any single performer or show.",
   "era": "1930s-1940s",
   "lat": 27.841,
   "lon": -82.355,
   "pos": "approximate",
   "minutes": 20,
   "best_time": "morning",
   "ask": "Ask a longtime local why showfolk picked this stretch of waterfront instead of a town further inland.",
   "claims": [
    "Carnival and circus workers began using the Gibsonton area as a winter base starting in the 1930s and 1940s.",
    "The town became known informally as 'Gibtown' because of this seasonal showfolk community."
   ],
   "respect": "Stay on public roads and right-of-way - much of the immediate waterfront here is private property."
  },
  {
   "id": "L2",
   "name": "Gibsonton Post Office",
   "kind": "oddity",
   "story": "Locals and showfolk tell of a low service counter built into the Gibsonton post office so that short-statured sideshow performers, who wintered in town alongside the carnivals, could be served standing on the floor like anyone else. It is one of the most repeated details about the town's showfolk years - a small fixture said to stand for a community that built its everyday life around its unusual neighbors instead of around them.",
   "era": "mid-20th century",
   "lat": 27.839,
   "lon": -82.3435,
   "pos": "approximate",
   "minutes": 10,
   "best_time": "midday",
   "ask": "Ask the staff or a longtime resident whether the low counter is still there, or whether it was removed when the building changed.",
   "claims": [
    "The Gibsonton post office had a lowered service counter installed to accommodate short-statured customers.",
    "Short-statured sideshow performers were long-term residents of Gibsonton during the mid-20th century."
   ],
   "respect": "This is a working post office - keep any visit brief and let customers go about their business."
  },
  "..."
 ],
 "dropped": [],
 "tips": [
  "Treat Gibsonton like a lived-in town, not a theme park - most of what makes it interesting is still someone's home or workplace.",
  "The showfolk community here is tied to a winter season by tradition, so a cooler-weather visit is more likely to feel lived-in than a midsummer one.",
  "..."
 ],
 "check_before": [
  "Confirm the Showmen's Museum's open days and hours before you drive out.",
  "Check whether any guided tour or docent talk at the museum needs booking ahead.",
  "..."
 ]
}

task: vet - a one-day showfolk-town trip with a pasted viral post (mostly-documented)

Input:

{
 "task": "vet",
 "trip_title": "Showfolk town day trip",
 "area": "Gibsonton and Riverview, Florida (Hillsborough County)",
 "claims": "[{\"id\":\"C1\",\"stop\":\"L1\",\"stop_name\":\"Alafia River waterfront, Gibsonton\",\"text\":\"Carnival and circus workers began using the Gibsonton area as a winter base starting in the 1930s and 1940s.\"},{\"id\":\"C2\",\"stop\":\"L1\",\"stop_name\":\"Alafia River waterfront, Gibsonton\",\"text\":\"The town became known informally as 'Gibtown' because of this seasonal showfolk community.\"},\"...\"]",
 "pasted": "This tiny Florida town is where every famous circus performer retired. Gibsonton is the only town in America where you can legally keep an elephant in ...",
 "heard": "Gibsonton is supposed to be where carnival and sideshow performers spent the winters. I read that the post office had a low counter for little people  ..."
}

Reply:

{
 "task": "vet",
 "title": "Gibsonton's Showfolk History, Fact-Checked",
 "summary": "Gibsonton's identity as a winter home for carnival and circus workers, the Tomainis' Giant's Camp, and the nearby showmen's museum are solid, well-corroborated local history. The embellishment creeps in around the post-office-counter and animal-keeping details, which are plausible but under-sourced, and especially in the pasted post's superlatives ('every famous performer', 'the only town in America') and its unattributed ghost claim.",
 "verdict": "mostly-documented",
 "ratings": [
  {
   "id": "C1",
   "rating": "documented",
   "confidence": "medium",
   "why": "Gibsonton's role as a winter base for traveling carnival and circus workers beginning in that era is well-established local history and broadly undisputed, though the exact starting decade shifts a little from source to source.",
   "check": "the county historical society and local newspaper archives from that period",
   "retell": "Carnival and circus workers started wintering in Gibsonton around the 1930s-40s, and the custom stuck for decades."
  },
  {
   "id": "C2",
   "rating": "documented",
   "confidence": "high",
   "why": "The 'Gibtown' nickname tied to the showfolk community is consistently used in local and regional accounts with no real dispute.",
   "check": "local newspaper archives and the town's own historical accounts",
   "retell": "Locals still call it 'Gibtown' after its long run as a carnival wintering town."
  },
  "..."
 ],
 "patterns": [
  "Superlatives like 'every famous circus performer' and 'the only town in America' stretch a real but narrower history into absolute claims.",
  "The elephant and equipment claims state a local-tolerance arrangement as flat legal fact, when it needs checking against current county zoning rules.",
  "..."
 ],
 "sources": [
  "the county historical society",
  "local newspaper archives from the mid-20th century onward",
  "..."
 ]
}

Build the input yourself

Load the script in node (global.window = {}; require("./lorekit.js")), then:

const K = LoreKit;
const trip = { title: "Mothman country weekend", area: "Point Pleasant, WV", base_name: "Rental", base_pos: "38.8510, -82.1290",
  start_date: "2026-10-24", days: 2, start_time: "09:00", speed: "rural", tz: "America/New_York",
  heard: "First sightings in November 1966 near the TNT area...", stops_text: "Mothman statue | 38.8446, -82.1372 | 20" };
const scan = K.scan(trip, null);                       // loop, daylight, schedule, checks
const wire = K.toWire(K.buildInput("scout", { scan }).input);   // POST to /estimate and /run
// later: const scout = K.normalize(K.parseReply(job.output.output));
// K.reconcile(scout, K.scan(trip, scout)) -> [{level, text}]
// vet: const v = K.buildInput("vet", { scan: K.scan(trip, scout), scout }); v.claims are the ids the reply must rate

Step 1 — a tiny client helper

One function that sends JSON and unwraps the envelope. Paste a personal token from /tokens.html, or leave it empty and mint a guest token in step 2.

BASE="https://api.skillsafe.ai/v1/app-api"
TOKEN="paste-your-token-here"   # from https://lore-loop.skillsafe.ai/tokens.html
api() { # api METHOD PATH [JSON-BODY]
  curl -s -X "$1" "$BASE$2" -H "Content-Type: application/json" \
    ${TOKEN:+-H "Authorization: Bearer $TOKEN"} ${3:+--data "$3"}
}

Step 2 — a token

A guest token is enough for /me and /estimate. A run is metered, so it needs a personal token: sign in on /tokens.html and copy it from there.

# a guest token (enough for /me and /estimate); a run needs your personal token from /tokens.html
TOKEN=$(curl -s -X POST "$BASE/guest" -H "Content-Type: application/json" -d '{"slug":"lore-loop"}' | jq -r '.data.token')

Step 3 — GET /me

Who the token is (subject_type: user or guest) and the credit balance.

api GET /me | jq '.data | {subject_type, credits}' 

Step 4 — POST /estimate

Free. The body is the run input itself, the bare object (never wrapped in {"input": ...}). hold_credits is a reservation, not the price; min_credits is what the balance must cover; model_alias reads gpt-terra.

# input.json: the run input object - {"task": "scout", "trip_title": "Mothman country weekend", "area": "Point Pleasant, WV", "base": "{...}", "dates": "{...}", "stops": "[...]"}
api POST /estimate "$(cat input.json)" | jq '.data | {hold_credits, min_credits, model, model_alias, markup_bps, warnings}' 

Step 5 — POST /run, then poll the job

Send an Idempotency-Key built from the lane and the input: a retry with the same key never bills twice. The page uses lore-loop:<task>:<inputHash>:a<attempt>, and its one reformat retry (with retry_note added) is attempt 2, a new key and a second run. The job's output.output is the reply text; truncated: true means the balance cut it short.

KEY="lore-loop:scout:$(shasum -a 256 input.json | cut -c1-16):a1"
JOB=$(curl -s -X POST "$BASE/run" -H "Content-Type: application/json" -H "Authorization: Bearer $TOKEN" \
  -H "Idempotency-Key: $KEY" --data @input.json | jq -r '.data.job_id')
while :; do
  J=$(api GET "/jobs/$JOB"); S=$(echo "$J" | jq -r '.data.status')
  case "$S" in succeeded|failed|cancelled) break;; esac; sleep 2
done
echo "$J" | jq -r '.data.output.output' > reply.json   # one JSON object, the reply contract
echo "$J" | jq '.data | {charged_credits, truncated}' 

Step 6 — POST /run-stream

The same run as Server-Sent Events, with the same input.json. Browsers receive progress ticks rather than text deltas; the final done event carries the reply.

# Server-Sent Events: tick/delta events while the job runs, then a final event with the job
curl -N -s -X POST "$BASE/run-stream" -H "Content-Type: application/json" -H "Authorization: Bearer $TOKEN" \
  -H "Idempotency-Key: lore-loop:scout:$(shasum -a 256 input.json | cut -c1-16):a1" --data @input.json