{"openapi":"3.1.0","info":{"title":"OpenDocs API","version":"1.0.0","description":"Canonical public documentation, clipping, ingestion, source attribution, auto-tagging, search, formatting, submission, metadata, and AI-readable knowledge layer for the PlatPhormNews web mesh.","contact":{"name":"OpenDocs","url":"https://docs.platphormnews.com"}},"servers":[{"url":"https://docs.platphormnews.com/api/v1","description":"Production"}],"security":[{"bearerAuth":[]},{"platphormApiKey":[]}],"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"}}}},"/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":"Protected operator key bootstrap. Platform auth examples use PLATPHORM_API_KEY only.","tags":["Authentication"],"responses":{"201":{"description":"Bootstrap key created"},"403":{"description":"Keys already exist"}}}},"/ingest":{"post":{"summary":"Ingest URL","description":"Fetch and ingest content from an external URL","tags":["Content"],"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"}}}},"/clip/preview":{"post":{"summary":"Preview public clip","description":"Public-safe preview for web pages, platform posts, Reddit URLs, public Google Drive/Docs links, Dropbox links, image URLs, feeds, JSON, Markdown, HTML, or pasted text. The route is SSRF-guarded, bounded, and does not persist documents.","tags":["Clipping"],"security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClipPreviewRequest"}}}},"responses":{"200":{"description":"Clip preview","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClipPreviewResponse"}}}},"400":{"description":"Invalid source or unsupported input"}}}},"/clip/commit":{"post":{"summary":"Commit public clip","description":"Submit a cleaned clip preview for review without an API key. Persisting a clip directly as a protected document requires PLATPHORM_API_KEY and mode=document.","tags":["Clipping"],"security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClipCommitRequest"}}}},"responses":{"201":{"description":"Clip committed as a pending submission or protected draft document"},"401":{"description":"PLATPHORM_API_KEY required for mode=document"},"503":{"description":"Server persistence unavailable; use local draft/export fallback"}}}},"/clip/platform-post":{"post":{"summary":"Preview platform post clip","description":"Public-safe clipping preview optimized for PlatPhormNews public posts and pages.","tags":["Clipping"],"security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClipPreviewRequest"}}}},"responses":{"200":{"description":"Platform post clip preview"}}}},"/clip/reddit":{"post":{"summary":"Preview Reddit clip","description":"Public Reddit post/comment preview without Reddit auth. Returns an honest degraded preview if Reddit blocks or hides the content.","tags":["Clipping"],"security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClipPreviewRequest"}}}},"responses":{"200":{"description":"Reddit clip preview or degraded status"}}}},"/clip/google-drive":{"post":{"summary":"Preview public Google Drive or Docs clip","description":"Public-link only Google Drive/Docs preview. Permission-denied or login-required links degrade honestly.","tags":["Clipping"],"security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClipPreviewRequest"}}}},"responses":{"200":{"description":"Google Drive/Docs clip preview or degraded status"}}}},"/clip/dropbox":{"post":{"summary":"Preview public Dropbox clip","description":"Public Dropbox shared-link preview with bounded download conversion and degraded permission handling.","tags":["Clipping"],"security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClipPreviewRequest"}}}},"responses":{"200":{"description":"Dropbox clip preview or degraded status"}}}},"/clip/image":{"post":{"summary":"Preview public image clip","description":"Public image URL preview with MIME and size checks, manual alt text support, attribution, and OCR/AI alt-text degraded status unless a backend provider is configured.","tags":["Clipping"],"security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClipPreviewRequest"}}}},"responses":{"200":{"description":"Image clip preview or degraded status"}}}},"/clip/paste":{"post":{"summary":"Preview pasted content clip","description":"Public-safe paste cleanup for text, Markdown, or HTML without network fetches.","tags":["Clipping"],"security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClipPreviewRequest"}}}},"responses":{"200":{"description":"Paste clip preview"}}}},"/sources":{"get":{"summary":"List public sources","description":"Aggregate public source inventory from published documentation. Returns degraded empty state if persistence is unavailable.","tags":["Sources"],"security":[],"responses":{"200":{"description":"Public source inventory"}}}},"/sources/{id}":{"get":{"summary":"Get public source","description":"Get public-safe source attribution details and linked published documents for a source identifier.","tags":["Sources"],"security":[],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Public source details"},"404":{"description":"Source not found"}}}},"/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"}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"PLATPHORM_API_KEY","description":"Use Authorization: Bearer $PLATPHORM_API_KEY for protected Docs operations."},"platphormApiKey":{"type":"apiKey","in":"header","name":"X-PlatPhorm-API-Key","description":"Alternative protected request header containing $PLATPHORM_API_KEY."}},"schemas":{"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"}}},"ClipPreviewRequest":{"type":"object","properties":{"url":{"type":"string","format":"uri","description":"Public URL to clip. SSRF-guarded and size-limited."},"content":{"type":"string","description":"Pasted plain text content."},"markdown":{"type":"string","description":"Pasted Markdown content."},"html":{"type":"string","description":"Pasted HTML content to clean."},"title":{"type":"string"},"sourceType":{"type":"string","enum":["webpage","platform_post","reddit","google_drive","google_docs","dropbox","image","paste","markdown","html","feed","json","text"]},"altText":{"type":"string","description":"Manual alt text for image clips."},"caption":{"type":"string","description":"Manual caption for image clips."}}},"ClipPreviewResponse":{"type":"object","properties":{"ok":{"type":"boolean"},"data":{"type":"object","properties":{"id":{"type":"string"},"sourceType":{"type":"string"},"status":{"type":"string","enum":["ready","degraded","unsupported"]},"title":{"type":"string"},"summary":{"type":"string"},"cleanedMarkdown":{"type":"string"},"attribution":{"type":"object"},"tags":{"type":"array","items":{"type":"object"}},"trace":{"type":"object"}}}}},"ClipCommitRequest":{"type":"object","required":["title","cleanedMarkdown"],"properties":{"mode":{"type":"string","enum":["submission","document"],"default":"submission"},"title":{"type":"string"},"cleanedMarkdown":{"type":"string"},"summary":{"type":"string"},"canonicalUrl":{"type":"string","format":"uri"},"sourceType":{"type":"string"},"category":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"attribution":{"type":"object"}}}}},"tags":[{"name":"Documents","description":"Document management"},{"name":"Submissions","description":"Content submissions from external sources"},{"name":"Clipping","description":"Public-safe clipping previews, formatting cleanup, source attribution, and clip commit"},{"name":"Search","description":"Full-text search"},{"name":"Categories","description":"Category management"},{"name":"Sources","description":"Public source attribution inventory"},{"name":"Webhooks","description":"Webhook management"},{"name":"Authentication","description":"API key management"},{"name":"Content","description":"Content ingestion and processing"},{"name":"Network","description":"MCP network and service discovery"},{"name":"Scoring","description":"Document and source scoring"}],"x-platphorm":{"service":"docs","purpose":"Canonical public documentation, clipping, ingestion, source attribution, auto-tagging, search, formatting, submission, metadata, and AI-readable knowledge layer for the PlatPhormNews web mesh.","auth":{"environmentVariable":"PLATPHORM_API_KEY","acceptedHeaders":["Authorization: Bearer $PLATPHORM_API_KEY","X-PlatPhorm-API-Key: $PLATPHORM_API_KEY"]},"routeStandard":["/api/health","/api/v1/health","/api/docs","/openapi.yaml","/openapi.json","/llms.txt","/llms-full.txt","/llms-index.json","/robots.txt","/sitemap.xml","/sitemap-main.xml","/sitemap-index.xml","/rss.xml","/feed.xml","/manifest.webmanifest","/faq","/.well-known/mcp.json","/.well-known/agents.json","/.well-known/ai-plugin.json","/.well-known/security.txt","/.well-known/trust.json","/api/mcp"],"mcp":{"endpoint":"https://docs.platphormnews.com/api/mcp","tools":["list_documents","get_document","create_document","update_document","delete_document","search","list_categories","get_related_docs","submit_content","ingest_url","clip_preview","clip_commit","clip_platform_post","clip_reddit","clip_google_drive","clip_dropbox","clip_image","clip_paste","clean_ingested_content","generate_source_attribution","suggest_tags","get_emoji","add_emoji_to_doc","bulk_import","regenerate_seo","generate_optimization","export_docs","get_stats","trigger_webhook","list_integrations","call_integration","parse_markdown","generate_share_links","search_docs","list_tags","list_project_docs","get_project_doc","trigger_automation","get_automation_status"],"resources":["project-docs://{slug}","docs://index","docs://categories","docs://recent","docs://popular","docs://tags","docs://sources","docs://submissions","docs://clips","docs://stats","docs://sitemap","docs://llms","docs://openapi","docs://trust-policy"],"prompts":["explain_doc","summarize_category","compare_docs","generate_faq","translate_doc","improve_seo","clean_ingested_content","clip_public_source","create_source_attribution","suggest_document_tags"]}}}