{
  "openapi": "3.1.0",
  "info": {
    "title": "checkra1n.dev Public API",
    "summary": "Public, key-free API and machine-readable resources for checkra1n.dev",
    "description": "Machine-readable surface of checkra1n.dev — the personal portfolio of checkra1n (GitHub: checkra1neth), a vibe coder and Web3 engineer. All endpoints are public: no API keys, no authentication. HTML pages additionally support `Accept: text/markdown` content negotiation and respond with `Vary: Accept, Accept-Encoding`. Unknown paths return structured JSON errors on /api/* and real HTTP 404s elsewhere.",
    "version": "1.0.0",
    "contact": {
      "name": "checkra1n (checkra1neth)",
      "url": "https://www.checkra1n.dev/contact",
      "email": "checkra1neth@gmail.com"
    },
    "license": {
      "name": "Content © checkra1n; cite with attribution and link",
      "url": "https://www.checkra1n.dev/about"
    }
  },
  "servers": [
    {
      "url": "https://www.checkra1n.dev",
      "description": "Production"
    }
  ],
  "externalDocs": {
    "description": "Developer portal with quickstart examples",
    "url": "https://www.checkra1n.dev/developers"
  },
  "paths": {
    "/api/github": {
      "get": {
        "operationId": "getGithubStats",
        "summary": "GitHub profile statistics for checkra1neth",
        "description": "Returns public repository counts, total stars, an approximate 20-week push-streak contribution grid, and follower counts fetched live from api.github.com. Cached at the edge for 5 minutes.",
        "tags": ["Data"],
        "responses": {
          "200": {
            "description": "GitHub statistics computed from public repositories",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/GitHubStats" }
              }
            }
          },
          "502": {
            "description": "Upstream GitHub API failure",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Error" }
              }
            }
          },
          "500": {
            "description": "Internal computation error",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Error" }
              }
            }
          }
        }
      }
    },
    "/api/indexnow": {
      "get": {
        "operationId": "pingIndexNowAllUrls",
        "summary": "Ping IndexNow with every canonical URL",
        "description": "Submits all canonical site URLs to the IndexNow endpoints (api.indexnow.org and bing.com) using the site's registered key. Intended for post-deploy indexing refreshes. Returns 200 when every upstream accepted the payload, otherwise 207 (multi-status).",
        "tags": ["Search"],
        "responses": {
          "200": {
            "description": "All IndexNow submissions accepted",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/IndexNowSubmission" }
              }
            }
          },
          "207": {
            "description": "Some IndexNow submissions failed; inspect per-endpoint results",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/IndexNowSubmission" }
              }
            }
          },
          "405": {
            "description": "Method not allowed",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Error" }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "submitIndexNowUrls",
        "summary": "Submit a custom URL list to IndexNow",
        "description": "Submits the provided URL list (must be URLs under www.checkra1n.dev) to IndexNow endpoints. Request body: {\"urls\": [\"...\"]}.",
        "tags": ["Search"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["urls"],
                "properties": {
                  "urls": {
                    "type": "array",
                    "items": { "type": "string", "format": "uri" },
                    "minItems": 1,
                    "description": "Canonical URLs hosted on www.checkra1n.dev"
                  }
                }
              },
              "example": {
                "urls": ["https://www.checkra1n.dev/intel/vibe-coding-agents"]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "All IndexNow submissions accepted",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/IndexNowSubmission" }
              }
            }
          },
          "207": {
            "description": "Partial failures; inspect per-endpoint results",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/IndexNowSubmission" }
              }
            }
          },
          "400": {
            "description": "Missing or empty urls array",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Error" }
              }
            }
          },
          "405": {
            "description": "Method not allowed",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Error" }
              }
            }
          }
        }
      }
    },
    "/api/og": {
      "get": {
        "operationId": "generateOgImage",
        "summary": "Generate an Open Graph PNG card",
        "description": "Renders a terminal-style social preview image (1200x630 PNG) used by blog posts. Edge-rendered via @vercel/og.",
        "tags": ["Media"],
        "parameters": [
          {
            "name": "title",
            "in": "query",
            "required": false,
            "description": "Headline rendered on the card",
            "schema": { "type": "string", "default": "checkra1n.blog" }
          },
          {
            "name": "subtitle",
            "in": "query",
            "required": false,
            "description": "Secondary line rendered under the title",
            "schema": { "type": "string", "default": "" }
          },
          {
            "name": "category",
            "in": "query",
            "required": false,
            "description": "Post category controlling accent color (AI gets amber, others green)",
            "schema": {
              "type": "string",
              "enum": ["AI", "DEV", "AUTOMATION", "TOOLS", "CAREER"],
              "default": "DEV"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Generated PNG image",
            "content": {
              "image/png": {}
            }
          }
        }
      }
    },
    "/intel/{slug}": {
      "get": {
        "operationId": "getIntelPost",
        "summary": "Fetch a blog post by slug",
        "description": "Returns one practitioner article from the Intel blog. Send `Accept: text/markdown` to receive a low-noise markdown variant (response carries `Vary: Accept, Accept-Encoding`); default is server-rendered HTML. Unknown slugs return HTTP 404 with pointers to the sitemap and llms.txt index.",
        "tags": ["Content"],
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "description": "URL slug of the post, e.g. vibe-coding-agents. Full list in /sitemap.xml or /llms.txt.",
            "schema": { "type": "string" },
            "example": "vibe-coding-agents"
          }
        ],
        "responses": {
          "200": {
            "description": "The requested post as HTML (default) or markdown (Accept: text/markdown)",
            "content": {
              "text/html": {},
              "text/markdown": {}
            }
          },
          "404": {
            "description": "Unknown slug; body points at sitemap.xml and llms.txt",
            "content": {
              "text/html": {},
              "text/markdown": {}
            }
          }
        }
      }
    },
    "/openapi.json": {
      "get": {
        "operationId": "getOpenApiSpec",
        "summary": "This OpenAPI specification",
        "description": "Serves the OpenAPI 3.1 document describing the full API surface.",
        "tags": ["Meta"],
        "responses": {
          "200": {
            "description": "OpenAPI specification document",
            "content": {
              "application/json": {
                "schema": { "type": "object" }
              }
            }
          }
        }
      }
    },
    "/llms.txt": {
      "get": {
        "operationId": "getLlmsIndex",
        "summary": "Curated LLM site index",
        "description": "Markdown-formatted index of the site for LLM ingestion: who checkra1n is, canonical page URLs, common questions with citable answers, key facts, and agent guidance ('When to use').",
        "tags": ["Content"],
        "responses": {
          "200": {
            "description": "Plain-text LLM index",
            "content": {
              "text/plain": {}
            }
          }
        }
      }
    },
    "/llms-full.txt": {
      "get": {
        "operationId": "getLlmsFullEn",
        "summary": "Full English blog archive",
        "description": "Complete English post corpus as plain text — prefer this over crawling individual post pages.",
        "tags": ["Content"],
        "responses": {
          "200": {
            "description": "Full English archive",
            "content": {
              "text/plain": {}
            }
          }
        }
      }
    },
    "/llms-full-uk.txt": {
      "get": {
        "operationId": "getLlmsFullUk",
        "summary": "Full Ukrainian blog archive",
        "description": "Complete Ukrainian post corpus as plain text.",
        "tags": ["Content"],
        "responses": {
          "200": {
            "description": "Full Ukrainian archive",
            "content": {
              "text/plain": {}
            }
          }
        }
      }
    },
    "/ai.txt": {
      "get": {
        "operationId": "getAiTxt",
        "summary": "Compact AI discovery index",
        "description": "Short machine-readable summary of the site, entity disambiguation, and post URL lists (EN/UK).",
        "tags": ["Content"],
        "responses": {
          "200": {
            "description": "AI discovery index",
            "content": {
              "text/plain": {}
            }
          }
        }
      }
    },
    "/sitemap.xml": {
      "get": {
        "operationId": "getSitemap",
        "summary": "XML sitemap of all pages",
        "description": "Every crawlable HTML page including posts, trust pages (/about, /contact, /privacy), and /developers. Cached 24 hours.",
        "tags": ["Meta"],
        "responses": {
          "200": {
            "description": "XML sitemap",
            "content": {
              "application/xml": {}
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "GitHubStats": {
        "type": "object",
        "description": "Aggregated public GitHub statistics for checkra1neth",
        "properties": {
          "username": { "type": "string", "description": "GitHub login", "example": "checkra1neth" },
          "totalRepos": { "type": "integer", "description": "Public repository count per GitHub profile" },
          "publicRepos": { "type": "integer", "description": "Non-fork repositories included in aggregation" },
          "totalStars": { "type": "integer", "description": "Sum of stargazers across non-fork public repos" },
          "streak": { "type": "integer", "description": "Distinct push days within the last 30 days (minimum 1)" },
          "followers": { "type": "integer" },
          "following": { "type": "integer" },
          "contributionGrid": {
            "type": "array",
            "description": "20 weeks x 7 days activity levels derived from recent pushes (0=none … 4=high)",
            "items": {
              "type": "array",
              "items": { "type": "integer", "minimum": 0, "maximum": 4 }
            }
          },
          "lastUpdated": { "type": "string", "format": "date-time" }
        }
      },
      "IndexNowSubmission": {
        "type": "object",
        "description": "Result of submitting URLs to IndexNow endpoints",
        "properties": {
          "submitted": { "type": "integer", "description": "Number of URLs submitted" },
          "results": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "endpoint": { "type": "string", "format": "uri", "description": "IndexNow endpoint called" },
                "ok": { "type": "boolean", "description": "Whether the endpoint accepted the submission" },
                "status": { "type": "integer", "description": "HTTP status returned by the endpoint (0 = network error)" }
              }
            }
          }
        }
      },
      "Error": {
        "type": "object",
        "description": "Structured error returned by all /api/* endpoints",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string",
                "description": "Stable machine-readable code",
                "enum": ["not_found", "bad_request", "method_not_allowed", "upstream_error", "internal_error"]
              },
              "message": { "type": "string", "description": "Human-readable explanation" },
              "hint": { "type": "string", "description": "Resolution hint for agents" },
              "status": { "type": "integer", "description": "HTTP status code" },
              "docs": { "type": "string", "format": "uri", "description": "Link to this specification" }
            },
            "required": ["code", "message", "status"]
          }
        },
        "required": ["error"]
      }
    }
  },
  "tags": [
    { "name": "Data", "description": "Structured data endpoints" },
    { "name": "Search", "description": "Search-engine submission utilities" },
    { "name": "Media", "description": "Image generation" },
    { "name": "Content", "description": "Readable site content for humans and LLMs" },
    { "name": "Meta", "description": "Discovery documents describing the site itself" }
  ]
}
