NeoSyntropyDocumentation

API reference

Backend control API

Opaque execute/commit loop for framework workflows. Prefer this surface over internal framework inference endpoints.

What the API exposes

The control API starts a backend-owned cycle and returns only client-visible fields: run status, current state, opaque execute steps, committed transitions, and rejection reasons.

It never returns topology, candidates, scores, providers, model names, or execution plans.

Authentication

402 if missing

User JWT

Authorization: Bearer <access_token> with an active subscription.

Optional X-NeoSyntropy-Project-ID

API key

Authorization: Bearer nsk_... with scope framework:invoke and an active subscription.

Endpoints

Returns ControlRunView

POST /api/v1/control/runs

Start a control run with a graph manifest and request context.

Commit or reject

POST /api/v1/control/runs/{run_id}/results

Submit local node results or a client_rejection; receive the next step or terminal status.

Ownership-scoped

GET /api/v1/control/runs/{run_id}

Poll client-visible run status. Sessions are in-memory with a one-hour TTL.

Start a run

Send a schema_version 1 graph manifest (nodes, edges, allow_unlisted_transitions) plus request context. Graphs require unique node ids and exactly one is_fallback: true node.

Requestshell
curl -X POST "$NEOSYNTROPY_API_URL/api/v1/control/runs" \
  -H "Authorization: Bearer $NEOSYNTROPY_API_KEY" \
  -H "X-NeoSyntropy-Project-ID: $NEOSYNTROPY_PROJECT_ID" \
  -H "Content-Type: application/json" \
  -d '{
    "graph": {
      "schema_version": 1,
      "nodes": [
        {
          "id": "Verify",
          "name": "Verify",
          "description": "verify identity",
          "prerequisites": [],
          "is_fallback": false
        },
        {
          "id": "OutOfScope",
          "name": "Out of scope",
          "description": "fallback",
          "prerequisites": [],
          "is_fallback": true
        }
      ],
      "edges": [
        {"source": "Start", "target": "Verify", "label": "first"},
        {"source": "Verify", "target": "End", "label": "complete"}
      ],
      "allow_unlisted_transitions": false
    },
    "request": {
      "intent": "refund my order",
      "current_state": "Start",
      "history": [],
      "prior_executions": [],
      "state": {},
      "metadata": {}
    },
    "category": "general"
  }'

Start response

Responsejson
{
  "run_id": "…",
  "status": "awaiting_execution",
  "current_state": "Start",
  "state": {},
  "step": { "step": 0, "nodes": ["Verify"] },
  "committed_transitions": [],
  "rejection": null,
  "completed": false
}

Submit results

Cover exactly the pending step.nodes with results, or send client_rejection (string ≤ 2000). The backend merges state, checks transition legality, commits at most one transition per step, and returns the next view.

Requestshell
curl -X POST "$NEOSYNTROPY_API_URL/api/v1/control/runs/$RUN_ID/results" \
  -H "Authorization: Bearer $NEOSYNTROPY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "results": [
      {
        "node_id": "Verify",
        "status": "succeeded",
        "output": null,
        "state_updates": {"verified": true},
        "next_state": "Verify",
        "error": null
      }
    ],
    "client_rejection": null
  }'

SDK path (preferred)

Most applications should use BackendClient and ControlManager instead of calling the HTTP loop directly. The SDK builds the control graph manifest, runs local handlers, and submits wired NodeResults.

Contracts from neo_syntropy_backend control_runs / control_engine and neosyntropy-framework BackendClient.