{"openapi":"3.1.0","info":{"title":"PlatPhorm Podcasts API","description":"Free podcast streaming API with sentiment analysis, webhooks, and automation features. Provides AI-powered discovery tools and dynamic endpoints. Part of the PlatPhorm News Network.","version":"1.0.0","contact":{"name":"PlatPhorm Support","email":"support@platphormnews.com","url":"https://platphormnews.com/support"},"license":{"name":"MIT","url":"https://opensource.org/licenses/MIT"},"x-crypto":"0x30589F2e1B8E9a48BBb2c66Ac012FE7ED2A7eB85"},"servers":[{"url":"https://podcasts.platphormnews.com","description":"Production"},{"url":"http://localhost:3000","description":"Development"}],"tags":[{"name":"Health","description":"Service health and status"},{"name":"Podcasts","description":"Podcast discovery and management"},{"name":"Community","description":"Community contributions and leaderboard"},{"name":"Sentiment","description":"AI-powered sentiment analysis"},{"name":"Events","description":"Event sourcing and outbox pattern"},{"name":"Webhooks","description":"Webhook management and delivery"},{"name":"Jobs","description":"Background job queue"},{"name":"Audit","description":"Audit logging and compliance"}],"paths":{"/api/health":{"get":{"tags":["Health"],"summary":"Health check","operationId":"getHealth","responses":{"200":{"description":"Service is healthy","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthResponse"}}}}}}},"/api/v1/podcasts":{"get":{"tags":["Podcasts"],"summary":"List podcasts","operationId":"listPodcasts","parameters":[{"name":"category","in":"query","schema":{"type":"string"},"description":"Filter by category"},{"name":"limit","in":"query","schema":{"type":"integer","default":20,"maximum":100},"description":"Items per page"},{"name":"offset","in":"query","schema":{"type":"integer","default":0},"description":"Pagination offset"}],"responses":{"200":{"description":"List of podcasts","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PodcastListResponse"}}}}}}},"/api/v1/ingest":{"post":{"tags":["Podcasts"],"summary":"Ingest podcast from URL","operationId":"ingestPodcast","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","format":"uri","description":"Podcast URL, RSS feed, or platform link"}},"required":["url"]}}}},"responses":{"200":{"description":"Podcast ingested successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IngestResponse"}}}},"400":{"description":"Invalid URL"},"404":{"description":"Podcast not found"}}}},"/api/v1/categories":{"get":{"tags":["Podcasts"],"summary":"List podcast categories","operationId":"listCategories","responses":{"200":{"description":"List of categories","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CategoryListResponse"}}}}}}},"/api/v1/sentiment":{"post":{"tags":["Sentiment"],"summary":"Analyze sentiment","operationId":"analyzeSentiment","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"text":{"type":"string"}},"required":["text"]}}}},"responses":{"200":{"description":"Sentiment analysis","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SentimentResponse"}}}}}}},"/api/v1/trending":{"get":{"tags":["Podcasts"],"summary":"Get trending podcasts","operationId":"getTrending","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","default":5,"maximum":20}}],"responses":{"200":{"description":"Trending podcasts","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PodcastListResponse"}}}}}}},"/api/v1/events":{"get":{"tags":["Events"],"summary":"List events (outbox pattern)","operationId":"listEvents","parameters":[{"name":"event_type","in":"query","schema":{"type":"string"},"description":"Filter by event type"},{"name":"aggregate_type","in":"query","schema":{"type":"string"},"description":"Filter by aggregate type"},{"name":"published","in":"query","schema":{"type":"boolean"},"description":"Filter by published status"},{"name":"limit","in":"query","schema":{"type":"integer","default":50,"maximum":100}},{"name":"offset","in":"query","schema":{"type":"integer","default":0}}],"responses":{"200":{"description":"List of events","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventListResponse"}}}}}},"post":{"tags":["Events"],"summary":"Create event","operationId":"createEvent","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"event_type":{"type":"string"},"aggregate_type":{"type":"string"},"aggregate_id":{"type":"string"},"payload":{"type":"object"}},"required":["event_type","aggregate_type","aggregate_id","payload"]}}}},"responses":{"201":{"description":"Event created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Event"}}}}}}},"/api/v1/webhooks":{"get":{"tags":["Webhooks"],"summary":"List webhook endpoints","operationId":"listWebhookEndpoints","responses":{"200":{"description":"List of webhook endpoints","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointListResponse"}}}}}},"post":{"tags":["Webhooks"],"summary":"Receive incoming webhook","operationId":"receiveWebhook","parameters":[{"name":"x-webhook-signature","in":"header","schema":{"type":"string"},"description":"HMAC signature"},{"name":"x-webhook-event","in":"header","schema":{"type":"string"},"description":"Event type"},{"name":"idempotency-key","in":"header","schema":{"type":"string"},"description":"Idempotency key for deduplication"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"Webhook received","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookReceiptResponse"}}}}}}},"/api/v1/jobs":{"get":{"tags":["Jobs"],"summary":"List background jobs","operationId":"listJobs","parameters":[{"name":"queue","in":"query","schema":{"type":"string"},"description":"Filter by queue"},{"name":"status","in":"query","schema":{"type":"string","enum":["pending","running","completed","failed","cancelled"]}},{"name":"limit","in":"query","schema":{"type":"integer","default":50,"maximum":100}},{"name":"offset","in":"query","schema":{"type":"integer","default":0}}],"responses":{"200":{"description":"List of jobs","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobListResponse"}}}}}},"post":{"tags":["Jobs"],"summary":"Create background job","operationId":"createJob","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"queue":{"type":"string","default":"default"},"name":{"type":"string"},"payload":{"type":"object"},"priority":{"type":"integer","default":0},"run_at":{"type":"string","format":"date-time"}},"required":["name","payload"]}}}},"responses":{"201":{"description":"Job created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"}}}}}}},"/api/v1/audit":{"get":{"tags":["Audit"],"summary":"List audit logs","operationId":"listAuditLogs","parameters":[{"name":"action","in":"query","schema":{"type":"string"},"description":"Filter by action"},{"name":"resource_type","in":"query","schema":{"type":"string"},"description":"Filter by resource type"},{"name":"user_id","in":"query","schema":{"type":"string","format":"uuid"},"description":"Filter by user"},{"name":"limit","in":"query","schema":{"type":"integer","default":50,"maximum":100}},{"name":"offset","in":"query","schema":{"type":"integer","default":0}}],"responses":{"200":{"description":"List of audit logs","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuditLogListResponse"}}}}}}},"/api/v1/leaderboard":{"get":{"tags":["Community"],"summary":"Get submission leaderboard","operationId":"getLeaderboard","description":"Returns top contributors ranked by approved submissions and helpful ratings","parameters":[{"name":"period","in":"query","schema":{"type":"string","enum":["all","week","month"],"default":"all"},"description":"Time period filter"},{"name":"limit","in":"query","schema":{"type":"integer","default":10,"maximum":100},"description":"Number of results"},{"name":"offset","in":"query","schema":{"type":"integer","default":0},"description":"Pagination offset"}],"responses":{"200":{"description":"Leaderboard data","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LeaderboardResponse"}}}}}}},"/api/v1/community":{"get":{"tags":["Community"],"summary":"List community-submitted podcasts","operationId":"listCommunityPodcasts","parameters":[{"name":"category","in":"query","schema":{"type":"string"},"description":"Filter by category"},{"name":"sort","in":"query","schema":{"type":"string","enum":["recent","popular","rating"],"default":"recent"}},{"name":"limit","in":"query","schema":{"type":"integer","default":50,"maximum":100}},{"name":"offset","in":"query","schema":{"type":"integer","default":0}}],"responses":{"200":{"description":"Community podcasts","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PodcastListResponse"}}}}}}},"/api/v1/submissions":{"get":{"tags":["Community"],"summary":"List podcast submissions","operationId":"listSubmissions","parameters":[{"name":"user_id","in":"query","schema":{"type":"string","format":"uuid"},"description":"Filter by submitter"},{"name":"status","in":"query","schema":{"type":"string","enum":["pending","approved","rejected","needs_review"]}},{"name":"limit","in":"query","schema":{"type":"integer","default":20,"maximum":100}},{"name":"offset","in":"query","schema":{"type":"integer","default":0}}],"responses":{"200":{"description":"List of submissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubmissionListResponse"}}}}}},"post":{"tags":["Community"],"summary":"Submit a podcast for review","operationId":"createSubmission","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"podcast_url":{"type":"string","format":"uri","description":"URL of the podcast to submit"},"title":{"type":"string","description":"Optional title override"},"description":{"type":"string","description":"Optional description"},"category":{"type":"string","description":"Podcast category"},"user_id":{"type":"string","format":"uuid","description":"Submitter user ID"}},"required":["podcast_url"]}}}},"responses":{"201":{"description":"Submission created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubmissionResponse"}}}},"409":{"description":"Podcast already submitted"}}},"patch":{"tags":["Community"],"summary":"Update submission status (admin)","operationId":"updateSubmission","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"submission_id":{"type":"string"},"status":{"type":"string","enum":["pending","approved","rejected","needs_review"]},"reviewer_notes":{"type":"string"}},"required":["submission_id","status"]}}}},"responses":{"200":{"description":"Submission updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubmissionResponse"}}}}}}},"/api/v1/webhooks/deliver":{"get":{"tags":["Webhooks"],"summary":"Get webhook delivery history","operationId":"getDeliveryHistory","parameters":[{"name":"endpoint_id","in":"query","schema":{"type":"string"},"description":"Filter by endpoint"},{"name":"status","in":"query","schema":{"type":"string","enum":["pending","delivered","failed"]}},{"name":"limit","in":"query","schema":{"type":"integer","default":50,"maximum":100}},{"name":"offset","in":"query","schema":{"type":"integer","default":0}}],"responses":{"200":{"description":"Delivery history","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeliveryListResponse"}}}}}},"post":{"tags":["Webhooks"],"summary":"Deliver webhook to endpoint","operationId":"deliverWebhook","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"endpoint_id":{"type":"string"},"event_type":{"type":"string"},"payload":{"type":"object"},"event_id":{"type":"string","format":"uuid"}},"required":["endpoint_id","event_type","payload"]}}}},"responses":{"200":{"description":"Delivery result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeliveryResponse"}}}}}}}},"components":{"schemas":{"HealthResponse":{"type":"object","properties":{"status":{"type":"string","enum":["healthy"]},"service":{"type":"string"},"version":{"type":"string"},"timestamp":{"type":"string","format":"date-time"},"dependencies":{"type":"object"}}},"Podcast":{"type":"object","properties":{"id":{"type":"string"},"slug":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"author":{"type":"string"},"image_url":{"type":"string","format":"uri"},"feed_url":{"type":"string","format":"uri"},"category":{"type":"string"},"sentiment":{"type":"string","enum":["positive","negative","neutral","excited","calm"]},"episode_count":{"type":"integer"},"created_at":{"type":"string","format":"date-time"}}},"Episode":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"audio_url":{"type":"string","format":"uri"},"duration":{"type":"string"},"duration_seconds":{"type":"integer"},"published_at":{"type":"string","format":"date-time"}}},"Category":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"slug":{"type":"string"},"name":{"type":"string"},"icon":{"type":"string"},"color":{"type":"string"},"podcast_count":{"type":"integer"}}},"Event":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"event_type":{"type":"string"},"aggregate_type":{"type":"string"},"aggregate_id":{"type":"string"},"payload":{"type":"object"},"published":{"type":"boolean"},"published_at":{"type":"string","format":"date-time","nullable":true},"created_at":{"type":"string","format":"date-time"}}},"Job":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"queue":{"type":"string"},"name":{"type":"string"},"status":{"type":"string","enum":["pending","running","completed","failed","cancelled"]},"priority":{"type":"integer"},"attempts":{"type":"integer"},"max_attempts":{"type":"integer"},"run_at":{"type":"string","format":"date-time"},"started_at":{"type":"string","format":"date-time","nullable":true},"completed_at":{"type":"string","format":"date-time","nullable":true},"error":{"type":"string","nullable":true},"created_at":{"type":"string","format":"date-time"}}},"AuditLog":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"action":{"type":"string"},"resource_type":{"type":"string"},"resource_id":{"type":"string"},"user_id":{"type":"string","format":"uuid","nullable":true},"ip_address":{"type":"string"},"user_agent":{"type":"string"},"request_id":{"type":"string"},"created_at":{"type":"string","format":"date-time"}}},"SentimentResponse":{"type":"object","properties":{"sentiment":{"type":"string","enum":["positive","negative","neutral","excited","calm"]},"confidence":{"type":"number","minimum":0,"maximum":1},"keywords":{"type":"array","items":{"type":"string"}}}},"IngestResponse":{"type":"object","properties":{"success":{"type":"boolean"},"podcast":{"$ref":"#/components/schemas/Podcast"},"episodes":{"type":"array","items":{"$ref":"#/components/schemas/Episode"}},"spotifyFallback":{"type":"boolean"}}},"WebhookReceiptResponse":{"type":"object","properties":{"success":{"type":"boolean"},"event_id":{"type":"string","format":"uuid"},"delivery_id":{"type":"string"},"idempotent":{"type":"boolean"},"latency_ms":{"type":"integer"}}},"PodcastListResponse":{"type":"object","properties":{"success":{"type":"boolean"},"podcasts":{"type":"array","items":{"$ref":"#/components/schemas/Podcast"}},"pagination":{"$ref":"#/components/schemas/Pagination"}}},"CategoryListResponse":{"type":"object","properties":{"success":{"type":"boolean"},"categories":{"type":"array","items":{"$ref":"#/components/schemas/Category"}}}},"EventListResponse":{"type":"object","properties":{"success":{"type":"boolean"},"events":{"type":"array","items":{"$ref":"#/components/schemas/Event"}},"pagination":{"$ref":"#/components/schemas/Pagination"}}},"JobListResponse":{"type":"object","properties":{"success":{"type":"boolean"},"jobs":{"type":"array","items":{"$ref":"#/components/schemas/Job"}},"pagination":{"$ref":"#/components/schemas/Pagination"}}},"AuditLogListResponse":{"type":"object","properties":{"success":{"type":"boolean"},"logs":{"type":"array","items":{"$ref":"#/components/schemas/AuditLog"}},"pagination":{"$ref":"#/components/schemas/Pagination"}}},"WebhookEndpointListResponse":{"type":"object","properties":{"success":{"type":"boolean"},"endpoints":{"type":"array","items":{"type":"object"}},"count":{"type":"integer"}}},"Pagination":{"type":"object","properties":{"total":{"type":"integer"},"limit":{"type":"integer"},"offset":{"type":"integer"},"has_more":{"type":"boolean"}}},"LeaderboardEntry":{"type":"object","properties":{"user_id":{"type":"string","format":"uuid"},"username":{"type":"string"},"submission_count":{"type":"integer"},"helpful_count":{"type":"integer"},"rank":{"type":"integer"}}},"LeaderboardResponse":{"type":"object","properties":{"success":{"type":"boolean"},"leaderboard":{"type":"array","items":{"$ref":"#/components/schemas/LeaderboardEntry"}},"pagination":{"$ref":"#/components/schemas/Pagination"},"period":{"type":"string","enum":["all","week","month"]},"source":{"type":"string","enum":["database","fallback"]}}},"Submission":{"type":"object","properties":{"id":{"type":"string"},"user_id":{"type":"string","format":"uuid","nullable":true},"podcast_url":{"type":"string","format":"uri"},"title":{"type":"string","nullable":true},"description":{"type":"string","nullable":true},"category":{"type":"string"},"status":{"type":"string","enum":["pending","approved","rejected","needs_review"]},"helpful_count":{"type":"integer"},"reviewer_notes":{"type":"string","nullable":true},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"SubmissionResponse":{"type":"object","properties":{"success":{"type":"boolean"},"submission":{"$ref":"#/components/schemas/Submission"},"message":{"type":"string"}}},"SubmissionListResponse":{"type":"object","properties":{"success":{"type":"boolean"},"submissions":{"type":"array","items":{"$ref":"#/components/schemas/Submission"}},"pagination":{"$ref":"#/components/schemas/Pagination"}}},"WebhookDelivery":{"type":"object","properties":{"id":{"type":"string"},"endpoint_id":{"type":"string"},"event_type":{"type":"string"},"status":{"type":"string","enum":["pending","delivered","failed"]},"status_code":{"type":"integer","nullable":true},"attempt":{"type":"integer"},"max_attempts":{"type":"integer"},"latency_ms":{"type":"integer","nullable":true},"delivered_at":{"type":"string","format":"date-time","nullable":true},"created_at":{"type":"string","format":"date-time"}}},"DeliveryResponse":{"type":"object","properties":{"success":{"type":"boolean"},"delivery_id":{"type":"string"},"status":{"type":"string","enum":["delivered","failed"]},"status_code":{"type":"integer"},"latency_ms":{"type":"integer"},"will_retry":{"type":"boolean"}}},"DeliveryListResponse":{"type":"object","properties":{"success":{"type":"boolean"},"deliveries":{"type":"array","items":{"$ref":"#/components/schemas/WebhookDelivery"}},"pagination":{"$ref":"#/components/schemas/Pagination"}}}},"securitySchemes":{"apiKey":{"type":"apiKey","in":"header","name":"X-API-Key","description":"Optional API key for authenticated requests"},"tenantId":{"type":"apiKey","in":"header","name":"X-Tenant-ID","description":"Tenant identifier for multi-tenant requests"}}}}