{
  "openapi": "3.1.0",
  "info": {
    "title": "UploadCheck.app API",
    "version": "0.1.0",
    "description": "Programmatic quality checks for videos, podcasts, clips, uploads, and agent workflows."
  },
  "servers": [
    {
      "url": "https://api.uploadcheck.app"
    }
  ],
  "security": [
    {
      "bearerApiKey": []
    }
  ],
  "components": {
    "securitySchemes": {
      "bearerApiKey": {
        "type": "http",
        "scheme": "bearer",
        "description": "Workspace API key supplied as a bearer token."
      }
    },
    "schemas": {
      "QcJob": {
        "type": "object",
        "properties": {
          "jobId": { "type": "string" },
          "status": { "type": "string" },
          "progressPct": { "type": "integer" },
          "verdict": { "type": ["string", "null"], "enum": ["PASS", "WATCH", "BLOCK", null] },
          "minutesMetered": { "type": "integer" },
          "startedAt": { "type": "string", "format": "date-time" },
          "completedAt": { "type": "string", "format": "date-time" },
          "processingDurationMs": { "type": "integer", "description": "Wall-clock processing time in milliseconds from job start to completion." },
          "failureReason": { "type": ["string", "null"], "description": "Failure or fallback reason when the engine cannot complete normally." },
          "statusUrl": { "type": "string" },
          "reportUrl": { "type": "string" },
          "observability": {
            "type": ["object", "null"],
            "description": "Timing, engine, stage, provider-usage, and failure telemetry for job debugging and cost analysis.",
            "properties": {
              "startedAt": { "type": "string", "format": "date-time" },
              "completedAt": { "type": "string", "format": "date-time" },
              "processingDurationMs": { "type": "integer" },
              "outcome": { "type": ["string", "null"] },
              "engine": { "type": ["string", "null"] },
              "providerUsageEntries": { "type": "integer" },
              "failureReason": { "type": ["string", "null"] },
              "stages": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "status": { "type": "string" },
                    "progressPct": { "type": "integer" },
                    "elapsedMs": { "type": "integer" },
                    "at": { "type": "string", "format": "date-time" }
                  }
                }
              }
            }
          },
          "mediaIngress": {
            "type": ["object", "null"],
            "description": "Sanitized media ingress metadata. Inline media is processed ephemerally without exposing temporary server paths.",
            "properties": {
              "mode": { "type": "string", "enum": ["inline_ephemeral", "signed_upload", "youtube_url", "remote_url", "local_or_remote_source"] },
              "contentType": { "type": ["string", "null"] },
              "bytes": { "type": ["integer", "null"] },
              "sha256": { "type": ["string", "null"], "description": "SHA-256 hash of the checked media bytes when UploadCheck handled the bytes directly." },
              "ephemeral": { "type": "boolean" },
              "storageMode": { "type": "string", "enum": ["render_temp_storage", "durable_filesystem", "object_storage"] }
            }
          },
          "sidecarIngress": {
            "type": ["object", "null"],
            "description": "Sanitized sidecar ingress metadata. Remote sidecar URLs are fetched into temporary storage for the run and are never exposed in public job responses.",
            "properties": {
              "mode": { "type": "string", "enum": ["remote_https_sidecars"] },
              "ephemeral": { "type": "boolean" },
              "supplied": {
                "type": "array",
                "items": { "type": "string", "enum": ["manifest", "transcript", "watchlist", "expectedScript", "chunkSidecars"] }
              },
              "neverExposes": { "type": "array", "items": { "type": "string" } }
            }
          },
          "sourceRedacted": {
            "type": "boolean",
            "description": "True when an upload-backed local server path was removed from the public job response."
          },
          "costEstimate": {
            "type": "object",
            "properties": {
              "estimatedCogsUsd": { "type": "number" },
              "grossMarginBudgetUsd": { "type": "number" },
              "grossMarginTargetPct": { "type": "number" },
              "withinBudget": { "type": "boolean" },
              "modelCheckCents": { "type": "number" },
              "modelBackedChecks": { "type": "array", "items": { "type": "string" } },
              "maxAiReviewSecondsAtMargin": { "type": "integer" },
              "marginSafe": { "type": "boolean" }
            }
          }
        },
        "required": ["jobId", "status", "progressPct", "verdict", "minutesMetered"]
      },
      "Upload": {
        "type": "object",
        "properties": {
          "uploadId": { "type": "string" },
          "filename": { "type": "string" },
          "contentType": { "type": "string" },
          "sizeBytes": { "type": "integer" },
          "status": { "type": "string", "enum": ["created", "uploaded"] },
          "signedPutUrl": { "type": "string" },
          "expiresAt": { "type": "string", "format": "date-time" },
          "storageMode": { "type": "string", "enum": ["render_temp_storage", "durable_filesystem", "object_storage"] },
          "objectKey": { "type": "string", "nullable": true },
          "objectUrl": { "type": "string", "nullable": true }
        }
      },
      "UploadStored": {
        "type": "object",
        "properties": {
          "uploadId": { "type": "string" },
          "status": { "type": "string", "enum": ["uploaded"] },
          "storageMode": { "type": "string", "enum": ["render_temp_storage", "durable_filesystem", "object_storage"] },
          "bytesReceived": { "type": "integer" },
          "sha256": { "type": "string" },
          "objectKey": { "type": "string" },
          "objectUrl": { "type": "string" }
        },
        "required": ["uploadId", "status", "storageMode", "bytesReceived", "sha256"]
      },
      "WebhookEndpoint": {
        "type": "object",
        "properties": {
          "webhookId": { "type": "string" },
          "url": { "type": "string" },
          "eventTypes": { "type": "array", "items": { "type": "string" } },
          "signingSecretPreview": { "type": "string" },
          "signingSecret": { "type": "string", "description": "Returned once on creation." },
          "signingSecretStorage": { "type": "string", "enum": ["encrypted", "plaintext"] }
        }
      },
      "WebhookDelivery": {
        "type": "object",
        "properties": {
          "deliveryId": { "type": "string" },
          "webhookId": { "type": "string" },
          "eventType": { "type": "string" },
          "jobId": { "type": "string" },
          "status": { "type": "string", "enum": ["pending", "sent", "failed"] },
          "url": { "type": "string" },
          "attemptCount": { "type": "integer" },
          "nextAttemptAt": { "type": ["string", "null"], "format": "date-time" },
          "lastAttemptAt": { "type": ["string", "null"], "format": "date-time" },
          "responseStatus": { "type": ["integer", "null"] },
          "lastError": { "type": ["string", "null"] },
          "sentAt": { "type": ["string", "null"], "format": "date-time" },
          "createdAt": { "type": "string", "format": "date-time" },
          "signatureHeader": { "type": "string", "const": "X-UploadCheck-Signature" },
          "legacySignatureHeader": { "type": "string", "const": "X-QCGenie-Signature" },
          "signature": { "type": "string" },
          "payload": { "type": "object" }
        }
      },
      "WebhookDeliveryList": {
        "type": "object",
        "properties": {
          "deliveries": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/WebhookDelivery" }
          }
        },
        "required": ["deliveries"]
      },
      "WebhookDrainResult": {
        "type": "object",
        "properties": {
          "processed": { "type": "integer" },
          "results": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/WebhookDelivery" }
          }
        },
        "required": ["processed", "results"]
      }
    }
  },
  "paths": {
    "/healthz": {
      "get": {
        "summary": "Health check",
        "security": [],
        "responses": {
          "200": { "description": "Service is healthy" }
        }
      }
    },
    "/v1/readiness": {
      "get": {
        "summary": "Launch readiness and operational configuration status",
        "security": [],
        "responses": {
          "200": {
            "description": "No-secret readiness report for checkout, custom domain, persistence, storage, and Product Hunt launch state"
          }
        }
      }
    },
    "/v1/launch-status": {
      "get": {
        "summary": "Live Product Hunt launch status",
        "security": [],
        "responses": {
          "200": {
            "description": "Live machine-readable launch go/no-go state derived from readiness checks, including completed controls, current blockers, and operator commands.",
            "content": {
              "application/json": { "schema": { "type": "object" } }
            }
          }
        }
      }
    },
    "/v1/launch-handoff": {
      "get": {
        "summary": "Live Product Hunt launch handoff",
        "security": [],
        "responses": {
          "200": {
            "description": "Live operator and agent handoff derived from readiness checks, including current blockers, required actions, proof commands, and the no-launch rule.",
            "content": {
              "application/json": { "schema": { "type": "object" } }
            }
          }
        }
      }
    },
    "/v1/launch-doctor": {
      "get": {
        "summary": "Live Product Hunt launch doctor",
        "security": [],
        "responses": {
          "200": {
            "description": "Live blocker fix plan and normalized launch-doctor command coverage derived from readiness checks.",
            "content": {
              "application/json": { "schema": { "type": "object" } }
            }
          }
        }
      }
    },
    "/v1/launch-evidence": {
      "get": {
        "summary": "Redacted live Product Hunt launch evidence",
        "security": [],
        "responses": {
          "200": {
            "description": "Redacted launch evidence bundle derived from the live launch doctor, suitable for agents and public Product Hunt readiness audits.",
            "content": {
              "application/json": { "schema": { "type": "object" } }
            }
          }
        }
      }
    },
    "/agent-manifest.json": {
      "get": {
        "summary": "UploadCheck agent manifest",
        "security": [],
        "responses": {
          "200": {
            "description": "Machine-readable agent manifest for MCP, CLI, API, pricing, and launch metadata.",
            "content": {
              "application/json": { "schema": { "type": "object" } }
            }
          }
        }
      }
    },
    "/pipeline-handoff.json": {
      "get": {
        "summary": "UploadCheck production pipeline handoff",
        "security": [],
        "responses": {
          "200": {
            "description": "Machine-readable runbook for NTO/NPO and creator production pipelines that call UploadCheck.",
            "content": {
              "application/json": { "schema": { "type": "object" } }
            }
          }
        }
      }
    },
    "/pipeline-recipes.json": {
      "get": {
        "summary": "UploadCheck pipeline recipes",
        "security": [],
        "responses": {
          "200": {
            "description": "Machine-readable NTO/NPO and creator pipeline profiles.",
            "content": {
              "application/json": { "schema": { "type": "object" } }
            }
          }
        }
      }
    },
    "/npo-pipeline-handoff.json": {
      "get": {
        "summary": "UploadCheck NPO pipeline handoff",
        "security": [],
        "responses": {
          "200": {
            "description": "Focused callable runbook for NPO podcast/audio production pipelines.",
            "content": {
              "application/json": { "schema": { "type": "object" } }
            }
          }
        }
      }
    },
    "/launch-targets.json": {
      "get": {
        "summary": "UploadCheck launch targets",
        "security": [],
        "responses": {
          "200": {
            "description": "Machine-readable Render service IDs, DNS records, HTTP targets, and verification commands.",
            "content": {
              "application/json": { "schema": { "type": "object" } }
            }
          }
        }
      }
    },
    "/launch-status.json": {
      "get": {
        "summary": "UploadCheck launch status",
        "security": [],
        "responses": {
          "200": {
            "description": "Machine-readable Product Hunt launch go/no-go state, completed controls, remaining blockers, and operator commands.",
            "content": {
              "application/json": { "schema": { "type": "object" } }
            }
          }
        }
      }
    },
    "/product-hunt-launch-kit.json": {
      "get": {
        "summary": "Product Hunt launch kit",
        "security": [],
        "responses": {
          "200": {
            "description": "Machine-readable Product Hunt launch copy, demo flow, proof links, pricing posture, and go/no-go rule.",
            "content": {
              "application/json": { "schema": { "type": "object" } }
            }
          }
        }
      }
    },
    "/cost-basis.json": {
      "get": {
        "summary": "UploadCheck cost basis",
        "security": [],
        "responses": {
          "200": {
            "description": "Machine-readable cost-per-minute, plan, and gross-margin assumptions.",
            "content": {
              "application/json": { "schema": { "type": "object" } }
            }
          }
        }
      }
    },
    "/llms.txt": {
      "get": {
        "summary": "UploadCheck llms.txt",
        "security": [],
        "responses": {
          "200": {
            "description": "Text guidance for answer engines and coding agents.",
            "content": {
              "text/plain": { "schema": { "type": "string" } }
            }
          }
        }
      }
    },
    "/sample-reports/index.json": {
      "get": {
        "summary": "Public UploadCheck sample report index",
        "security": [],
        "responses": {
          "200": {
            "description": "PASS, WATCH, and BLOCK sample report artifacts.",
            "content": {
              "application/json": { "schema": { "type": "object" } }
            }
          }
        }
      }
    },
    "/v1/qc/estimate": {
      "post": {
        "summary": "Preflight cost and margin estimate",
        "security": [{ "bearerApiKey": [] }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "minutes": { "type": "number" },
                  "duration_seconds": { "type": "number" },
                  "checks": { "type": "string" },
                  "plan_id": { "type": "string" },
                  "plan_price_cents": { "type": "integer" },
                  "included_minutes": { "type": "integer" },
                  "ai_review_seconds": { "type": "number" },
                  "cost_guardrail": { "type": "string", "enum": ["downgrade", "block", "off"] }
                }
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Cost estimate and effective guardrail behavior" },
          "401": { "description": "Missing or invalid API key" },
          "403": { "description": "Insufficient scope" }
        }
      }
    },
    "/v1/qc/jobs": {
      "post": {
        "summary": "Create a QC job",
        "security": [{ "bearerApiKey": [] }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "youtube_url": { "type": "string" },
                  "upload_id": { "type": "string" },
                  "signed_url": { "type": "string" },
                  "callback_url": { "type": "string" },
                  "idempotency_key": { "type": "string" },
                  "media_base64": { "type": "string" },
                  "media_content_type": { "type": "string" },
                  "media_kind": { "type": "string", "enum": ["video", "audio", "image"] },
                  "video_base64": { "type": "string" },
                  "video_content_type": { "type": "string" },
                  "audio_base64": { "type": "string" },
                  "audio_content_type": { "type": "string" },
                  "data_url": { "type": "string" },
                  "filename": { "type": "string" },
                  "process_async": {
                    "description": "When true, leave the job queued for POST /v1/qc/jobs/drain instead of running QC in the create request. Inline media and inline sidecars are not supported in queued mode.",
                    "type": "boolean"
                  },
                  "duration_seconds": {
                    "description": "Declared media duration used for cost, usage, and abuse-limit preflight.",
                    "type": "number"
                  },
                  "size_bytes": {
                    "description": "Declared media size used for upload abuse-limit preflight.",
                    "type": "integer"
                  },
                  "manifest_json": {
                    "description": "Optional storybook/edit manifest JSON used by repeat_fatigue for visual reuse and source-family analysis.",
                    "type": ["object", "array", "string"]
                  },
                  "manifest_base64": {
                    "description": "Optional base64-encoded storybook/edit manifest JSON.",
                    "type": "string"
                  },
                  "manifest_filename": { "type": "string" },
                  "manifest_url": {
                    "description": "HTTPS URL for a remote storybook/edit manifest. Use for process_async jobs because inline sidecars are ephemeral.",
                    "type": "string"
                  },
                  "transcript_text": {
                    "description": "Optional transcript/script text used by spoken_leaks without ASR spend.",
                    "type": "string"
                  },
                  "transcript_json": {
                    "description": "Optional transcript JSON with text or words fields used by spoken_leaks.",
                    "type": ["object", "array", "string"]
                  },
                  "transcript_base64": {
                    "description": "Optional base64-encoded transcript text or JSON.",
                    "type": "string"
                  },
                  "transcript_filename": { "type": "string" },
                  "transcript_url": {
                    "description": "HTTPS URL for a remote transcript text or JSON sidecar. Use for process_async jobs because inline sidecars are ephemeral.",
                    "type": "string"
                  },
                  "watchlist_json": {
                    "description": "Optional pronunciation/term watchlist JSON for pronunciation_watchlist.",
                    "type": ["object", "array", "string"]
                  },
                  "watchlist_base64": {
                    "description": "Optional base64-encoded pronunciation/term watchlist JSON.",
                    "type": "string"
                  },
                  "watchlist_filename": { "type": "string" },
                  "watchlist_url": {
                    "description": "HTTPS URL for a remote pronunciation/term watchlist JSON sidecar. Use for process_async jobs because inline sidecars are ephemeral.",
                    "type": "string"
                  },
                  "expected_script_text": {
                    "description": "Optional locked script text used by script_faithfulness with transcript_text/transcript_json.",
                    "type": "string"
                  },
                  "expected_script_json": {
                    "description": "Optional locked script JSON with text, script, or words fields used by script_faithfulness.",
                    "type": ["object", "array", "string"]
                  },
                  "expected_script_base64": {
                    "description": "Optional base64-encoded locked script text or JSON.",
                    "type": "string"
                  },
                  "expected_script_filename": { "type": "string" },
                  "expected_script_url": {
                    "description": "HTTPS URL for a remote locked-script text or JSON sidecar. Use for process_async jobs because inline sidecars are ephemeral.",
                    "type": "string"
                  },
                  "chunk_sidecars_json": {
                    "description": "Optional array or object map of chunk QC sidecar JSON files used by chunk_sidecar_failures, for example packaged *.garble-report.json entries.",
                    "type": ["array", "object", "string"]
                  },
                  "chunk_sidecars_base64": {
                    "description": "Optional base64-encoded JSON array or object map of chunk QC sidecar files.",
                    "type": "string"
                  },
                  "chunk_sidecar_dirname": { "type": "string" },
                  "chunk_sidecars_url": {
                    "description": "HTTPS URL for a remote JSON array or object map of chunk QC sidecars. Use for process_async jobs because inline sidecars are ephemeral.",
                    "type": "string"
                  },
                  "plan_id": {
                    "description": "Optional plan preset for cost estimates and margin guardrails: creator, studio, network, or stress_99_5000.",
                    "type": "string"
                  },
                  "plan_price_cents": {
                    "description": "Optional custom monthly plan price in cents for cost guardrail calculations.",
                    "type": "integer"
                  },
                  "included_minutes": {
                    "description": "Optional included monthly checked minutes for cost guardrail calculations.",
                    "type": "integer"
                  },
                  "ai_review_seconds": {
                    "description": "Internal or explicitly authorized model-review seconds for cost guardrails. Public included minutes are deterministic QC minutes.",
                    "type": "number"
                  },
                  "cost_guardrail": {
                    "description": "Margin guardrail behavior when requested AI review would break the >95% gross-margin target.",
                    "type": "string",
                    "enum": ["downgrade", "block", "off"]
                  },
                  "checks": { "type": "string" }
                }
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Existing idempotent job returned" },
          "202": { "description": "Job queued" },
          "413": { "description": "Duration or upload-size abuse limit exceeded" },
          "429": { "description": "Active job concurrency limit exceeded" },
          "401": { "description": "Missing or invalid API key" },
          "403": { "description": "Insufficient scope" }
        }
      },
      "get": {
        "summary": "List recent QC jobs",
        "parameters": [
          { "name": "limit", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 100 } },
          { "name": "status", "in": "query", "schema": { "type": "string" } },
          { "name": "source_url", "in": "query", "schema": { "type": "string" } }
        ],
        "responses": {
          "200": { "description": "Recent jobs" }
        }
      }
    },
    "/v1/qc/jobs/drain": {
      "post": {
        "summary": "Drain queued async QC jobs",
        "security": [{ "bearerApiKey": [] }],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "limit": { "type": "integer", "minimum": 1, "maximum": 25 }
                }
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Queued jobs processed" },
          "401": { "description": "Missing or invalid API key" },
          "403": { "description": "Insufficient scope" }
        }
      }
    },
    "/v1/qc/jobs/{job_id}": {
      "get": {
        "summary": "Get QC job status",
        "parameters": [{ "name": "job_id", "in": "path", "required": true, "schema": { "type": "string" } }],
        "responses": {
          "200": { "description": "Job status" }
        }
      }
    },
    "/v1/qc/jobs/{job_id}/report": {
      "get": {
        "summary": "Get QC report",
        "parameters": [{ "name": "job_id", "in": "path", "required": true, "schema": { "type": "string" } }],
        "responses": {
          "200": { "description": "Timestamped report" }
        }
      }
    },
    "/v1/qc/jobs/{job_id}/events": {
      "get": {
        "summary": "List QC lifecycle events for a job",
        "parameters": [{ "name": "job_id", "in": "path", "required": true, "schema": { "type": "string" } }],
        "responses": {
          "200": { "description": "Lifecycle events" }
        }
      }
    },
    "/v1/qc/jobs/{job_id}/artifacts": {
      "get": {
        "summary": "List report artifacts for a job",
        "parameters": [{ "name": "job_id", "in": "path", "required": true, "schema": { "type": "string" } }],
        "responses": {
          "200": { "description": "Artifacts" }
        }
      }
    },
    "/v1/qc/jobs/{job_id}/artifacts/markers": {
      "get": {
        "summary": "Download editor marker export CSV",
        "parameters": [{ "name": "job_id", "in": "path", "required": true, "schema": { "type": "string" } }],
        "responses": {
          "200": {
            "description": "CSV marker export",
            "content": {
              "text/csv": {
                "schema": { "type": "string" }
              }
            }
          }
        }
      }
    },
    "/v1/qc/jobs/{job_id}/gate-verdict": {
      "post": {
        "summary": "Import an external full-video gate verdict",
        "parameters": [{ "name": "job_id", "in": "path", "required": true, "schema": { "type": "string" } }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "verdict": { "type": "string", "enum": ["SHIP-OK", "BLOCK", "PASS"] },
                  "blocked": { "type": "array", "items": { "type": "string" } },
                  "skipped": { "type": "array", "items": { "type": "string" } },
                  "per_check": { "type": "object" }
                }
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Gate verdict imported" },
          "404": { "description": "Job not found" }
        }
      }
    },
    "/v1/usage": {
      "get": {
        "summary": "List recent usage ledger entries",
        "responses": {
          "200": { "description": "Usage ledger entries" }
        }
      }
    },
    "/v1/usage/margins": {
      "get": {
        "summary": "Summarize usage cost and gross-margin telemetry",
        "parameters": [
          { "name": "billing_period", "in": "query", "required": false, "schema": { "type": "string" } },
          { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer" } }
        ],
        "responses": {
          "200": { "description": "Usage COGS, allocated revenue, cost per minute, and gross-margin summary" }
        }
      }
    },
    "/v1/qc/jobs/{job_id}/cancel": {
      "post": {
        "summary": "Cancel a QC job",
        "parameters": [{ "name": "job_id", "in": "path", "required": true, "schema": { "type": "string" } }],
        "responses": {
          "200": { "description": "Job cancelled" }
        }
      }
    },
    "/v1/uploads": {
      "post": {
        "summary": "Create a signed upload target",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "filename": { "type": "string" },
                  "content_type": { "type": "string" },
                  "size_bytes": { "type": "integer" }
                },
                "required": ["filename", "content_type", "size_bytes"]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Signed upload target",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Upload" }
              }
            }
          },
          "413": { "description": "Upload reservation exceeds configured maximum size" }
        }
      }
    },
    "/v1/uploads/{upload_id}": {
      "get": {
        "summary": "Get upload metadata and processing status",
        "parameters": [{ "name": "upload_id", "in": "path", "required": true, "schema": { "type": "string" } }],
        "responses": {
          "200": {
            "description": "Upload status",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Upload" }
              }
            }
          },
          "404": { "description": "Upload not found" }
        }
      }
    },
    "/v1/uploads/{upload_id}/content": {
      "put": {
        "summary": "Upload local media bytes to a signed UploadCheck URL",
        "security": [],
        "parameters": [
          { "name": "upload_id", "in": "path", "required": true, "schema": { "type": "string" } },
          { "name": "token", "in": "query", "required": true, "schema": { "type": "string" } }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/octet-stream": { "schema": { "type": "string", "format": "binary" } },
            "video/mp4": { "schema": { "type": "string", "format": "binary" } },
            "audio/mpeg": { "schema": { "type": "string", "format": "binary" } }
          }
        },
        "responses": {
          "200": {
            "description": "Upload bytes stored for a QC job",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/UploadStored" }
              }
            }
          },
          "403": { "description": "Invalid upload token" },
          "410": { "description": "Upload URL expired" },
          "413": { "description": "Upload too large" },
          "404": { "description": "Upload not found" }
        }
      }
    },
    "/v1/webhooks": {
      "post": {
        "summary": "Register a workspace webhook endpoint",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": { "type": "string" },
                  "event_types": {
                    "type": "array",
                    "items": { "type": "string" }
                  }
                },
                "required": ["url"]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Webhook registered",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/WebhookEndpoint" }
              }
            }
          }
        }
      }
    },
    "/v1/webhooks/{webhook_id}/delivery-preview": {
      "get": {
        "summary": "Preview signed webhook delivery metadata",
        "parameters": [{ "name": "webhook_id", "in": "path", "required": true, "schema": { "type": "string" } }],
        "responses": {
          "200": {
            "description": "Signed delivery preview",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/WebhookDelivery" }
              }
            }
          },
          "404": { "description": "Webhook not found" }
        }
      }
    },
    "/v1/webhooks/deliveries": {
      "get": {
        "summary": "List recent webhook deliveries",
        "parameters": [
          { "name": "limit", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 100 } },
          { "name": "status", "in": "query", "schema": { "type": "string", "enum": ["pending", "sent", "failed"] } },
          { "name": "webhook_id", "in": "query", "schema": { "type": "string" } }
        ],
        "responses": {
          "200": {
            "description": "Webhook delivery log entries",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/WebhookDeliveryList" }
              }
            }
          }
        }
      }
    },
    "/v1/webhooks/deliveries/{delivery_id}/retry": {
      "post": {
        "summary": "Retry a pending or failed webhook delivery",
        "parameters": [{ "name": "delivery_id", "in": "path", "required": true, "schema": { "type": "string" } }],
        "responses": {
          "200": {
            "description": "Delivery attempt result",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/WebhookDelivery" }
              }
            }
          },
          "404": { "description": "Delivery not found" }
        }
      }
    },
    "/v1/webhooks/deliveries/drain": {
      "post": {
        "summary": "Process due pending webhook deliveries",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "limit": { "type": "integer", "minimum": 1, "maximum": 25 }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Due delivery drain result",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/WebhookDrainResult" }
              }
            }
          }
        }
      }
    }
  }
}
