{"openapi":"3.1.0","info":{"title":"CloudYali Public API","summary":"Public, unauthenticated endpoints published by the CloudYali website.","description":"CloudYali is a FinOps platform for cloud cost visibility and management across AWS, Azure and GCP.\n\nThis document describes the public, unauthenticated endpoints served by www.cloudyali.io.\nThey let agents and integrations discover what CloudYali does, read published content,\nand submit a demo request without scraping HTML.\n\nAll responses are JSON. Successful responses use the envelope `{ \"success\": true, \"data\": ... }`.\nErrors use `{ \"success\": false, \"error\": { \"code\", \"message\", \"hint\", \"documentation_url\", \"request_id\" } }`\nand the `code` field is stable and safe to branch on.\n\nNo authentication is required for any operation in this document. Rate limits are not currently enforced.\nThe authenticated CloudYali platform API used by the console is documented separately at https://docs.cloudyali.io.","version":"1.0.0","termsOfService":"https://www.cloudyali.io/terms-of-service","contact":{"name":"CloudYali Support","email":"support@cloudyali.io","url":"https://www.cloudyali.io/developers"},"license":{"name":"CloudYali API Terms","url":"https://www.cloudyali.io/terms-of-service"}},"servers":[{"url":"https://www.cloudyali.io","description":"CloudYali production website"}],"externalDocs":{"description":"CloudYali developer resources","url":"https://www.cloudyali.io/developers"},"tags":[{"name":"Discovery","description":"Endpoint discovery and service health."},{"name":"Product","description":"CloudYali product capability catalog."},{"name":"Content","description":"Published CloudYali blog content."},{"name":"Sales","description":"Demo requests and sales contact."}],"paths":{"/api":{"get":{"operationId":"getApiIndex","summary":"List available CloudYali public API endpoints","description":"Returns a discovery document listing every public endpoint, the URL of this OpenAPI specification, and links to CloudYali developer resources. Call this first when exploring the API.","tags":["Discovery"],"security":[],"responses":{"200":{"description":"Discovery document.","content":{"application/json":{"schema":{"type":"object","title":"ApiIndexResponse","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","required":["service","openapi_url","endpoints"],"properties":{"service":{"type":"string"},"description":{"type":"string"},"documentation_url":{"type":"string","format":"uri"},"openapi_url":{"type":"string","format":"uri"},"llms_txt_url":{"type":"string","format":"uri"},"endpoints":{"type":"array","items":{"type":"object","required":["method","path","operation_id","description"],"properties":{"method":{"type":"string","enum":["GET","POST"]},"path":{"type":"string"},"operation_id":{"type":"string"},"description":{"type":"string"}}}}}}}}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/health":{"get":{"operationId":"getServiceHealth","summary":"Check CloudYali website API health","description":"Returns the liveness status of the CloudYali public website API. Use this to verify connectivity before issuing other calls. Always returns HTTP 200 when the service is reachable.","tags":["Discovery"],"security":[],"responses":{"200":{"description":"Service is healthy.","content":{"application/json":{"schema":{"type":"object","title":"HealthResponse","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","required":["status","service","version","timestamp"],"properties":{"status":{"type":"string","enum":["ok"]},"service":{"type":"string"},"version":{"type":"string"},"timestamp":{"type":"string","format":"date-time"}}}}}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/features":{"get":{"operationId":"listProductFeatures","summary":"List CloudYali product capabilities","description":"Returns the full catalog of CloudYali FinOps capabilities — cost visibility, cost savings, budget management, asset inventory, tag governance, AI cost tracking and integrations — including which cloud providers each capability covers. Use this to answer questions about what CloudYali does.","tags":["Product"],"security":[],"responses":{"200":{"description":"Product capability catalog.","content":{"application/json":{"schema":{"type":"object","title":"FeatureListResponse","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","required":["features","count"],"properties":{"count":{"type":"integer","minimum":0},"features":{"type":"array","items":{"$ref":"#/components/schemas/Feature"}}}}}}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/blogs":{"get":{"operationId":"listBlogPosts","summary":"List published CloudYali blog posts","description":"Returns a paginated list of published CloudYali blog posts about FinOps and cloud cost management, newest first. Each item includes a canonical URL and a markdown URL suitable for agent ingestion.","tags":["Content"],"security":[],"parameters":[{"name":"limit","in":"query","required":false,"description":"Maximum number of posts to return.","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}},{"name":"offset","in":"query","required":false,"description":"Number of posts to skip, for pagination.","schema":{"type":"integer","minimum":0,"maximum":10000,"default":0}},{"name":"category","in":"query","required":false,"description":"Filter to a single category slug, for example `finops`.","schema":{"type":"string","pattern":"^[a-z0-9-]{1,120}$"}}],"responses":{"200":{"description":"Paginated list of blog posts.","content":{"application/json":{"schema":{"type":"object","title":"BlogListResponse","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","required":["posts","total","limit","offset"],"properties":{"total":{"type":"integer","minimum":0,"description":"Total posts matching the filter, ignoring pagination."},"limit":{"type":"integer"},"offset":{"type":"integer"},"posts":{"type":"array","items":{"$ref":"#/components/schemas/BlogPostSummary"}}}}}}}}},"400":{"description":"Malformed request — invalid JSON body or query parameter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"An upstream dependency of this endpoint failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/blogs/{slug}":{"get":{"operationId":"getBlogPostBySlug","summary":"Retrieve one CloudYali blog post","description":"Returns a single published blog post by its slug, including the full body rendered as Markdown. Use `listBlogPosts` to discover valid slugs.","tags":["Content"],"security":[],"parameters":[{"name":"slug","in":"path","required":true,"description":"URL-safe identifier of the post, as returned by `listBlogPosts`.","schema":{"type":"string","pattern":"^[a-z0-9-]{1,200}$"}}],"responses":{"200":{"description":"The requested blog post.","content":{"application/json":{"schema":{"type":"object","title":"BlogDetailResponse","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/BlogPostDetail"}}}}}},"400":{"description":"Malformed request — invalid JSON body or query parameter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"The requested resource does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"An upstream dependency of this endpoint failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/demo-request":{"get":{"operationId":"getDemoRequestStatus","summary":"Check the demo request endpoint","description":"Returns the availability and version of the demo request endpoint without submitting anything.","tags":["Sales"],"security":[],"responses":{"200":{"description":"Endpoint is available.","content":{"application/json":{"schema":{"type":"object","title":"DemoRequestStatusResponse","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","required":["status","version"],"properties":{"status":{"type":"string","enum":["ok"]},"version":{"type":"string"},"message":{"type":"string"}}}}}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"submitDemoRequest","summary":"Submit a CloudYali demo request","description":"Submits a request for a CloudYali product demo. All listed fields are required. Returns a confirmation id on success. This creates a sales lead — only call it on explicit instruction from a real person who wants to be contacted.","tags":["Sales"],"security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DemoRequest"}}}},"responses":{"200":{"description":"Demo request accepted.","content":{"application/json":{"schema":{"type":"object","title":"DemoRequestResponse","required":["success","message"],"properties":{"success":{"type":"boolean","enum":[true]},"message":{"type":"string"},"data":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string","format":"email"}}}}}}}},"400":{"description":"Malformed request — invalid JSON body or query parameter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Request was well-formed but failed field validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"An upstream dependency of this endpoint failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}}},"components":{"securitySchemes":{},"schemas":{"ErrorResponse":{"type":"object","title":"ErrorResponse","description":"Structured error envelope returned by every CloudYali public endpoint. Never HTML.","required":["success","error"],"additionalProperties":false,"properties":{"success":{"type":"boolean","enum":[false],"description":"Always false on an error response."},"error":{"type":"object","required":["code","message","hint","documentation_url","request_id"],"properties":{"code":{"type":"string","enum":["bad_request","validation_error","invalid_json","not_found","method_not_allowed","rate_limited","upstream_error","configuration_error","internal_error"],"description":"Stable machine-readable error code. Safe to branch on."},"message":{"type":"string","description":"Human-readable description of what went wrong."},"hint":{"type":"string","description":"Suggested resolution step for the caller."},"details":{"description":"Optional machine-readable context, such as the offending field."},"documentation_url":{"type":"string","format":"uri","description":"Where to read more about this endpoint."},"request_id":{"type":"string","description":"Correlation id for this request. Include it in support tickets."}}}}},"Feature":{"type":"object","title":"Feature","required":["id","name","summary","capabilities","providers","url"],"properties":{"id":{"type":"string","enum":["cost-visibility","cost-savings","budget-management","asset-inventory","tag-governance","ai-cost-tracking","integrations"],"description":"Stable feature identifier, matching the feature page slug."},"name":{"type":"string","description":"Human-readable capability name."},"summary":{"type":"string","description":"One-sentence description of the capability."},"capabilities":{"type":"array","items":{"type":"string"},"description":"Concrete things this capability lets a team do."},"providers":{"type":"array","items":{"type":"string"},"description":"Cloud providers and services this capability covers."},"url":{"type":"string","format":"uri","description":"Canonical feature page URL."}}},"BlogPostSummary":{"type":"object","title":"BlogPostSummary","required":["slug","title","url"],"properties":{"slug":{"type":"string","description":"URL-safe unique identifier for the post."},"title":{"type":"string","description":"Post title."},"excerpt":{"type":"string","description":"Short summary of the post."},"url":{"type":"string","format":"uri","description":"Canonical URL of the post."},"markdown_url":{"type":"string","format":"uri","description":"Plain-markdown rendering of the post, for agent consumption."},"published_at":{"type":"string","format":"date-time","description":"ISO 8601 publication timestamp."},"reading_time_minutes":{"type":"integer","minimum":0},"author":{"type":"string","description":"Author display name."},"categories":{"type":"array","items":{"type":"string"}},"tags":{"type":"array","items":{"type":"string"}}}},"BlogPostDetail":{"allOf":[{"$ref":"#/components/schemas/BlogPostSummary"},{"type":"object","title":"BlogPostDetail","properties":{"body_markdown":{"type":"string","description":"Full post body rendered as Markdown."}}}]},"DemoRequest":{"type":"object","title":"DemoRequest","description":"Fields required to request a CloudYali product demo.","required":["firstName","lastName","businessEmail","companyName","jobTitle","cloudBill","howDidYouHear"],"properties":{"firstName":{"type":"string","minLength":1,"description":"Requester first name."},"lastName":{"type":"string","minLength":1,"description":"Requester last name."},"businessEmail":{"type":"string","format":"email","description":"Business email address to send the demo invitation to."},"companyName":{"type":"string","minLength":1,"description":"Company name."},"jobTitle":{"type":"string","minLength":1,"description":"Requester job title."},"cloudBill":{"type":"string","minLength":1,"description":"Approximate annual cloud spend band, for example \"$100k - $500k\"."},"howDidYouHear":{"type":"string","minLength":1,"description":"How the requester heard about CloudYali."}}}}},"security":[]}