{
  "openapi": "3.1.0",
  "info": {
    "title": "write.cv public site resources",
    "version": "2.1.0",
    "description": "Machine-readable description of the public, read-only HTTP resources served by write.cv — a free, browser-based CV/resume builder. write.cv is local-first: user CV data lives in the browser and there is no user-data API. For ATS scoring and CV JSON authoring, use the MCP endpoint at https://write.cv/mcp.",
    "contact": {
      "name": "Abdullah Al-Taheri",
      "url": "https://altaheri.me"
    }
  },
  "servers": [
    {
      "url": "https://write.cv"
    }
  ],
  "components": {
    "schemas": {
      "HtmlPage": {
        "type": "string",
        "description": "A server-rendered HTML page containing the full page content, JSON-LD structured data, and semantic landmarks. Request the same path with 'Accept: text/markdown' to receive the MarkdownPage representation instead."
      },
      "MarkdownPage": {
        "type": "string",
        "description": "A Markdown rendition of the page (title, description, features, FAQ, links) served via HTTP content negotiation — about 80% fewer tokens than the HTML representation."
      },
      "PlainTextDocument": {
        "type": "string",
        "description": "A plain-text (Markdown-formatted) document such as llms.txt, intended for direct consumption by LLMs and agents."
      },
      "XmlSitemap": {
        "type": "string",
        "description": "An XML sitemap conforming to the sitemaps.org protocol, listing every indexable URL on write.cv."
      },
      "Error": {
        "type": "object",
        "description": "Standard error body returned for failed requests.",
        "properties": {
          "status": {
            "type": "integer",
            "description": "The HTTP status code of the error, e.g. 404 or 500."
          },
          "message": {
            "type": "string",
            "description": "A human-readable explanation of what went wrong."
          }
        },
        "required": [
          "status",
          "message"
        ]
      },
      "Problem": {
        "type": "object",
        "required": [
          "title",
          "status"
        ],
        "properties": {
          "type": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "status": {
            "type": "integer"
          },
          "detail": {
            "type": "string"
          }
        }
      }
    }
  },
  "paths": {
    "/": {
      "get": {
        "operationId": "getLanding",
        "summary": "English landing page describing the CV builder",
        "description": "Server-rendered landing page with JSON-LD structured data, feature list, and FAQ. Supports content negotiation: send 'Accept: text/markdown' to receive Markdown.",
        "responses": {
          "200": {
            "description": "Landing page (HTML, or Markdown when requested via Accept header).",
            "content": {
              "text/html": {
                "schema": {
                  "$ref": "#/components/schemas/HtmlPage"
                }
              },
              "text/markdown": {
                "schema": {
                  "$ref": "#/components/schemas/MarkdownPage"
                }
              }
            }
          },
          "404": {
            "description": "The requested resource does not exist.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/{lang}": {
      "get": {
        "operationId": "getLanding",
        "summary": "Landing page (en = English, ar = Arabic RTL)",
        "description": "Product landing page: features, templates, example profiles, reviews and FAQ. Supports content negotiation: send 'Accept: text/markdown' to receive a Markdown summary of the page.",
        "parameters": [
          {
            "name": "lang",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "en",
                "ar"
              ]
            },
            "description": "Interface language: en (English) or ar (Arabic, right-to-left)."
          }
        ],
        "responses": {
          "200": {
            "description": "Landing page (HTML, or Markdown when requested via Accept header).",
            "content": {
              "text/html": {
                "schema": {
                  "$ref": "#/components/schemas/HtmlPage"
                }
              },
              "text/markdown": {
                "schema": {
                  "$ref": "#/components/schemas/MarkdownPage"
                }
              }
            }
          },
          "404": {
            "description": "The requested resource does not exist.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/{lang}/app": {
      "get": {
        "operationId": "getBuilder",
        "summary": "The CV builder app (en = English, ar = Arabic RTL)",
        "description": "The interactive CV builder (not indexed). No sign-up needed; CV data stays in the browser.",
        "parameters": [
          {
            "name": "lang",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "en",
                "ar"
              ]
            },
            "description": "Interface language: en (English) or ar (Arabic, right-to-left)."
          }
        ],
        "responses": {
          "200": {
            "description": "CV builder page (HTML).",
            "content": {
              "text/html": {
                "schema": {
                  "$ref": "#/components/schemas/HtmlPage"
                }
              }
            }
          },
          "404": {
            "description": "The requested resource does not exist.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/llms.txt": {
      "get": {
        "operationId": "getLlmsTxt",
        "summary": "Short machine-readable site overview for LLMs",
        "description": "Curated entry point for AI agents per the llms.txt specification.",
        "responses": {
          "200": {
            "description": "Markdown overview of write.cv.",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/PlainTextDocument"
                }
              }
            }
          },
          "404": {
            "description": "The requested resource does not exist.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/llms-full.txt": {
      "get": {
        "operationId": "getLlmsFullTxt",
        "summary": "Expanded LLM context: features, pages, and the CV JSON schema",
        "description": "Everything an agent needs to author a write.cv-compatible CV JSON file, plus the full feature list and FAQ.",
        "responses": {
          "200": {
            "description": "Expanded Markdown context document.",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/PlainTextDocument"
                }
              }
            }
          },
          "404": {
            "description": "The requested resource does not exist.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/AGENTS.md": {
      "get": {
        "operationId": "getAgentsGuide",
        "summary": "Agent guide: what the site offers and how to interact with it",
        "description": "Describes the MCP endpoint, discovery files, data/privacy model, and etiquette for AI agents.",
        "responses": {
          "200": {
            "description": "Markdown agent guide.",
            "content": {
              "text/markdown": {
                "schema": {
                  "$ref": "#/components/schemas/PlainTextDocument"
                }
              }
            }
          },
          "404": {
            "description": "The requested resource does not exist.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/sitemap.xml": {
      "get": {
        "operationId": "getSitemap",
        "summary": "XML sitemap of all indexable URLs",
        "description": "Sitemap conforming to the sitemaps.org protocol.",
        "responses": {
          "200": {
            "description": "XML sitemap.",
            "content": {
              "application/xml": {
                "schema": {
                  "$ref": "#/components/schemas/XmlSitemap"
                }
              }
            }
          },
          "404": {
            "description": "The requested resource does not exist.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/reviews": {
      "get": {
        "operationId": "getReviews",
        "summary": "Published reviews and rating aggregate",
        "description": "Published user reviews (name, stars, comment, country, date) plus the aggregate count and average. Public, no auth, cached ~60 s.",
        "responses": {
          "200": {
            "description": "Reviews wall.",
            "headers": {
              "RateLimit-Policy": {
                "description": "Rate-limit policy (IETF draft): 200 requests per 60 s per IP across /api/* and /mcp.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "description": "Requests allowed per window.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "reviews",
                    "count",
                    "avg"
                  ],
                  "properties": {
                    "count": {
                      "type": "integer"
                    },
                    "avg": {
                      "type": "number"
                    },
                    "reviews": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "name": {
                            "type": "string"
                          },
                          "stars": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 5
                          },
                          "comment": {
                            "type": "string"
                          },
                          "country": {
                            "type": "string",
                            "description": "ISO 3166-1 alpha-2, may be empty"
                          },
                          "date": {
                            "type": "integer",
                            "description": "Unix seconds"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Problem details (RFC 9457).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      }
    },
    "/api/stats": {
      "get": {
        "operationId": "getStats",
        "summary": "Lifetime count of CVs created",
        "description": "Number of CVs created (exported to PDF) on write.cv. Public, no auth, cached ~5 min.",
        "responses": {
          "200": {
            "description": "Counter.",
            "headers": {
              "RateLimit-Policy": {
                "description": "Rate-limit policy (IETF draft): 200 requests per 60 s per IP across /api/* and /mcp.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "description": "Requests allowed per window.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "created"
                  ],
                  "properties": {
                    "created": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Problem details (RFC 9457).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      }
    },
    "/developers": {
      "get": {
        "operationId": "getDeveloperDocs",
        "summary": "Developer documentation",
        "description": "Human-readable docs: MCP server, public endpoints, auth, rate limits, errors.",
        "responses": {
          "200": {
            "description": "Docs page.",
            "content": {
              "text/html": {
                "schema": {
                  "$ref": "#/components/schemas/HtmlPage"
                }
              }
            }
          }
        }
      }
    }
  },
  "externalDocs": {
    "description": "Developer documentation",
    "url": "https://write.cv/developers"
  }
}
