{"openapi":"3.1.0","info":{"title":"OpenContent API","version":"1.0.0","description":"Attribution-first media and content ingestion, metadata, share-card, discovery, and MCP/API layer for OpenContent.","contact":{"name":"OpenContent","url":"https://opencontent.platphormnews.com"}},"servers":[{"url":"https://opencontent.platphormnews.com/api/v1","description":"Production"},{"url":"https://opencontent.platphormnews.com","description":"Canonical site root for platform discovery routes"}],"security":[{"bearerAuth":[]}],"paths":{"/documents":{"get":{"summary":"List documents","description":"List all published documents with pagination and filtering","tags":["Documents"],"security":[],"parameters":[{"name":"page","in":"query","schema":{"type":"integer","default":1}},{"name":"per_page","in":"query","schema":{"type":"integer","default":20,"maximum":100}},{"name":"status","in":"query","schema":{"type":"string","default":"published"}},{"name":"category","in":"query","schema":{"type":"string"}},{"name":"q","in":"query","schema":{"type":"string"},"description":"Search query"},{"name":"tag","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"List of documents","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentList"}}}}}},"post":{"summary":"Create document","description":"Create a new document","tags":["Documents"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentCreate"}}}},"responses":{"201":{"description":"Document created"},"401":{"description":"Unauthorized"}}}},"/documents/{slug}":{"get":{"summary":"Get document","description":"Get a specific document by slug","tags":["Documents"],"security":[],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Document details"},"404":{"description":"Not found"}}},"put":{"summary":"Update document","description":"Update an existing document","tags":["Documents"],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentUpdate"}}}},"responses":{"200":{"description":"Document updated"},"401":{"description":"Unauthorized"},"404":{"description":"Not found"}}},"delete":{"summary":"Delete document","description":"Soft delete a document","tags":["Documents"],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Document deleted"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden - requires admin scope"},"404":{"description":"Not found"}}}},"/submissions":{"get":{"summary":"List submissions","description":"List all submissions","tags":["Submissions"],"parameters":[{"name":"status","in":"query","schema":{"type":"string","enum":["pending","approved","rejected"]}},{"name":"source_url","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"List of submissions"},"401":{"description":"Unauthorized"}}},"post":{"summary":"Create submission","description":"Submit new content for review (open endpoint)","tags":["Submissions"],"security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubmissionCreate"}}}},"responses":{"201":{"description":"Submission created"},"400":{"description":"Validation error"}}}},"/submissions/{id}":{"get":{"summary":"Get submission","tags":["Submissions"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Submission details"},"404":{"description":"Not found"}}},"post":{"summary":"Review submission","description":"Approve or reject a submission","tags":["Submissions"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubmissionReview"}}}},"responses":{"200":{"description":"Submission reviewed"}}}},"/search":{"get":{"summary":"Search documents","description":"Full-text search across all documents","tags":["Search"],"security":[],"parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string","minLength":2}},{"name":"category","in":"query","schema":{"type":"string"}},{"name":"tag","in":"query","schema":{"type":"string"}},{"name":"page","in":"query","schema":{"type":"integer"}},{"name":"per_page","in":"query","schema":{"type":"integer"}}],"responses":{"200":{"description":"Search results"}}}},"/content":{"get":{"summary":"List content entries","description":"List public media/content archive entries with filtering by type, platform, category, tag, and search term.","tags":["Content"],"security":[],"parameters":[{"name":"type","in":"query","schema":{"type":"string"}},{"name":"platform","in":"query","schema":{"type":"string"}},{"name":"category","in":"query","schema":{"type":"string"}},{"name":"tags","in":"query","schema":{"type":"string"}},{"name":"search","in":"query","schema":{"type":"string"}},{"name":"page","in":"query","schema":{"type":"integer","default":1}},{"name":"limit","in":"query","schema":{"type":"integer","default":20,"maximum":100}}],"responses":{"200":{"description":"Content archive entries"}}},"post":{"summary":"Create uploaded content","description":"Publicly create an uploaded content entry with generated attribution, SEO/AEO, OG/Twitter, JSON-LD, metatags, share-card metadata, and dynamic share links.","tags":["Content"],"security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentCreate"}}}},"responses":{"200":{"description":"Content created"},"400":{"description":"Validation error"}}}},"/content/ingest":{"post":{"summary":"Add URL content","description":"Public OpenContent URL ingestion with SSRF protection. Creates or refreshes a content archive entry with attribution, SEO/AEO, OG/Twitter, JSON-LD, metatags, share-card metadata, and dynamic share links.","tags":["Content"],"security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["url"],"properties":{"url":{"type":"string","format":"uri","description":"Public URL to ingest"},"title":{"type":"string"},"description":{"type":"string"},"category":{"type":"string","description":"Category slug"},"tags":{"type":"array","items":{"type":"string"}},"targetAudience":{"type":"string","default":"everyone"},"autoPublish":{"type":"boolean","default":true,"description":"Publish immediately when true"},"refreshExisting":{"type":"boolean","default":false,"description":"Protected: refresh an existing entry instead of returning a duplicate error. Requires PLATPHORM_API_KEY."},"creatorName":{"type":"string"},"creatorUrl":{"type":"string","format":"uri"},"attributionText":{"type":"string"}}}}}},"responses":{"200":{"description":"Existing content refreshed"},"201":{"description":"Content ingested"},"400":{"description":"Invalid or unsafe URL"},"401":{"description":"PLATPHORM_API_KEY required when refreshExisting is true"},"409":{"description":"Content already exists"}}}},"/content/{id}":{"get":{"summary":"Get content entry","description":"Get a single content entry by slug or id.","tags":["Content"],"security":[],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Content slug or UUID"}],"responses":{"200":{"description":"Content entry"},"404":{"description":"Not found"}}}},"/content/{id}/metadata":{"get":{"summary":"Get generated metadata","description":"Retrieve or dynamically generate SEO, AEO, OpenGraph, Twitter/X card, JSON-LD, metatags, share-card, share links, canonical URL, and attribution for an existing entry without re-ingesting it.","tags":["Metadata"],"security":[],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Content slug or UUID"}],"responses":{"200":{"description":"Generated metadata bundle"},"404":{"description":"Not found"}}}},"/content/{id}/metadata/regenerate":{"post":{"summary":"Regenerate generated metadata","description":"Protected action that regenerates and persists SEO, AEO, OpenGraph, Twitter/X card, JSON-LD, metatags, share-card, and share links for an existing entry. Requires PLATPHORM_API_KEY.","tags":["Metadata"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Content slug or UUID"}],"responses":{"200":{"description":"Metadata regenerated"},"401":{"description":"PLATPHORM_API_KEY required"},"404":{"description":"Not found"}}}},"/content/{id}/share-links":{"get":{"summary":"Get dynamic share links","description":"Get post-creation share links for X, LinkedIn, Facebook, Reddit, Bluesky, Threads, Mastodon, email, generic share, and copy link.","tags":["Metadata"],"security":[],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Content slug or UUID"}],"responses":{"200":{"description":"Share links"},"404":{"description":"Not found"}}}},"/content/{id}/share-links/regenerate":{"post":{"summary":"Regenerate share links","description":"Protected alias for metadata regeneration focused on share-link persistence. Requires PLATPHORM_API_KEY.","tags":["Metadata"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Content slug or UUID"}],"responses":{"200":{"description":"Share links regenerated"},"401":{"description":"PLATPHORM_API_KEY required"}}}},"/content/{id}/share-card":{"get":{"summary":"Get share-card metadata","description":"Get the share-card preview metadata for an existing entry.","tags":["Metadata"],"security":[],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Content slug or UUID"}],"responses":{"200":{"description":"Share-card metadata"},"404":{"description":"Not found"}}}},"/content/{id}/share-card/regenerate":{"post":{"summary":"Regenerate share-card metadata","description":"Protected action that persists refreshed share-card metadata. Requires PLATPHORM_API_KEY.","tags":["Metadata"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Content slug or UUID"}],"responses":{"200":{"description":"Share card regenerated"},"401":{"description":"PLATPHORM_API_KEY required"}}}},"/url-preview":{"get":{"summary":"Preview URL metadata","description":"Public-safe URL preview with SSRF protection. Does not persist content.","tags":["Content"],"security":[],"parameters":[{"name":"url","in":"query","required":true,"schema":{"type":"string","format":"uri"}}],"responses":{"200":{"description":"URL preview metadata"},"400":{"description":"Invalid or unsafe URL"}}},"post":{"summary":"Preview URL metadata","description":"Public-safe URL preview with SSRF protection. Does not persist content.","tags":["Content"],"security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["url"],"properties":{"url":{"type":"string","format":"uri"}}}}}},"responses":{"200":{"description":"URL preview metadata"},"400":{"description":"Invalid or unsafe URL"}}}},"/content/preview":{"get":{"summary":"Preview content URL metadata","description":"Canonical public-safe content preview alias for /url-preview. Uses SSRF protection and does not persist content.","tags":["Content"],"security":[],"parameters":[{"name":"url","in":"query","required":true,"schema":{"type":"string","format":"uri"}}],"responses":{"200":{"description":"URL preview metadata"},"400":{"description":"Invalid or unsafe URL"}}},"post":{"summary":"Preview content URL metadata","description":"Canonical public-safe content preview alias for /url-preview. Uses SSRF protection and does not persist content.","tags":["Content"],"security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["url"],"properties":{"url":{"type":"string","format":"uri"}}}}}},"responses":{"200":{"description":"URL preview metadata"},"400":{"description":"Invalid or unsafe URL"}}}},"/categories":{"get":{"summary":"List categories","tags":["Categories"],"security":[],"responses":{"200":{"description":"List of categories"}}},"post":{"summary":"Create category","tags":["Categories"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CategoryCreate"}}}},"responses":{"201":{"description":"Category created"}}}},"/webhooks":{"get":{"summary":"List webhooks","tags":["Webhooks"],"responses":{"200":{"description":"List of webhooks"}}},"post":{"summary":"Create webhook","tags":["Webhooks"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookCreate"}}}},"responses":{"201":{"description":"Webhook created"}}}},"/keys":{"get":{"summary":"List API keys","tags":["Authentication"],"responses":{"200":{"description":"List of API keys"}}},"post":{"summary":"Create API key","tags":["Authentication"],"responses":{"201":{"description":"API key created"}}},"put":{"summary":"Bootstrap API key","description":"Create initial admin key (only works if no keys exist)","tags":["Authentication"],"security":[],"responses":{"201":{"description":"Bootstrap key created"},"403":{"description":"Keys already exist"}}}},"/ingest":{"post":{"summary":"Legacy protected document URL ingest","description":"Legacy protected document-ingest endpoint. Public OpenContent archive ingestion is available at /content/ingest.","tags":["Documents"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["url"],"properties":{"url":{"type":"string","format":"uri","description":"URL to ingest"},"category":{"type":"string","description":"Category slug"},"tags":{"type":"array","items":{"type":"string"}},"auto_publish":{"type":"boolean","default":false},"target_audience":{"type":"string"}}}}}},"responses":{"201":{"description":"Content ingested successfully"},"400":{"description":"Invalid URL or fetch error"}}}},"/network":{"get":{"summary":"Get network status","description":"Get MCP network status and node configuration","tags":["Network"],"security":[],"parameters":[{"name":"action","in":"query","schema":{"type":"string","enum":["graph","discover"]}},{"name":"type","in":"query","schema":{"type":"string"},"description":"Service type filter"}],"responses":{"200":{"description":"Network status"}}},"post":{"summary":"Network actions","description":"Register with network, send heartbeat, or score documents","tags":["Network"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["action"],"properties":{"action":{"type":"string","enum":["register","heartbeat","score-documents","score-sources","call-mcp"]},"slugs":{"type":"array","items":{"type":"string"}},"identifiers":{"type":"array","items":{"type":"string"}},"endpoint":{"type":"string"},"tool":{"type":"string"},"params":{"type":"object"}}}}}},"responses":{"200":{"description":"Action completed"}}}},"/scores":{"get":{"summary":"Get document/source scores","description":"Get quality scores for documents or sources","tags":["Scoring"],"security":[],"parameters":[{"name":"type","in":"query","schema":{"type":"string","enum":["document","source","documents","sources","top"]}},{"name":"slug","in":"query","schema":{"type":"string"}},{"name":"source","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","maximum":100}}],"responses":{"200":{"description":"Score data"}}},"post":{"summary":"Batch score items","description":"Score multiple documents or sources","tags":["Scoring"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["type"],"properties":{"type":{"type":"string","enum":["documents","sources","external-documents","external-sources"]},"slugs":{"type":"array","items":{"type":"string"}},"identifiers":{"type":"array","items":{"type":"string"}}}}}}},"responses":{"200":{"description":"Scores calculated"}}}},"/api/web/status":{"get":{"summary":"Get Web Status","description":"Public-safe Web Status response for OpenContent route, discovery, metric, MCP, and attribution readiness. Counts include source labels and degraded states.","tags":["Web Status"],"security":[],"responses":{"200":{"description":"Web Status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebStatus"}}}}}}},"/api/web/scorecard":{"get":{"summary":"Get Web Status scorecard","description":"Public-safe Web Status scorecard generated from readiness and compliance state.","tags":["Web Status"],"security":[],"responses":{"200":{"description":"Web Status scorecard"}}}},"/api/web/manifest":{"get":{"summary":"Get Web manifest","description":"Public-safe manifest of Web Status APIs, discovery routes, MCP registry names, and auth boundary.","tags":["Web Status"],"security":[],"responses":{"200":{"description":"Web manifest"}}}},"/api/web/fingerprints":{"get":{"summary":"Get public-safe Web fingerprints","description":"Public-safe SHA-256 fingerprints for Web Status, manifest, route evidence, metrics, and MCP manifest. Never includes auth tokens, raw IPs, cookies, session IDs, or raw headers.","tags":["Web Status"],"security":[],"responses":{"200":{"description":"Public-safe Web fingerprints"}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"Use PLATPHORM_API_KEY as Authorization: Bearer $PLATPHORM_API_KEY. X-PlatPhorm-API-Key is also accepted by protected endpoints."},"platphormApiKey":{"type":"apiKey","in":"header","name":"X-PlatPhorm-API-Key","description":"PLATPHORM_API_KEY header form for protected platform actions."}},"schemas":{"ContentCreate":{"type":"object","required":["title","content"],"properties":{"title":{"type":"string"},"description":{"type":"string"},"content":{"type":"string"},"category":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"sourceUrl":{"type":"string","format":"uri"},"authorName":{"type":"string"},"authorEmail":{"type":"string","format":"email"},"targetAudience":{"type":"string"}}},"DocumentCreate":{"type":"object","required":["title","content"],"properties":{"slug":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"content":{"type":"string"},"content_format":{"type":"string","enum":["markdown","html","text"]},"source_url":{"type":"string","format":"uri"},"source_identifier":{"type":"string"},"author_name":{"type":"string"},"author_email":{"type":"string","format":"email"},"category":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"status":{"type":"string","enum":["draft","published"]}}},"DocumentUpdate":{"type":"object","properties":{"title":{"type":"string"},"description":{"type":"string"},"content":{"type":"string"},"status":{"type":"string","enum":["draft","published","archived"]}}},"DocumentList":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"array","items":{"type":"object"}},"meta":{"type":"object"}}},"SubmissionCreate":{"type":"object","required":["source_url","title","content"],"properties":{"source_url":{"type":"string","format":"uri"},"source_identifier":{"type":"string"},"title":{"type":"string"},"content":{"type":"string"},"author_name":{"type":"string"},"author_email":{"type":"string","format":"email"}}},"SubmissionReview":{"type":"object","required":["action"],"properties":{"action":{"type":"string","enum":["approve","reject"]},"slug":{"type":"string"},"category":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"publish_immediately":{"type":"boolean"},"reason":{"type":"string"}}},"CategoryCreate":{"type":"object","required":["slug","name"],"properties":{"slug":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"parent_id":{"type":"string","format":"uuid"},"icon":{"type":"string"},"order_index":{"type":"integer"}}},"WebhookCreate":{"type":"object","required":["url"],"properties":{"url":{"type":"string","format":"uri"},"events":{"type":"array","items":{"type":"string"}},"active":{"type":"boolean"}}},"WebStatus":{"type":"object","required":["schemaVersion","site","service","generatedAt","storage","readiness","counts","metrics","webReadiness","webCompliance","webScorecard","warnings","errors"],"properties":{"schemaVersion":{"type":"string","const":"web.status.v1"},"site":{"type":"string","format":"uri"},"service":{"type":"string","const":"OpenContent"},"generatedAt":{"type":"string","format":"date-time"},"storage":{"type":"object","properties":{"databaseRequired":{"type":"boolean","const":false},"mode":{"type":"string","enum":["configured_live_database","generated_snapshot","degraded_snapshot"]},"degraded":{"type":"boolean"}}},"readiness":{"type":"object","additionalProperties":{"type":"string","enum":["pass","partial","degraded","fail"]}},"counts":{"type":"object","additionalProperties":{"type":"number"}},"metrics":{"type":"object","additionalProperties":{"type":"object","required":["key","label","value","source","sourceUrl","generatedAt","fetchedAt","state","traceId"],"properties":{"key":{"type":"string"},"label":{"type":"string"},"value":{"type":"number"},"source":{"type":"string"},"sourceUrl":{"type":["string","null"],"format":"uri"},"generatedAt":{"type":"string","format":"date-time"},"fetchedAt":{"type":["string","null"],"format":"date-time"},"state":{"type":"string","enum":["live","cached","generated","degraded","sample"]},"traceId":{"type":["string","null"]}}}},"warnings":{"type":"array","items":{"type":"string"}},"errors":{"type":"array","items":{"type":"string"}}}}}},"tags":[{"name":"Documents","description":"Document management"},{"name":"Submissions","description":"Content submissions from external sources"},{"name":"Search","description":"Full-text search"},{"name":"Categories","description":"Category management"},{"name":"Webhooks","description":"Webhook management"},{"name":"Authentication","description":"API key management"},{"name":"Content","description":"Content ingestion, archive, URL preview, and processing"},{"name":"Metadata","description":"Post-creation SEO/AEO/social metadata, share links, and share-card regeneration"},{"name":"Network","description":"MCP network and service discovery"},{"name":"Scoring","description":"Document and source scoring"},{"name":"Web Status","description":"Public-safe Web Status, scorecard, manifest, and fingerprints"}]}