{
  "openapi": "3.0.3",
  "info": {
    "title": "Kugie public machine API",
    "version": "1.0.0",
    "description": "Machine-readable surface of kugie.app. This is a marketing and docs site for Kugie, a Jakarta software house (legal name PT Semesta Solusi Digital). Everything here is public and read-only except the four /api/qualify endpoints, which back the hire form at /contact/work. Those are same-origin only, are not a public API, and are documented so a crawler understands the site rather than so anyone calls them. There is no general product REST API and no authentication. Do not invent product resources that are not listed here.",
    "contact": {
      "name": "Kugie",
      "email": "company@kugie.app",
      "url": "https://kugie.app/contact"
    }
  },
  "servers": [
    {
      "url": "https://kugie.app",
      "description": "Production"
    }
  ],
  "tags": [
    {
      "name": "Discovery",
      "description": "Indexes and crawler files."
    },
    {
      "name": "Pages",
      "description": "HTML pages that also negotiate markdown."
    },
    {
      "name": "Markdown twins",
      "description": "Explicit .md URLs for docs and blog posts."
    },
    {
      "name": "Qualify",
      "description": "Same-origin write endpoints behind the hire form at /contact/work."
    },
    {
      "name": "Errors",
      "description": "JSON error shape for API-ish paths."
    }
  ],
  "paths": {
    "/openapi.json": {
      "get": {
        "operationId": "getOpenApiSpec",
        "summary": "Kugie OpenAPI spec",
        "description": "Returns this OpenAPI 3 document. No auth. Use it to discover the real public GETs on kugie.app.",
        "tags": [
          "Discovery"
        ],
        "responses": {
          "200": {
            "description": "OpenAPI 3.0.3 document.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          }
        }
      }
    },
    "/llms.txt": {
      "get": {
        "operationId": "getLlmsTxt",
        "summary": "Kugie llms.txt",
        "description": "Curated studio brief for agents: when to use Kugie, Fit and Principles docs, developer resources. Not a full blog dump.",
        "tags": [
          "Discovery"
        ],
        "responses": {
          "200": {
            "description": "Plain-text llms.txt index.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/llms-full.txt": {
      "get": {
        "operationId": "getLlmsFullTxt",
        "summary": "Kugie llms-full.txt",
        "description": "Concatenated markdown of every /docs page and every published blog post, with source URLs in a small header per section.",
        "tags": [
          "Discovery"
        ],
        "responses": {
          "200": {
            "description": "Plain-text full corpus.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/agents.md": {
      "get": {
        "operationId": "getAgentsMd",
        "summary": "Kugie agent instructions",
        "description": "When to use Kugie, how to contact the studio, and what is out of scope (no product REST API, no kugie.app MCP, no CLI).",
        "tags": [
          "Discovery"
        ],
        "responses": {
          "200": {
            "description": "Markdown agent instructions.",
            "content": {
              "text/markdown": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/sitemap.xml": {
      "get": {
        "operationId": "getSitemap",
        "summary": "HTML sitemap",
        "description": "Standard XML sitemap of indexable HTML pages.",
        "tags": [
          "Discovery"
        ],
        "responses": {
          "200": {
            "description": "XML sitemap.",
            "content": {
              "application/xml": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/robots.txt": {
      "get": {
        "operationId": "getRobotsTxt",
        "summary": "robots.txt",
        "description": "Crawler policy. /openapi.json is allowed. Other *.json paths stay disallowed. /api/* is disallowed because it is not a product API.",
        "tags": [
          "Discovery"
        ],
        "responses": {
          "200": {
            "description": "robots.txt body.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/": {
      "get": {
        "operationId": "getHome",
        "summary": "Home",
        "description": "Studio landing page. Accept: text/markdown returns the same facts as the HTML page without the chrome.",
        "tags": [
          "Pages"
        ],
        "parameters": [
          {
            "name": "Accept",
            "in": "header",
            "required": false,
            "description": "Content negotiation. text/markdown or text/plain returns markdown. text/html returns the visual page. application/json on errors returns JsonError. Unsupported types receive 406.",
            "schema": {
              "type": "string",
              "example": "text/markdown"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page representation matching Accept.",
            "headers": {
              "Vary": {
                "schema": {
                  "type": "string",
                  "example": "Accept"
                }
              }
            },
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              },
              "text/markdown": {
                "schema": {
                  "type": "string"
                }
              },
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Unknown path. HTML 404 page, markdown 404 body, or JsonError.",
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              },
              "text/markdown": {
                "schema": {
                  "type": "string"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonError"
                }
              }
            }
          },
          "406": {
            "description": "Accept header rejected every type this site produces.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/about": {
      "get": {
        "operationId": "getAbout",
        "summary": "About",
        "description": "Studio story and the two founders, Setasena and Gerald.",
        "tags": [
          "Pages"
        ],
        "parameters": [
          {
            "name": "Accept",
            "in": "header",
            "required": false,
            "description": "Content negotiation. text/markdown or text/plain returns markdown. text/html returns the visual page. application/json on errors returns JsonError. Unsupported types receive 406.",
            "schema": {
              "type": "string",
              "example": "text/markdown"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page representation matching Accept.",
            "headers": {
              "Vary": {
                "schema": {
                  "type": "string",
                  "example": "Accept"
                }
              }
            },
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              },
              "text/markdown": {
                "schema": {
                  "type": "string"
                }
              },
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Unknown path. HTML 404 page, markdown 404 body, or JsonError.",
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              },
              "text/markdown": {
                "schema": {
                  "type": "string"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonError"
                }
              }
            }
          },
          "406": {
            "description": "Accept header rejected every type this site produces.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/pricing": {
      "get": {
        "operationId": "getPricing",
        "summary": "Pricing",
        "description": "Published kickoff ranges and monthly retainers.",
        "tags": [
          "Pages"
        ],
        "parameters": [
          {
            "name": "Accept",
            "in": "header",
            "required": false,
            "description": "Content negotiation. text/markdown or text/plain returns markdown. text/html returns the visual page. application/json on errors returns JsonError. Unsupported types receive 406.",
            "schema": {
              "type": "string",
              "example": "text/markdown"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page representation matching Accept.",
            "headers": {
              "Vary": {
                "schema": {
                  "type": "string",
                  "example": "Accept"
                }
              }
            },
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              },
              "text/markdown": {
                "schema": {
                  "type": "string"
                }
              },
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Unknown path. HTML 404 page, markdown 404 body, or JsonError.",
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              },
              "text/markdown": {
                "schema": {
                  "type": "string"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonError"
                }
              }
            }
          },
          "406": {
            "description": "Accept header rejected every type this site produces.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/contact": {
      "get": {
        "operationId": "getContact",
        "summary": "Contact",
        "description": "Company facts for Kugie: legal name, company email, phone, and address (NAP for the legal entity). Not a hire channel. There is no public WhatsApp, no booking link, and no partnership mailbox.",
        "tags": [
          "Pages"
        ],
        "parameters": [
          {
            "name": "Accept",
            "in": "header",
            "required": false,
            "description": "Content negotiation. text/markdown or text/plain returns markdown. text/html returns the visual page. application/json on errors returns JsonError. Unsupported types receive 406.",
            "schema": {
              "type": "string",
              "example": "text/markdown"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page representation matching Accept.",
            "headers": {
              "Vary": {
                "schema": {
                  "type": "string",
                  "example": "Accept"
                }
              }
            },
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              },
              "text/markdown": {
                "schema": {
                  "type": "string"
                }
              },
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Unknown path. HTML 404 page, markdown 404 body, or JsonError.",
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              },
              "text/markdown": {
                "schema": {
                  "type": "string"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonError"
                }
              }
            }
          },
          "406": {
            "description": "Accept header rejected every type this site produces.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/contact/work": {
      "get": {
        "operationId": "getContactWork",
        "summary": "Start the assessment",
        "description": "We choose who we work with. Tell us who you are and what you sell.",
        "tags": [
          "Pages"
        ],
        "parameters": [
          {
            "name": "Accept",
            "in": "header",
            "required": false,
            "description": "Content negotiation. text/markdown or text/plain returns markdown. text/html returns the visual page. application/json on errors returns JsonError. Unsupported types receive 406.",
            "schema": {
              "type": "string",
              "example": "text/markdown"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page representation matching Accept.",
            "headers": {
              "Vary": {
                "schema": {
                  "type": "string",
                  "example": "Accept"
                }
              }
            },
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              },
              "text/markdown": {
                "schema": {
                  "type": "string"
                }
              },
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Unknown path. HTML 404 page, markdown 404 body, or JsonError.",
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              },
              "text/markdown": {
                "schema": {
                  "type": "string"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonError"
                }
              }
            }
          },
          "406": {
            "description": "Accept header rejected every type this site produces.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/work": {
      "get": {
        "operationId": "getWork",
        "summary": "Work",
        "description": "Case study index for Indonesian lifestyle and F&B engagements.",
        "tags": [
          "Pages"
        ],
        "parameters": [
          {
            "name": "Accept",
            "in": "header",
            "required": false,
            "description": "Content negotiation. text/markdown or text/plain returns markdown. text/html returns the visual page. application/json on errors returns JsonError. Unsupported types receive 406.",
            "schema": {
              "type": "string",
              "example": "text/markdown"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page representation matching Accept.",
            "headers": {
              "Vary": {
                "schema": {
                  "type": "string",
                  "example": "Accept"
                }
              }
            },
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              },
              "text/markdown": {
                "schema": {
                  "type": "string"
                }
              },
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Unknown path. HTML 404 page, markdown 404 body, or JsonError.",
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              },
              "text/markdown": {
                "schema": {
                  "type": "string"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonError"
                }
              }
            }
          },
          "406": {
            "description": "Accept header rejected every type this site produces.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/docs": {
      "get": {
        "operationId": "getDocsIndex",
        "summary": "Docs index",
        "description": "Handbook index: principles, fit, team, guides.",
        "tags": [
          "Pages"
        ],
        "parameters": [
          {
            "name": "Accept",
            "in": "header",
            "required": false,
            "description": "Content negotiation. text/markdown or text/plain returns markdown. text/html returns the visual page. application/json on errors returns JsonError. Unsupported types receive 406.",
            "schema": {
              "type": "string",
              "example": "text/markdown"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page representation matching Accept.",
            "headers": {
              "Vary": {
                "schema": {
                  "type": "string",
                  "example": "Accept"
                }
              }
            },
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              },
              "text/markdown": {
                "schema": {
                  "type": "string"
                }
              },
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Unknown path. HTML 404 page, markdown 404 body, or JsonError.",
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              },
              "text/markdown": {
                "schema": {
                  "type": "string"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonError"
                }
              }
            }
          },
          "406": {
            "description": "Accept header rejected every type this site produces.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/docs/api": {
      "get": {
        "operationId": "getDocsApi",
        "summary": "Kugie public API",
        "description": "Human and agent docs for this machine surface. States there is no general product REST API and no auth.",
        "tags": [
          "Pages"
        ],
        "parameters": [
          {
            "name": "Accept",
            "in": "header",
            "required": false,
            "description": "Content negotiation. text/markdown or text/plain returns markdown. text/html returns the visual page. application/json on errors returns JsonError. Unsupported types receive 406.",
            "schema": {
              "type": "string",
              "example": "text/markdown"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page representation matching Accept.",
            "headers": {
              "Vary": {
                "schema": {
                  "type": "string",
                  "example": "Accept"
                }
              }
            },
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              },
              "text/markdown": {
                "schema": {
                  "type": "string"
                }
              },
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Unknown path. HTML 404 page, markdown 404 body, or JsonError.",
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              },
              "text/markdown": {
                "schema": {
                  "type": "string"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonError"
                }
              }
            }
          },
          "406": {
            "description": "Accept header rejected every type this site produces.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/blog": {
      "get": {
        "operationId": "getBlogIndex",
        "summary": "Blog index",
        "description": "Studio notes index. Full post bodies are in /llms-full.txt and /blog/{slug}.md.",
        "tags": [
          "Pages"
        ],
        "parameters": [
          {
            "name": "Accept",
            "in": "header",
            "required": false,
            "description": "Content negotiation. text/markdown or text/plain returns markdown. text/html returns the visual page. application/json on errors returns JsonError. Unsupported types receive 406.",
            "schema": {
              "type": "string",
              "example": "text/markdown"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page representation matching Accept.",
            "headers": {
              "Vary": {
                "schema": {
                  "type": "string",
                  "example": "Accept"
                }
              }
            },
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              },
              "text/markdown": {
                "schema": {
                  "type": "string"
                }
              },
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Unknown path. HTML 404 page, markdown 404 body, or JsonError.",
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              },
              "text/markdown": {
                "schema": {
                  "type": "string"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonError"
                }
              }
            }
          },
          "406": {
            "description": "Accept header rejected every type this site produces.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/docs/{category}": {
      "get": {
        "operationId": "getDocsCategory",
        "summary": "Docs category index",
        "description": "Lists the docs in one handbook category.",
        "tags": [
          "Pages"
        ],
        "parameters": [
          {
            "name": "Accept",
            "in": "header",
            "required": false,
            "description": "Content negotiation. text/markdown or text/plain returns markdown. text/html returns the visual page. application/json on errors returns JsonError. Unsupported types receive 406.",
            "schema": {
              "type": "string",
              "example": "text/markdown"
            }
          },
          {
            "name": "category",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "principles",
                "fit",
                "team",
                "guides"
              ]
            },
            "description": "Docs category id from the published handbook."
          }
        ],
        "responses": {
          "200": {
            "description": "Category index as HTML or markdown.",
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              },
              "text/markdown": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Structured JSON error for agents.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonError"
                }
              }
            }
          }
        }
      }
    },
    "/docs/{category}/{slug}": {
      "get": {
        "operationId": "getDocsArticle",
        "summary": "Docs article",
        "description": "A handbook article. Accept: text/markdown rewrites to the /llms.md twin of the same article.",
        "tags": [
          "Pages"
        ],
        "parameters": [
          {
            "name": "Accept",
            "in": "header",
            "required": false,
            "description": "Content negotiation. text/markdown or text/plain returns markdown. text/html returns the visual page. application/json on errors returns JsonError. Unsupported types receive 406.",
            "schema": {
              "type": "string",
              "example": "text/markdown"
            }
          },
          {
            "name": "category",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "principles",
                "fit",
                "team",
                "guides"
              ]
            }
          },
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Article slug, for example we-embed."
          }
        ],
        "responses": {
          "200": {
            "description": "Article as HTML or markdown.",
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              },
              "text/markdown": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Unknown article.",
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              },
              "text/markdown": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/docs/{category}/{slug}/llms.md": {
      "get": {
        "operationId": "getDocsArticleMarkdown",
        "summary": "Docs article raw markdown",
        "description": "Explicit markdown twin of a handbook article. Always text/markdown, even without an Accept header.",
        "tags": [
          "Markdown twins"
        ],
        "parameters": [
          {
            "name": "category",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "principles",
                "fit",
                "team",
                "guides"
              ]
            }
          },
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Markdown representation of the page.",
            "headers": {
              "Vary": {
                "schema": {
                  "type": "string",
                  "example": "Accept"
                },
                "description": "Must include Accept so caches do not mix HTML and markdown."
              }
            },
            "content": {
              "text/markdown": {
                "schema": {
                  "type": "string"
                }
              },
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Unknown article.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/blog/{slug}.md": {
      "get": {
        "operationId": "getBlogPostMarkdown",
        "summary": "Blog post raw markdown",
        "description": "Explicit markdown twin of a published blog post. Generated at build time from Terradium.",
        "tags": [
          "Markdown twins"
        ],
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Blog post slug."
          }
        ],
        "responses": {
          "200": {
            "description": "Markdown representation of the page.",
            "headers": {
              "Vary": {
                "schema": {
                  "type": "string",
                  "example": "Accept"
                },
                "description": "Must include Accept so caches do not mix HTML and markdown."
              }
            },
            "content": {
              "text/markdown": {
                "schema": {
                  "type": "string"
                }
              },
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "HTML page for browsers.",
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/api/qualify/research": {
      "post": {
        "operationId": "postQualifyResearch",
        "summary": "Open a brief and research the brand",
        "description": "Takes the five brief fields, fetches the website when one is given, looks the brand up on Tokopedia, Shopee, and TikTok Shop, and opens a short-lived session. A brand with a live marketplace shop and no website of its own passes: that is the ideal client. The only stop is a brand with neither.",
        "tags": [
          "Qualify"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "company": {
                    "type": "string"
                  },
                  "role": {
                    "type": "string"
                  },
                  "brand": {
                    "type": "string"
                  },
                  "website": {
                    "type": "string",
                    "description": "Optional."
                  }
                },
                "required": [
                  "name",
                  "company",
                  "role",
                  "brand"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Step accepted.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "Structured JSON error for agents.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonError"
                }
              }
            }
          },
          "403": {
            "description": "Structured JSON error for agents.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonError"
                }
              }
            }
          },
          "409": {
            "description": "Structured JSON error for agents.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonError"
                }
              }
            }
          },
          "410": {
            "description": "Structured JSON error for agents.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonError"
                }
              }
            }
          },
          "429": {
            "description": "Structured JSON error for agents.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonError"
                }
              }
            }
          },
          "503": {
            "description": "Structured JSON error for agents.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonError"
                }
              }
            }
          }
        }
      }
    },
    "/api/qualify/budget": {
      "post": {
        "operationId": "postQualifyBudget",
        "summary": "Record the retainer choice",
        "description": "Accepts 25 or 40 only, and only on a session whose research passed. Anything below 25 is a stop that points at /pricing.",
        "tags": [
          "Qualify"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "sessionId": {
                    "type": "string",
                    "pattern": "^[a-f0-9]{32}$",
                    "description": "Session id returned by /api/qualify/research."
                  },
                  "budget": {
                    "type": "integer",
                    "enum": [
                      25,
                      40
                    ]
                  }
                },
                "required": [
                  "sessionId",
                  "budget"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Step accepted.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "Structured JSON error for agents.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonError"
                }
              }
            }
          },
          "403": {
            "description": "Structured JSON error for agents.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonError"
                }
              }
            }
          },
          "409": {
            "description": "Structured JSON error for agents.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonError"
                }
              }
            }
          },
          "410": {
            "description": "Structured JSON error for agents.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonError"
                }
              }
            }
          },
          "429": {
            "description": "Structured JSON error for agents.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonError"
                }
              }
            }
          },
          "503": {
            "description": "Structured JSON error for agents.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonError"
                }
              }
            }
          }
        }
      }
    },
    "/api/qualify/otp/send": {
      "post": {
        "operationId": "postQualifyOtpSend",
        "summary": "Send a WhatsApp verification code",
        "description": "Last step, and the only paid one. Refuses unless the session already carries a passing research verdict and a 25 or 40 retainer, both read from the server, never from the request.",
        "tags": [
          "Qualify"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "sessionId": {
                    "type": "string",
                    "pattern": "^[a-f0-9]{32}$",
                    "description": "Session id returned by /api/qualify/research."
                  },
                  "phone": {
                    "type": "string",
                    "description": "Indonesian mobile."
                  }
                },
                "required": [
                  "sessionId",
                  "phone"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Step accepted.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "Structured JSON error for agents.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonError"
                }
              }
            }
          },
          "403": {
            "description": "Structured JSON error for agents.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonError"
                }
              }
            }
          },
          "409": {
            "description": "Structured JSON error for agents.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonError"
                }
              }
            }
          },
          "410": {
            "description": "Structured JSON error for agents.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonError"
                }
              }
            }
          },
          "429": {
            "description": "Structured JSON error for agents.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonError"
                }
              }
            }
          },
          "503": {
            "description": "Structured JSON error for agents.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonError"
                }
              }
            }
          }
        }
      }
    },
    "/api/qualify/otp/verify": {
      "post": {
        "operationId": "postQualifyOtpVerify",
        "summary": "Verify the code and hand the lead on",
        "description": "On success the lead is written to the Kugie CRM and posted to an internal Slack channel. A wrong or expired code writes nothing at all.",
        "tags": [
          "Qualify"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "sessionId": {
                    "type": "string",
                    "pattern": "^[a-f0-9]{32}$",
                    "description": "Session id returned by /api/qualify/research."
                  },
                  "code": {
                    "type": "string",
                    "pattern": "^[0-9]{6}$"
                  }
                },
                "required": [
                  "sessionId",
                  "code"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Step accepted.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "Structured JSON error for agents.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonError"
                }
              }
            }
          },
          "403": {
            "description": "Structured JSON error for agents.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonError"
                }
              }
            }
          },
          "409": {
            "description": "Structured JSON error for agents.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonError"
                }
              }
            }
          },
          "410": {
            "description": "Structured JSON error for agents.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonError"
                }
              }
            }
          },
          "429": {
            "description": "Structured JSON error for agents.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonError"
                }
              }
            }
          },
          "503": {
            "description": "Structured JSON error for agents.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonError"
                }
              }
            }
          }
        }
      }
    },
    "/api/{path}": {
      "get": {
        "operationId": "getMissingApiPath",
        "summary": "Missing API path (JSON error)",
        "description": "kugie.app has no general product API. Any /api/* path that is not an internal rewrite or one of the /api/qualify endpoints returns a structured JSON error.",
        "tags": [
          "Errors"
        ],
        "parameters": [
          {
            "name": "path",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Remaining path after /api/."
          }
        ],
        "responses": {
          "404": {
            "description": "Structured JSON error for agents.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonError"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "JsonError": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "code",
              "message",
              "hint"
            ],
            "properties": {
              "code": {
                "type": "string",
                "enum": [
                  "not_found",
                  "method_not_allowed",
                  "not_acceptable",
                  "bad_request"
                ],
                "description": "Stable machine-readable error code."
              },
              "message": {
                "type": "string",
                "description": "Human-readable explanation of what failed."
              },
              "hint": {
                "type": "string",
                "description": "Where an agent should look next (OpenAPI and llms.txt)."
              }
            }
          }
        }
      }
    }
  }
}