{"openapi":"3.1.0","info":{"title":"NextGen Interactive — Public HTTP API","version":"1.7.0","summary":"OpenAPI 3.1.0 contract for ngi.video's public endpoints: health, the video tool list, build-time portfolio link data, live portfolio link status and early-access intake.","description":"GPU video processing has no public API; it is in private early access (https://ngi.video/#contact). GET /api/portfolio/status probes portfolio links live; GET /api/health/links serves data captured at build time.","contact":{"name":"NextGen Interactive","url":"https://ngi.video","email":"nextgen.video.dev@gmail.com"}},"servers":[{"url":"https://ngi.video","description":"Production server (Helios / Coolify)"}],"paths":{"/api/health":{"get":{"operationId":"getHealth","summary":"Build SHA, build time and database reachability","responses":{"200":{"description":"The site is serving. Database reachability is reported in `database` (probed at most every 30 s) and does not change `ok`.","content":{"application/json":{"schema":{"type":"object","required":["ok","service","app","version","builtAt","database"],"additionalProperties":false,"properties":{"ok":{"type":"boolean"},"service":{"type":"string","example":"ngi.video"},"app":{"type":"string","example":"site"},"version":{"type":"string","description":"GIT_SHA, VERCEL_GIT_COMMIT_SHA or SOURCE_COMMIT; \"unknown\" when none is set","example":"unknown"},"builtAt":{"type":"string","description":"ISO-8601 build time or \"unknown\""},"database":{"type":"string","enum":["ok","unreachable","not_configured"]}}}}}}}}},"/api/health/links":{"get":{"operationId":"getHealthLinks","summary":"Portfolio link data captured at build time; use /api/portfolio/status for live checks","responses":{"200":{"description":"Build-time portfolio and route link data","content":{"application/json":{"schema":{"type":"object","required":["ok","source","summary","routes","portfolio"],"properties":{"ok":{"type":"boolean"},"source":{"type":"string","const":"build-time"},"summary":{"type":"object","properties":{"totalRepos":{"type":"integer"},"onlineDeployments":{"type":"integer"},"offlineDeactivated":{"type":"integer"},"localPackages":{"type":"integer"},"publicGithubRepos":{"type":"integer"},"privateGithubRepos":{"type":"integer"}}},"routes":{"type":"array","items":{"type":"string"}},"portfolio":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"deploymentStatus":{"type":"string","enum":["online","offline","local"]},"liveUrl":{"type":["string","null"]},"offlineDomain":{"type":["string","null"]},"statusReason":{"type":["string","null"]},"githubPublic":{"type":"boolean"},"githubUrl":{"type":"string"}}}}}}}}}}}},"/api/portfolio/status":{"get":{"operationId":"getPortfolioStatus","summary":"Dynamic runtime probe of portfolio card live deployments and GitHub links","responses":{"200":{"description":"Live portfolio card link status map","content":{"application/json":{"schema":{"type":"object","required":["checkedAt","summary","statuses"]}}}}}}},"/api/registry/tools":{"get":{"operationId":"listBrVideoTools","summary":"List the video tools with outcome-level descriptions and availability","parameters":[{"name":"category","in":"query","required":false,"schema":{"type":"string","enum":["all","compression","enhancement","editing","search"]}},{"name":"q","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Video tool list","content":{"application/json":{"schema":{"type":"object","required":["object","version","count","total","tools"],"properties":{"tools":{"type":"array","items":{"type":"object","required":["name","title","summary","whyUseful","category","tags","availability"],"properties":{"name":{"type":"string"},"title":{"type":"string"},"summary":{"type":"string"},"whyUseful":{"type":"string"},"category":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"availability":{"type":"string","enum":["browser","early_access"]}}}}}}}}}}}},"/api/registry/tools/{toolId}":{"get":{"operationId":"getBrVideoTool","summary":"Retrieve one video tool (outcome-level fields only) by ID","parameters":[{"name":"toolId","in":"path","required":true,"schema":{"type":"string","enum":["compress","upres","seamless_cut","neural-cut","concatenate","segment","srt_search","visual_index","live-portrait","thumbnailer","loudnorm"]}}],"responses":{"200":{"description":"Single capability (outcome-level fields only)"},"404":{"description":"Capability not found"}}}},"/api/early-access":{"get":{"operationId":"getEarlyAccessIntake","summary":"Intake metadata: whether requests are stored, supported intents, contact email","responses":{"200":{"description":"Intake metadata","content":{"application/json":{"schema":{"type":"object","required":["service","storage","supportedIntents","directContactEmail"],"properties":{"service":{"type":"string"},"storage":{"type":"string","enum":["postgres","not_configured"]},"supportedIntents":{"type":"array","items":{"type":"string"}},"directContactEmail":{"type":"string","format":"email"}}}}}}}},"post":{"operationId":"submitEarlyAccessRequest","summary":"Submit a GPU early-access request or B2B engineering inquiry","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["email","useCase"],"properties":{"email":{"type":"string","format":"email","maxLength":254},"organization":{"type":"string","maxLength":160},"intent":{"type":"string","enum":["hosted_brvideo_early_access","b2b_engineering"],"default":"hosted_brvideo_early_access"},"useCase":{"type":"string","minLength":8,"maxLength":2000}}}}}},"responses":{"201":{"description":"Request saved in the database; body has requestId and status \"pending\""},"400":{"description":"Request body is not valid JSON"},"413":{"description":"Request body is over 16384 characters"},"422":{"description":"Body is not a JSON object, a field is not a string, invalid email, useCase shorter than 8 characters, an intent outside the enum, or a field over its maxLength"},"429":{"description":"More than 10 requests per minute from this address"},"503":{"description":"Request NOT saved (storage not configured or the write failed); body has status \"not_stored\". Email the contact address instead."},"504":{"description":"Request sent but not confirmed in time; body has status \"unconfirmed\". It may or may not have been saved; email the contact address."}}}}}}