{
  "openapi": "3.0.3",
  "info": {
    "title": "DocForge API",
    "description": "Fast, reliable document format conversion API. Convert between Markdown, HTML, CSV, JSON, and YAML with a single API call. No AI, no databases, pure computation with sub-50ms responses.\n\n## Authentication\n\nThe API supports three tiers based on the `X-Api-Key` header:\n\n| Tier | Key Prefix | Requests/Day | Max Input Size |\n|------|-----------|-------------|----------------|\n| Free | *(none)* | 500 | 100 KB |\n| Pro | `dk_pro_` | 50,000 | 5 MB |\n| Team | `dk_team_` | 500,000 | 25 MB |\n\nThe **Free** tier requires no API key. Pro and Team keys are issued after subscribing.\n\n## Rate Limiting\n\nAll responses include rate limit headers. When the daily limit is exceeded, the API returns a `429` status with a `RATE_LIMITED` error code.\n\n## Error Handling\n\nAll errors follow a consistent JSON structure with `error`, `code`, and optional `details` fields.",
    "version": "1.0.0",
    "contact": {
      "name": "AlberaMarc",
      "url": "https://github.com/AlberaMarc/docforge-api"
    },
    "license": {
      "name": "MIT"
    }
  },
  "servers": [
    {
      "url": "https://docforge-api.vercel.app",
      "description": "Production"
    }
  ],
  "paths": {
    "/api/index": {
      "get": {
        "operationId": "getApiDirectory",
        "summary": "API Directory",
        "description": "Returns the API name, version, and a list of all available endpoints.",
        "tags": ["General"],
        "responses": {
          "200": {
            "description": "API directory listing",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiDirectory"
                },
                "example": {
                  "name": "DocForge API",
                  "version": "1.0.0",
                  "status": "operational",
                  "endpoints": [
                    { "method": "POST", "path": "/api/md-to-html", "description": "Convert Markdown to sanitized HTML" },
                    { "method": "POST", "path": "/api/csv-to-json", "description": "Parse CSV/TSV to JSON array" },
                    { "method": "POST", "path": "/api/json-to-csv", "description": "Convert JSON array to CSV" },
                    { "method": "POST", "path": "/api/yaml-json", "description": "Convert between YAML and JSON" }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/md-to-html": {
      "post": {
        "operationId": "mdToHtml",
        "summary": "Markdown to HTML",
        "description": "Convert Markdown text to sanitized HTML. Supports headings, bold, italic, strikethrough, links, images, code blocks (with language annotation), lists (ordered and unordered), blockquotes, and horizontal rules. Returns the rendered HTML along with metadata including word count and extracted heading text.",
        "tags": ["Conversion"],
        "security": [
          {},
          { "ApiKeyAuth": [] }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MdToHtmlRequest"
              },
              "example": {
                "markdown": "# Hello World\n\nThis is **bold** and *italic*.\n\n- Item one\n- Item two"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful conversion",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MdToHtmlResponse"
                },
                "example": {
                  "html": "<h1>Hello World</h1>\n<p>This is <strong>bold</strong> and <em>italic</em>.</p>\n<ul>\n<li>Item one</li>\n<li>Item two</li>\n</ul>",
                  "meta": {
                    "wordCount": 9,
                    "headings": ["Hello World"]
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input (missing or malformed `markdown` field)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "error": "markdown is required",
                  "code": "INVALID_INPUT"
                }
              }
            }
          },
          "405": {
            "description": "Method not allowed (only POST is accepted)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "error": "Method not allowed",
                  "code": "INVALID_INPUT"
                }
              }
            }
          },
          "413": {
            "description": "Input exceeds tier size limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "error": "Input exceeds 102400 byte limit",
                  "code": "INPUT_TOO_LARGE"
                }
              }
            }
          },
          "429": {
            "description": "Daily rate limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "error": "Daily request limit exceeded",
                  "code": "RATE_LIMITED"
                }
              }
            }
          }
        }
      }
    },
    "/api/csv-to-json": {
      "post": {
        "operationId": "csvToJson",
        "summary": "CSV to JSON",
        "description": "Parse CSV (or TSV) data into a JSON array of objects. The first row is treated as column headers. Supports quoted fields with escaped double-quotes, and a configurable delimiter character (defaults to comma). Returns the parsed data array along with metadata including row count and column names.",
        "tags": ["Conversion"],
        "security": [
          {},
          { "ApiKeyAuth": [] }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CsvToJsonRequest"
              },
              "example": {
                "csv": "name,email,role\nAlice,alice@example.com,admin\nBob,bob@example.com,user",
                "delimiter": ","
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful conversion",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CsvToJsonResponse"
                },
                "example": {
                  "data": [
                    { "name": "Alice", "email": "alice@example.com", "role": "admin" },
                    { "name": "Bob", "email": "bob@example.com", "role": "user" }
                  ],
                  "meta": {
                    "rowCount": 2,
                    "columns": ["name", "email", "role"]
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input (missing or malformed `csv` field)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "405": {
            "description": "Method not allowed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "413": {
            "description": "Input exceeds tier size limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "description": "Daily rate limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/api/json-to-csv": {
      "post": {
        "operationId": "jsonToCsv",
        "summary": "JSON to CSV",
        "description": "Convert an array of JSON objects to CSV format. Columns are automatically detected from all keys across all rows. Fields containing the delimiter, double quotes, or newlines are properly escaped with double-quote enclosure. Supports a configurable delimiter character (defaults to comma). Returns the CSV string along with metadata including row count and column names.",
        "tags": ["Conversion"],
        "security": [
          {},
          { "ApiKeyAuth": [] }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/JsonToCsvRequest"
              },
              "example": {
                "data": [
                  { "name": "Alice", "email": "alice@example.com", "role": "admin" },
                  { "name": "Bob", "email": "bob@example.com", "role": "user" }
                ],
                "delimiter": ","
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful conversion",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonToCsvResponse"
                },
                "example": {
                  "csv": "name,email,role\nAlice,alice@example.com,admin\nBob,bob@example.com,user",
                  "meta": {
                    "rowCount": 2,
                    "columns": ["name", "email", "role"]
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input (missing, empty, or malformed `data` array)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "405": {
            "description": "Method not allowed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "413": {
            "description": "Input exceeds tier size limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "description": "Daily rate limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/api/md-to-document": {
      "post": {
        "operationId": "mdToDocument",
        "summary": "Convert Markdown to styled standalone HTML document",
        "description": "Converts Markdown to a complete, styled HTML document with themes, table of contents, syntax highlighting, and print support. Choose from four built-in themes (github, notion, minimal, academic), enable dark mode with a toggle button, generate a table of contents from headings, and include print-optimized stylesheets. The academic theme adds heading numbering and footnote support. Returns the full HTML document along with metadata including word count, reading time, headings, code block count, and character count.",
        "tags": ["Conversion"],
        "security": [
          {},
          { "ApiKeyAuth": [] }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MdToDocumentRequest"
              },
              "example": {
                "markdown": "# Project Report\n\n## Introduction\n\nThis is a **sample** document with `inline code`.\n\n## Features\n\n- Table of contents\n- Syntax highlighting\n- Dark mode\n\n```js\nconsole.log('hello');\n```",
                "theme": "github",
                "options": {
                  "toc": true,
                  "syntaxHighlight": true,
                  "darkMode": false,
                  "printStylesheet": true,
                  "meta": {
                    "title": "Project Report",
                    "author": "DocForge",
                    "description": "A sample project report"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful conversion",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MdToDocumentResponse"
                },
                "example": {
                  "html": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>...</head>\n<body>...</body>\n</html>",
                  "meta": {
                    "wordCount": 18,
                    "readingTime": "1 min",
                    "headings": ["Project Report", "Introduction", "Features"],
                    "codeBlocks": 1,
                    "characterCount": 210
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input (missing or malformed `markdown` field, invalid theme, or invalid options)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "error": "markdown is required",
                  "code": "INVALID_INPUT"
                }
              }
            }
          },
          "413": {
            "description": "Input exceeds tier size limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "error": "Input exceeds 102400 byte limit",
                  "code": "INPUT_TOO_LARGE"
                }
              }
            }
          },
          "429": {
            "description": "Daily rate limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "error": "Daily request limit exceeded",
                  "code": "RATE_LIMITED"
                }
              }
            }
          }
        }
      }
    },
    "/api/yaml-json": {
      "post": {
        "operationId": "yamlJson",
        "summary": "YAML / JSON Conversion",
        "description": "Bidirectional conversion between YAML and JSON. Specify `direction` as either `yaml-to-json` or `json-to-yaml`. The YAML parser supports scalars (string, number, boolean, null), nested objects, and arrays. Returns the converted output string along with metadata including the top-level key count.",
        "tags": ["Conversion"],
        "security": [
          {},
          { "ApiKeyAuth": [] }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/YamlJsonRequest"
              },
              "examples": {
                "yaml-to-json": {
                  "summary": "Convert YAML to JSON",
                  "value": {
                    "input": "name: DocForge\nversion: 1.0.0\nfeatures:\n  - fast\n  - reliable",
                    "direction": "yaml-to-json"
                  }
                },
                "json-to-yaml": {
                  "summary": "Convert JSON to YAML",
                  "value": {
                    "input": "{\"name\":\"DocForge\",\"version\":\"1.0.0\"}",
                    "direction": "json-to-yaml"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful conversion",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/YamlJsonResponse"
                },
                "example": {
                  "output": "{\"name\":\"DocForge\",\"version\":\"1.0.0\",\"features\":[\"fast\",\"reliable\"]}",
                  "meta": {
                    "keys": 3
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input (missing fields, invalid direction, or parse error)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "405": {
            "description": "Method not allowed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "413": {
            "description": "Input exceeds tier size limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "description": "Daily rate limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "X-Api-Key",
        "description": "API key for Pro (`dk_pro_*`) and Team (`dk_team_*`) tiers. Omit for Free tier (500 requests/day, 100 KB input limit)."
      }
    },
    "schemas": {
      "ApiError": {
        "type": "object",
        "required": ["error", "code"],
        "properties": {
          "error": {
            "type": "string",
            "description": "Human-readable error message"
          },
          "code": {
            "type": "string",
            "enum": ["INVALID_INPUT", "PARSE_ERROR", "RATE_LIMITED", "INPUT_TOO_LARGE", "INTERNAL_ERROR"],
            "description": "Machine-readable error code"
          },
          "details": {
            "type": "string",
            "description": "Additional context about the error (optional)"
          }
        }
      },
      "ApiDirectory": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "example": "DocForge API"
          },
          "version": {
            "type": "string",
            "example": "1.0.0"
          },
          "status": {
            "type": "string",
            "example": "operational"
          },
          "endpoints": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EndpointInfo"
            }
          }
        }
      },
      "EndpointInfo": {
        "type": "object",
        "properties": {
          "method": {
            "type": "string",
            "example": "POST"
          },
          "path": {
            "type": "string",
            "example": "/api/md-to-html"
          },
          "description": {
            "type": "string",
            "example": "Convert Markdown to sanitized HTML"
          }
        }
      },
      "MdToHtmlRequest": {
        "type": "object",
        "required": ["markdown"],
        "properties": {
          "markdown": {
            "type": "string",
            "minLength": 1,
            "description": "Markdown text to convert to HTML",
            "example": "# Hello World\n\nThis is **bold**."
          }
        }
      },
      "MdToHtmlResponse": {
        "type": "object",
        "properties": {
          "html": {
            "type": "string",
            "description": "Rendered HTML output"
          },
          "meta": {
            "type": "object",
            "properties": {
              "wordCount": {
                "type": "integer",
                "minimum": 0,
                "description": "Number of words in the input markdown"
              },
              "headings": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "Extracted heading text from the markdown"
              }
            }
          }
        }
      },
      "MdToDocumentRequest": {
        "type": "object",
        "required": ["markdown"],
        "properties": {
          "markdown": {
            "type": "string",
            "minLength": 1,
            "description": "Markdown text to convert to a styled HTML document",
            "example": "# Hello World\n\nThis is **bold**."
          },
          "theme": {
            "type": "string",
            "enum": ["github", "notion", "minimal", "academic"],
            "default": "github",
            "description": "Visual theme for the output document"
          },
          "options": {
            "type": "object",
            "description": "Document generation options",
            "properties": {
              "toc": {
                "type": "boolean",
                "default": false,
                "description": "Generate a table of contents from headings"
              },
              "syntaxHighlight": {
                "type": "boolean",
                "default": true,
                "description": "Enable syntax highlighting for code blocks"
              },
              "darkMode": {
                "type": "boolean",
                "default": false,
                "description": "Include dark mode support with a toggle button"
              },
              "printStylesheet": {
                "type": "boolean",
                "default": true,
                "description": "Include print-optimized CSS styles"
              },
              "meta": {
                "type": "object",
                "description": "Document metadata for HTML head tags",
                "properties": {
                  "title": {
                    "type": "string",
                    "description": "Document title (defaults to first h1 heading or \"Document\")"
                  },
                  "author": {
                    "type": "string",
                    "description": "Document author for the meta author tag"
                  },
                  "description": {
                    "type": "string",
                    "description": "Document description for meta and Open Graph tags"
                  }
                }
              }
            }
          }
        }
      },
      "MdToDocumentResponse": {
        "type": "object",
        "properties": {
          "html": {
            "type": "string",
            "description": "Complete standalone HTML document with embedded styles"
          },
          "meta": {
            "type": "object",
            "properties": {
              "wordCount": {
                "type": "integer",
                "minimum": 0,
                "description": "Number of words in the input markdown"
              },
              "readingTime": {
                "type": "string",
                "description": "Estimated reading time (e.g. \"3 min\")"
              },
              "headings": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "Extracted heading text from the markdown"
              },
              "codeBlocks": {
                "type": "integer",
                "minimum": 0,
                "description": "Number of code blocks in the document"
              },
              "characterCount": {
                "type": "integer",
                "minimum": 0,
                "description": "Character count of the input markdown"
              }
            }
          }
        }
      },
      "CsvToJsonRequest": {
        "type": "object",
        "required": ["csv"],
        "properties": {
          "csv": {
            "type": "string",
            "minLength": 1,
            "description": "CSV text to parse. First row is treated as column headers."
          },
          "delimiter": {
            "type": "string",
            "minLength": 1,
            "maxLength": 1,
            "default": ",",
            "description": "Single-character delimiter (defaults to comma). Use `\\t` for TSV."
          }
        }
      },
      "CsvToJsonResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            },
            "description": "Array of row objects keyed by column headers"
          },
          "meta": {
            "type": "object",
            "properties": {
              "rowCount": {
                "type": "integer",
                "minimum": 0,
                "description": "Number of data rows (excluding header)"
              },
              "columns": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "Column names extracted from the header row"
              }
            }
          }
        }
      },
      "JsonToCsvRequest": {
        "type": "object",
        "required": ["data"],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            },
            "minItems": 1,
            "description": "Non-empty array of JSON objects to convert to CSV"
          },
          "delimiter": {
            "type": "string",
            "minLength": 1,
            "maxLength": 1,
            "default": ",",
            "description": "Single-character delimiter (defaults to comma)"
          }
        }
      },
      "JsonToCsvResponse": {
        "type": "object",
        "properties": {
          "csv": {
            "type": "string",
            "description": "CSV output with header row and data rows"
          },
          "meta": {
            "type": "object",
            "properties": {
              "rowCount": {
                "type": "integer",
                "minimum": 0,
                "description": "Number of data rows"
              },
              "columns": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "Column names (union of all keys across rows)"
              }
            }
          }
        }
      },
      "YamlJsonRequest": {
        "type": "object",
        "required": ["input", "direction"],
        "properties": {
          "input": {
            "type": "string",
            "minLength": 1,
            "description": "The YAML or JSON string to convert"
          },
          "direction": {
            "type": "string",
            "enum": ["yaml-to-json", "json-to-yaml"],
            "description": "Conversion direction"
          }
        }
      },
      "YamlJsonResponse": {
        "type": "object",
        "properties": {
          "output": {
            "type": "string",
            "description": "The converted output (JSON string or YAML string)"
          },
          "meta": {
            "type": "object",
            "properties": {
              "keys": {
                "type": "integer",
                "minimum": 0,
                "description": "Number of top-level keys in the parsed object"
              }
            }
          }
        }
      }
    }
  },
  "tags": [
    {
      "name": "General",
      "description": "API status and directory"
    },
    {
      "name": "Conversion",
      "description": "Document format conversion endpoints"
    }
  ]
}
