# Sleeper Hit Studio Story API — Agent Integration Guide > This document is written for AI agents and engineering teams integrating the Story API. It complements the machine-readable spec at `/api/v1/openapi.json` and the capability manifest at `/api/v1/capabilities`. ## 1. What this API is for The Story API accepts sources (URLs, text, markdown, PDFs, scripts, brand guides) and produces narrative deliverables: pitch deck video + PDF, table reads, storyboards, and future trailer / production video. The canonical abstraction is a `StoryPlan` — a source-grounded plan with thesis, evidence, narrative beats, visual system, and per-artifact render intents — not a screenplay or raw prompt. Today the API ships production-stable identity, auth, credits, and discovery. Source ingestion, StoryPlan jobs, artifacts, and webhooks are landing incrementally. Read `/api/v1/capabilities` at the start of any new run so your agent adapts as new features go live instead of failing on hardcoded assumptions. ## 2. Authentication Create production API keys at https://docs.sleeperhit.studio/dashboard/api. Tokens are shown once and never displayed again — store them in your secret manager. Every request: ``` Authorization: Bearer sh__ ``` Keys are revocable and may carry an expiration. The scopes assigned at creation gate which endpoints the key can call. Initial scopes: - `story:read` - `story:write` - `source:read` - `source:write` - `artifact:read` - `artifact:publish` - `credits:read` - `webhook:write` Provider credentials (OpenAI, Anthropic, Mux, etc.) are owned by Sleeper Hit and are never required from API customers. ## 3. Discovery before integration Before any flow, fetch the capability manifest: ```bash curl -s https://docs.sleeperhit.studio/api/v1/capabilities \ -H "Authorization: Bearer sh__" ``` The response lists supported source types, artifact types and their current availability (`available` vs `planned`), accepted scopes, idempotency support, and links to OpenAPI + examples. Cache for at most a minute. For the full machine-readable contract: - `GET https://docs.sleeperhit.studio/api/v1/openapi.json` — OpenAPI 3.1 spec with stable operation IDs and named JSON Schemas. - `GET https://docs.sleeperhit.studio/api/v1/agent-guidance` — backend-managed workflow guidance. Read it at the start of every agent-run because admins can adjust it without changing the MCP/CLI binaries. - `GET https://docs.sleeperhit.studio/agent-index.json` — docs-site page, section, operation, CLI, and MCP index for agents. - `GET https://docs.sleeperhit.studio/docs/search-index.json` — searchable docs corpus with stable ids and canonical URLs. - `GET https://docs.sleeperhit.studio/api/v1/examples` — recipes with cURL + Node snippets for live flows. ## 4. Error model Every error response is the same shape: ```json { "error": { "code": "insufficient_scope", "message": "The API key does not have the required scope for this endpoint.", "requestId": "7f9d4b6a-4f0a-4a8c-9c2e-d5b3b8e6a0f1" } } ``` Match on `code`. Human `message` text is subject to change. The same `requestId` is set in the `X-Request-Id` response header so you can quote it in support reports. Stable codes: - `authentication_required` — No bearer API key was supplied in the Authorization header. - `invalid_api_key` — The API key is malformed, unknown, or does not match the stored secret. - `api_key_revoked` — The API key has been revoked by an account owner. - `api_key_expired` — The API key has passed its configured expiration timestamp. - `account_disabled` — The account that owns this API key has been disabled. - `ip_not_allowed` — The request originated from an IP that is not in the key allowlist. - `insufficient_scope` — The API key does not include the scope required for this endpoint. - `rate_limited` — The per-key + per-IP rate limit for this route family was exceeded. - `idempotency_key_required` — The endpoint requires an Idempotency-Key header for safe retries. - `idempotency_conflict` — A request with the supplied Idempotency-Key is already processing or used incompatible parameters. - `validation_failed` — The request payload failed validation. The error message names the offending field. - `project_not_found` — The story project does not exist, was deleted, or is owned by another account. - `source_not_found` — The story source does not exist, was deleted, or is owned by another account. - `source_type_unsupported` — The requested source type is not yet supported by this API phase. Check `/api/v1/capabilities`. - `source_too_large` — The source payload exceeds the documented size limit. See `details.maxBytes`. - `source_fetch_failed` — A URL or PDF source could not be safely fetched (SSRF block, redirect limit, size limit, content-type mismatch, or upstream error). - `story_plan_not_found` — The story plan does not exist, was deleted, or is owned by another account. - `story_plan_state_invalid` — The story plan is in a state that does not allow the requested operation. See `details.status` and `details.allowed`. - `story_plan_failed` — StoryPlan generation or refinement failed. See `details` for the underlying reason when available. - `story_job_not_found` — The story job does not exist, was deleted, or is owned by another account. - `story_job_state_invalid` — The story job is in a state that does not allow the requested operation (e.g. canceling a job that has already reached a terminal state). See `details.status` and `details.allowed`. - `artifact_not_found` — The story artifact does not exist or is owned by another account. - `artifact_not_ready` — The artifact is not in a state where this operation is valid yet (e.g. requesting an MP4 render before the share link exists). See `details.status`. - `artifact_generation_failed` — The artifact adapter failed to produce a shareable output. The job and artifact rows stay inspectable; see the artifact `failureCode` / `failureMessage`. - `insufficient_credits` — The account does not have enough Studio Credits to reserve this job. See `details.required` and `details.available`. - `internal_error` — The Sleeper Hit Story API failed unexpectedly. Retrying with the same Idempotency-Key is safe. Generation-related codes (`insufficient_credits`, `story_job_not_found`, `story_job_state_invalid`, `artifact_not_found`, `artifact_not_ready`, `artifact_generation_failed`) are returned by the story-job and artifact endpoints. Additional codes will appear in the spec as remaining artifact adapters ship. ## 5. Rate limiting Requests are bucketed per API key + IP + route family. Default tier allows 120 requests per minute; elevated keys allow 600. Every response includes: - `RateLimit-Limit` - `RateLimit-Remaining` - `RateLimit-Reset` (seconds until window reset) `429` responses additionally include `Retry-After`. Back off and retry only after that many seconds. ## 6. Idempotency Any idempotent POST that reserves Studio Credits, queues generation work, or mutates an artifact requires an `Idempotency-Key` header. Generate a stable identifier per logical operation (UUID is fine). Retrying the request with the same key replays the original response with `Idempotency-Replayed: true` instead of double-charging or double-queuing. Replaying with a different request body for the same key returns `idempotency_conflict`. Recommended client behavior: 1. Generate the key once per logical job. 2. Persist the key alongside the local job record before issuing the request. 3. On network failure or 5xx, retry with the same key. 4. On `idempotency_conflict` while the original is still processing, poll for status (when polling endpoints land) instead of re-submitting. ## 7. Credits Studio Credits are the single shared meter for everything: source extraction, planning, artifact generation, refine, and finalize. Read the current balance with: ```bash curl -s https://docs.sleeperhit.studio/api/v1/credits \ -H "Authorization: Bearer sh__" ``` Response fields: `balance`, `monthlyBucketAllocated`, `monthlyBucketUsed`, `monthlyBucketRemaining`, `perpetualBalance`, `cycleStartedAt`, `cycleExpiresAt`. Once generation endpoints ship, jobs will include a `credits` block with `quoted`, `reserved`, `settled`, and `released` so the full cost story is observable through the same API. ## 8. The polling-only happy path (table read) The minimum viable flow to produce a live table read: 1. `GET /api/v1/capabilities` — confirm `artifacts.table_read.availability` is `available`. 2. `GET /api/v1/agent-guidance` — load the current admin-managed workflow instructions for planning, approval, live audio mutation, and finalize behavior. 3. `GET /api/v1/credits` — confirm balance is plausibly enough. 4. `POST /api/v1/story-projects` — create a project with `Idempotency-Key`. 5. `POST /api/v1/story-projects/{id}/sources` — attach sources; the plan `quote` previews the credit estimate with no spend. 6. `POST /api/v1/story-projects/{id}/story-plans` with `creativeBrief` and `Idempotency-Key`; follow the guidance response for the current approval gate and intake expectations. 7. Poll `GET /api/v1/story-plans/{planId}` until `REQUIRES_APPROVAL`; review `plan.plan.scriptBlueprint` with the user, then `POST /api/v1/story-plans/{planId}/approve`. 8. `POST /api/v1/story-jobs` with the approved `storyPlanId` and `Idempotency-Key`. Credits reserve here; `402 insufficient_credits` short-circuits. 9. `GET /api/v1/story-jobs/{jobId}` every 5–15s until status is terminal (`READY` / `PARTIAL` / `FAILED` / `CANCELED`). 10. Read the `table_read` artifact manifest from the job (or `GET /api/v1/artifacts/{artifactId}`) and return the theater/audio URLs when useful. 11. Read actual script content with `GET /api/v1/artifacts/{artifactId}/script?scope=page&page=1` (or `scope=scene|character|range`) before answering questions about what was built. 12. Use the refine, music, SFX, and finalize endpoints as described by `/api/v1/agent-guidance`. The full mental model: sources → plan → approve → job → artifact → (refine ⟳) → finalize. Agents that prefer push semantics can register webhook endpoints when that surface ships and skip polling. Both modes will be supported. ## 9. Versioning The current API base is `/api/v1`. Breaking changes ship behind a new base prefix. Additive changes (new endpoints, new optional fields, new artifact types, new scopes) land inside `/api/v1` and are reflected in `/api/v1/capabilities` and `/api/v1/openapi.json` immediately. ## 10. Where to look next - Capability manifest: https://docs.sleeperhit.studio/api/v1/capabilities - OpenAPI 3.1 spec: https://docs.sleeperhit.studio/api/v1/openapi.json - Examples: https://docs.sleeperhit.studio/api/v1/examples - Short doc map for agents: https://docs.sleeperhit.studio/llms.txt - API key management: https://docs.sleeperhit.studio/dashboard/api