Files
scriptorium/docs/api.md

6.9 KiB

HTTP API Reference

Scope

This document is the canonical public 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_id
  • inputs (must contain at least one named input)

Input reference types currently supported by runtime artifact loading:

  • file
  • inline

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 temperature preserves the selected profile/default value, while "temperature": 0 explicitly sets the effective temperature to zero.
  • extra_params accepts JSON-compatible values: strings, numbers, booleans, objects, and arrays.
  • extra_params are passed through effective model metadata and flattened into top-level provider request fields by the OpenAI-compatible client.
  • extra_params keys 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, or response_format.
  • Raw API-key values are not accepted. Use api_key_env to name an environment variable.

Strict JSON Rules

Request decoding uses strict JSON field checks:

  • unknown request fields are rejected with 400 invalid_json
  • unknown model fields are rejected with 400 invalid_json
  • raw API-key payload fields such as api_key are 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.status is failed
  • 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 fields
  • 400 invalid_request: missing/invalid request fields
  • 400 profile_required: no explicit profile_id and prompt has no default_profile
  • 400 prompt_load_failed: prompt definition invalid/unloadable
  • 400 profile_load_failed: profile invalid/unloadable
  • 400 artifact_not_allowed: file input artifact is outside the configured artifact root or file refs are not enabled
  • 400 artifact_read_failed: input artifact loading failed
  • 400 prompt_render_failed: template render failed
  • 400 api_key_env_missing: named API-key environment variable is missing
  • 413 request_too_large: request body exceeds the configured request limit
  • 413 artifact_too_large: HTTP file input artifact exceeds the configured artifact limit
  • 413 response_too_large: encoded JSON response exceeds the configured response limit
  • 404 prompt_not_found
  • 404 profile_not_found
  • 502 llm_failed: outbound model request failed
  • 500 validation_runtime_failed: validator runtime/schema-load failure
  • 500 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).