{"openapi":"3.1.0","info":{"title":"Pain Spotter Public API","version":"1.0.0","description":"Programmatic, read-only access to AI-scored business opportunities mined from Reddit, Hacker News, Product Hunt, Stack Exchange and other open communities. Authenticate with an API key (X-API-Key header or ?api_key= query). Quotas: Free 20 / Pro 1,000 / Business 5,000 calls per month (resets 1st of each month UTC). Get a key at https://painspotter.ai/account.","contact":{"email":"paininsight40@outlook.com"},"termsOfService":"https://painspotter.ai/terms"},"servers":[{"url":"https://painspotter.ai","description":"Production"}],"externalDocs":{"description":"Human-readable API docs","url":"https://painspotter.ai/api-docs"},"security":[{"ApiKeyHeader":[]},{"ApiKeyQuery":[]}],"paths":{"/api/v1/opportunities":{"get":{"operationId":"listOpportunities","tags":["opportunities"],"summary":"List opportunities with filters and pagination","parameters":[{"name":"platform","in":"query","required":false,"schema":{"type":"string"},"description":"reddit | hackernews | producthunt | stackexchange | …"},{"name":"channel","in":"query","required":false,"schema":{"type":"string"},"description":"Channel / subreddit name (case-sensitive)."},{"name":"q","in":"query","required":false,"schema":{"type":"string","maxLength":100},"description":"Keyword search across title + description."},{"name":"min_score","in":"query","required":false,"schema":{"type":"integer","minimum":0,"maximum":100,"default":0}},{"name":"recommendation","in":"query","required":false,"schema":{"type":"string","enum":["Build","Validate","Skip"]}},{"name":"online_only","in":"query","required":false,"schema":{"type":"boolean","default":true},"description":"Only ideas shippable as software / SaaS."},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":20}}],"responses":{"200":{"description":"Paginated list of opportunities.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpportunityListResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"422":{"description":"Invalid query parameter."},"429":{"$ref":"#/components/responses/QuotaExceeded"}}}},"/api/v1/opportunities/{id}":{"get":{"operationId":"getOpportunity","tags":["opportunities"],"summary":"Get full opportunity detail","description":"404s do NOT count against your quota.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Full opportunity detail.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpportunityDetail"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"description":"Opportunity not found (not counted against quota)."},"429":{"$ref":"#/components/responses/QuotaExceeded"}}}},"/api/v1/blog":{"get":{"operationId":"listBlogPosts","tags":["blog"],"summary":"List published blog analyses","description":"Free tier — any valid key. Each article is an original AI synthesis (no verbatim community quotes).","parameters":[{"name":"q","in":"query","required":false,"schema":{"type":"string","maxLength":100},"description":"Keyword search across title + excerpt."},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":20}}],"responses":{"200":{"description":"Paginated list of published articles.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BlogListResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/QuotaExceeded"}}}},"/api/v1/blog/{slug}":{"get":{"operationId":"getBlogPost","tags":["blog"],"summary":"Get a published article (incl. raw Markdown body)","description":"404s do NOT count against your quota. `body_md` is the article in clean Markdown, ideal for ingestion / citation.","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Full article incl. body_md.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BlogPost"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"description":"Article not found (not counted against quota)."},"429":{"$ref":"#/components/responses/QuotaExceeded"}}}}},"components":{"securitySchemes":{"ApiKeyHeader":{"type":"apiKey","in":"header","name":"X-API-Key"},"ApiKeyQuery":{"type":"apiKey","in":"query","name":"api_key"}},"responses":{"Unauthorized":{"description":"Missing or invalid API key."},"QuotaExceeded":{"description":"Monthly quota exceeded.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"quota_exceeded"},"current":{"type":"integer","example":1000},"limit":{"type":"integer","example":1000},"reset_at":{"type":"string","format":"date-time"}}}}}}},"schemas":{"OpportunityListItem":{"type":"object","properties":{"id":{"type":"integer","example":7301},"platform":{"type":"string","example":"reddit","description":"Source platform: reddit | hackernews | producthunt | stackexchange | …"},"channel_name":{"type":"string","example":"SaaS"},"title":{"type":"string","description":"LLM-rewritten title (not the original post headline)."},"slug":{"type":"string","example":"llm-firewall-proxy-api"},"recommendation":{"type":"string","enum":["Build","Validate","Skip"]},"score":{"type":"integer","minimum":0,"maximum":100,"description":"0–100 composite opportunity score."},"pain_point_intensity":{"type":"integer","minimum":0,"maximum":10},"willingness_to_pay_score":{"type":"integer","minimum":0,"maximum":10},"tech_difficulty":{"type":"integer","minimum":0,"maximum":10},"sustainability_score":{"type":"integer","minimum":0,"maximum":10},"target_audience":{"type":"string"},"monetization_model":{"type":"string"},"evidence_count":{"type":"integer"},"merged_from_count":{"type":"integer"},"is_online_deliverable":{"type":"boolean"},"created_at":{"type":"string","format":"date-time"}}},"OpportunityDetail":{"type":"object","description":"List item fields plus long-form detail-only fields.","properties":{"id":{"type":"integer","example":7301},"platform":{"type":"string","example":"reddit","description":"Source platform: reddit | hackernews | producthunt | stackexchange | …"},"channel_name":{"type":"string","example":"SaaS"},"title":{"type":"string","description":"LLM-rewritten title (not the original post headline)."},"slug":{"type":"string","example":"llm-firewall-proxy-api"},"recommendation":{"type":"string","enum":["Build","Validate","Skip"]},"score":{"type":"integer","minimum":0,"maximum":100,"description":"0–100 composite opportunity score."},"pain_point_intensity":{"type":"integer","minimum":0,"maximum":10},"willingness_to_pay_score":{"type":"integer","minimum":0,"maximum":10},"tech_difficulty":{"type":"integer","minimum":0,"maximum":10},"sustainability_score":{"type":"integer","minimum":0,"maximum":10},"target_audience":{"type":"string"},"monetization_model":{"type":"string"},"evidence_count":{"type":"integer"},"merged_from_count":{"type":"integer"},"is_online_deliverable":{"type":"boolean"},"created_at":{"type":"string","format":"date-time"},"description":{"type":"string","description":"Long-form pain narrative."},"market_size_estimate":{"type":"string"},"key_features":{"type":"array","items":{"type":"string"}},"competitors":{"type":"array","items":{"type":"string"}},"differentiation":{"type":"string"},"risks":{"type":"array","items":{"type":"string"}},"related_article_url":{"type":"string","nullable":true,"description":"URL of the published blog analysis for this opportunity, if one exists."}}},"OpportunityListResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/OpportunityListItem"}},"total":{"type":"integer"},"page":{"type":"integer"},"page_size":{"type":"integer"}}},"BlogListItem":{"type":"object","properties":{"slug":{"type":"string","example":"aeo-analytics-the-new-stack-for-ai-search-visibility-9824"},"title":{"type":"string"},"excerpt":{"type":"string"},"cover_image_url":{"type":"string","nullable":true},"tags":{"type":"array","items":{"type":"string"}},"url":{"type":"string","description":"Canonical public URL of the article."},"related_opportunity_id":{"type":"integer","nullable":true},"published_at":{"type":"string","format":"date-time","nullable":true}}},"BlogPost":{"type":"object","description":"List item fields plus the full Markdown body.","properties":{"slug":{"type":"string"},"title":{"type":"string"},"excerpt":{"type":"string"},"body_md":{"type":"string","description":"Article body in clean Markdown."},"cover_image_url":{"type":"string","nullable":true},"tags":{"type":"array","items":{"type":"string"}},"url":{"type":"string"},"related_opportunity_id":{"type":"integer","nullable":true},"published_at":{"type":"string","format":"date-time","nullable":true},"updated_at":{"type":"string","format":"date-time","nullable":true}}},"BlogListResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/BlogListItem"}},"total":{"type":"integer"},"page":{"type":"integer"},"page_size":{"type":"integer"}}}}}}