---
"openapi": "3.1.0"
"info":
  "title": "Curiosive API"
  "version": "1.0.0"
  "summary": "Read-only access to everything published on curiosive.com."
  "description": "Curiosive is an AI-native software studio and long-term engineering partner, building web products, mobile apps, AI experiences and browser extensions with senior engineers reviewing every line.\n\nEvery endpoint is public, read-only and unauthenticated, except the cache\npurge endpoint, which is used by the publishing pipeline.\n\nErrors always return JSON in the shape described by the Error schema:\na stable `code`, a human-readable `message`, a `hint` describing what to\ndo instead, and a link back to this document.\n\nEvery HTML page on the site is also available as Markdown, either by\nsending `Accept: text/markdown` to the page URL or by prefixing the path\nwith `/md` (for example https://curiosive.com/md/blog).\n\n## Versioning\n\n- The stable base path is /api/v1. Pin it.\n- The unversioned /api/... paths are an alias for the current major and may move when a new one ships.\n- Within a major, fields are only ever added; nothing is removed or retyped.\n- A breaking change ships as /api/v2 while /api/v1 keeps answering.\n- An endpoint that is going away answers with Deprecation and Sunset headers for at least 6 months first, and a Link header pointing at its replacement.\n\nThe full policy, with worked examples, is at https://curiosive.com/developers."
  "contact":
    "name": "Curiosive"
    "email": "hello@curiosive.com"
    "url": "https://curiosive.com"
  "license":
    "name": "Content is copyright Curiosive; the API may be used freely by agents."
    "identifier": "LicenseRef-Curiosive-Content"
"servers":
  - "url": "https://curiosive.com"
    "description": "Production"
"security": []
"externalDocs":
  "description": "llms.txt"
  "url": "https://curiosive.com/llms.txt"
"tags":
  - "name": "Studio"
    "description": "Who the studio is, what it sells and what it has shipped."
  - "name": "Content"
    "description": "Articles and landing pages published from the CMS."
  - "name": "Documents"
    "description": "Machine-readable files describing the site."
  - "name": "Operations"
    "description": "Endpoints used by the publishing pipeline."
