211 lines
5.6 KiB
Markdown
211 lines
5.6 KiB
Markdown
# 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](../cli.md).
|
|
|
|
## 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
|
|
|
|
```json
|
|
{
|
|
"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`
|
|
|
|
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
|
|
|
|
## Success Response
|
|
|
|
Status: `200 OK`
|
|
|
|
Response shape:
|
|
|
|
```json
|
|
{
|
|
"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:
|
|
|
|
```json
|
|
{
|
|
"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_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
|
|
- `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).
|