Documentation
The API
One namespace, one permission check, and no route that reads or writes a twin without proving the caller is allowed to touch it. This is the API the interface itself uses, documented because you are entitled to know what your browser is doing.
Namespace cfct/v1. No public token authentication yet, and not versioned for third parties.
Read this before you build anything on it
This is the application talking to itself. It is documented so you can see what the front end does, script your own account, and check that nothing is happening you did not ask for. It is not a public platform API and should not be treated as one yet.
- Authentication is the WordPress logged in cookie plus a REST nonce in the X-WP-Nonce header. That is it
- There is no token, no API key, no OAuth and no machine account. Anything calling these routes is calling them as a signed in human
- The namespace is cfct/v1, but it is not versioned in the sense that matters to an integrator. Routes and response shapes can change in a point release, and they will
- Rate limits are plan limits on runs and sweeps per month, not request limits per second
If you want a stable integration surface, say so on the contact form. It is a reasonable thing to want and it is on the roadmap rather than in the product, and this page is not going to imply otherwise.
Calling it from the page
The app is given its own base url and nonce on the page that holds the shortcode, as a global called CFCT. From the browser console on that page, this runs a saved scenario and prints the change in operating profit against doing nothing.
const res = await fetch( CFCT.rest + '/twins/12/scenarios/48/run', {
method: 'POST',
credentials: 'same-origin',
headers: {
'Content-Type': 'application/json',
'X-WP-Nonce': CFCT.nonce
},
body: JSON.stringify( { reps: 200, horizon: 12 } )
} );
const run = await res.json();
console.log( run.summary.deltas.ebitda.vs_baseline );Leave out the credentials or the nonce and you get a 401. The response is the full run: the median series, the p10 and p90 at every month, the aggregated events with their frequencies, and the brief.
The routes
Everything under /twins/{id} checks that the twin exists and that the caller owns it or holds a seat on it, and returns 404 or 403 before doing anything else.
| Route | Methods | What it does |
|---|---|---|
| /boot | GET | The only route that does not require a login. Returns the version, whether you are signed in, your plan and limits, the lever dictionary, the scenario templates, the nine agent classes, the thirteen source kinds, the metric keys and, if you have a plan, your twins. |
| /twins | GET, POST | List your twins, or create one. Creating derives the assumption ledger, builds the graph, generates agents and installs the starter scenarios in one call. |
| /twins/demo | POST | Build the worked example: the invented Harborline Components, with its sources, facts, graph, agents and scenarios. |
| /twins/{id} | GET, POST, DELETE | The overview with recent and pending jobs, update the name, industry, currency or settings, or delete the twin and everything under it. |
| /twins/{id}/rebuild | POST | Re-extract, rebuild the graph, regenerate agents and refresh the ledger. Pass ai to include the optional model pass over chunks the rules could not read. Locked assumptions survive. |
| /twins/{id}/sources | GET, POST | List sources with the gaps the twin still has, or add one. POST takes either a multipart file or a text field for pasted notes, plus a kind and a title. |
| /twins/{id}/sources/{sid} | GET, DELETE | One source with a preview of its first chunk, or delete it. Deleting removes the file from disk along with its chunks and its facts. |
| /twins/{id}/graph | GET | The whole knowledge graph: nodes, edges, types, and which nodes were inferred rather than read. |
| /twins/{id}/agents | GET | Every agent with counts by class, plus the six personality axes. |
| /twins/{id}/agents/{aid} | GET, POST | One agent, or edit it. Name, role, summary, objectives, constraints, personality, parameters, and whether it is enabled at all. |
| /twins/{id}/assumptions | GET | The full ledger with the confidence breakdown by origin. |
| /twins/{id}/assumptions/{aid} | POST | Set one assumption, which locks it against future rebuilds, or pass unlock to hand it back to the deriver. Either way the readiness score is recomputed. |
| /twins/{id}/scenarios | GET, POST | List scenarios with the templates and the lever dictionary, or save one. Naming a template with no levers fills the levers from the template against this twin. |
| /twins/{id}/scenarios/{sid} | DELETE | Delete a scenario. Its past runs stay. |
| /twins/{id}/scenarios/{sid}/run | POST | Run it. Replications and horizon are optional and are capped by your plan. Returns the finished run with its brief. |
| /twins/{id}/runs | GET | Every run on this twin, newest first. |
| /twins/{id}/runs/{rid} | GET | One run: the series with its bands, the baseline, the aggregated events and the brief. |
| /twins/{id}/runs/{rid}/narrate | POST | Ask the configured language model to rewrite the finished brief in better English. Returns an error explaining that the engine brief stands on its own if no model is configured. The numbers are not touched. |
| /twins/{id}/sensitivity/{sid} | POST | Move each load bearing assumption to the ends of its own band, one at a time, and report how far cumulative operating profit swings. Ranked by swing. |
| /twins/{id}/compare | POST | Up to eight scenarios against one baseline on one set of seeds. |
| /twins/{id}/sweeps | GET, POST | List sweeps, or create one: a lever, a range, a number of steps, replications, a horizon and an objective. A second lever makes it a grid. |
| /twins/{id}/sweeps/{wid} | GET, DELETE | A sweep with its points so far and the best point found, or delete it. |
| /twins/{id}/sweeps/{wid}/advance | POST | Do a few more seconds of work on a sweep and return the updated curve. This is how a two thousand simulation sweep progresses without a request timing out. |
| /twins/{id}/ask | GET, POST | The question history, or ask a question. Answers come from the graph, the ledger and the runs, and carry the rows that produced them. |
| /account | GET, POST | Your profile, plan, limits, usage this month and seats. POST saves profile fields and, if the site allows it, your own model key. |
| /tick | POST | Do a slice of queued background work, between two and twenty seconds of it. The browser calls this while you watch a job run. |
| /cron | GET | No login. Takes a key parameter which must match the site cron token, and runs a 25 second slice of the queue. This is the route an external cron service calls when WP-Cron is unreliable. |
The braces are path parameters and are numeric ids: id is the twin, sid a source or scenario depending on the route, aid an agent or an assumption, rid a run, wid a sweep.
Errors
Errors are ordinary WordPress REST errors with a code, a message written for a human, and a status.
- 401 means you are not signed in
- 402 means you are signed in with no plan on the account, and the message is whatever the site owner set as the gate message
- 403 means either the twin is not yours, or you have used this month's runs or sweeps, or you are at your plan limit for twins or files
- 404 means the twin, source, agent, run or sweep does not exist, or does exist and belongs to someone else, which is reported the same way on purpose
- 400 means the request was empty or malformed, such as an add source call with neither a file nor any text
- 502 means the optional language model was asked for something and did not answer. The engine output is unchanged
If you want to run this yourself
It is two WordPress plugins, and the whole API runs on your own server with your own database behind it.