"paths":
  "/api":
    "get":
      "tags":
        - "Documents"
      "operationId": "getApiIndex"
      "summary": "Curiosive API index: versions, endpoints and where the docs are"
      "description": "The entry point for an agent that knows only the origin. Lists the supported versions, the base path to pin, and every document describing this API."
      "responses":
        "200":
          "description": "The API index."
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/ApiIndex"
  "/api/v1/site":
    "get":
      "tags":
        - "Studio"
      "operationId": "getSite"
      "summary": "Studio profile, services, pricing and machine-readable entry points"
      "parameters":
        - "name": "locale"
          "in": "query"
          "required": false
          "description": "Language of the content. Defaults to \"en\"."
          "schema":
            "type": "string"
            "enum":
              - "en"
              - "tr"
            "default": "en"
      "responses":
        "200":
          "description": "The studio profile."
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/Site"
        "400":
          "description": "A query parameter was not valid."
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/Error"
        "405":
          "description": "The HTTP method is not supported by this endpoint."
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/Error"
  "/api/v1/projects":
    "get":
      "tags":
        - "Studio"
      "operationId": "listProjects"
      "summary": "Products the studio has shipped that are live today"
      "parameters":
        - "name": "limit"
          "in": "query"
          "required": false
          "description": "Maximum number of items to return."
          "schema":
            "type": "integer"
            "minimum": 1
            "maximum": 100
            "default": 100
      "responses":
        "200":
          "description": "Products in production."
          "content":
            "application/json":
              "schema":
                "type": "object"
                "required":
                  - "count"
                  - "projects"
                "properties":
                  "count":
                    "type": "integer"
                  "projects":
                    "type": "array"
                    "items":
                      "$ref": "#/components/schemas/Project"
        "400":
          "description": "A query parameter was not valid."
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/Error"
        "405":
          "description": "The HTTP method is not supported by this endpoint."
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/Error"
  "/api/v1/posts":
    "get":
      "tags":
        - "Content"
      "operationId": "listPosts"
      "summary": "Published articles, newest first"
      "parameters":
        - "name": "locale"
          "in": "query"
          "required": false
          "description": "Language of the content. Defaults to \"en\"."
          "schema":
            "type": "string"
            "enum":
              - "en"
              - "tr"
            "default": "en"
        - "name": "limit"
          "in": "query"
          "required": false
          "description": "Maximum number of items to return."
          "schema":
            "type": "integer"
            "minimum": 1
            "maximum": 100
            "default": 100
      "responses":
        "200":
          "description": "Articles available in the requested language."
          "content":
            "application/json":
              "schema":
                "type": "object"
                "required":
                  - "count"
                  - "locale"
                  - "posts"
                "properties":
                  "count":
                    "type": "integer"
                  "locale":
                    "type": "string"
                    "enum":
                      - "en"
                      - "tr"
                  "posts":
                    "type": "array"
                    "items":
                      "$ref": "#/components/schemas/PostSummary"
        "400":
          "description": "A query parameter was not valid."
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/Error"
        "405":
          "description": "The HTTP method is not supported by this endpoint."
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/Error"
  "/api/v1/posts/{slug}":
    "get":
      "tags":
        - "Content"
      "operationId": "getPost"
      "summary": "One article, including its full body as Markdown"
      "parameters":
        - "name": "slug"
          "in": "path"
          "required": true
          "description": "Slug of the article, as listed by /api/v1/posts."
          "schema":
            "type": "string"
        - "name": "locale"
          "in": "query"
          "required": false
          "description": "Language of the content. Defaults to \"en\"."
          "schema":
            "type": "string"
            "enum":
              - "en"
              - "tr"
            "default": "en"
      "responses":
        "200":
          "description": "The article."
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/Post"
        "400":
          "description": "A query parameter was not valid."
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/Error"
        "404":
          "description": "No article exists with that slug in that language."
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/Error"
        "405":
          "description": "The HTTP method is not supported by this endpoint."
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/Error"
  "/api/v1/pages":
    "get":
      "tags":
        - "Content"
      "operationId": "listPages"
      "summary": "Landing pages describing services, technologies and locations"
      "parameters":
        - "name": "locale"
          "in": "query"
          "required": false
          "description": "Language of the content. Defaults to \"en\"."
          "schema":
            "type": "string"
            "enum":
              - "en"
              - "tr"
            "default": "en"
        - "name": "limit"
          "in": "query"
          "required": false
          "description": "Maximum number of items to return."
          "schema":
            "type": "integer"
            "minimum": 1
            "maximum": 100
            "default": 100
      "responses":
        "200":
          "description": "Landing pages."
          "content":
            "application/json":
              "schema":
                "type": "object"
                "required":
                  - "count"
                  - "locale"
                  - "pages"
                "properties":
                  "count":
                    "type": "integer"
                  "locale":
                    "type": "string"
                    "enum":
                      - "en"
                      - "tr"
                  "pages":
                    "type": "array"
                    "items":
                      "$ref": "#/components/schemas/PageSummary"
        "400":
          "description": "A query parameter was not valid."
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/Error"
        "405":
          "description": "The HTTP method is not supported by this endpoint."
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/Error"
  "/api/v1/pages/{slug}":
    "get":
      "tags":
        - "Content"
      "operationId": "getPage"
      "summary": "One landing page with its sections and FAQ"
      "parameters":
        - "name": "slug"
          "in": "path"
          "required": true
          "description": "Slug of the page, as listed by /api/v1/pages."
          "schema":
            "type": "string"
        - "name": "locale"
          "in": "query"
          "required": false
          "description": "Language of the content. Defaults to \"en\"."
          "schema":
            "type": "string"
            "enum":
              - "en"
              - "tr"
            "default": "en"
      "responses":
        "200":
          "description": "The landing page."
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/Page"
        "400":
          "description": "A query parameter was not valid."
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/Error"
        "404":
          "description": "No landing page exists with that slug in that language."
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/Error"
        "405":
          "description": "The HTTP method is not supported by this endpoint."
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/Error"
  "/api/v1/revalidate":
    "post":
      "tags":
        - "Operations"
      "operationId": "revalidate"
      "summary": "Purge the CMS query cache"
      "description": "Used by the publishing pipeline so a newly published article is reachable immediately instead of waiting out the cache window."
      "security":
        - "bearerAuth": []
      "responses":
        "200":
          "description": "The cache was purged."
          "content":
            "application/json":
              "schema":
                "type": "object"
                "required":
                  - "revalidated"
                  - "at"
                "properties":
                  "revalidated":
                    "type": "string"
                  "at":
                    "type": "string"
                    "format": "date-time"
        "401":
          "description": "The bearer token was missing or wrong."
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/Error"
        "405":
          "description": "The HTTP method is not supported by this endpoint."
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/Error"
        "500":
          "description": "The server has no revalidation secret configured."
          "content":
            "application/json":
              "schema":
                "$ref": "#/components/schemas/Error"
  "/md/{path}":
    "get":
      "tags":
        - "Documents"
      "operationId": "getMarkdown"
      "summary": "Any page of the site rendered as Markdown"
      "description": "The same document is returned from the canonical URL when the request sends `Accept: text/markdown`. Unknown paths return 404 with a Markdown body listing where to look instead."
      "parameters":
        - "name": "path"
          "in": "path"
          "required": true
          "description": "Site path without the leading slash. Use \".\" for the homepage."
          "schema":
            "type": "string"
          "examples":
            "homepage":
              "value": ""
            "article":
              "value": "blog/code-review-is-the-real-bottleneck"
            "turkish":
              "value": "tr/cozumler"
      "responses":
        "200":
          "description": "The page as Markdown."
          "content":
            "text/markdown":
              "schema":
                "type": "string"
        "404":
          "description": "No such page. The body lists the site's entry points."
          "content":
            "text/markdown":
              "schema":
                "type": "string"
  "/llms.txt":
    "get":
      "tags":
        - "Documents"
      "operationId": "getLlmsTxt"
      "summary": "The whole site summarised for a language model (llmstxt.org)"
      "responses":
        "200":
          "description": "The llms.txt document."
          "content":
            "text/plain":
              "schema":
                "type": "string"
  "/sitemap.xml":
    "get":
      "tags":
        - "Documents"
      "operationId": "getSitemap"
      "summary": "Every indexable URL, in both languages"
      "responses":
        "200":
          "description": "A urlset sitemap."
          "content":
            "application/xml":
              "schema":
                "type": "string"
  "/feed.xml":
    "get":
      "tags":
        - "Documents"
      "operationId": "getFeed"
      "summary": "RSS feed of the English articles"
      "responses":
        "200":
          "description": "An RSS 2.0 feed."
          "content":
            "application/rss+xml":
              "schema":
                "type": "string"
  "/developers":
    "get":
      "tags":
        - "Documents"
      "operationId": "getDeveloperPortal"
      "summary": "Curiosive developer portal: quickstart, authentication and the versioning policy"
      "description": "Human-readable documentation. Send `Accept: text/markdown` for the same page as Markdown."
      "responses":
        "200":
          "description": "The developer portal."
          "content":
            "text/html":
              "schema":
                "type": "string"
            "text/markdown":
              "schema":
                "type": "string"
  "/openapi.json":
    "get":
      "tags":
        - "Documents"
      "operationId": "getOpenApiJson"
      "summary": "This document"
      "responses":
        "200":
          "description": "The OpenAPI document."
          "content":
            "application/json":
              "schema":
                "type": "object"
  "/openapi.yaml":
    "get":
      "tags":
        - "Documents"
      "operationId": "getOpenApiYaml"
      "summary": "This document, as YAML"
      "responses":
        "200":
          "description": "The OpenAPI document."
          "content":
            "application/yaml":
              "schema":
                "type": "string"
