Skip to content
TOPOVOID

Developer docs · Preview

State API

Lightweight, effective model customization with representation engineering.

Base URL
https://api.topovoid.com/reflecho
Authentication
Authorization: Bearer
Updated

Overview

The State API learns how the User side of your conversations writes and makes decisions, building a persistent State in the base model’s representation space without modifying its weights.

Once a State is built from your uploaded conversations, calling /completions generates the next User message for a given context. Each API key manages one State; the full OpenAPI specification is available at GET /openapi.yaml.

Authentication

All API requests are authenticated with an API key. To request a key, email hello@topovoid.com, then call /register once to activate it before making other calls.

Every endpoint except /register and /openapi.yaml requires an Authorization: Bearer $TOPOVOID_API_KEY header. Keep your API key on the server side—never embed it in browsers, mobile apps, or other client-side code.

POST/registerKey in the body

Activates and registers an API key. This endpoint is idempotent; calling it again with an already-registered key is a no-op.

Parameter Type Description
apikey string Required. Your API key

Returns {"ok": true, "user_id": "..."}.

Example
curl https://api.topovoid.com/reflecho/register \
  -H "Content-Type: application/json" \
  -d "{\"apikey\": \"$TOPOVOID_API_KEY\"}"

Upload conversations

POST/uploadBearer key

Uploads training conversations as a JSON array (optionally compressed with Content-Encoding: gzip). Uploading a conversation whose id already exists overwrites the previous version; setting value to null deletes that conversation.

Parameter Type Description
id string Required. Unique conversation ID
value object or null Required. {"messages": [...]} to create or replace a conversation, or null to delete it

Each entry in messages has the following shape:

Parameter Type Description
type string Role tag: User, Assistant, AssistantThink or ToolCall
content string Message body
name string Tool name (required for ToolCall entries only)

Every conversation must end with a User message, and consecutive User messages must be separated by at least one non-User turn. AssistantThink and ToolCall entries are preserved as context but excluded from the training loss.

Returns 204 No Content on success.

sessions.json
[
  {
    "id": "0199f1a2-6c3e-7d10-9a4b-2f8e5c1d7a30",
    "value": {
      "messages": [
        { "type": "User", "content": "Review the service entry point." },
        { "type": "Assistant", "content": "Config and start-up are coupled." },
        { "type": "User", "content": "Don't change it. Show me the tests." }
      ]
    }
  }
]
Example
curl https://api.topovoid.com/reflecho/upload \
  -H "Authorization: Bearer $TOPOVOID_API_KEY" \
  -H "Content-Type: application/json" \
  --data-binary @sessions.json

Build a State

POST/flush-stateBearer key

Triggers a background build across all currently uploaded conversations. Once trained, the candidate State is promoted to active only after passing automated validation checks; if a build or check fails, your previously active State remains in service untouched.

Building a State requires at least 10 training examples, where each User turn preceded by at least one earlier message in the same conversation counts as one example. The request body is optional—any omitted hyperparameters fall back to the selected preset:

Parameter Type Description
preset string fast (default) or full
learning_rate number Peak learning rate, in (0, 0.001]
epochs integer Maximum training epochs, from 1 to 10
train_token_budget integer or null Cap on total training tokens (minimum 10,000, or null for no cap)
Preset fast full
Training token limit 300,000 Unlimited
Maximum epochs 2 2
Max example length 4,096 tokens 8,192 tokens
Peak learning rate 2e-4 1e-4
Typical duration ~9 minutes Tens of minutes to a few hours

Returns 202 Accepted with the same status payload as /state-status.

Example
curl https://api.topovoid.com/reflecho/flush-state \
  -H "Authorization: Bearer $TOPOVOID_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"preset": "full"}'

Check build status

GET/state-statusBearer key

Returns the current status of the most recent build job. When waiting for a build to finish, polling every ~30 seconds is recommended.

Field Type Description
status string Job status: building, finished or failed
phase string Current stage: queued, preparing, training, checking or activating
progress object Step-level training progress
active object or null Metadata for the currently active State (null if no State has been activated yet)
reason string Failure code when status is failed: no_dev_improvement (validation loss did not beat the base model; usually resolved by uploading more examples), generation_check_failed, consistency_check_failed, training_error or internal_error
Example
curl https://api.topovoid.com/reflecho/state-status \
  -H "Authorization: Bearer $TOPOVOID_API_KEY"
200 OK
{
  "status": "building",
  "phase": "training",
  "progress": { "attempt": 1, "step": 18, "total_steps": 37 },
  "start_at": "2026-10-16T08:12:03.418+00:00",
  "active": null
}

Create a completion

POST/completionsBearer key

Generates the next User message for an ongoing conversation using your active State.

Parameter Type Description
id string Required. Unique request ID
context string Required. Conversation transcript formatted as described in Context format
systemprompt string Optional. Overrides the default system prompt (note: States are trained under the default system prompt)
thinking string Optional. Reasoning effort: off (default), low, medium or xhigh
Response field Type Description
response string Generated User message
time integer End-to-end generation latency in milliseconds
confidence number or null Geometric mean of the output token probabilities (null when thinking is enabled)
Example
curl https://api.topovoid.com/reflecho/completions \
  -H "Authorization: Bearer $TOPOVOID_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"id": "0199f1a2-8b40-7c55-a1d3-5e7f00c2b9a4",
       "context": "User: All tests pass. Ready to commit.\n\nAssistant:"}'
200 OK
{
  "response": "Cover the failure paths too.",
  "time": 1842,
  "confidence": 0.74
}

Context format

Because the underlying model always completes after an Assistant: prefix while your State models the User, role labels in context are swapped relative to /upload: format prior User turns as Assistant: and prior Assistant turns as User:. Separate turns with a blank line, omit AssistantThink and ToolCall entries, and end the string with Assistant: so the model generates the next user reply:

context
Assistant: Review the service entry point.

User: Config and start-up are coupled.

Assistant: Don't change it. Show me the tests.

User: All tests pass. Ready to commit.

Assistant:

Errors

Failed requests return a JSON body of the form {"code": "...", "message": "..."}. Branch on code rather than the human-readable message:

Status code Cause
400 bad_request Malformed parameter, fewer than 10 training examples, or prompt exceeding the context limit
401 unauthorized Missing or invalid API key
404 not_found API key not registered, no conversations uploaded yet, or no build has been run
405 method_not_allowed Unsupported HTTP method for this path
409 conflict A build is already queued or running, or /completions was called before a State finished building
413 payload_too_large Request payload exceeds size limits
415 unsupported_content_encoding Content encoding other than gzip
500 internal_error Unexpected server-side error
503 service_unavailable Service temporarily overloaded or unavailable

Limits

  • Prompts are capped at roughly 32,000 tokens.
  • /completions returns a single JSON response; token streaming is not supported.
  • Build and completion jobs are processed sequentially and may queue under load.
  • Uploaded conversations persist until explicitly deleted via /upload with value: null. Completion requests and responses are logged on the server.