{"openapi":"3.1.0","info":{"title":"ClipZyn API","description":"ClipZyn's public API for agents: sign up, run podcast-to-clips jobs, fetch artifacts, manage billing. Errors follow one envelope (error.code / retryable / retry_after_sec / hint); every response carries X-Request-Id.","version":"1.0"},"paths":{"/signup":{"post":{"summary":"Create a sandbox account and mint its first API key","description":"Create a sandbox account and return {account_id, api_key, tier, limits, billing, docs, email, email_confirmation}; api_key is shown once. ClipZyn emails a confirmation link to the returned email (the normalized address) and the key answers 403 email_unconfirmed until a person opens it. This call costs nothing quota-wise and must come before authenticated operations. Send one Idempotency-Key per signup intent. Recover from account_exists by asking the owner to use the web key page, from validation_error by fixing the named field, and from rate_limited or signup_capacity by waiting retry_after_sec before retrying.","operationId":"signup","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignupRequest"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Idempotent-Replay":{"$ref":"#/components/headers/Idempotent-Replay"}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Idempotent-Replay":{"$ref":"#/components/headers/Idempotent-Replay"}}}}}},"/billing":{"get":{"summary":"Read the account tier, quota period, and purchasable plans","description":"Read billing state and return {tier, period, payment_method_attached, plans, checkout}. This call costs nothing quota-wise. Call it after authentication, after quota_exceeded, or after a human confirms checkout. Poll no more than once per five minutes, with at most six checks. Recover from invalid_key at the web key page; for billing_unavailable or rate_limited, wait retry_after_sec and retry once.","operationId":"get_billing","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Get Billing"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"}}}},"security":[{"bearerAuth":[]}]}},"/billing/checkout":{"post":{"summary":"Create a Stripe checkout URL for a listed plan","description":"Create checkout and return {checkout_url, expires_at}. Minting the URL costs nothing quota-wise; the selected paid plan changes billing only after Stripe confirms payment. Call GET /v1/billing first, send one Idempotency-Key per offer, and relay checkout_url verbatim to the human principal. Recover from plan_unknown by choosing a returned plan id, from already_subscribed with POST /v1/billing/portal, and from billing_unavailable by waiting retry_after_sec before one retry.","operationId":"create_checkout","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Idempotent-Replay":{"$ref":"#/components/headers/Idempotent-Replay"}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Idempotent-Replay":{"$ref":"#/components/headers/Idempotent-Replay"}}}},"security":[{"bearerAuth":[]}]}},"/billing/portal":{"post":{"summary":"Create a Stripe portal URL for account billing changes","description":"Create a billing session and return {portal_url}. Minting the URL costs nothing quota-wise; Stripe applies any card, plan, or cancellation change selected by the human. Call this for an existing account, then relay portal_url verbatim instead of opening it for the user. Recover from invalid_key by replacing the API key and from billing_unavailable or rate_limited by waiting retry_after_sec before one retry.","operationId":"create_billing_portal","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Create Billing Portal"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Idempotent-Replay":{"$ref":"#/components/headers/Idempotent-Replay"}}}},"security":[{"bearerAuth":[]}]}},"/webhooks":{"get":{"summary":"List Webhooks","description":"List this account's webhook endpoints and delivery health without returning secrets.\n\nCosts nothing quota-wise. Call after registration or when auditing delivery; minting or\nrotating a secret is a separate operation. Recover from invalid_key by replacing the API\nkey. For rate_limited or service_unavailable, wait retry_after_sec and retry once; never\ninfer endpoint deletion from a transient error.","operationId":"list_webhooks","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Response List Webhooks"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"}}}},"security":[{"bearerAuth":[]}]},"post":{"summary":"Create Webhook","description":"Create a signed webhook endpoint and return its id, URL, events, and one-time secret.\n\nCosts nothing quota-wise. Call after choosing a non-empty subset of the six events, and\nstore the returned secret immediately. Recover from validation_error by fixing the HTTPS\nURL or event names, webhook_limit_reached by deleting an unused endpoint, and\nrate_limited by waiting retry_after_sec before retrying.","operationId":"create_webhook","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateWebhookRequest"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Idempotent-Replay":{"$ref":"#/components/headers/Idempotent-Replay"}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Idempotent-Replay":{"$ref":"#/components/headers/Idempotent-Replay"}}}},"security":[{"bearerAuth":[]}]}},"/webhooks/{endpoint_id}":{"delete":{"summary":"Delete Webhook","description":"Disable one webhook endpoint owned by this account and return an empty success body.\n\nCosts nothing quota-wise. Call only when delivery should stop; repeating the intent is\nsafe after confirming the endpoint list. Recover from not_found by calling GET\n/v1/webhooks and using an id it returns. For rate_limited or service_unavailable, wait\nretry_after_sec and retry once.","operationId":"delete_webhook","parameters":[{"name":"endpoint_id","in":"path","required":true,"schema":{"type":"string","title":"Endpoint Id"}}],"responses":{"204":{"description":"Successful Response","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"}}}},"security":[{"bearerAuth":[]}]}},"/runs":{"post":{"summary":"Create Run","description":"Create one queued run and return {run_id, status, eta_sec, options_effective}.\n\noptions_effective.resolved_order is the authoritative per-format count and\nrequest-compiler activation echo for the accepted run.\n\nTHIS CALL SPENDS QUOTA when a new run is accepted. Call GET /v1/account first, send one\nIdempotency-Key per intended run, then poll GET /v1/runs/{run_id}/progress first at\neta_sec and at most once every 60 to 120 seconds. Recover from quota_exceeded through\nPOST /v1/billing/checkout; for concurrency_limited or daily_limit, wait retry_after_sec\nbefore retrying. Fix validation_error, source_invalid, or feature_not_entitled before a\nnew attempt.","operationId":"create_run","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunRequest"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunResponse"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Idempotent-Replay":{"$ref":"#/components/headers/Idempotent-Replay"}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Idempotent-Replay":{"$ref":"#/components/headers/Idempotent-Replay"}}}},"security":[{"bearerAuth":[]}]},"get":{"summary":"List Runs","description":"List this account's runs newest first as {items, next_cursor} with keyset pagination.\n\nCosts nothing quota-wise. Call to recover ids after duplicate_run or an idempotency\nconflict; pass next_cursor back as before without parsing it. Recover from invalid_key by\nreplacing the API key. For rate_limited or service_unavailable, wait retry_after_sec and\nretry once without changing the cursor.","operationId":"list_runs","parameters":[{"name":"before","in":"query","required":false,"schema":{"type":"string","default":"","title":"Before"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":25,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response List Runs"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"}}}},"security":[{"bearerAuth":[]}]}},"/runs/preflight":{"post":{"summary":"Dry-run a POST /v1/runs body: will it be admitted, and what does it cost","description":"Preview whether this exact body would be admitted by POST /v1/runs, returning\n{allowed, quota_cost, tier, rejection, resolved_order}.\n\nThis call SPENDS NOTHING: nothing is enqueued, no quota is reserved, and no\nIdempotency-Key is consumed (never send one here). quota_cost is the account's\nperiod upload cost of an accepted run, the same quota math GET /v1/account shows\nas period.used/period.cap, never a money figure. When allowed is false, rejection\ncarries the exact typed error a real run would return (same code, hint, and\nretry_after_sec), so fix that before POST /v1/runs. Preflight validates request\nadmissibility (source shape, plan entitlements, sandbox limits, quota, option\nbounds); it does not fetch the source object, so source_invalid or\nupload_too_large can still surface on the real run. Requires runs:write. Recover\nfrom a rejection by following rejection.hint; for service_unavailable or\nrate_limited, wait retry_after_sec and retry once.","operationId":"preflight_run","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PreflightResponse"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Idempotent-Replay":{"$ref":"#/components/headers/Idempotent-Replay"}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Idempotent-Replay":{"$ref":"#/components/headers/Idempotent-Replay"}}}},"security":[{"bearerAuth":[]}]}},"/runs/{run_id}":{"get":{"summary":"Get Run","description":"Read the D18-projected run object with status, outcome, counts, and clips, without URLs.\n\nCosts nothing quota-wise. Call for durable run metadata; use the progress operation while\nwork is active and the artifacts operation after completion. Recover from run_not_found\nby calling GET /v1/runs and selecting an id returned for this account. For\nservice_unavailable or rate_limited, wait retry_after_sec and retry once.","operationId":"get_run","parameters":[{"name":"run_id","in":"path","required":true,"schema":{"type":"string","title":"Run Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Run"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"}}}},"security":[{"bearerAuth":[]}]}},"/runs/{run_id}/progress":{"get":{"summary":"Get Run Progress","description":"Read live progress and terminal {formats, format_outcomes} without internals.\n\nCosts nothing quota-wise. First poll at the run's eta_sec, then at most once every 60 to\n120 seconds until terminal; never tighten cadence after a 429. Recover from run_not_found\nwith GET /v1/runs. For rate_limited or service_unavailable, wait retry_after_sec and retry\nonce while preserving the documented cadence.","operationId":"get_run_progress","parameters":[{"name":"run_id","in":"path","required":true,"schema":{"type":"string","title":"Run Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProgressResponse"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"}}}},"security":[{"bearerAuth":[]}]}},"/runs/{run_id}/cancel":{"post":{"summary":"Cancel Run","description":"Request cancellation and return {run_id, cancelling, state, phase}; the call is idempotent.\n\nCosts nothing quota-wise. Call only on an explicit cancellation intent; phase pre_mine\nmeans quota was not spent, while post_mine remains billed. Recover from run_not_found by\ncalling GET /v1/runs. For rate_limited or service_unavailable, wait retry_after_sec and\nretry once, then confirm terminal state with GET /v1/runs/{run_id}/progress.","operationId":"cancel_run","parameters":[{"name":"run_id","in":"path","required":true,"schema":{"type":"string","title":"Run Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Cancel Run"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Idempotent-Replay":{"$ref":"#/components/headers/Idempotent-Replay"}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Idempotent-Replay":{"$ref":"#/components/headers/Idempotent-Replay"}}}},"security":[{"bearerAuth":[]}]}},"/runs/{run_id}/language":{"post":{"summary":"Answer Language Hold","description":"Answer a run parked at the language checkpoint and resume it.\n\nA run whose status is ``awaiting_language`` stopped before any selection and waits\nfor the account owner to name the episode language; ``language_hold.candidates`` on\nGET /v1/runs/{run_id} lists the codes the checkpoint heard. Send one ISO 639-3 code\nhere (the same write the app's checkpoint makes) and the run is re-dispatched with\nthe payload it parked with. THIS CALL SPENDS NO QUOTA: the quota was taken when the\nrun was created, and the resumed run keeps it. Idempotent in effect: the store\naccepts one answer while the hold is open, so a second call answers\nvalidation_error (the checkpoint is closed); poll GET /v1/runs/{run_id}/progress.\nrun_not_found for an unknown or foreign run; validation_error for an unsupported\ncode or a run that is not parked; service_unavailable when the durable close could\nnot be written (nothing was dispatched; the hold stays open; retry).","operationId":"answer_language_hold","parameters":[{"name":"run_id","in":"path","required":true,"schema":{"type":"string","title":"Run Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LanguageAnswerRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LanguageAnswerResponse"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Idempotent-Replay":{"$ref":"#/components/headers/Idempotent-Replay"}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Idempotent-Replay":{"$ref":"#/components/headers/Idempotent-Replay"}}}},"security":[{"bearerAuth":[]}]}},"/runs/{run_id}/clips":{"get":{"summary":"List Run Clips","description":"List a run's projected clips and the finishing styles this account may request.\n\nCosts nothing quota-wise. Call after a completed run to choose a clip or style; URLs are\nminted only by download-url operations. Recover from run_not_found by calling GET\n/v1/runs and using an owned id. For rate_limited or service_unavailable, wait\nretry_after_sec and retry once.","operationId":"list_run_clips","parameters":[{"name":"run_id","in":"path","required":true,"schema":{"type":"string","title":"Run Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response List Run Clips"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"}}}},"security":[{"bearerAuth":[]}]}},"/runs/{run_id}/clips/{clip_id}":{"get":{"summary":"Get Run Clip","description":"Read one clip's projected hooks, finishes, banner state, and available styles without URLs.\n\nCosts nothing quota-wise. Call after GET /v1/runs/{run_id}/clips when detailed state is\nneeded. Recover from clip_not_found by listing the run's clips and using an id returned\nthere; recover from run_not_found with GET /v1/runs. For rate_limited or\nservice_unavailable, wait retry_after_sec and retry once.","operationId":"get_run_clip","parameters":[{"name":"run_id","in":"path","required":true,"schema":{"type":"string","title":"Run Id"}},{"name":"clip_id","in":"path","required":true,"schema":{"type":"string","title":"Clip Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Run Clip"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"}}}},"security":[{"bearerAuth":[]}]}},"/runs/{run_id}/artifacts":{"get":{"summary":"Get Run Artifacts","description":"Read clips, format outcomes, transcript metadata, trailer, midform, and zip state.\n\nCosts nothing quota-wise. Call after terminal completed, save the response verbatim as\nrun_manifest.json, then mint URLs only for artifacts being downloaded. Transcript word\ntimings live inside transcript.json; ephemeral per-clip SRT/VTT files are not exposed.\nRecover from run_not_ready by polling GET /v1/runs/{run_id}/progress at the documented\ncadence, and from run_not_found with GET /v1/runs. Retry service_unavailable after\nretry_after_sec.","operationId":"get_run_artifacts","parameters":[{"name":"run_id","in":"path","required":true,"schema":{"type":"string","title":"Run Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ArtifactsResponse"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"}}}},"security":[{"bearerAuth":[]}]}},"/runs/{run_id}/clips/{clip_id}/download-url":{"post":{"summary":"Create Clip Download Url","description":"Mint {url, expires_at, suggested_filename} for one selected clip artifact.\n\nCosts nothing quota-wise. Call at the moment of download because URLs expire in about 30\nminutes; re-mint instead of reusing history. Recover from clip_not_found by listing clips,\nrun_not_ready by checking progress or finish status, and validation_error by using an\nartifact combination from GET /v1/runs/{run_id}/artifacts. Retry service_unavailable\nafter retry_after_sec.","operationId":"create_clip_download_url","parameters":[{"name":"run_id","in":"path","required":true,"schema":{"type":"string","title":"Run Id"}},{"name":"clip_id","in":"path","required":true,"schema":{"type":"string","title":"Clip Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClipDownloadRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Create Clip Download Url"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Idempotent-Replay":{"$ref":"#/components/headers/Idempotent-Replay"}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Idempotent-Replay":{"$ref":"#/components/headers/Idempotent-Replay"}}}},"security":[{"bearerAuth":[]}]}},"/runs/{run_id}/artifacts/download-url":{"post":{"summary":"Create Run Download Url","description":"Mint {url, expires_at} for transcript, trailer, midform, or the curated run zip.\n\nCosts nothing quota-wise. Call at the moment of download because URLs expire; use the\nartifact and midform_id values from the run manifest. Recover from run_not_ready by\npolling progress, transcript_not_available by omitting that download, validation_error by\nchoosing a listed artifact, and run_not_found with GET /v1/runs. For service_unavailable,\nwait retry_after_sec and retry once.","operationId":"create_run_download_url","parameters":[{"name":"run_id","in":"path","required":true,"schema":{"type":"string","title":"Run Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunDownloadRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Create Run Download Url"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Idempotent-Replay":{"$ref":"#/components/headers/Idempotent-Replay"}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Idempotent-Replay":{"$ref":"#/components/headers/Idempotent-Replay"}}}},"security":[{"bearerAuth":[]}]}},"/uploads":{"post":{"summary":"Create Upload","description":"Mint {upload_id, storage_path, put_url, token_expires_at, max_bytes} for one source.\n\nCosts nothing quota-wise. Call before POST /v1/runs when a local file must be uploaded,\nthen execute the signed PUT directly and probe readiness. Recover from\nunsupported_media_type by re-encoding to an allowed extension, upload_too_large by using\na supported source_url, and validation_error by fixing the named field. Retry\nservice_unavailable after retry_after_sec.","operationId":"create_upload","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UploadRequest"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Create Upload"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Idempotent-Replay":{"$ref":"#/components/headers/Idempotent-Replay"}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Idempotent-Replay":{"$ref":"#/components/headers/Idempotent-Replay"}}}},"security":[{"bearerAuth":[]}]}},"/uploads/{upload_id}":{"get":{"summary":"Get Upload","description":"Read {upload_id, storage_path, ready, size_bytes} for the caller's pending upload.\n\nCosts nothing quota-wise. Call after the signed PUT; when ready is true, pass storage_path\nto POST /v1/runs. Check no more than once every 60 seconds while the object is pending.\nRecover from not_found by using the upload_id returned by POST /v1/uploads. For\nrate_limited or service_unavailable, wait retry_after_sec and retry once.","operationId":"get_upload","parameters":[{"name":"upload_id","in":"path","required":true,"schema":{"type":"string","title":"Upload Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Upload"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"}}}},"security":[{"bearerAuth":[]}]}},"/runs/{run_id}/clips/{clip_id}/finish":{"post":{"summary":"Create Clip Finish","description":"Queue the vertical edit for ONE clip in the named styles (v2 §4.5).\nCosts finishing quota only when work is queued. Idempotent per\n(clip, style): styles the clip already has finished are skipped; all-skipped\nreturns {queued:false, already:true} at $0. Call only after the run completes.\nRecover from run_not_ready by waiting for terminal progress, clip_not_found by listing\nclips, and feature_not_entitled by dropping the style or upgrading. For rate_limited or\nservice_unavailable, wait retry_after_sec and retry once.","operationId":"create_clip_finish","parameters":[{"name":"run_id","in":"path","required":true,"schema":{"type":"string","title":"Run Id"}},{"name":"clip_id","in":"path","required":true,"schema":{"type":"string","title":"Clip Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FinishRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Create Clip Finish"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Idempotent-Replay":{"$ref":"#/components/headers/Idempotent-Replay"}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Idempotent-Replay":{"$ref":"#/components/headers/Idempotent-Replay"}}}},"security":[{"bearerAuth":[]}]}},"/runs/{run_id}/finish-status":{"get":{"summary":"Get Finish Status","description":"Read a run's finishing jobs; per-clip style outcomes remain on the clip objects.\n\nCosts nothing quota-wise. Poll at most once every 60 seconds while a finish is in flight,\nthen list clips when the job is done. Recover from run_not_found by calling GET /v1/runs.\nFor rate_limited or service_unavailable, wait retry_after_sec and retry once without\ntightening the polling cadence.","operationId":"get_finish_status","parameters":[{"name":"run_id","in":"path","required":true,"schema":{"type":"string","title":"Run Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Finish Status"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"}}}},"security":[{"bearerAuth":[]}]}},"/runs/{run_id}/banner-hooks":{"get":{"summary":"List every clip's composed banner lines, ranked, with the burned one marked","description":"Read the banner lines this run already composed for each clip, best first.\n\nCosts nothing: no quota, no burn, no render, no money. Each clip returns its\nlines ordered by urank (1 = best), each carrying the lane and rank pair the\nbanner write routes take as the line's address, plus selected (the variant\nactually burned, or null when none is) and provenance (where the burned line\ncame from: title_fallback means the shipped banner was a fallback even though\nthese composed lines existed). To apply a different line, hand its exact lane\nand rank to POST /v1/runs/{run_id}/clips/{clip_id}/banner-text, which is\ntext-only and spends nothing, or to POST /v1/runs/{run_id}/clips/{clip_id}/banner\nto burn it onto the master. Only clips that can carry a banner family are\nlisted, which is the same set those routes accept. unaddressable_items is\nnormally 0 and counts lines withheld from that clip because the stored record\ngave them a malformed address; when it is above 0 the clip has that many more\nlines than items shows, and none of them can be burned until the record is\nrepaired. Recover from run_not_found by calling GET /v1/runs and choosing an id\nreturned for this account, from run_not_ready by polling\nGET /v1/runs/{run_id}/progress until the run is terminal, and from\nscope_missing by minting a runs:read key. For rate_limited or\nservice_unavailable, wait retry_after_sec and retry once.","operationId":"list_run_banner_hooks","parameters":[{"name":"run_id","in":"path","required":true,"schema":{"type":"string","title":"Run Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response List Run Banner Hooks"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"}}}},"security":[{"bearerAuth":[]}]}},"/runs/{run_id}/clips/{clip_id}/banner":{"post":{"summary":"Create Clip Banner","description":"Burn ONE banner onto an ALREADY-FINISHED clip's vertical master (or its\n16:9 render) and select it (v2 §4.6). The text is server-resolved from the\nclip's persisted hooks by lane and rank; client-supplied text is ignored.\nThis does not consume finishing quota, because a burn is CPU-only, and an\nalready-burned variant is reused at $0 (reused:true). Recover from\nscope_missing by minting a finish:write key, run_not_ready by polling\nprogress until the run completes, run_not_found or clip_not_found by listing\nyour runs and their clips, and validation_error (an unknown hook, or a\nbasic-family style whose banner is engine-owned) by fixing lane, rank, or\ntarget. For rate_limited or service_unavailable, wait retry_after_sec and\nretry once.","operationId":"create_clip_banner","parameters":[{"name":"run_id","in":"path","required":true,"schema":{"type":"string","title":"Run Id"}},{"name":"clip_id","in":"path","required":true,"schema":{"type":"string","title":"Clip Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BannerBurnRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Create Clip Banner"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Idempotent-Replay":{"$ref":"#/components/headers/Idempotent-Replay"}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Idempotent-Replay":{"$ref":"#/components/headers/Idempotent-Replay"}}}},"security":[{"bearerAuth":[]}]}},"/runs/{run_id}/clips/{clip_id}/banner/select":{"post":{"summary":"Select Clip Banner","description":"Point an ALREADY-FINISHED clip at one of its existing burned banner\nvariants (v2 §4.6). This is a pure pointer flip with no burn, no render, and\nno finishing quota spent. Name a variant from the clip's variants list, which\nthe burn endpoint returns. Recover from scope_missing by minting a\nfinish:write key, run_not_ready by polling progress until the run completes,\nrun_not_found or clip_not_found by listing your runs and their clips, and\nvalidation_error by naming a variant that exists on this clip. For\nservice_unavailable, wait retry_after_sec and retry once.","operationId":"select_clip_banner","parameters":[{"name":"run_id","in":"path","required":true,"schema":{"type":"string","title":"Run Id"}},{"name":"clip_id","in":"path","required":true,"schema":{"type":"string","title":"Clip Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BannerSelectRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Select Clip Banner"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Idempotent-Replay":{"$ref":"#/components/headers/Idempotent-Replay"}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Idempotent-Replay":{"$ref":"#/components/headers/Idempotent-Replay"}}}},"security":[{"bearerAuth":[]}]}},"/runs/{run_id}/clips/{clip_id}/banner-text":{"post":{"summary":"Set Clip Banner Text","description":"Set (or clear) the TEXTUAL banner on an ALREADY-FINISHED clip (v2 §4.6): a\nhook address (lane and rank, resolved server-side), a custom text of at most\n400 characters, or clear set to true. This is a text-only intent with no\nrender, no burn, and no finishing quota spent. Provide exactly one of the\nthree shapes. Recover from scope_missing by minting a finish:write key,\nrun_not_ready by polling progress until the run completes, run_not_found or\nclip_not_found by listing your runs and their clips, and validation_error by\nproviding exactly one valid shape (a real lane and rank, a non-empty text, or\nclear). For service_unavailable, wait retry_after_sec and retry once.","operationId":"set_clip_banner_text","parameters":[{"name":"run_id","in":"path","required":true,"schema":{"type":"string","title":"Run Id"}},{"name":"clip_id","in":"path","required":true,"schema":{"type":"string","title":"Clip Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BannerTextRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Set Clip Banner Text"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Idempotent-Replay":{"$ref":"#/components/headers/Idempotent-Replay"}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Idempotent-Replay":{"$ref":"#/components/headers/Idempotent-Replay"}}}},"security":[{"bearerAuth":[]}]}},"/account":{"get":{"summary":"Get Account","description":"Read the account's tier, quota period, limits, capabilities, styles, and brain state.\n\nCosts nothing quota-wise. Call this first in a session and again after an upgrade so run\noptions stay within live limits. Recover from invalid_key by replacing the key from the\nweb key page. For rate_limited or service_unavailable, wait retry_after_sec and retry\nonce; do not guess capabilities during an outage.","operationId":"get_account","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Get Account"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"}}}},"security":[{"bearerAuth":[]}]}},"/styles":{"get":{"summary":"Get Styles","description":"List the edit and finishing styles this account may request for source_type.\n\nCosts nothing quota-wise. Call before requesting a finish and use a returned style\nliterally. Recover from validation_error by changing source_type to a supported value,\nand from invalid_key by replacing the API key. For rate_limited or service_unavailable,\nwait retry_after_sec and retry once.","operationId":"get_styles","parameters":[{"name":"source_type","in":"query","required":false,"schema":{"type":"string","default":"irl","title":"Source Type"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Styles"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"}}}},"security":[{"bearerAuth":[]}]}},"/estimate":{"get":{"summary":"Get Estimate","description":"Pre-commit ETA range for a prospective run (v2 §4.7: authenticated on\n/v1, unlike the legacy route). ETA ONLY -- no cost figure exists to expose\n(A11 governs any future cost surface). Delegates to the browser's estimate\nhandler (the exact run-time planner; ``{eta_range_sec, eta_basis, top_n}``,\nfail-open to a null estimate, never a 500). Costs nothing quota-wise. Call before a run\nwhen the human asks for timing, and report a null range as unknown. Recover from\nvalidation_error by fixing duration_sec or top_n. For rate_limited or\nservice_unavailable, wait retry_after_sec and retry once.","operationId":"get_estimate","parameters":[{"name":"duration_sec","in":"query","required":false,"schema":{"anyOf":[{"type":"number","maximum":200000,"minimum":0},{"type":"null"}],"title":"Duration Sec"}},{"name":"top_n","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","minimum":0},{"type":"null"}],"title":"Top N"}},{"name":"kind","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":16},{"type":"null"}],"title":"Kind"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Estimate"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"}}}},"security":[{"bearerAuth":[]}]}},"/brains":{"get":{"summary":"Get Brains","description":"The named brain configurations (v2 §4.7) and ``current``, the brain this account's\nnext run takes. Since owner ruling D8 (2026-10-06) a stored choice no longer changes\nthe brain: every run takes the default unless it asks for the Deep cut with\n``engine: \"deep\"``. Only default and selectable configs (E1), and only for a\nsigned-in account; seats and archived brains are never listed. Display id + label\nonly, never model or effort internals. Costs nothing quota-wise.\nRecover from unknown_brain by reading this list again; for rate_limited or\nservice_unavailable, wait retry_after_sec and retry once.","operationId":"get_brains","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Get Brains"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"}}}},"security":[{"bearerAuth":[]}]}},"/account/brain":{"put":{"summary":"Set Brain","description":"Persist this account's brain choice (v2 §4.7). Since owner ruling D8 (2026-10-06)\na stored choice no longer changes the brain a run takes (the default, or the Deep cut\nfor a run sent with ``engine: \"deep\"``); the call is kept so existing clients do not\nbreak. A key whose principal carries no email is refused with feature_not_entitled.\nCosts nothing quota-wise. Requires the account:write scope (owner-gated, not minted by\ndefault): a key without it is refused with scope_missing, not a 404. Send config as one\nof the exact ids from GET /v1/brains; an unknown id is rejected with unknown_brain.\nRecover from unknown_brain by reading GET /v1/brains again; from feature_not_entitled by\nnot calling this on an ineligible account; for service_unavailable, wait retry_after_sec\nand retry the same request once.","operationId":"set_brain","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrainRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Set Brain"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"}}}},"security":[{"bearerAuth":[]}]}},"/account/keys":{"get":{"summary":"List Account Keys","description":"List this account's API keys using display-safe metadata only.\n\nCosts nothing quota-wise and never returns a raw key or key hash. Each row\nincludes the id needed by rotate/revoke plus key_prefix, name, scopes,\ncreated_at, last_used_at, and revoked_at. Recover from scope_missing with an\naccount:read key; for rate_limited or service_unavailable, wait for\nretry_after_sec and retry once without inferring that a key disappeared.","operationId":"list_account_keys","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Response List Account Keys"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"}}}},"security":[{"bearerAuth":[]}]},"post":{"summary":"Create Account Key","description":"Mint an API key and return its raw credential exactly once.\n\nCosts nothing quota-wise. Store the response's key immediately because only\nits hash and display prefix persist. The account:write scope is owner-gated.\nRecover from key_limit_reached by revoking an unused key, from scope_missing\nwith an owner-authorized key, and from rate_limited or service_unavailable by\nwaiting retry_after_sec before retrying; never log the response credential.","operationId":"create_account_key","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MintKeyRequest"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Idempotent-Replay":{"$ref":"#/components/headers/Idempotent-Replay"}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Idempotent-Replay":{"$ref":"#/components/headers/Idempotent-Replay"}}}},"security":[{"bearerAuth":[]}]}},"/account/keys/{key_id}/rotate":{"post":{"summary":"Rotate Account Key","description":"Atomically revoke one owned key and return its replacement exactly once.\n\nCosts nothing quota-wise. The replacement keeps the old key's name and\nscopes; the old credential stops authenticating as soon as this call commits.\nRecover from not_found by listing keys and using an active owned id, from\nscope_missing with an owner-authorized key, and from rate_limited or\nservice_unavailable by waiting retry_after_sec before retrying once.","operationId":"rotate_account_key","parameters":[{"name":"key_id","in":"path","required":true,"schema":{"type":"string","title":"Key Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Rotate Account Key"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Idempotent-Replay":{"$ref":"#/components/headers/Idempotent-Replay"}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Idempotent-Replay":{"$ref":"#/components/headers/Idempotent-Replay"}}}},"security":[{"bearerAuth":[]}]}},"/account/keys/{key_id}/revoke":{"post":{"summary":"Revoke Account Key","description":"Immediately revoke one active API key owned by this account.\n\nCosts nothing quota-wise and returns no credential material. A foreign,\nunknown, or already-revoked id is the same not_found response, preserving\nowner isolation. Recover by listing keys and choosing an active id; for\nscope_missing use an owner-authorized key, and for rate_limited or\nservice_unavailable wait retry_after_sec before retrying once.","operationId":"revoke_account_key","parameters":[{"name":"key_id","in":"path","required":true,"schema":{"type":"string","title":"Key Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Revoke Account Key"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Idempotent-Replay":{"$ref":"#/components/headers/Idempotent-Replay"}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Idempotent-Replay":{"$ref":"#/components/headers/Idempotent-Replay"}}}},"security":[{"bearerAuth":[]}]}},"/connections":{"get":{"summary":"Connections List","description":"List the caller's connections in the whitelist projection.\n\nToken ciphertext, decrypted payloads, the OAuth state, user_id and\ntoken_key_version are structurally unreachable from this shape. A dark\nsurface answers not_found; a key without bernayser:read receives scope_missing\nonly once the surface is live. Neither is retryable as-is. Requires the explicitly minted `bernayser:read` scope; bernayser:read permits safe projections and bernayser:write permits mutations. This BERNAYSER operation is quota-neutral. While dark it returns not_found, and a valid key without the required scope receives scope_missing. Fix a non-retryable request or credential before retrying; for rate_limited or service_unavailable, wait for retry_after_sec and retry once.","operationId":"connections_list","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Connections List"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"}}}},"security":[{"bearerAuth":[]}]},"post":{"summary":"Connections Create","description":"Create a connection. RSS carries its feed url and activates immediately; an\nOAuth provider creates a PENDING connection and returns the authorize URL +\nsigned state the caller redirects the owner to.\n\nOptional person_id attaches the connection to one of your people. An unknown or foreign person_id is validation_error; the dark\nsurface is not_found. Fix the body before retrying. Requires the explicitly minted `bernayser:write` scope; bernayser:read permits safe projections and bernayser:write permits mutations. This BERNAYSER operation is quota-neutral. While dark it returns not_found, and a valid key without the required scope receives scope_missing. Fix a non-retryable request or credential before retrying; for rate_limited or service_unavailable, wait for retry_after_sec and retry once.","operationId":"connections_create","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectionCreateRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Connections Create"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Idempotent-Replay":{"$ref":"#/components/headers/Idempotent-Replay"}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Idempotent-Replay":{"$ref":"#/components/headers/Idempotent-Replay"}}}},"security":[{"bearerAuth":[]}]}},"/connections/{connection_id}":{"delete":{"summary":"Connections Revoke","description":"Revoke a connection: status revoked, encrypted token row deleted, audited.\n\nIdempotent, so a client that lost the response may safely repeat it; the\nciphertext is never resurrected. An unknown or foreign connection is\nnot_found, identical to one that never existed. Do not retry a not_found. Requires the explicitly minted `bernayser:write` scope; bernayser:read permits safe projections and bernayser:write permits mutations. This BERNAYSER operation is quota-neutral. While dark it returns not_found, and a valid key without the required scope receives scope_missing. Fix a non-retryable request or credential before retrying; for rate_limited or service_unavailable, wait for retry_after_sec and retry once.","operationId":"connections_revoke","parameters":[{"name":"connection_id","in":"path","required":true,"schema":{"type":"string","title":"Connection Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Connections Revoke"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"}}}},"security":[{"bearerAuth":[]}]}},"/connections/{connection_id}/enumerate":{"post":{"summary":"Connections Enumerate","description":"Enumerate a connection's catalog and stage what it finds as catalog sources.\n\nRuns the provider's connector over a bounded window and upserts each item, so\nrepeating the call is safe and reports how many rows were new. YouTube and\nDrive need external_account_id (the channel or folder) the first time, since\nconsent is account-wide; send it in the body once and it is remembered. A\nconnection that is not active is validation_error, an unknown one is\nnot_found, and a provider with no connector here is ENGINE_PENDING. Requires the explicitly minted `bernayser:write` scope; bernayser:read permits safe projections and bernayser:write permits mutations. This BERNAYSER operation is quota-neutral. While dark it returns not_found, and a valid key without the required scope receives scope_missing. Fix a non-retryable request or credential before retrying; for rate_limited or service_unavailable, wait for retry_after_sec and retry once.","operationId":"connections_enumerate","parameters":[{"name":"connection_id","in":"path","required":true,"schema":{"type":"string","title":"Connection Id"}}],"requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ConnectionEnumerateRequest"},{"type":"null"}],"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Idempotent-Replay":{"$ref":"#/components/headers/Idempotent-Replay"}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Idempotent-Replay":{"$ref":"#/components/headers/Idempotent-Replay"}}}},"security":[{"bearerAuth":[]}]}},"/connections/oauth/callback":{"get":{"summary":"Connections Oauth Callback","description":"OAuth redirect landing. Authenticated by its signed state, not a bearer key.\n\nThe provider sends the owner's browser here, so no Authorization header can\nexist; the state is the credential. It is verified in constant time, expires,\nand is spendable once, while the connection is still pending. Every refusal is\nthe same not_found, so nothing about a connection id, an expiry, or a replay\nis disclosed. Do not retry a not_found; start again with POST /v1/connections.\nOn success the token is sealed and the connection becomes active. Requires the explicitly minted `bernayser:write` scope; bernayser:read permits safe projections and bernayser:write permits mutations. This BERNAYSER operation is quota-neutral. While dark it returns not_found, and a valid key without the required scope receives scope_missing. Fix a non-retryable request or credential before retrying; for rate_limited or service_unavailable, wait for retry_after_sec and retry once.","operationId":"connections_oauth_callback","parameters":[{"name":"state","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"}},{"name":"code","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Connections Oauth Callback"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"}}}},"security":[{"bearerAuth":[]}]}},"/people":{"get":{"summary":"People List","description":"List the caller's SWEEP people using a URL-free safe projection.\n\nThis bernayser:read operation costs no run quota and never returns user_id,\nprofile JSON, operator receipts, or internal hashes. The whole surface is a\ncloaked not_found while SWEEP is dark; scope_missing identifies a valid key\nthat lacks read access. For rate_limited or service_unavailable, wait for\nretry_after_sec and retry once without guessing catalog state. Requires the explicitly minted `bernayser:read` scope; bernayser:read permits safe projections and bernayser:write permits mutations. This BERNAYSER operation is quota-neutral. While dark it returns not_found, and a valid key without the required scope receives scope_missing. Fix a non-retryable request or credential before retrying; for rate_limited or service_unavailable, wait for retry_after_sec and retry once.","operationId":"people_list","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response People List"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"}}}},"security":[{"bearerAuth":[]}]},"post":{"summary":"People Create","description":"Create one owner-scoped SWEEP person candidate.\n\nThis operation is quota-neutral and requires bernayser:write. It accepts a\nprofile for identity processing but returns only display-safe named fields;\nraw profile JSON and user_id never egress. A dark caller receives not_found,\na key without the scope receives scope_missing, and validation_error names a\nmalformed body. Correct the request or credential before retrying. Requires the explicitly minted `bernayser:write` scope; bernayser:read permits safe projections and bernayser:write permits mutations. This BERNAYSER operation is quota-neutral. While dark it returns not_found, and a valid key without the required scope receives scope_missing. Fix a non-retryable request or credential before retrying; for rate_limited or service_unavailable, wait for retry_after_sec and retry once.","operationId":"people_create","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PersonCreateRequest"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response People Create"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Idempotent-Replay":{"$ref":"#/components/headers/Idempotent-Replay"}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Idempotent-Replay":{"$ref":"#/components/headers/Idempotent-Replay"}}}},"security":[{"bearerAuth":[]}]}},"/people/{person_id}":{"get":{"summary":"People Get","description":"Read one owned SWEEP person through the safe field allowlist.\n\nThe read is quota-neutral and requires bernayser:read. Unknown and foreign\nidentifiers share not_found, preserving owner cloaking, and a dark surface\nuses the same response. No profile, confirmation JSON, user_id, token, or\nURL can appear. Recover from scope_missing with an explicitly minted catalog\nkey; retry rate_limited or service_unavailable only after retry_after_sec. Requires the explicitly minted `bernayser:read` scope; bernayser:read permits safe projections and bernayser:write permits mutations. This BERNAYSER operation is quota-neutral. While dark it returns not_found, and a valid key without the required scope receives scope_missing. Fix a non-retryable request or credential before retrying; for rate_limited or service_unavailable, wait for retry_after_sec and retry once.","operationId":"people_get","parameters":[{"name":"person_id","in":"path","required":true,"schema":{"type":"string","title":"Person Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response People Get"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"}}}},"security":[{"bearerAuth":[]}]}},"/people/{person_id}/withdraw":{"post":{"summary":"People Withdraw","description":"Withdraw one owned person, or report its existing legal state while dark. Requires the explicitly minted `bernayser:write` scope. This legal-state operation is quota-neutral and remains available while the BERNAYSER product is dark; it performs no discovery or rendering. An unknown person returns not_found, and a valid key without the required scope receives scope_missing. Repeating an active withdrawal reports its current state. For service_unavailable, wait for retry_after_sec and retry once.","operationId":"people_withdraw","parameters":[{"name":"person_id","in":"path","required":true,"schema":{"type":"string","title":"Person Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PersonWithdrawRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response People Withdraw"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Idempotent-Replay":{"$ref":"#/components/headers/Idempotent-Replay"}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Idempotent-Replay":{"$ref":"#/components/headers/Idempotent-Replay"}}}},"security":[{"bearerAuth":[]}]}},"/people/{person_id}/appearances":{"get":{"summary":"Appearances List","description":"List every recorded appearance for one owned SWEEP person.\n\nThis bernayser:read call consumes no run quota. Rows are explicitly projected:\nverification JSON, verified_by, user_id, ciphertext, tokens, metadata, and\nURLs are impossible to emit. A foreign person or dark surface is not_found;\nscope_missing identifies a credential issue. Wait for retry_after_sec before\nretrying rate_limited or service_unavailable responses. Requires the explicitly minted `bernayser:read` scope; bernayser:read permits safe projections and bernayser:write permits mutations. This BERNAYSER operation is quota-neutral. While dark it returns not_found, and a valid key without the required scope receives scope_missing. Fix a non-retryable request or credential before retrying; for rate_limited or service_unavailable, wait for retry_after_sec and retry once.","operationId":"appearances_list","parameters":[{"name":"person_id","in":"path","required":true,"schema":{"type":"string","title":"Person Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Appearances List"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"}}}},"security":[{"bearerAuth":[]}]}},"/people/{person_id}/library":{"get":{"summary":"Library Get","description":"Read a person's verified conversation library.\n\nThe quota-neutral bernayser:read projection includes verified appearances,\nsafe conversation fields, and publication-asset counts. It never returns\nsource URLs or raw JSON blobs.\nUnknown owners and a dark surface are not_found; recover from scope_missing\nwith an explicit catalog key and retry transient errors after retry_after_sec. Requires the explicitly minted `bernayser:read` scope; bernayser:read permits safe projections and bernayser:write permits mutations. This BERNAYSER operation is quota-neutral. While dark it returns not_found, and a valid key without the required scope receives scope_missing. Fix a non-retryable request or credential before retrying; for rate_limited or service_unavailable, wait for retry_after_sec and retry once.","operationId":"library_get","parameters":[{"name":"person_id","in":"path","required":true,"schema":{"type":"string","title":"Person Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Library Get"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"}}}},"security":[{"bearerAuth":[]}]}},"/bernayser":{"post":{"summary":"Sweeps Create","description":"Create a draft SWEEP batch after the structural rights front-door gate.\n\nThis bernayser:write call is quota-neutral at creation and cannot enqueue an\nengine tick. A render sweep without a connection proof receives 422 RIGHTS.\nrender_mode catalog_only builds an index only, can never produce a clip, and\nneeds no proof, but is itself 422 RIGHTS where that mode is not enabled.\nMalformed inputs receive validation_error and the dark surface is not_found.\nAdd the required proof or fix the body before retrying. The batch starts\ndraft, and only the separate approve operation can move it to approved. Requires the explicitly minted `bernayser:write` scope; bernayser:read permits safe projections and bernayser:write permits mutations. This BERNAYSER operation is quota-neutral. While dark it returns not_found, and a valid key without the required scope receives scope_missing. Fix a non-retryable request or credential before retrying; for rate_limited or service_unavailable, wait for retry_after_sec and retry once.","operationId":"sweeps_create","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SweepCreateRequest"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Idempotent-Replay":{"$ref":"#/components/headers/Idempotent-Replay"}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Idempotent-Replay":{"$ref":"#/components/headers/Idempotent-Replay"}}}},"security":[{"bearerAuth":[]}]}},"/bernayser/{sweep_id}":{"get":{"summary":"Sweeps Get","description":"Read one sweep's safe batch projection, item counts, and ledger totals.\n\nThis quota-neutral bernayser:read operation omits user_id and every raw JSONB\nfield. Reserve and actual money are converted through Decimal and become\nfloats only at the JSON boundary. Unknown or foreign ids are not_found.\nRecover from scope_missing with an explicit catalog key; wait for\nretry_after_sec before retrying rate_limited or service_unavailable. Requires the explicitly minted `bernayser:read` scope; bernayser:read permits safe projections and bernayser:write permits mutations. This BERNAYSER operation is quota-neutral. While dark it returns not_found, and a valid key without the required scope receives scope_missing. Fix a non-retryable request or credential before retrying; for rate_limited or service_unavailable, wait for retry_after_sec and retry once.","operationId":"sweeps_get","parameters":[{"name":"sweep_id","in":"path","required":true,"schema":{"type":"string","title":"Sweep Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Sweeps Get"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"}}}},"security":[{"bearerAuth":[]}]}},"/bernayser/{sweep_id}/cancel":{"post":{"summary":"Sweeps Cancel","description":"Cancel an active sweep through the engine's run and money policy.\n\nThe bernayser:write control call consumes no new quota. The engine cancels\ndownstream runs, settles or releases their reservations, and transitions\nevery nonterminal item. A foreign id is not_found and a terminal state yields\nvalidation_error. Fix the id or state before retrying; retry transient\nrate_limited or service_unavailable responses only after retry_after_sec. Requires the explicitly minted `bernayser:write` scope; bernayser:read permits safe projections and bernayser:write permits mutations. This BERNAYSER operation is quota-neutral. While dark it returns not_found, and a valid key without the required scope receives scope_missing. Fix a non-retryable request or credential before retrying; for rate_limited or service_unavailable, wait for retry_after_sec and retry once.","operationId":"sweeps_cancel","parameters":[{"name":"sweep_id","in":"path","required":true,"schema":{"type":"string","title":"Sweep Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Sweeps Cancel"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Idempotent-Replay":{"$ref":"#/components/headers/Idempotent-Replay"}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Idempotent-Replay":{"$ref":"#/components/headers/Idempotent-Replay"}}}},"security":[{"bearerAuth":[]}]}},"/bernayser/{sweep_id}/retry":{"post":{"summary":"Sweeps Retry","description":"Retry failed sweep items through the engine's reopening policy.\n\nThe quota-neutral bernayser:write action atomically moves eligible failed\nitems to approved, increments their attempts, updates totals and records the\nmatching receipt. A completed batch reopens to admitting only when an item\nmoved, while items at three attempts remain failed. Unknown ownership is\nnot_found. Recover from scope_missing with a catalog key and retry transient\nfailures only after retry_after_sec. Requires the explicitly minted `bernayser:write` scope; bernayser:read permits safe projections and bernayser:write permits mutations. This BERNAYSER operation is quota-neutral. While dark it returns not_found, and a valid key without the required scope receives scope_missing. Fix a non-retryable request or credential before retrying; for rate_limited or service_unavailable, wait for retry_after_sec and retry once.","operationId":"sweeps_retry","parameters":[{"name":"sweep_id","in":"path","required":true,"schema":{"type":"string","title":"Sweep Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Sweeps Retry"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Idempotent-Replay":{"$ref":"#/components/headers/Idempotent-Replay"}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Idempotent-Replay":{"$ref":"#/components/headers/Idempotent-Replay"}}}},"security":[{"bearerAuth":[]}]}},"/bernayser/{sweep_id}/approve":{"post":{"summary":"Sweeps Approve","description":"Approve an awaiting-approval sweep against an exact manifest digest.\n\nThis bernayser:write operation is the only API route into approved and costs\nno run quota itself. The store compare-and-set accepts only\nawaiting_approval; any other state returns validation_error, and unknown or\nforeign ids are not_found. Fix the manifest or state before retrying; for\ntransient rate_limited or service_unavailable, wait retry_after_sec. Requires the explicitly minted `bernayser:write` scope; bernayser:read permits safe projections and bernayser:write permits mutations. This BERNAYSER operation is quota-neutral. While dark it returns not_found, and a valid key without the required scope receives scope_missing. Fix a non-retryable request or credential before retrying; for rate_limited or service_unavailable, wait for retry_after_sec and retry once.","operationId":"sweeps_approve","parameters":[{"name":"sweep_id","in":"path","required":true,"schema":{"type":"string","title":"Sweep Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SweepApproveRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Sweeps Approve"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Idempotent-Replay":{"$ref":"#/components/headers/Idempotent-Replay"}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Idempotent-Replay":{"$ref":"#/components/headers/Idempotent-Replay"}}}},"security":[{"bearerAuth":[]}]}}},"components":{"schemas":{"ArtifactsResponse":{"properties":{"run_id":{"type":"string","title":"Run Id"},"clips":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Clips"},"trailer":{"anyOf":[{"$ref":"#/components/schemas/TrailerBlock"},{"type":"null"}]},"midform":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Midform"},"carousels":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Carousels","description":"Delivered image carousels (id, idx, title, hook_grade, slide_count, deliverable); null when the run ordered none. Slides download via the web bundle; this manifest carries no URLs."},"zip_available":{"type":"boolean","title":"Zip Available"},"transcript":{"$ref":"#/components/schemas/TranscriptArtifact","description":"Durable episode transcript metadata. The downloadable transcript.json contains the word stream and per-word timings; ephemeral per-clip SRT/VTT files are deliberately not exposed."},"format_outcomes":{"additionalProperties":{"$ref":"#/components/schemas/vbeclip__api__v1__artifact_models__FormatOutcome"},"type":"object","title":"Format Outcomes","description":"Per-format delivery outcomes for ordered or explicitly refused formats. Keys are among shorts, twitter, midform, trailers, and carousels."}},"type":"object","required":["run_id","clips","zip_available","transcript","format_outcomes"],"title":"ArtifactsResponse","description":"GET /v1/runs/{id}/artifacts response; no URLs ride this cacheable shape."},"BannerBurnRequest":{"properties":{"lane":{"type":"string","enum":["s","q"],"title":"Lane"},"rank":{"type":"integer","maximum":99.0,"minimum":0.0,"title":"Rank"},"target":{"type":"string","enum":["vertical","r169"],"title":"Target","default":"vertical"}},"additionalProperties":false,"type":"object","required":["lane","rank"],"title":"BannerBurnRequest","description":"v2 §4.6 burn: a hook address (lane+rank) from the clip's PERSISTED set; the\ntext is server-resolved (client text never reaches the burn). ``target`` picks\nthe finished 9:16 master (default) or the plain 16:9 render."},"BannerSelectRequest":{"properties":{"variant":{"type":"string","title":"Variant"},"target":{"type":"string","enum":["vertical","r169"],"title":"Target","default":"vertical"}},"additionalProperties":false,"type":"object","required":["variant"],"title":"BannerSelectRequest","description":"v2 §4.6 select: flip the SELECTED variant pointer to an existing variant."},"BannerTextRequest":{"properties":{"lane":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lane"},"rank":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Rank"},"text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Text"},"clear":{"type":"boolean","title":"Clear","default":false}},"additionalProperties":false,"type":"object","title":"BannerTextRequest","description":"v2 §4.6 banner-text: text-only intent (no render, no spend). Exactly one of\na hook address (lane+rank), custom ``text`` (<=400), or ``clear``."},"BatchKind":{"type":"string","enum":["own_catalog","name_sweep"],"title":"BatchKind"},"BrainRequest":{"properties":{"config":{"type":"string","title":"Config"}},"type":"object","required":["config"],"title":"BrainRequest"},"CheckoutRequest":{"properties":{"plan":{"type":"string","title":"Plan"}},"type":"object","required":["plan"],"title":"CheckoutRequest"},"ClipDownloadRequest":{"properties":{"artifact":{"type":"string","title":"Artifact"},"style":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Style"},"variant":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Variant"}},"additionalProperties":false,"type":"object","required":["artifact"],"title":"ClipDownloadRequest"},"ConnectionCreateRequest":{"properties":{"provider":{"type":"string","maxLength":32,"title":"Provider"},"display_name":{"type":"string","maxLength":200,"title":"Display Name"},"feed_url":{"anyOf":[{"type":"string","maxLength":2048},{"type":"null"}],"title":"Feed Url"},"person_id":{"anyOf":[{"type":"string","maxLength":128},{"type":"null"}],"title":"Person Id"}},"additionalProperties":false,"type":"object","required":["provider","display_name"],"title":"ConnectionCreateRequest"},"ConnectionEnumerateRequest":{"properties":{"external_account_id":{"anyOf":[{"type":"string","maxLength":512},{"type":"null"}],"title":"External Account Id"}},"additionalProperties":false,"type":"object","title":"ConnectionEnumerateRequest"},"CreateWebhookRequest":{"properties":{"url":{"type":"string","title":"Url"},"events":{"items":{"type":"string"},"type":"array","title":"Events"}},"type":"object","required":["url","events"],"title":"CreateWebhookRequest"},"FinishRequest":{"properties":{"styles":{"items":{"type":"string"},"type":"array","maxItems":8,"minItems":1,"title":"Styles"},"banner_mode":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Banner Mode"},"banner_text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Banner Text"},"hook":{"anyOf":[{"$ref":"#/components/schemas/HookRef"},{"type":"null"}]}},"additionalProperties":false,"type":"object","required":["styles"],"title":"FinishRequest"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"HookRef":{"properties":{"lane":{"type":"string","title":"Lane"},"rank":{"type":"integer","title":"Rank"}},"additionalProperties":false,"type":"object","required":["lane","rank"],"title":"HookRef","description":"A P2-1 hook address: pick a generated hook by (lane, rank). The banner\nTEXT is resolved SERVER-side from the clip's persisted hook set (never client\ntext -- the model-output trust boundary)."},"LanguageAnswerRequest":{"properties":{"language":{"type":"string","maxLength":3,"minLength":3,"title":"Language","description":"The episode language as an ISO 639-3 code, one of ``language_hold.candidates`` on the parked run (or any supported code)."}},"type":"object","required":["language"],"title":"LanguageAnswerRequest","description":"The owner's answer to a run parked at the language checkpoint."},"LanguageAnswerResponse":{"properties":{"run_id":{"type":"string","title":"Run Id"},"language":{"type":"string","title":"Language"},"revision":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Revision"},"resume_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Resume Status","description":"``dispatched`` or ``already_dispatched`` when the run is back in the queue; ``refused`` with ``resume_refusal`` when the close was saved but the resume could not be dispatched (the hold stays answered; poll the run)."},"resume_refusal":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Resume Refusal"}},"type":"object","required":["run_id","language"],"title":"LanguageAnswerResponse","description":"What the language door did: the close and the resume, named."},"MintKeyRequest":{"properties":{"name":{"type":"string","title":"Name","default":""},"scopes":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Scopes"}},"type":"object","title":"MintKeyRequest"},"OptionsEffective":{"additionalProperties":true,"type":"object"},"PersonCreateRequest":{"properties":{"canonical_name":{"type":"string","maxLength":300,"minLength":1,"title":"Canonical Name"},"display_name":{"anyOf":[{"type":"string","maxLength":300},{"type":"null"}],"title":"Display Name"},"primary_language":{"anyOf":[{"type":"string","maxLength":32},{"type":"null"}],"title":"Primary Language"},"profile":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Profile"}},"additionalProperties":false,"type":"object","required":["canonical_name"],"title":"PersonCreateRequest"},"PersonWithdrawRequest":{"properties":{"reason":{"type":"string","maxLength":1000,"minLength":1,"title":"Reason"}},"additionalProperties":false,"type":"object","required":["reason"],"title":"PersonWithdrawRequest"},"PreflightRejection":{"properties":{"code":{"type":"string","title":"Code"},"message":{"type":"string","title":"Message"},"detail":{"title":"Detail"},"retryable":{"type":"boolean","title":"Retryable"},"retry_after_sec":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Retry After Sec"},"hint":{"type":"string","title":"Hint"},"docs":{"type":"string","title":"Docs"},"request_id":{"type":"string","title":"Request Id"}},"type":"object","required":["code","message","retryable","hint","docs","request_id"],"title":"PreflightRejection","description":"The typed reject a real POST /v1/runs WOULD have produced, embedded in a\npreflight verdict (R-v5-5). Same shape as the ``error`` object of the D27\nenvelope, so an agent parses a predicted reject exactly like a live one."},"PreflightResponse":{"properties":{"allowed":{"type":"boolean","title":"Allowed"},"quota_cost":{"type":"integer","title":"Quota Cost"},"tier":{"type":"string","title":"Tier"},"rejection":{"anyOf":[{"$ref":"#/components/schemas/PreflightRejection"},{"type":"null"}]},"resolved_order":{"$ref":"#/components/schemas/ResolvedOrder","description":"Resolved output counts and request-compiler activation for this body."}},"type":"object","required":["allowed","quota_cost","tier","resolved_order"],"title":"PreflightResponse","description":"POST /v1/runs/preflight 200 body (R-v5-5): a QUOTA-DENOMINATED dry run.\n\n``allowed`` is whether the same body would be admitted right now; ``quota_cost``\nis what an accepted run spends against the account's period upload cap (the\nnumber GET /v1/account already exposes as period.used/period.cap), NEVER a\nmoney/COGS figure; ``tier`` is the effective tier the verdict was computed on;\n``rejection`` is the typed reject a real run would return (null when allowed).\n``resolved_order`` previews the exact per-format counts and compiler activation.\nNothing is enqueued, no quota is spent, and no Idempotency-Key is consumed."},"ProgressCancel":{"properties":{"requested":{"type":"boolean","title":"Requested"},"phase":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phase"}},"type":"object","required":["requested"],"title":"ProgressCancel"},"ProgressResponse":{"additionalProperties":true,"type":"object"},"PulsePerson":{"properties":{"name":{"type":"string","maxLength":80,"title":"Name"},"role":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}],"title":"Role"},"note":{"anyOf":[{"type":"string","maxLength":160},{"type":"null"}],"title":"Note"}},"additionalProperties":false,"type":"object","required":["name"],"title":"PulsePerson","description":"One person the caller asserts is in the episode (PULSE live-context intake).\n\nThe same wire bounds as the browser's PulsePersonModel: ``name`` is the only\nload-bearing field (speaker resolution joins on it), ``role`` and ``note`` are\nfree-text hints. ``extra: forbid`` matches the surrounding /v1 grammar, so a typo'd\nkey is a 422 rather than a silently ignored fact."},"RenderMode":{"type":"string","enum":["render","catalog_only"],"title":"RenderMode"},"ResolvedOrder":{"properties":{"shorts":{"type":"integer","title":"Shorts","description":"Number of short-form clip families ordered."},"twitter":{"type":"integer","title":"Twitter","description":"Number of Twitter/X clips ordered."},"midform":{"type":"integer","title":"Midform","description":"Number of mid-form segments ordered."},"carousels":{"type":"integer","title":"Carousels","description":"Number of image carousels ordered: 0 when not ordered, and 0 when the engine owns the count (engine count_mode with no carousels_n); options_effective.carousels says whether carousels were admitted.","default":0},"trailer_takes":{"type":"integer","title":"Trailer Takes","description":"Number of distinct trailer takes ordered."},"compiler":{"type":"boolean","title":"Compiler","description":"Whether the per-format request compiler will run."}},"type":"object","required":["shorts","twitter","midform","trailer_takes","compiler"],"title":"ResolvedOrder","description":"The exact per-format order a run will execute after count resolution.\n\nCounts are zero for formats that are not ordered. ``compiler`` reports\nwhether non-empty per-format instructions activate the request compiler."},"RunDownloadRequest":{"properties":{"artifact":{"type":"string","title":"Artifact","description":"Run artifact to download. Omit for the existing curated zip bundle behavior; use transcript to download transcript.json with word timings.","default":"zip"},"midform_id":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Midform Id"}},"additionalProperties":false,"type":"object","title":"RunDownloadRequest"},"RunRequest":{"properties":{"storage_path":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Storage Path"},"source_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Url"},"sources":{"anyOf":[{"items":{"$ref":"#/components/schemas/SourceInput"},"type":"array","maxItems":6},{"type":"null"}],"title":"Sources"},"top_n":{"type":"integer","maximum":30.0,"minimum":1.0,"title":"Top N","default":5},"sub_clips":{"type":"boolean","title":"Sub Clips","default":true},"shorts":{"type":"boolean","title":"Shorts","default":true},"midform":{"type":"boolean","title":"Midform","default":false},"midform_n":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Midform N"},"midform_request":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Midform Request"},"trailer":{"type":"boolean","title":"Trailer","default":false},"trailer_request":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Trailer Request"},"twitter":{"type":"boolean","title":"Twitter","default":false},"twitter_n":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Twitter N"},"twitter_request":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Twitter Request"},"carousels":{"type":"boolean","title":"Carousels","default":false},"carousels_n":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Carousels N"},"carousels_request":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Carousels Request"},"clip_request":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Clip Request"},"count_mode":{"anyOf":[{"type":"string","enum":["exact","engine"]},{"type":"null"}],"title":"Count Mode"},"engine":{"anyOf":[{"type":"string","enum":["standard","deep"]},{"type":"null"}],"title":"Engine","description":"The cut to run: 'standard' (the normal cut) or 'deep' (the deep cut). Omit it for the default routing. 'deep' is refused with validation_error while the deep cut is switched off. Echoed as options_effective.engine."},"title":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Title"},"host_name":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"title":"Host Name"},"guest_name":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"title":"Guest Name"},"source_type":{"type":"string","title":"Source Type","default":"irl"},"duration_sec":{"anyOf":[{"type":"number","maximum":200000.0,"minimum":0.0},{"type":"null"}],"title":"Duration Sec"},"pulse_recorded_at":{"anyOf":[{"type":"string","maxLength":10,"pattern":"^\\d{4}-\\d{2}-\\d{2}$"},{"type":"null"}],"title":"Pulse Recorded At"},"pulse_go_live_at":{"anyOf":[{"type":"string","maxLength":10,"pattern":"^\\d{4}-\\d{2}-\\d{2}$"},{"type":"null"}],"title":"Pulse Go Live At"},"pulse_people":{"anyOf":[{"items":{"$ref":"#/components/schemas/PulsePerson"},"type":"array","maxItems":8},{"type":"null"}],"title":"Pulse People"},"pulse_episode_context":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Pulse Episode Context"},"pulse_focus_topics":{"anyOf":[{"items":{"type":"string","maxLength":80},"type":"array","maxItems":5},{"type":"null"}],"title":"Pulse Focus Topics"},"pulse_avoid_topics":{"anyOf":[{"items":{"type":"string","maxLength":80},"type":"array","maxItems":5},{"type":"null"}],"title":"Pulse Avoid Topics"},"pulse_source_published_at":{"anyOf":[{"type":"string","maxLength":10,"pattern":"^\\d{4}-\\d{2}-\\d{2}$"},{"type":"null"}],"title":"Pulse Source Published At"}},"additionalProperties":false,"type":"object","title":"RunRequest","description":"POST /v1/runs body (v2 §4.2). Exactly one of storage_path | source_url |\nsources. No ``force`` (admin-only, never on /v1), no ``video`` (dev\nlocal-path), no ``re_run_id`` (deferred, A6): the /v1 grammar is narrower\nthan the browser's on purpose."},"RunResponse":{"properties":{"run_id":{"type":"string","title":"Run Id"},"status":{"type":"string","title":"Status"},"eta_sec":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Eta Sec"},"options_effective":{"$ref":"#/components/schemas/OptionsEffective"},"deprecation_notice":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Deprecation Notice"}},"type":"object","required":["run_id","status","options_effective"],"title":"RunResponse","description":"POST /v1/runs 201 body."},"SignupRequest":{"properties":{"email":{"type":"string","title":"Email"},"name":{"type":"string","title":"Name","default":""}},"type":"object","required":["email"],"title":"SignupRequest"},"SourceInput":{"properties":{"role":{"anyOf":[{"type":"string","maxLength":32},{"type":"null"}],"title":"Role"},"media_kind":{"anyOf":[{"type":"string","maxLength":16},{"type":"null"}],"title":"Media Kind"},"origin":{"type":"string","maxLength":16,"title":"Origin"},"filename":{"type":"string","maxLength":512,"title":"Filename"},"storage_key":{"anyOf":[{"type":"string","maxLength":1024},{"type":"null"}],"title":"Storage Key"},"source_url":{"anyOf":[{"type":"string","maxLength":2048},{"type":"null"}],"title":"Source Url"},"size_bytes":{"anyOf":[{"type":"integer","maximum":200000000000.0,"minimum":0.0},{"type":"null"}],"title":"Size Bytes"},"subject_hint":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Subject Hint"}},"additionalProperties":false,"type":"object","required":["origin","filename"],"title":"SourceInput","description":"One multicam source (v2 §4.2): the same wire bounds as the browser's\nSourceInputModel -- role/media_kind optional (server infers), origin\nrequired, storage_key XOR source_url validated in the shared intake.\n\n``subject_hint`` (W3.1) is an optional declared person label kept in LOCKSTEP with\nthe browser SourceInputModel: NO raw max_length (which would accept control chars and\nreject a valid whitespace-padded 64-char label); the SHARED\n``manifest.validate_subject_hint`` is applied identically here via a field_validator\nand again at the intake. Consulted only behind VBE_MULTICAM_DECLARED_ROLES."},"SweepApproveRequest":{"properties":{"manifest_sha":{"type":"string","maxLength":256,"minLength":1,"title":"Manifest Sha"}},"additionalProperties":false,"type":"object","required":["manifest_sha"],"title":"SweepApproveRequest"},"SweepCreateRequest":{"properties":{"person_id":{"type":"string","maxLength":128,"minLength":1,"title":"Person Id"},"kind":{"$ref":"#/components/schemas/BatchKind"},"render_mode":{"$ref":"#/components/schemas/RenderMode","default":"render"},"brief":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Brief"},"budget":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Budget"}},"additionalProperties":false,"type":"object","required":["person_id","kind"],"title":"SweepCreateRequest"},"TrailerBlock":{"properties":{"available":{"type":"boolean","title":"Available"},"n_beats":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"N Beats"}},"type":"object","required":["available"],"title":"TrailerBlock"},"TranscriptArtifact":{"properties":{"available":{"type":"boolean","title":"Available","description":"Whether the durable transcript.json artifact exists."},"language":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Language","description":"Persisted transcript language, when recorded in the manifest."},"words":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Words","description":"Persisted word count, when recorded in the transcript manifest."},"duration_sec":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Duration Sec","description":"Persisted transcript/source duration in seconds, when recorded."}},"type":"object","required":["available"],"title":"TranscriptArtifact","description":"Availability and durable manifest metadata for transcript.json."},"UploadRequest":{"properties":{"filename":{"type":"string","maxLength":512,"minLength":1,"title":"Filename"},"size":{"type":"integer","minimum":0.0,"title":"Size","default":0},"content_type":{"type":"string","maxLength":200,"title":"Content Type","default":""},"content_sha256":{"anyOf":[{"type":"string","maxLength":64,"minLength":64},{"type":"null"}],"title":"Content Sha256"}},"additionalProperties":false,"type":"object","required":["filename"],"title":"UploadRequest"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"vbeclip__api__v1__artifact_models__FormatOutcome":{"properties":{"ordered":{"type":"integer","title":"Ordered","description":"Number of outputs ordered for this format."},"delivered":{"type":"integer","title":"Delivered","description":"Number of durable projected outputs delivered."},"zero_match":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Zero Match","description":"Whether an ordered format truthfully found no match. Currently recorded only for shorts; null means this pipeline format does not persist that signal."},"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason","description":"Stable refusal reason when the requested format was not admitted."}},"type":"object","required":["ordered","delivered","zero_match"],"title":"FormatOutcome","description":"Requested and delivered counts for one output format."},"vbeclip__api__v1__run_models__FormatOutcome":{"properties":{"ordered":{"type":"integer","title":"Ordered","description":"Number of outputs requested for this format."},"delivered":{"type":"integer","title":"Delivered","description":"Number of outputs persisted in the run manifest."},"zero_match":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Zero Match","description":"Whether the format completed with an explained zero-match result; null when the pipeline records no zero-match evidence for this format."},"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason","description":"Stable refusal reason when the requested format was not admitted."}},"type":"object","required":["ordered","delivered","zero_match"],"title":"FormatOutcome","description":"Terminal delivery accounting for one requested output format."},"ErrorBody":{"additionalProperties":false,"properties":{"code":{"title":"Code","type":"string"},"message":{"title":"Message","type":"string"},"detail":{"default":null,"title":"Detail"},"retryable":{"title":"Retryable","type":"boolean"},"retry_after_sec":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Retry After Sec"},"hint":{"title":"Hint","type":"string"},"docs":{"title":"Docs","type":"string"},"request_id":{"title":"Request Id","type":"string"}},"required":["code","message","retryable","retry_after_sec","hint","docs","request_id"],"title":"ErrorBody","type":"object"},"ErrorEnvelope":{"additionalProperties":false,"properties":{"error":{"$ref":"#/components/schemas/ErrorBody"}},"required":["error"],"title":"ErrorEnvelope","type":"object"}},"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"headers":{"X-Request-Id":{"description":"Stable request id for support and log correlation.","schema":{"type":"string"}},"Idempotent-Replay":{"description":"True when this response replays a stored POST outcome.","schema":{"type":"string","enum":["true"]}}}},"servers":[{"url":"/v1"},{"url":"https://www.clipzyn.com"}]}