"components":
  "securitySchemes":
    "bearerAuth":
      "type": "http"
      "scheme": "bearer"
      "description": "Shared secret held by the publishing pipeline."
  "schemas":
    "Error":
      "type": "object"
      "required":
        - "error"
      "description": "The body of every failing request."
      "properties":
        "error":
          "type": "object"
          "required":
            - "code"
            - "status"
            - "message"
            - "hint"
            - "documentation"
          "properties":
            "code":
              "type": "string"
              "description": "Stable machine-readable identifier for the failure."
              "enum":
                - "bad_request"
                - "invalid_parameter"
                - "unauthorized"
                - "not_found"
                - "method_not_allowed"
                - "not_acceptable"
                - "server_error"
            "status":
              "type": "integer"
              "description": "The HTTP status code."
            "message":
              "type": "string"
              "description": "What went wrong, in a sentence."
            "hint":
              "type": "string"
              "description": "What to do instead."
            "documentation":
              "type": "string"
              "format": "uri"
    "ApiIndex":
      "type": "object"
      "required":
        - "name"
        - "version"
        - "basePath"
        - "endpoints"
        - "documentation"
      "properties":
        "name":
          "type": "string"
        "description":
          "type": "string"
        "version":
          "type": "string"
          "description": "Current major, as \"v1\"."
        "basePath":
          "type": "string"
          "description": "The path to pin."
        "versioning":
          "type": "object"
          "description": "How this API is versioned and how deprecation is signalled."
          "properties":
            "scheme":
              "type": "string"
              "enum":
                - "url-path"
            "current":
              "type": "string"
            "supported":
              "type": "array"
              "items":
                "type": "string"
            "deprecated":
              "type": "array"
              "items":
                "type": "string"
            "sunsetNoticeMonths":
              "type": "integer"
            "policy":
              "type": "array"
              "items":
                "type": "string"
            "documentation":
              "type": "string"
              "format": "uri"
        "endpoints":
          "type": "array"
          "items":
            "type": "object"
            "required":
              - "method"
              - "path"
              - "summary"
            "properties":
              "method":
                "type": "string"
              "path":
                "type": "string"
              "summary":
                "type": "string"
        "documentation":
          "type": "object"
          "additionalProperties":
            "type": "string"
            "format": "uri"
    "Site":
      "type": "object"
      "required":
        - "name"
        - "url"
        - "description"
        - "services"
        - "pricing"
      "properties":
        "name":
          "type": "string"
        "url":
          "type": "string"
          "format": "uri"
        "tagline":
          "type": "string"
        "description":
          "type": "string"
        "email":
          "type": "string"
          "format": "email"
        "location":
          "type": "string"
        "locale":
          "type": "string"
          "enum":
            - "en"
            - "tr"
        "founder":
          "type": "object"
          "properties":
            "name":
              "type": "string"
            "url":
              "type": "string"
              "format": "uri"
        "services":
          "type": "array"
          "items":
            "type": "object"
            "required":
              - "id"
              - "title"
              - "description"
            "properties":
              "id":
                "type": "string"
              "title":
                "type": "string"
              "description":
                "type": "string"
              "stack":
                "type": "array"
                "items":
                  "type": "string"
        "pricing":
          "type": "array"
          "items":
            "type": "object"
            "required":
              - "id"
              - "name"
              - "from"
            "properties":
              "id":
                "type": "string"
              "name":
                "type": "string"
              "from":
                "type": "string"
                "description": "Starting price, in USD."
              "unit":
                "type": "string"
              "description":
                "type": "string"
              "includes":
                "type": "array"
                "items":
                  "type": "string"
        "stack":
          "type": "array"
          "items":
            "type": "string"
        "documents":
          "type": "object"
          "description": "Machine-readable entry points for this site."
          "additionalProperties":
            "type": "string"
            "format": "uri"
    "Project":
      "type": "object"
      "required":
        - "id"
        - "title"
      "properties":
        "id":
          "type": "string"
        "slug":
          "type": "string"
        "title":
          "type": "string"
        "tagline":
          "type": "string"
        "url":
          "type":
            - "string"
            - "null"
          "format": "uri"
        "technologies":
          "type": "array"
          "items":
            "type": "string"
        "country":
          "type":
            - "string"
            - "null"
    "PostSummary":
      "type": "object"
      "required":
        - "slug"
        - "title"
        - "url"
      "properties":
        "slug":
          "type": "string"
        "title":
          "type": "string"
        "excerpt":
          "type": "string"
        "url":
          "type": "string"
          "format": "uri"
        "markdownUrl":
          "type": "string"
          "format": "uri"
        "tags":
          "type": "array"
          "items":
            "type": "string"
        "author":
          "type": "string"
        "publishedAt":
          "type": "string"
          "format": "date-time"
        "updatedAt":
          "type":
            - "string"
            - "null"
          "format": "date-time"
        "readingMinutes":
          "type": "integer"
    "Post":
      "allOf":
        - "$ref": "#/components/schemas/PostSummary"
        - "type": "object"
          "required":
            - "body"
          "properties":
            "body":
              "type": "string"
              "description": "The full article, as Markdown."
            "faq":
              "type": "array"
              "items":
                "type": "object"
                "properties":
                  "question":
                    "type": "string"
                  "answer":
                    "type": "string"
    "PageSummary":
      "type": "object"
      "required":
        - "slug"
        - "title"
        - "url"
      "properties":
        "slug":
          "type": "string"
        "kind":
          "type": "string"
          "enum":
            - "service"
            - "technology"
            - "comparison"
            - "city"
        "title":
          "type": "string"
        "description":
          "type": "string"
        "url":
          "type": "string"
          "format": "uri"
        "markdownUrl":
          "type": "string"
          "format": "uri"
    "Page":
      "allOf":
        - "$ref": "#/components/schemas/PageSummary"
        - "type": "object"
          "properties":
            "intro":
              "type": "array"
              "items":
                "type": "string"
            "sections":
              "type": "array"
              "items":
                "type": "object"
                "properties":
                  "heading":
                    "type": "string"
                  "body":
                    "type": "string"
            "faq":
              "type": "array"
              "items":
                "type": "object"
                "properties":
                  "question":
                    "type": "string"
                  "answer":
                    "type": "string"
            "technologies":
              "type": "array"
              "items":
                "type": "string"
            "related":
              "type": "array"
              "items":
                "$ref": "#/components/schemas/PageSummary"
