> ## Documentation Index
> Fetch the complete documentation index at: https://docs.stateset.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Preview Job V1

> Dry-run a trigger payload without queueing. Resolves template defaults + per-job overrides into the final params dict, surfaces what model + agent_mode would…

Dry-run a trigger payload without queueing.

Resolves template defaults + per-job overrides into the final
`params` dict, surfaces what model + agent\_mode would actually be
used, and reports whether the request would currently pass quota.
Does NOT create a Job row, consume an idempotency key, or count
against quota — purely diagnostic.

Useful before sending a large batch: catch the misconfigured
`agent_type`, the wrong model alias, the missing template default,
without burning the budget.

### Request body

`TriggerRequest`

<ParamField body="agent_type" type="string">
  Built-in template name (general, analytics\_notebook, code\_interpreter, jupyter\_notebook, outbound\_sequence, case\_study, slide\_deck) or the name of a tenant-owned Template row. Alphanumeric + dash/underscore, ≤128 chars.
</ParamField>

<ParamField body="instruction" type="string" required>
  Natural-language task description shown to the agent. Whitespace-only is rejected with 422.
</ParamField>

<ParamField body="params" type="object">
  Free-form template parameters merged into the worker's context. Reserved keys (model, effort\_level, max\_cost\_usd, webhook\_url) are populated from the typed fields below.
</ParamField>

<ParamField body="webhook_url" type="string,null">
  Optional one-shot webhook called when the job reaches a terminal state (succeeded / failed). Single best-effort POST, no retries. Provide `webhook_secret` alongside to receive an HMAC-SHA256 signature. Tenants needing reliable delivery should register a tenant webhook via the dashboard instead.
</ParamField>

<ParamField body="webhook_secret" type="string,null">
  Optional shared secret for signing the ad-hoc webhook body. Adds `X-Webhook-Signature: t=&lt;unix>,v1=&lt;hex>` to the delivery where v1 = HMAC-SHA256(secret, f'\{t}.\{body}'). Receivers verify by recomputing the HMAC with the same secret and rejecting deliveries with stale or mismatched signatures. Length 16..256.
</ParamField>

<ParamField body="model" type="string,null">
  Pin a provider-compatible model. Claude aliases include haiku / sonnet / opus; agent\_mode='openai' accepts gpt-5.6-sol. Canonical IDs are accepted directly. Omit to use the selected provider's default.
</ParamField>

<ParamField body="effort" type="string,null">
  Provider reasoning-effort knob. Accepted values: low, medium, high, xhigh, max. Support depends on the selected model.
</ParamField>

<ParamField body="max_cost_usd" type="number,null">
  Hard per-job cost ceiling in USD. The worker monitors running cost each iteration; when the cap is crossed the job is cancelled with status='cancelled' before the next API call. Range: (0, 1000].
</ParamField>

<ParamField body="agent_mode" type="string,null">
  Execution backend. 'agent' (default; alias for 'claude') runs the Anthropic LLM sampling loop. 'openai' runs GPT-5.6 Sol with the Responses API GA computer tool. 'nsr' routes to the local neuro-symbolic engine — zero API tokens and deterministic.
</ParamField>

<ParamField body="tags" type="string[],null">
  Free-form labels stored alongside the job. Up to 20 entries, each ≤64 chars, alphanumeric + underscore + dash + colon. Filter on `GET /jobs?tag=&lt;value>` to retrieve a slice.
</ParamField>

<ParamField body="outcome_type" type="string,null">
  Strategy §4 SKU. Setting this turns the Job into a billable Outcome on success. Choices: resolved\_contact ($2), resolved_return ($2), wismo\_resolution ($1.50), abandoned_cart_recovery ($3), qualified\_lead ($5), b2b_reorder ($5), billing\_dispute ($5), upsell ($20), pre\_purchase\_consultation ($10), triage ($0.50). Order Form may override per-SKU pricing.
</ParamField>

<ParamField body="inquiry_id" type="string,null">
  Stable Customer-side identifier for the conversation this Job is working — typically the upstream system's id (Zendesk ticket, Gorgias conversation, Shopify order). Drives Multi-Touch Consolidation: follow-up Jobs with the same inquiry within the 72h Resolution Window roll up under one billable Outcome (Appendix A.1). Falls back to the Job's UUID if omitted.
