6.9 KiB
HTTP API Integration
Scope
This document defines the implemented inbound HTTP contract for Scriptorium.
Current scope is only:
POST /v1/runs
For CLI behavior, see the CLI reference.
Endpoint
- Method:
POST - Path:
/v1/runs - Content type: JSON request/response
Route behavior:
- unknown path:
404 not_found - unsupported method on
/v1/runs:405 method_not_allowed
Copyable request example file:
examples/http-run.json
Request Body
{
"prompt_id": "generic.structured_events",
"profile_id": "local-quality",
"prompt_version": "1.0.0",
"inputs": {
"transcript": {"type": "file", "uri": "./examples/fixtures/transcript.md"},
"glossary": {"type": "inline", "body": "party:\n - Rin"}
},
"vars": {
"session_date": "2026-05-04"
},
"model": {
"endpoint": "http://localhost:8000/v1",
"model": "gpt-4o-mini",
"temperature": 0.0,
"max_tokens": 800,
"top_p": 1.0,
"timeout_seconds": 120,
"service_tier": "priority",
"reasoning_effort": "medium",
"api_key_env": "SCRIPTORIUM_API_KEY",
"extra_params": {
"route": "primary",
"provider_options": {
"retry_budget": 2
}
}
},
"include_raw_output": false
}
Required fields:
prompt_idinputs(must contain at least one named input)
Input reference types currently supported by runtime artifact loading:
fileinline
HTTP file references require server.artifact_root or serve --artifact-root.
Relative file URIs resolve against that root. Absolute file URIs are accepted
only when they are lexically inside the root. Requests that escape the root by
lexical traversal, including .. traversal and absolute paths outside the root,
return 400 artifact_not_allowed. Symlinks inside the root are followed by the
operating system, including symlinks that point outside the root. The artifact
root must not be writable by untrusted users. inline references do not require
an artifact root.
HTTP file artifacts above the configured artifact limit return
413 artifact_too_large. Inline bodies are bounded by the request body limit.
Model override notes:
- Numeric model override fields distinguish omitted values from explicit zero values. For example, omitting
temperaturepreserves the selected profile/default value, while"temperature": 0explicitly sets the effective temperature to zero. extra_paramsaccepts JSON-compatible values: strings, numbers, booleans, objects, and arrays.extra_paramsare passed through effective model metadata and flattened into top-level provider request fields by the OpenAI-compatible client.extra_paramskeys must not be empty and must not collide with reserved outbound fields:model,session_id,messages,temperature,max_tokens,top_p,service_tier,reasoning_effort, orresponse_format.- Raw API-key values are not accepted. Use
api_key_envto name an environment variable.
Strict JSON Rules
Request decoding uses strict JSON field checks:
- unknown request fields are rejected with
400 invalid_json - unknown
modelfields are rejected with400 invalid_json - raw API-key payload fields such as
api_keyare rejected as unknown fields - request bodies above the configured request limit are rejected with
413 request_too_large - trailing JSON tokens after the request object are rejected with
400 invalid_json
Success Response
Status: 200 OK
Response shape:
{
"artifact": {
"name": "output",
"content_type": "application/json",
"body": "{\"summary\":\"...\"}",
"uri": "",
"size": 123,
"hash": "..."
},
"validation": {
"status": "passed",
"mode": "json_schema",
"errors": [],
"schema_path": "structured_events.schema.json",
"repair_attempts": 0,
"is_valid": true
},
"metadata": {
"run_id": "...",
"prompt_id": "generic.structured_events",
"prompt_version": "1.0.0",
"prompt_hash": "...",
"rendered_prompt_hash": "...",
"selected_profile_id": "local-quality",
"model_name": "gpt-4o-mini",
"endpoint": "http://localhost:8000/v1",
"model_params": {
"endpoint": "http://localhost:8000/v1",
"model": "gpt-4o-mini",
"temperature": 0,
"max_tokens": 800,
"top_p": 1,
"timeout_seconds": 120,
"service_tier": "priority",
"reasoning_effort": "medium",
"api_key_env": "SCRIPTORIUM_API_KEY",
"extra_params": {
"route": "primary",
"provider_options": {
"retry_budget": 2
}
}
},
"input_hashes": {
"transcript": "..."
},
"usage": {
"prompt_tokens": 11,
"completion_tokens": 22,
"total_tokens": 33,
"cached_tokens": 0,
"cache_write_tokens": 0
},
"start_time": "2026-05-04T12:00:00Z",
"end_time": "2026-05-04T12:00:01Z",
"duration_ms": 1000,
"validation_mode": "json_schema",
"validation_status": "passed",
"repair_attempts_used": 0
}
}
raw_model_output is omitted by default.
metadata.usage.cached_tokens and metadata.usage.cache_write_tokens are always present as numbers. They are 0 when the provider omits compatible cache usage fields or reports no cache activity.
To include it, send:
"include_raw_output": true
Validation Failure Behavior
Validation content failures do not map to HTTP error status.
Behavior:
- status remains
200 OK validation.statusisfailed- validation errors are returned in
validation.errors
Error Responses
Error body shape:
{
"error": {
"code": "invalid_request",
"message": "prompt_id is required"
}
}
Current error mapping (non-exhaustive):
400 invalid_json: malformed JSON or unknown JSON fields400 invalid_request: missing/invalid request fields400 profile_required: no explicitprofile_idand prompt has nodefault_profile400 prompt_load_failed: prompt definition invalid/unloadable400 profile_load_failed: profile invalid/unloadable400 artifact_not_allowed: file input artifact is outside the configured artifact root or file refs are not enabled400 artifact_read_failed: input artifact loading failed400 prompt_render_failed: template render failed400 api_key_env_missing: named API-key environment variable is missing413 request_too_large: request body exceeds the configured request limit413 artifact_too_large: HTTP file input artifact exceeds the configured artifact limit413 response_too_large: encoded JSON response exceeds the configured response limit404 prompt_not_found404 profile_not_found502 llm_failed: outbound model request failed500 validation_runtime_failed: validator runtime/schema-load failure500 internal_error
Security And Deployment Note
The HTTP adapter has no built-in authentication or authorization.
Deploy behind trusted controls (for example authenticated gateway/reverse proxy and network boundaries).