{"openapi":"3.0.3","info":{"title":"OrigamiFlow Public API","version":"1.0.0","description":"Public API for the OrigamiFlow architecture management platform.\n\n## Versioning\nREST endpoints use `/v1/` URL path versioning. The current stable version is **v1**.\nDeprecated endpoints include `Deprecation: true` and `Sunset: <date>` response headers.\nPrevious API versions are supported for a minimum of 12 months after a new version is released.\n\n## Rate Limits\n60 requests per 60-second window per IP. Standard `RateLimit-*` headers are returned on all responses.\nHTTP 429 includes a `Retry-After` header.\n\n## Errors\nAll errors return `application/json` with `{ error, code, hint }` schema.\n\n## AI Agents\n- LLMs.txt: https://www.origamiflow.com.br/llms.txt\n- Full context: https://www.origamiflow.com.br/llms-full.txt\n- Sitemap: https://www.origamiflow.com.br/sitemap.xml","contact":{"name":"OrigamiFlow Support","email":"suporte@origamiflow.com.br","url":"https://www.origamiflow.com.br/developers"},"x-deprecation-policy":"Minimum 12 months notice via Deprecation + Sunset headers","x-llms-txt":"https://www.origamiflow.com.br/llms.txt","x-rate-limit":"60 req/60s per IP — RFC RateLimit headers on all responses"},"servers":[{"url":"https://www.origamiflow.com.br","description":"Production (v1)"}],"tags":[{"name":"blog","description":"Blog content endpoints (v1)"},{"name":"system","description":"System status and health"},{"name":"meta","description":"Machine-readable metadata files"}],"paths":{"/api/v1/blog":{"get":{"operationId":"listBlogPostsV1","tags":["blog"],"summary":"List published blog posts","description":"Returns a paginated list of published architecture blog posts. Sorted by publish date descending.","parameters":[{"name":"page","in":"query","schema":{"type":"integer","minimum":1,"default":1},"description":"Page number (1-based)"},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":20},"description":"Items per page (max 100)"}],"responses":{"200":{"description":"Paginated list of blog posts","headers":{"RateLimit-Limit":{"schema":{"type":"integer"},"description":"Max requests per window"},"RateLimit-Policy":{"schema":{"type":"string"},"description":"Rate limit policy (RFC draft-ietf-httpapi-ratelimit-headers)"},"Retry-After":{"schema":{"type":"integer"},"description":"Seconds to wait before retrying (on 429 only)"}},"content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/BlogPost"}},"meta":{"$ref":"#/components/schemas/BlogListMeta"}}}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Service unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/blog/{slug}":{"get":{"operationId":"getBlogPostV1","tags":["blog"],"summary":"Get a single blog post by slug","description":"Returns full content of a published blog post. Includes rich content blocks.","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"},"example":"como-fazer-rrt-cau-guia-pratico","description":"URL-safe slug (find valid slugs via /api/v1/blog or /sitemap.xml)"}],"responses":{"200":{"description":"Blog post","headers":{"RateLimit-Limit":{"schema":{"type":"integer"},"description":"Max requests per window"},"RateLimit-Policy":{"schema":{"type":"string"},"description":"Rate limit policy (RFC draft-ietf-httpapi-ratelimit-headers)"},"Retry-After":{"schema":{"type":"integer"},"description":"Seconds to wait before retrying (on 429 only)"}},"content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/BlogPost"}}}}}},"400":{"description":"Bad request — missing or invalid slug","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Post not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/health":{"get":{"operationId":"getHealth","tags":["system"],"summary":"System health check","description":"Returns platform health status, service availability, and response latency. Returns HTTP 503 if any service is degraded.","responses":{"200":{"description":"System healthy","headers":{"RateLimit-Limit":{"schema":{"type":"integer"},"description":"Max requests per window"},"RateLimit-Policy":{"schema":{"type":"string"},"description":"Rate limit policy (RFC draft-ietf-httpapi-ratelimit-headers)"},"Retry-After":{"schema":{"type":"integer"},"description":"Seconds to wait before retrying (on 429 only)"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Health"}}}},"503":{"description":"System degraded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Health"}}}}}}},"/sitemap.xml":{"get":{"operationId":"getSitemap","tags":["meta"],"summary":"XML sitemap","description":"XML sitemap listing all indexable URLs with lastmod and priority. 90 URLs including blog posts.","responses":{"200":{"description":"XML sitemap","content":{"application/xml":{"schema":{"type":"string"}}}}}}},"/robots.txt":{"get":{"operationId":"getRobots","tags":["meta"],"summary":"robots.txt","description":"Crawl rules for 14 named AI agent groups (GPTBot, Google-Extended, ClaudeBot, PerplexityBot, DeepSeekBot, etc.). All AI agents are explicitly allowed.","responses":{"200":{"description":"robots.txt","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/llms.txt":{"get":{"operationId":"getLlmsTxt","tags":["meta"],"summary":"LLM instruction file (llms.txt spec)","description":"Machine-readable description of OrigamiFlow for AI agents. Includes when-to-use guidance, feature list, pricing table, blog index, and agent instructions. Conforms to the llms.txt specification.","responses":{"200":{"description":"LLMs.txt","headers":{"Vary":{"schema":{"type":"string"},"description":"Accept, Accept-Encoding"}},"content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/llms-full.txt":{"get":{"operationId":"getLlmsFullTxt","tags":["meta"],"summary":"Full LLM context file","description":"All published blog post content in markdown for bulk AI ingestion. Served when Accept: text/markdown is sent to homepage or /blog.","responses":{"200":{"description":"Full LLMs context","headers":{"Vary":{"schema":{"type":"string"},"description":"Accept, Accept-Encoding"}},"content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/openapi.json":{"get":{"operationId":"getOpenApiSpec","tags":["meta"],"summary":"This OpenAPI 3.0 specification","description":"Machine-readable OpenAPI spec for all public OrigamiFlow endpoints. Use for function calling, API discovery, and agent integration.","responses":{"200":{"description":"OpenAPI 3.0 spec","content":{"application/json":{"schema":{"type":"object"}}}}}}}},"components":{"schemas":{"BlogPost":{"type":"object","required":["slug","title","url","publishedAt"],"properties":{"slug":{"type":"string","example":"como-fazer-rrt-cau-guia-pratico"},"title":{"type":"string","example":"Como fazer RRT no CAU — Guia Prático"},"excerpt":{"type":"string","nullable":true,"example":"Aprenda como fazer o RRT no CAU em 2025."},"url":{"type":"string","format":"uri","example":"https://www.origamiflow.com.br/blog/como-fazer-rrt-cau-guia-pratico"},"publishedAt":{"type":"string","format":"date-time","example":"2025-01-01T00:00:00Z"},"updatedAt":{"type":"string","format":"date-time","nullable":true},"tags":{"type":"array","items":{"type":"string"},"example":["rrt","cau","arquitetura"]},"coverImage":{"type":"string","format":"uri","nullable":true},"author":{"type":"string","example":"OrigamiFlow"},"readingTime":{"type":"string","nullable":true,"example":"5 min"},"content":{"type":"object","nullable":true,"description":"Rich content blocks (only on single-post endpoint)"}}},"BlogListMeta":{"type":"object","required":["total","page","limit","pages","hasNextPage","hasPrevPage"],"properties":{"total":{"type":"integer","example":84},"page":{"type":"integer","example":1},"limit":{"type":"integer","example":20},"pages":{"type":"integer","example":5},"hasNextPage":{"type":"boolean"},"hasPrevPage":{"type":"boolean"}}},"Error":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human-readable error message","example":"Post not found"},"code":{"type":"string","description":"Machine-readable error code","example":"NOT_FOUND","enum":["NOT_FOUND","MISSING_PARAM","DATABASE_ERROR","SERVICE_UNAVAILABLE","UNAUTHORIZED","FORBIDDEN"]},"hint":{"type":"string","description":"Suggested resolution","example":"Check /api/v1/blog for valid slugs"}}},"Health":{"type":"object","required":["status","version","timestamp"],"properties":{"status":{"type":"string","enum":["ok","degraded"],"example":"ok"},"version":{"type":"string","example":"1.0.0"},"timestamp":{"type":"string","format":"date-time"},"latencyMs":{"type":"integer","example":12},"services":{"type":"object","properties":{"database":{"type":"string","enum":["ok","degraded","unavailable"]},"api":{"type":"string","enum":["ok","degraded"]}}}}}}}}