</ParamField>

<ParamField body="system_of_record_event_id" type="string,null">
  Upstream system-of-record event id proving the Outcome happened (Zendesk ticket id closed, NetSuite RMA id, etc). Required for SoR-bound SKUs (resolved\_contact, resolved\_return, b2b\_reorder, billing\_dispute) — Outcome is not minted without it.
</ParamField>

<ParamField body="triggered_human_handoff" type="boolean,null">
  Set true when the agent escalated to a human. The worker routes such Jobs to a TRIAGE Outcome at \$0.50 regardless of the requested SKU (Strategy §4 margin protection).
</ParamField>

<ParamField body="high_value_action" type="boolean,null">
  Set true when the resolution involved an Appendix B.3 High-Value Action (refund > threshold, PII modification, subscription/payment-instrument change). Recorded on the Outcome row for audit; a future safety classifier will gate on this flag.
</ParamField>

<ParamField body="completion_criterion" type="object,null">
  Per-SKU proof structure (Appendix A.2). Keys vary by SKU — resolved\_contact accepts ticket\_id, reopen\_check; wismo\_resolution accepts tracking\_delivered, session\_id, read\_receipt; abandoned\_cart\_recovery accepts order\_id, tracked\_link, conversion\_at; etc. Unrecognized keys are kept under `_unrecognized_keys` rather than rejected.
</ParamField>

<ParamField body="outcome_metadata" type="object,null">
  Free-form metadata attached to the Outcome row (extra\_metadata column). Use for per-customer integration fields you want to surface in the Outcome Accounting Dashboard without polluting completion\_criterion.
</ParamField>

<ParamField body="output_schema" type="object,null">
  Optional JSON Schema constraining the agent's final output. When set, the worker injects a system-prompt directive instructing the agent to emit a single JSON object matching this schema. Validation is currently caller-side — pull `summary` and `jsonschema.validate()` against it; full agent-side enforcement is a roadmap item. Schemas larger than 8 KB serialised are rejected.
</ParamField>

### Response

`JobPreviewResponse`

<ResponseField name="agent_type" type="string" required />

<ResponseField name="agent_type_kind" type="string" required>
  How the agent\_type resolves: `builtin` ships with the platform; `tenant` is owned by your org; `unknown` would be rejected by /trigger but is shown here so callers can confirm typos.
</ResponseField>

<ResponseField name="instruction" type="string" required>
  The trimmed instruction that would land on the worker.
</ResponseField>

<ResponseField name="resolved_params" type="object" required>
  The full `params` dict the worker would see, with template defaults merged underneath your per-job overrides.
</ResponseField>

<ResponseField name="resolved_model" type="string,null" required>
  Canonical model id after alias resolution. None = deployment default.
</ResponseField>

<ResponseField name="resolved_agent_mode" type="string" required>
  `claude` (default), `openai` (GPT-5.6 Sol), or `nsr` (local engine).
</ResponseField>

<ResponseField name="quota_ok" type="boolean" required>
  True iff sending this job right now would clear the tenant's quota check.
</ResponseField>

<ResponseField name="quota_used" type="integer" required />

<ResponseField name="quota_limit" type="integer" required />

### Status codes

| Code  | Meaning             |
| ----- | ------------------- |
| `200` | Successful Response |
| `422` | Validation Error    |

<RequestExample>
  ```bash cURL theme={null}
  curl --request POST \
    --url 'https://api.computer.stateset.app/api/v1/jobs/preview' \
    --header 'X-API-Key: YOUR_API_KEY' \
    --header 'Content-Type: application/json' \
    --data '{
    "agent_type": "general",
    "effort": "low",
    "instruction": "Open https://example.com and report the page title.",
    "max_cost_usd": 0.1,
    "model": "haiku",
    "webhook_url": "https://hooks.example.com/cua"
  }'
  ```
</RequestExample>

<ResponseExample>
  ```json 200 theme={null}
  {
    "agent_type": "string",
    "agent_type_kind": "builtin",
    "instruction": "string",
    "resolved_params": {},
    "resolved_model": "string",
    "resolved_agent_mode": "string",
    "quota_ok": true,
    "quota_used": 1,
    "quota_limit": 1
  }
  ```
</ResponseExample>
